@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,57 @@
1
+ import type { SurfaceRegion } from '@flighthq/types';
2
+ /**
3
+ * Writes a brightness color matrix into `out` (length 20). Multiplies RGB by
4
+ * `amount` (CSS `brightness()` semantics): 1 is identity, 0 is black, >1 brightens.
5
+ */
6
+ export declare function buildSurfaceBrightnessColorMatrix(out: number[], amount: number): void;
7
+ /**
8
+ * Writes a contrast color matrix into `out` (length 20). Scales RGB around the
9
+ * midpoint (CSS `contrast()` semantics): 1 is identity, 0 is flat grey, >1 raises
10
+ * contrast.
11
+ */
12
+ export declare function buildSurfaceContrastColorMatrix(out: number[], amount: number): void;
13
+ /**
14
+ * Writes a grayscale color matrix into `out` (length 20). Equivalent to
15
+ * `buildSurfaceSaturationColorMatrix(out, 0)`; uses the W3C luma coefficients.
16
+ */
17
+ export declare function buildSurfaceGrayscaleColorMatrix(out: number[]): void;
18
+ /**
19
+ * Writes a hue-rotation color matrix into `out` (length 20). `degrees` rotates
20
+ * hue around the luma axis (CSS `hue-rotate()` semantics, W3C coefficients).
21
+ * 0° is identity; 180° inverts hue; values outside 0..360 wrap naturally.
22
+ */
23
+ export declare function buildSurfaceHueRotationColorMatrix(out: number[], degrees: number): void;
24
+ /**
25
+ * Writes an invert color matrix into `out` (length 20). Inverts RGB
26
+ * (`255 - channel`); alpha is preserved.
27
+ */
28
+ export declare function buildSurfaceInvertColorMatrix(out: number[]): void;
29
+ /**
30
+ * Writes a saturation color matrix into `out` (length 20). `amount` is 1 for
31
+ * identity, 0 for grayscale, >1 for oversaturated (CSS `saturate()` semantics,
32
+ * W3C luma coefficients).
33
+ */
34
+ export declare function buildSurfaceSaturationColorMatrix(out: number[], amount: number): void;
35
+ /**
36
+ * Writes a sepia color matrix into `out` (length 20), matching CSS `sepia(1)`.
37
+ */
38
+ export declare function buildSurfaceSepiaColorMatrix(out: number[]): void;
39
+ /**
40
+ * Applies a 4×5 color matrix to `source` and writes into `out`.
41
+ * `out` must be at least `source.width * source.height * 4` bytes.
42
+ *
43
+ * Safe to pass `source.surface.data` as `out` when the region covers the
44
+ * full surface — each pixel's input channels are read before any channel
45
+ * of that pixel is written.
46
+ */
47
+ export declare function colorMatrixSurface(out: Uint8ClampedArray, source: Readonly<SurfaceRegion>, matrix: ReadonlyArray<number>): void;
48
+ /**
49
+ * Composes two 4×5 color matrices into `out` (length 20): the result applies
50
+ * `first`, then `second`. `out` must not alias `first` or `second`.
51
+ */
52
+ export declare function concatSurfaceColorMatrix(out: number[], first: ReadonlyArray<number>, second: ReadonlyArray<number>): void;
53
+ /**
54
+ * Writes the identity color matrix into `out` (length 20).
55
+ */
56
+ export declare function setSurfaceColorMatrixIdentity(out: number[]): void;
57
+ //# sourceMappingURL=surfaceColorMatrix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceColorMatrix.d.ts","sourceRoot":"","sources":["../src/surfaceColorMatrix.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAKrD;;;GAGG;AACH,wBAAgB,iCAAiC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAErF;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAGnF;AAED;;;GAGG;AACH,wBAAgB,gCAAgC,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,CAEpE;AAED;;;;GAIG;AACH,wBAAgB,kCAAkC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CA2BvF;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,CAEjE;AAED;;;;GAIG;AACH,wBAAgB,iCAAiC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAMrF;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,CAEhE;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,iBAAiB,EACtB,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC/B,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,GAC5B,IAAI,CAqBN;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,EAAE,EACb,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,EAC5B,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,GAC5B,IAAI,CAUN;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,CAEjE"}
@@ -0,0 +1,127 @@
1
+ // 4×5 color matrices are row-major: 4 rows (R, G, B, A output), each with 5
2
+ // columns (R, G, B, A multipliers + a constant offset in 0..255 units).
3
+ /**
4
+ * Writes a brightness color matrix into `out` (length 20). Multiplies RGB by
5
+ * `amount` (CSS `brightness()` semantics): 1 is identity, 0 is black, >1 brightens.
6
+ */
7
+ export function buildSurfaceBrightnessColorMatrix(out, amount) {
8
+ setColorMatrix(out, amount, 0, 0, 0, 0, 0, amount, 0, 0, 0, 0, 0, amount, 0, 0, 0, 0, 0, 1, 0);
9
+ }
10
+ /**
11
+ * Writes a contrast color matrix into `out` (length 20). Scales RGB around the
12
+ * midpoint (CSS `contrast()` semantics): 1 is identity, 0 is flat grey, >1 raises
13
+ * contrast.
14
+ */
15
+ export function buildSurfaceContrastColorMatrix(out, amount) {
16
+ const t = 127.5 * (1 - amount);
17
+ setColorMatrix(out, amount, 0, 0, 0, t, 0, amount, 0, 0, t, 0, 0, amount, 0, t, 0, 0, 0, 1, 0);
18
+ }
19
+ /**
20
+ * Writes a grayscale color matrix into `out` (length 20). Equivalent to
21
+ * `buildSurfaceSaturationColorMatrix(out, 0)`; uses the W3C luma coefficients.
22
+ */
23
+ export function buildSurfaceGrayscaleColorMatrix(out) {
24
+ buildSurfaceSaturationColorMatrix(out, 0);
25
+ }
26
+ /**
27
+ * Writes a hue-rotation color matrix into `out` (length 20). `degrees` rotates
28
+ * hue around the luma axis (CSS `hue-rotate()` semantics, W3C coefficients).
29
+ * 0° is identity; 180° inverts hue; values outside 0..360 wrap naturally.
30
+ */
31
+ export function buildSurfaceHueRotationColorMatrix(out, degrees) {
32
+ const radians = (degrees * Math.PI) / 180;
33
+ const c = Math.cos(radians);
34
+ const s = Math.sin(radians);
35
+ setColorMatrix(out, 0.213 + c * 0.787 - s * 0.213, 0.715 - c * 0.715 - s * 0.715, 0.072 - c * 0.072 + s * 0.928, 0, 0, 0.213 - c * 0.213 + s * 0.143, 0.715 + c * 0.285 + s * 0.14, 0.072 - c * 0.072 - s * 0.283, 0, 0, 0.213 - c * 0.213 - s * 0.787, 0.715 - c * 0.715 + s * 0.715, 0.072 + c * 0.928 + s * 0.072, 0, 0, 0, 0, 0, 1, 0);
36
+ }
37
+ /**
38
+ * Writes an invert color matrix into `out` (length 20). Inverts RGB
39
+ * (`255 - channel`); alpha is preserved.
40
+ */
41
+ export function buildSurfaceInvertColorMatrix(out) {
42
+ setColorMatrix(out, -1, 0, 0, 0, 255, 0, -1, 0, 0, 255, 0, 0, -1, 0, 255, 0, 0, 0, 1, 0);
43
+ }
44
+ /**
45
+ * Writes a saturation color matrix into `out` (length 20). `amount` is 1 for
46
+ * identity, 0 for grayscale, >1 for oversaturated (CSS `saturate()` semantics,
47
+ * W3C luma coefficients).
48
+ */
49
+ export function buildSurfaceSaturationColorMatrix(out, amount) {
50
+ const inv = 1 - amount;
51
+ const r = LUMA_R * inv;
52
+ const g = LUMA_G * inv;
53
+ const b = LUMA_B * inv;
54
+ setColorMatrix(out, r + amount, g, b, 0, 0, r, g + amount, b, 0, 0, r, g, b + amount, 0, 0, 0, 0, 0, 1, 0);
55
+ }
56
+ /**
57
+ * Writes a sepia color matrix into `out` (length 20), matching CSS `sepia(1)`.
58
+ */
59
+ export function buildSurfaceSepiaColorMatrix(out) {
60
+ setColorMatrix(out, 0.393, 0.769, 0.189, 0, 0, 0.349, 0.686, 0.168, 0, 0, 0.272, 0.534, 0.131, 0, 0, 0, 0, 0, 1, 0);
61
+ }
62
+ /**
63
+ * Applies a 4×5 color matrix to `source` and writes into `out`.
64
+ * `out` must be at least `source.width * source.height * 4` bytes.
65
+ *
66
+ * Safe to pass `source.surface.data` as `out` when the region covers the
67
+ * full surface — each pixel's input channels are read before any channel
68
+ * of that pixel is written.
69
+ */
70
+ export function colorMatrixSurface(out, source, matrix) {
71
+ if (matrix.length < 20)
72
+ throw new Error('Color matrix filter requires 20 values');
73
+ for (let py = 0; py < source.height; py++) {
74
+ const sourceY = source.y + py;
75
+ if (sourceY < 0 || sourceY >= source.surface.height)
76
+ continue;
77
+ for (let px = 0; px < source.width; px++) {
78
+ const sourceX = source.x + px;
79
+ if (sourceX < 0 || sourceX >= source.surface.width)
80
+ continue;
81
+ const si = (sourceY * source.surface.width + sourceX) * 4;
82
+ const di = (py * source.width + px) * 4;
83
+ const r = source.surface.data[si];
84
+ const g = source.surface.data[si + 1];
85
+ const b = source.surface.data[si + 2];
86
+ const a = source.surface.data[si + 3];
87
+ out[di] = clampByte(r * matrix[0] + g * matrix[1] + b * matrix[2] + a * matrix[3] + matrix[4]);
88
+ out[di + 1] = clampByte(r * matrix[5] + g * matrix[6] + b * matrix[7] + a * matrix[8] + matrix[9]);
89
+ out[di + 2] = clampByte(r * matrix[10] + g * matrix[11] + b * matrix[12] + a * matrix[13] + matrix[14]);
90
+ out[di + 3] = clampByte(r * matrix[15] + g * matrix[16] + b * matrix[17] + a * matrix[18] + matrix[19]);
91
+ }
92
+ }
93
+ }
94
+ /**
95
+ * Composes two 4×5 color matrices into `out` (length 20): the result applies
96
+ * `first`, then `second`. `out` must not alias `first` or `second`.
97
+ */
98
+ export function concatSurfaceColorMatrix(out, first, second) {
99
+ for (let row = 0; row < 4; row++) {
100
+ for (let col = 0; col < 5; col++) {
101
+ let sum = col === 4 ? second[row * 5 + 4] : 0;
102
+ for (let k = 0; k < 4; k++) {
103
+ sum += second[row * 5 + k] * (col === 4 ? first[k * 5 + 4] : first[k * 5 + col]);
104
+ }
105
+ out[row * 5 + col] = sum;
106
+ }
107
+ }
108
+ }
109
+ /**
110
+ * Writes the identity color matrix into `out` (length 20).
111
+ */
112
+ export function setSurfaceColorMatrixIdentity(out) {
113
+ setColorMatrix(out, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0);
114
+ }
115
+ // W3C luma coefficients (matching CSS saturate/grayscale), so the CPU result
116
+ // agrees with the eventual CSS filter backend.
117
+ const LUMA_R = 0.213;
118
+ const LUMA_G = 0.715;
119
+ const LUMA_B = 0.072;
120
+ function clampByte(value) {
121
+ return Math.max(0, Math.min(255, Math.round(value)));
122
+ }
123
+ function setColorMatrix(out, ...values) {
124
+ for (let i = 0; i < 20; i++)
125
+ out[i] = values[i];
126
+ }
127
+ //# sourceMappingURL=surfaceColorMatrix.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceColorMatrix.js","sourceRoot":"","sources":["../src/surfaceColorMatrix.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,wEAAwE;AAExE;;;GAGG;AACH,MAAM,UAAU,iCAAiC,CAAC,GAAa,EAAE,MAAc;IAC7E,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACjG,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,+BAA+B,CAAC,GAAa,EAAE,MAAc;IAC3E,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;IAC/B,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACjG,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gCAAgC,CAAC,GAAa;IAC5D,iCAAiC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kCAAkC,CAAC,GAAa,EAAE,OAAe;IAC/E,MAAM,OAAO,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC;IAC1C,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC5B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC5B,cAAc,CACZ,GAAG,EACH,KAAK,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,KAAK,EAC7B,KAAK,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,KAAK,EAC7B,KAAK,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,KAAK,EAC7B,CAAC,EACD,CAAC,EACD,KAAK,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,KAAK,EAC7B,KAAK,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,IAAI,EAC5B,KAAK,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,KAAK,EAC7B,CAAC,EACD,CAAC,EACD,KAAK,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,KAAK,EAC7B,KAAK,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,KAAK,EAC7B,KAAK,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,KAAK,EAC7B,CAAC,EACD,CAAC,EACD,CAAC,EACD,CAAC,EACD,CAAC,EACD,CAAC,EACD,CAAC,CACF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAAC,GAAa;IACzD,cAAc,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAC3F,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iCAAiC,CAAC,GAAa,EAAE,MAAc;IAC7E,MAAM,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC;IACvB,MAAM,CAAC,GAAG,MAAM,GAAG,GAAG,CAAC;IACvB,MAAM,CAAC,GAAG,MAAM,GAAG,GAAG,CAAC;IACvB,MAAM,CAAC,GAAG,MAAM,GAAG,GAAG,CAAC;IACvB,cAAc,CAAC,GAAG,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAC7G,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,4BAA4B,CAAC,GAAa;IACxD,cAAc,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACtH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAChC,GAAsB,EACtB,MAA+B,EAC/B,MAA6B;IAE7B,IAAI,MAAM,CAAC,MAAM,GAAG,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAElF,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;QAC9B,IAAI,OAAO,GAAG,CAAC,IAAI,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM;YAAE,SAAS;QAC9D,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;YAC9B,IAAI,OAAO,GAAG,CAAC,IAAI,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK;gBAAE,SAAS;YAC7D,MAAM,EAAE,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;YAC1D,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;YACxC,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAClC,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YACtC,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YACtC,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YACtC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/F,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YACnG,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;YACxG,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1G,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CACtC,GAAa,EACb,KAA4B,EAC5B,MAA6B;IAE7B,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC;QACjC,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC;YACjC,IAAI,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,GAAG,IAAI,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YACnF,CAAC;YACD,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;QAC3B,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,6BAA6B,CAAC,GAAa;IACzD,cAAc,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAClF,CAAC;AAED,6EAA6E;AAC7E,+CAA+C;AAC/C,MAAM,MAAM,GAAG,KAAK,CAAC;AACrB,MAAM,MAAM,GAAG,KAAK,CAAC;AACrB,MAAM,MAAM,GAAG,KAAK,CAAC;AAErB,SAAS,SAAS,CAAC,KAAa;IAC9B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,cAAc,CAAC,GAAa,EAAE,GAAG,MAAgB;IACxD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE;QAAE,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { Surface, SurfaceMismatch } from '@flighthq/types';
2
+ /**
3
+ * Compares two surfaces pixel by pixel. Returns `null` if they are identical,
4
+ * or a new Surface showing per-channel absolute differences (with alpha set to
5
+ * 255 wherever any channel differs). Throws if the surfaces have different
6
+ * dimensions — comparing incompatible surfaces is a programmer error.
7
+ */
8
+ export declare function compareSurface(source: Readonly<Surface>, other: Readonly<Surface>): Surface | null;
9
+ /**
10
+ * Compares two equally sized surfaces with a per-channel tolerance and returns summary metrics rather
11
+ * than a diff image. A pixel is "mismatched" when its largest RGBA channel difference exceeds
12
+ * `channelTolerance` (0..255). Use a small tolerance plus a `fraction` threshold to assert that two
13
+ * backends rendered the same scene (cross-backend differential) or that a render still matches a prior
14
+ * one, while ignoring antialiasing noise. Throws if the surfaces differ in size — comparing
15
+ * incompatible surfaces is a programmer error (mirrors compareSurface).
16
+ */
17
+ export declare function getSurfaceMismatch(source: Readonly<Surface>, other: Readonly<Surface>, channelTolerance?: number): SurfaceMismatch;
18
+ //# sourceMappingURL=surfaceCompare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceCompare.d.ts","sourceRoot":"","sources":["../src/surfaceCompare.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAIhE;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,OAAO,GAAG,IAAI,CAyBlG;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,EACzB,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,EACxB,gBAAgB,GAAE,MAAU,GAC3B,eAAe,CA6BjB"}
@@ -0,0 +1,64 @@
1
+ import { createSurface } from './surface';
2
+ /**
3
+ * Compares two surfaces pixel by pixel. Returns `null` if they are identical,
4
+ * or a new Surface showing per-channel absolute differences (with alpha set to
5
+ * 255 wherever any channel differs). Throws if the surfaces have different
6
+ * dimensions — comparing incompatible surfaces is a programmer error.
7
+ */
8
+ export function compareSurface(source, other) {
9
+ if (source.width !== other.width || source.height !== other.height) {
10
+ throw new Error(`compareSurface: surface dimensions do not match (${source.width}×${source.height} vs ${other.width}×${other.height})`);
11
+ }
12
+ const result = createSurface(source.width, source.height);
13
+ let hasDiff = false;
14
+ for (let i = 0; i < source.data.length; i += 4) {
15
+ const dr = Math.abs(source.data[i] - other.data[i]);
16
+ const dg = Math.abs(source.data[i + 1] - other.data[i + 1]);
17
+ const db = Math.abs(source.data[i + 2] - other.data[i + 2]);
18
+ const da = Math.abs(source.data[i + 3] - other.data[i + 3]);
19
+ if (dr !== 0 || dg !== 0 || db !== 0 || da !== 0) {
20
+ result.data[i] = dr;
21
+ result.data[i + 1] = dg;
22
+ result.data[i + 2] = db;
23
+ result.data[i + 3] = 255;
24
+ hasDiff = true;
25
+ }
26
+ }
27
+ return hasDiff ? result : null;
28
+ }
29
+ /**
30
+ * Compares two equally sized surfaces with a per-channel tolerance and returns summary metrics rather
31
+ * than a diff image. A pixel is "mismatched" when its largest RGBA channel difference exceeds
32
+ * `channelTolerance` (0..255). Use a small tolerance plus a `fraction` threshold to assert that two
33
+ * backends rendered the same scene (cross-backend differential) or that a render still matches a prior
34
+ * one, while ignoring antialiasing noise. Throws if the surfaces differ in size — comparing
35
+ * incompatible surfaces is a programmer error (mirrors compareSurface).
36
+ */
37
+ export function getSurfaceMismatch(source, other, channelTolerance = 0) {
38
+ if (source.width !== other.width || source.height !== other.height) {
39
+ throw new Error(`getSurfaceMismatch: surface dimensions do not match (${source.width}×${source.height} vs ${other.width}×${other.height})`);
40
+ }
41
+ const a = source.data;
42
+ const b = other.data;
43
+ const totalPixels = source.width * source.height;
44
+ let mismatchedPixels = 0;
45
+ let maxChannelDelta = 0;
46
+ for (let i = 0; i < a.length; i += 4) {
47
+ const dr = Math.abs(a[i] - b[i]);
48
+ const dg = Math.abs(a[i + 1] - b[i + 1]);
49
+ const db = Math.abs(a[i + 2] - b[i + 2]);
50
+ const da = Math.abs(a[i + 3] - b[i + 3]);
51
+ const pixelDelta = Math.max(dr, dg, db, da);
52
+ if (pixelDelta > maxChannelDelta)
53
+ maxChannelDelta = pixelDelta;
54
+ if (pixelDelta > channelTolerance)
55
+ mismatchedPixels++;
56
+ }
57
+ return {
58
+ mismatchedPixels,
59
+ totalPixels,
60
+ fraction: totalPixels === 0 ? 0 : mismatchedPixels / totalPixels,
61
+ maxChannelDelta,
62
+ };
63
+ }
64
+ //# sourceMappingURL=surfaceCompare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceCompare.js","sourceRoot":"","sources":["../src/surfaceCompare.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import type { SurfaceRegion } from '@flighthq/types';
2
+ import { BlendMode } from '@flighthq/types';
3
+ /**
4
+ * Alpha-composites `pixels` over `dest`. `pixels` must be at least
5
+ * `dest.width * dest.height * 4` bytes in row-major RGBA order.
6
+ *
7
+ * `blendMode` selects how the source combines with the backdrop. Separable
8
+ * blends applied before the Porter-Duff source-over: Normal (default) and Layer
9
+ * (= Normal), Multiply, Screen, Add, Subtract, Darken, Lighten, Difference,
10
+ * Overlay, Hardlight, Invert. Erase is a destination-out knockout. Alpha and
11
+ * Shader are display-list concepts with no surface meaning and throw.
12
+ */
13
+ export declare function compositeSurfacePixels(dest: Readonly<SurfaceRegion>, pixels: Readonly<Uint8ClampedArray>, blendMode?: BlendMode): void;
14
+ /**
15
+ * Alpha-composites `source` over `dest`. See `compositeSurfacePixels` for the
16
+ * `blendMode` semantics.
17
+ */
18
+ export declare function compositeSurfaceRegion(dest: Readonly<SurfaceRegion>, source: Readonly<SurfaceRegion>, blendMode?: BlendMode): void;
19
+ /**
20
+ * Copies `source` into `out` in row-major, tightly-packed RGBA order
21
+ * (stride = source.width). `out` must be at least
22
+ * `source.width * source.height * 4` bytes.
23
+ *
24
+ * Safe to pass `source.surface.data` as `out` when the region covers the
25
+ * full surface (x=0, y=0, width=source.surface.width,
26
+ * height=source.surface.height).
27
+ */
28
+ export declare function extractSurfacePixels(out: Uint8ClampedArray, source: Readonly<SurfaceRegion>): void;
29
+ /**
30
+ * Copies `source` into `out` as one packed `0xRRGGBBAA` color per pixel
31
+ * (`0xRRGGBBAA` packed colors, the same packing `getSurfacePixel` returns), in row-major order with
32
+ * stride = source.width. `out` must hold at least
33
+ * `source.width * source.height` entries.
34
+ *
35
+ * This is the bulk, color-per-element counterpart to the byte-per-channel
36
+ * `extractSurfacePixels`: use it when you want to read or compare whole
37
+ * regions of colors without reassembling channel bytes.
38
+ */
39
+ export declare function extractSurfacePixels32(out: Uint32Array, source: Readonly<SurfaceRegion>): void;
40
+ /**
41
+ * Writes `pixels` into `dest`, overwriting existing content.
42
+ * `pixels` must be at least `dest.width * dest.height * 4` bytes in
43
+ * row-major RGBA order.
44
+ */
45
+ export declare function writeSurfacePixels(dest: Readonly<SurfaceRegion>, pixels: Readonly<Uint8ClampedArray>): void;
46
+ /**
47
+ * Writes `pixels` into `dest`, overwriting existing content. Each entry is a
48
+ * packed `0xRRGGBBAA` color (the form `setSurfacePixel` takes), read in
49
+ * row-major order. `pixels` must hold at least `dest.width * dest.height`
50
+ * entries. This is the color-per-element counterpart to `writeSurfacePixels`.
51
+ */
52
+ export declare function writeSurfacePixels32(dest: Readonly<SurfaceRegion>, pixels: Readonly<Uint32Array>): void;
53
+ //# sourceMappingURL=surfaceComposite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceComposite.d.ts","sourceRoot":"","sources":["../src/surfaceComposite.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC7B,MAAM,EAAE,QAAQ,CAAC,iBAAiB,CAAC,EACnC,SAAS,GAAE,SAA4B,GACtC,IAAI,CAqBN;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC7B,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC/B,SAAS,GAAE,SAA4B,GACtC,IAAI,CAyBN;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,iBAAiB,EAAE,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,GAAG,IAAI,CAelG;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,GAAG,IAAI,CAgB9F;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAgB3G;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,IAAI,CAgBvG"}
@@ -0,0 +1,230 @@
1
+ import { invalidateImageResource } from '@flighthq/image';
2
+ import { BlendMode } from '@flighthq/types';
3
+ /**
4
+ * Alpha-composites `pixels` over `dest`. `pixels` must be at least
5
+ * `dest.width * dest.height * 4` bytes in row-major RGBA order.
6
+ *
7
+ * `blendMode` selects how the source combines with the backdrop. Separable
8
+ * blends applied before the Porter-Duff source-over: Normal (default) and Layer
9
+ * (= Normal), Multiply, Screen, Add, Subtract, Darken, Lighten, Difference,
10
+ * Overlay, Hardlight, Invert. Erase is a destination-out knockout. Alpha and
11
+ * Shader are display-list concepts with no surface meaning and throw.
12
+ */
13
+ export function compositeSurfacePixels(dest, pixels, blendMode = BlendMode.Normal) {
14
+ assertCompositeBlendMode(blendMode);
15
+ for (let py = 0; py < dest.height; py++) {
16
+ const y = dest.y + py;
17
+ if (y < 0 || y >= dest.surface.height)
18
+ continue;
19
+ for (let px = 0; px < dest.width; px++) {
20
+ const x = dest.x + px;
21
+ if (x < 0 || x >= dest.surface.width)
22
+ continue;
23
+ const si = (py * dest.width + px) * 4;
24
+ compositePixelInto(dest.surface.data, (y * dest.surface.width + x) * 4, pixels[si], pixels[si + 1], pixels[si + 2], pixels[si + 3], blendMode);
25
+ }
26
+ }
27
+ invalidateImageResource(dest.surface);
28
+ }
29
+ /**
30
+ * Alpha-composites `source` over `dest`. See `compositeSurfacePixels` for the
31
+ * `blendMode` semantics.
32
+ */
33
+ export function compositeSurfaceRegion(dest, source, blendMode = BlendMode.Normal) {
34
+ assertCompositeBlendMode(blendMode);
35
+ const sw = Math.min(dest.width, source.width);
36
+ const sh = Math.min(dest.height, source.height);
37
+ for (let py = 0; py < sh; py++) {
38
+ const sourceY = source.y + py;
39
+ const y = dest.y + py;
40
+ if (sourceY < 0 || sourceY >= source.surface.height || y < 0 || y >= dest.surface.height)
41
+ continue;
42
+ for (let px = 0; px < sw; px++) {
43
+ const sourceX = source.x + px;
44
+ const x = dest.x + px;
45
+ if (sourceX < 0 || sourceX >= source.surface.width || x < 0 || x >= dest.surface.width)
46
+ continue;
47
+ const si = (sourceY * source.surface.width + sourceX) * 4;
48
+ compositePixelInto(dest.surface.data, (y * dest.surface.width + x) * 4, source.surface.data[si], source.surface.data[si + 1], source.surface.data[si + 2], source.surface.data[si + 3], blendMode);
49
+ }
50
+ }
51
+ invalidateImageResource(dest.surface);
52
+ }
53
+ /**
54
+ * Copies `source` into `out` in row-major, tightly-packed RGBA order
55
+ * (stride = source.width). `out` must be at least
56
+ * `source.width * source.height * 4` bytes.
57
+ *
58
+ * Safe to pass `source.surface.data` as `out` when the region covers the
59
+ * full surface (x=0, y=0, width=source.surface.width,
60
+ * height=source.surface.height).
61
+ */
62
+ export function extractSurfacePixels(out, source) {
63
+ for (let py = 0; py < source.height; py++) {
64
+ const sourceY = source.y + py;
65
+ if (sourceY < 0 || sourceY >= source.surface.height)
66
+ continue;
67
+ for (let px = 0; px < source.width; px++) {
68
+ const sourceX = source.x + px;
69
+ if (sourceX < 0 || sourceX >= source.surface.width)
70
+ continue;
71
+ const si = (sourceY * source.surface.width + sourceX) * 4;
72
+ const di = (py * source.width + px) * 4;
73
+ out[di] = source.surface.data[si];
74
+ out[di + 1] = source.surface.data[si + 1];
75
+ out[di + 2] = source.surface.data[si + 2];
76
+ out[di + 3] = source.surface.data[si + 3];
77
+ }
78
+ }
79
+ }
80
+ /**
81
+ * Copies `source` into `out` as one packed `0xRRGGBBAA` color per pixel
82
+ * (`0xRRGGBBAA` packed colors, the same packing `getSurfacePixel` returns), in row-major order with
83
+ * stride = source.width. `out` must hold at least
84
+ * `source.width * source.height` entries.
85
+ *
86
+ * This is the bulk, color-per-element counterpart to the byte-per-channel
87
+ * `extractSurfacePixels`: use it when you want to read or compare whole
88
+ * regions of colors without reassembling channel bytes.
89
+ */
90
+ export function extractSurfacePixels32(out, source) {
91
+ for (let py = 0; py < source.height; py++) {
92
+ const sourceY = source.y + py;
93
+ if (sourceY < 0 || sourceY >= source.surface.height)
94
+ continue;
95
+ for (let px = 0; px < source.width; px++) {
96
+ const sourceX = source.x + px;
97
+ if (sourceX < 0 || sourceX >= source.surface.width)
98
+ continue;
99
+ const si = (sourceY * source.surface.width + sourceX) * 4;
100
+ out[py * source.width + px] =
101
+ ((source.surface.data[si] << 24) |
102
+ (source.surface.data[si + 1] << 16) |
103
+ (source.surface.data[si + 2] << 8) |
104
+ source.surface.data[si + 3]) >>>
105
+ 0;
106
+ }
107
+ }
108
+ }
109
+ /**
110
+ * Writes `pixels` into `dest`, overwriting existing content.
111
+ * `pixels` must be at least `dest.width * dest.height * 4` bytes in
112
+ * row-major RGBA order.
113
+ */
114
+ export function writeSurfacePixels(dest, pixels) {
115
+ for (let py = 0; py < dest.height; py++) {
116
+ const y = dest.y + py;
117
+ if (y < 0 || y >= dest.surface.height)
118
+ continue;
119
+ for (let px = 0; px < dest.width; px++) {
120
+ const x = dest.x + px;
121
+ if (x < 0 || x >= dest.surface.width)
122
+ continue;
123
+ const si = (py * dest.width + px) * 4;
124
+ const di = (y * dest.surface.width + x) * 4;
125
+ dest.surface.data[di] = pixels[si];
126
+ dest.surface.data[di + 1] = pixels[si + 1];
127
+ dest.surface.data[di + 2] = pixels[si + 2];
128
+ dest.surface.data[di + 3] = pixels[si + 3];
129
+ }
130
+ }
131
+ invalidateImageResource(dest.surface);
132
+ }
133
+ /**
134
+ * Writes `pixels` into `dest`, overwriting existing content. Each entry is a
135
+ * packed `0xRRGGBBAA` color (the form `setSurfacePixel` takes), read in
136
+ * row-major order. `pixels` must hold at least `dest.width * dest.height`
137
+ * entries. This is the color-per-element counterpart to `writeSurfacePixels`.
138
+ */
139
+ export function writeSurfacePixels32(dest, pixels) {
140
+ for (let py = 0; py < dest.height; py++) {
141
+ const y = dest.y + py;
142
+ if (y < 0 || y >= dest.surface.height)
143
+ continue;
144
+ for (let px = 0; px < dest.width; px++) {
145
+ const x = dest.x + px;
146
+ if (x < 0 || x >= dest.surface.width)
147
+ continue;
148
+ const color = pixels[py * dest.width + px];
149
+ const di = (y * dest.surface.width + x) * 4;
150
+ dest.surface.data[di] = (color >>> 24) & 0xff;
151
+ dest.surface.data[di + 1] = (color >> 16) & 0xff;
152
+ dest.surface.data[di + 2] = (color >> 8) & 0xff;
153
+ dest.surface.data[di + 3] = color & 0xff;
154
+ }
155
+ }
156
+ invalidateImageResource(dest.surface);
157
+ }
158
+ // Throws once, up front, for blend modes that have no surface-compositing meaning,
159
+ // rather than silently degrading to Normal mid-loop.
160
+ function assertCompositeBlendMode(blendMode) {
161
+ if (blendMode === BlendMode.Alpha || blendMode === BlendMode.Shader) {
162
+ throw new Error(`BlendMode.${BlendMode[blendMode]} is not supported by surface compositing`);
163
+ }
164
+ }
165
+ // Separable per-channel blend on 0..255 values. Normal/Layer (and any mode not
166
+ // listed) return the source channel unchanged, reducing the composite to
167
+ // source-over.
168
+ function blendChannel(mode, cb, cs) {
169
+ switch (mode) {
170
+ case BlendMode.Multiply:
171
+ return (cb * cs) / 255;
172
+ case BlendMode.Screen:
173
+ return cb + cs - (cb * cs) / 255;
174
+ case BlendMode.Add:
175
+ return Math.min(255, cb + cs);
176
+ case BlendMode.Subtract:
177
+ return Math.max(0, cb - cs);
178
+ case BlendMode.Darken:
179
+ return Math.min(cb, cs);
180
+ case BlendMode.Lighten:
181
+ return Math.max(cb, cs);
182
+ case BlendMode.Difference:
183
+ return Math.abs(cb - cs);
184
+ case BlendMode.Overlay:
185
+ return cb < 128 ? (2 * cb * cs) / 255 : 255 - (2 * (255 - cb) * (255 - cs)) / 255;
186
+ case BlendMode.Hardlight:
187
+ return cs < 128 ? (2 * cb * cs) / 255 : 255 - (2 * (255 - cb) * (255 - cs)) / 255;
188
+ case BlendMode.Invert:
189
+ return 255 - cb;
190
+ default:
191
+ return cs;
192
+ }
193
+ }
194
+ function compositePixelInto(dest, di, r, g, b, a, blendMode) {
195
+ const srcA = a / 255;
196
+ const dstA = dest[di + 3] / 255;
197
+ // Erase is a destination-out knockout: the source alpha carves into the
198
+ // backdrop's alpha, leaving its color untouched.
199
+ if (blendMode === BlendMode.Erase) {
200
+ const eraseA = dstA * (1 - srcA);
201
+ if (eraseA <= 0) {
202
+ dest[di] = 0;
203
+ dest[di + 1] = 0;
204
+ dest[di + 2] = 0;
205
+ }
206
+ dest[di + 3] = Math.round(eraseA * 255);
207
+ return;
208
+ }
209
+ const outA = srcA + dstA * (1 - srcA);
210
+ if (outA <= 0) {
211
+ dest[di] = 0;
212
+ dest[di + 1] = 0;
213
+ dest[di + 2] = 0;
214
+ dest[di + 3] = 0;
215
+ return;
216
+ }
217
+ // W3C compositing: mix the blended color into the source by the backdrop alpha,
218
+ // then source-over. Read backdrop channels before writing any of them.
219
+ const cbR = dest[di];
220
+ const cbG = dest[di + 1];
221
+ const cbB = dest[di + 2];
222
+ const csR = (1 - dstA) * r + dstA * blendChannel(blendMode, cbR, r);
223
+ const csG = (1 - dstA) * g + dstA * blendChannel(blendMode, cbG, g);
224
+ const csB = (1 - dstA) * b + dstA * blendChannel(blendMode, cbB, b);
225
+ dest[di] = Math.round((csR * srcA + cbR * dstA * (1 - srcA)) / outA);
226
+ dest[di + 1] = Math.round((csG * srcA + cbG * dstA * (1 - srcA)) / outA);
227
+ dest[di + 2] = Math.round((csB * srcA + cbB * dstA * (1 - srcA)) / outA);
228
+ dest[di + 3] = Math.round(outA * 255);
229
+ }
230
+ //# sourceMappingURL=surfaceComposite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceComposite.js","sourceRoot":"","sources":["../src/surfaceComposite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { SurfaceEdgeMode, SurfaceRegion } from '@flighthq/types';
2
+ export interface SurfaceConvolutionOptions {
3
+ bias?: number;
4
+ /** How to handle kernel samples outside the surface. Default 'clamp'. */
5
+ edge?: SurfaceEdgeMode;
6
+ divisor?: number;
7
+ matrix: ReadonlyArray<number>;
8
+ matrixX: number;
9
+ matrixY: number;
10
+ preserveAlpha?: boolean;
11
+ }
12
+ /**
13
+ * Applies a convolution kernel to `source` and writes into `out`.
14
+ * `out` must be at least `source.width * source.height * 4` bytes.
15
+ *
16
+ * `out` must not alias `source.surface.data` — convolution reads neighboring
17
+ * pixels during kernel evaluation; overlapping source and destination produces
18
+ * undefined results.
19
+ *
20
+ * Edge modes:
21
+ * - `'clamp'` (default): repeat the nearest edge pixel
22
+ * - `'transparent'`: treat out-of-bounds samples as transparent black
23
+ * - `'wrap'`: tile the surface toroidally
24
+ * - `'mirror'`: reflect the image at boundaries
25
+ */
26
+ export declare function convolveSurface(out: Uint8ClampedArray, source: Readonly<SurfaceRegion>, options: Readonly<SurfaceConvolutionOptions>): void;
27
+ //# sourceMappingURL=surfaceConvolution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surfaceConvolution.d.ts","sourceRoot":"","sources":["../src/surfaceConvolution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEtE,MAAM,WAAW,yBAAyB;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,iBAAiB,EACtB,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC/B,OAAO,EAAE,QAAQ,CAAC,yBAAyB,CAAC,GAC3C,IAAI,CAqEN"}