@flighthq/surface 0.3.0-next.906.07cea63 → 0.5.1-edge.1467.7e2fc7d

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 (236) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +17 -0
  3. package/dist/canvasSurface.d.ts +5 -0
  4. package/dist/canvasSurface.d.ts.map +1 -0
  5. package/dist/canvasSurface.js +24 -0
  6. package/dist/canvasSurface.js.map +1 -0
  7. package/dist/contract.d.ts +4 -40
  8. package/dist/contract.d.ts.map +1 -1
  9. package/dist/contract.js +4 -40
  10. package/dist/contract.js.map +1 -1
  11. package/dist/glSurface.d.ts +5 -0
  12. package/dist/glSurface.d.ts.map +1 -0
  13. package/dist/glSurface.js +29 -0
  14. package/dist/glSurface.js.map +1 -0
  15. package/dist/index.d.ts +4 -1
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +4 -1
  18. package/dist/index.js.map +1 -1
  19. package/dist/surface.d.ts +4 -15
  20. package/dist/surface.d.ts.map +1 -1
  21. package/dist/surface.js +18 -82
  22. package/dist/surface.js.map +1 -1
  23. package/dist/surfaceDisplay.d.ts +4 -0
  24. package/dist/surfaceDisplay.d.ts.map +1 -0
  25. package/dist/surfaceDisplay.js +11 -0
  26. package/dist/surfaceDisplay.js.map +1 -0
  27. package/dist/wgpuSurface.d.ts +5 -0
  28. package/dist/wgpuSurface.d.ts.map +1 -0
  29. package/dist/wgpuSurface.js +30 -0
  30. package/dist/wgpuSurface.js.map +1 -0
  31. package/package.json +6 -5
  32. package/src/canvasSurface.test.ts +68 -0
  33. package/src/glSurface.test.ts +99 -0
  34. package/src/surface.test.ts +32 -63
  35. package/src/surfaceDisplay.test.ts +45 -0
  36. package/src/wgpuSurface.test.ts +74 -0
  37. package/dist/surfaceAffine.d.ts +0 -27
  38. package/dist/surfaceAffine.d.ts.map +0 -1
  39. package/dist/surfaceAffine.js +0 -159
  40. package/dist/surfaceAffine.js.map +0 -1
  41. package/dist/surfaceAlpha.d.ts +0 -27
  42. package/dist/surfaceAlpha.d.ts.map +0 -1
  43. package/dist/surfaceAlpha.js +0 -83
  44. package/dist/surfaceAlpha.js.map +0 -1
  45. package/dist/surfaceBevel.d.ts +0 -24
  46. package/dist/surfaceBevel.d.ts.map +0 -1
  47. package/dist/surfaceBevel.js +0 -102
  48. package/dist/surfaceBevel.js.map +0 -1
  49. package/dist/surfaceBlur.d.ts +0 -57
  50. package/dist/surfaceBlur.d.ts.map +0 -1
  51. package/dist/surfaceBlur.js +0 -263
  52. package/dist/surfaceBlur.js.map +0 -1
  53. package/dist/surfaceChannel.d.ts +0 -24
  54. package/dist/surfaceChannel.d.ts.map +0 -1
  55. package/dist/surfaceChannel.js +0 -127
  56. package/dist/surfaceChannel.js.map +0 -1
  57. package/dist/surfaceColorMatrix.d.ts +0 -57
  58. package/dist/surfaceColorMatrix.d.ts.map +0 -1
  59. package/dist/surfaceColorMatrix.js +0 -127
  60. package/dist/surfaceColorMatrix.js.map +0 -1
  61. package/dist/surfaceCompare.d.ts +0 -18
  62. package/dist/surfaceCompare.d.ts.map +0 -1
  63. package/dist/surfaceCompare.js +0 -64
  64. package/dist/surfaceCompare.js.map +0 -1
  65. package/dist/surfaceComposite.d.ts +0 -54
  66. package/dist/surfaceComposite.d.ts.map +0 -1
  67. package/dist/surfaceComposite.js +0 -262
  68. package/dist/surfaceComposite.js.map +0 -1
  69. package/dist/surfaceConvolution.d.ts +0 -17
  70. package/dist/surfaceConvolution.d.ts.map +0 -1
  71. package/dist/surfaceConvolution.js +0 -103
  72. package/dist/surfaceConvolution.js.map +0 -1
  73. package/dist/surfaceCopy.d.ts +0 -23
  74. package/dist/surfaceCopy.d.ts.map +0 -1
  75. package/dist/surfaceCopy.js +0 -78
  76. package/dist/surfaceCopy.js.map +0 -1
  77. package/dist/surfaceCoverage.d.ts +0 -11
  78. package/dist/surfaceCoverage.d.ts.map +0 -1
  79. package/dist/surfaceCoverage.js +0 -29
  80. package/dist/surfaceCoverage.js.map +0 -1
  81. package/dist/surfaceCrop.d.ts +0 -33
  82. package/dist/surfaceCrop.d.ts.map +0 -1
  83. package/dist/surfaceCrop.js +0 -177
  84. package/dist/surfaceCrop.js.map +0 -1
  85. package/dist/surfaceDisplacement.d.ts +0 -22
  86. package/dist/surfaceDisplacement.d.ts.map +0 -1
  87. package/dist/surfaceDisplacement.js +0 -131
  88. package/dist/surfaceDisplacement.js.map +0 -1
  89. package/dist/surfaceDissolve.d.ts +0 -21
  90. package/dist/surfaceDissolve.d.ts.map +0 -1
  91. package/dist/surfaceDissolve.js +0 -97
  92. package/dist/surfaceDissolve.js.map +0 -1
  93. package/dist/surfaceDraw.d.ts +0 -8
  94. package/dist/surfaceDraw.d.ts.map +0 -1
  95. package/dist/surfaceDraw.js +0 -14
  96. package/dist/surfaceDraw.js.map +0 -1
  97. package/dist/surfaceEncode.d.ts +0 -3
  98. package/dist/surfaceEncode.d.ts.map +0 -1
  99. package/dist/surfaceEncode.js +0 -18
  100. package/dist/surfaceEncode.js.map +0 -1
  101. package/dist/surfaceFill.d.ts +0 -12
  102. package/dist/surfaceFill.d.ts.map +0 -1
  103. package/dist/surfaceFill.js +0 -85
  104. package/dist/surfaceFill.js.map +0 -1
  105. package/dist/surfaceFingerprint.d.ts +0 -26
  106. package/dist/surfaceFingerprint.d.ts.map +0 -1
  107. package/dist/surfaceFingerprint.js +0 -99
  108. package/dist/surfaceFingerprint.js.map +0 -1
  109. package/dist/surfaceFlip.d.ts +0 -16
  110. package/dist/surfaceFlip.d.ts.map +0 -1
  111. package/dist/surfaceFlip.js +0 -98
  112. package/dist/surfaceFlip.js.map +0 -1
  113. package/dist/surfaceFormat.d.ts +0 -26
  114. package/dist/surfaceFormat.d.ts.map +0 -1
  115. package/dist/surfaceFormat.js +0 -80
  116. package/dist/surfaceFormat.js.map +0 -1
  117. package/dist/surfaceFrom.d.ts +0 -14
  118. package/dist/surfaceFrom.d.ts.map +0 -1
  119. package/dist/surfaceFrom.js +0 -91
  120. package/dist/surfaceFrom.js.map +0 -1
  121. package/dist/surfaceGradient.d.ts +0 -36
  122. package/dist/surfaceGradient.d.ts.map +0 -1
  123. package/dist/surfaceGradient.js +0 -176
  124. package/dist/surfaceGradient.js.map +0 -1
  125. package/dist/surfaceGradientFill.d.ts +0 -32
  126. package/dist/surfaceGradientFill.d.ts.map +0 -1
  127. package/dist/surfaceGradientFill.js +0 -120
  128. package/dist/surfaceGradientFill.js.map +0 -1
  129. package/dist/surfaceHistogram.d.ts +0 -20
  130. package/dist/surfaceHistogram.d.ts.map +0 -1
  131. package/dist/surfaceHistogram.js +0 -61
  132. package/dist/surfaceHistogram.js.map +0 -1
  133. package/dist/surfaceImageChannel.d.ts +0 -2
  134. package/dist/surfaceImageChannel.d.ts.map +0 -1
  135. package/dist/surfaceImageChannel.js +0 -2
  136. package/dist/surfaceImageChannel.js.map +0 -1
  137. package/dist/surfaceMedian.d.ts +0 -14
  138. package/dist/surfaceMedian.d.ts.map +0 -1
  139. package/dist/surfaceMedian.js +0 -77
  140. package/dist/surfaceMedian.js.map +0 -1
  141. package/dist/surfaceMorphological.d.ts +0 -29
  142. package/dist/surfaceMorphological.d.ts.map +0 -1
  143. package/dist/surfaceMorphological.js +0 -81
  144. package/dist/surfaceMorphological.js.map +0 -1
  145. package/dist/surfaceNoise.d.ts +0 -48
  146. package/dist/surfaceNoise.d.ts.map +0 -1
  147. package/dist/surfaceNoise.js +0 -245
  148. package/dist/surfaceNoise.js.map +0 -1
  149. package/dist/surfacePaletteMap.d.ts +0 -17
  150. package/dist/surfacePaletteMap.d.ts.map +0 -1
  151. package/dist/surfacePaletteMap.js +0 -45
  152. package/dist/surfacePaletteMap.js.map +0 -1
  153. package/dist/surfacePixel.d.ts +0 -9
  154. package/dist/surfacePixel.d.ts.map +0 -1
  155. package/dist/surfacePixel.js +0 -36
  156. package/dist/surfacePixel.js.map +0 -1
  157. package/dist/surfacePixelate.d.ts +0 -13
  158. package/dist/surfacePixelate.d.ts.map +0 -1
  159. package/dist/surfacePixelate.js +0 -61
  160. package/dist/surfacePixelate.js.map +0 -1
  161. package/dist/surfaceQuery.d.ts +0 -13
  162. package/dist/surfaceQuery.d.ts.map +0 -1
  163. package/dist/surfaceQuery.js +0 -46
  164. package/dist/surfaceQuery.js.map +0 -1
  165. package/dist/surfaceRegion.d.ts +0 -20
  166. package/dist/surfaceRegion.d.ts.map +0 -1
  167. package/dist/surfaceRegion.js +0 -28
  168. package/dist/surfaceRegion.js.map +0 -1
  169. package/dist/surfaceResize.d.ts +0 -17
  170. package/dist/surfaceResize.d.ts.map +0 -1
  171. package/dist/surfaceResize.js +0 -191
  172. package/dist/surfaceResize.js.map +0 -1
  173. package/dist/surfaceRotate.d.ts +0 -32
  174. package/dist/surfaceRotate.d.ts.map +0 -1
  175. package/dist/surfaceRotate.js +0 -143
  176. package/dist/surfaceRotate.js.map +0 -1
  177. package/dist/surfaceShadow.d.ts +0 -72
  178. package/dist/surfaceShadow.d.ts.map +0 -1
  179. package/dist/surfaceShadow.js +0 -175
  180. package/dist/surfaceShadow.js.map +0 -1
  181. package/dist/surfaceSharpen.d.ts +0 -16
  182. package/dist/surfaceSharpen.d.ts.map +0 -1
  183. package/dist/surfaceSharpen.js +0 -47
  184. package/dist/surfaceSharpen.js.map +0 -1
  185. package/dist/surfaceTone.d.ts +0 -28
  186. package/dist/surfaceTone.d.ts.map +0 -1
  187. package/dist/surfaceTone.js +0 -69
  188. package/dist/surfaceTone.js.map +0 -1
  189. package/dist/surfaceTransform.d.ts +0 -40
  190. package/dist/surfaceTransform.d.ts.map +0 -1
  191. package/dist/surfaceTransform.js +0 -163
  192. package/dist/surfaceTransform.js.map +0 -1
  193. package/dist/surfaceWarp.d.ts +0 -48
  194. package/dist/surfaceWarp.d.ts.map +0 -1
  195. package/dist/surfaceWarp.js +0 -284
  196. package/dist/surfaceWarp.js.map +0 -1
  197. package/src/surfaceAffine.test.ts +0 -98
  198. package/src/surfaceAlpha.test.ts +0 -113
  199. package/src/surfaceBevel.test.ts +0 -67
  200. package/src/surfaceBlur.test.ts +0 -240
  201. package/src/surfaceChannel.test.ts +0 -97
  202. package/src/surfaceColorMatrix.test.ts +0 -220
  203. package/src/surfaceCompare.test.ts +0 -92
  204. package/src/surfaceComposite.test.ts +0 -265
  205. package/src/surfaceConvolution.test.ts +0 -136
  206. package/src/surfaceCopy.test.ts +0 -54
  207. package/src/surfaceCoverage.test.ts +0 -39
  208. package/src/surfaceCrop.test.ts +0 -116
  209. package/src/surfaceDisplacement.test.ts +0 -142
  210. package/src/surfaceDissolve.test.ts +0 -99
  211. package/src/surfaceDraw.test.ts +0 -74
  212. package/src/surfaceEncode.test.ts +0 -18
  213. package/src/surfaceFill.test.ts +0 -89
  214. package/src/surfaceFingerprint.test.ts +0 -103
  215. package/src/surfaceFlip.test.ts +0 -59
  216. package/src/surfaceFormat.test.ts +0 -124
  217. package/src/surfaceFrom.test.ts +0 -62
  218. package/src/surfaceGradient.test.ts +0 -91
  219. package/src/surfaceGradientFill.test.ts +0 -107
  220. package/src/surfaceHistogram.test.ts +0 -70
  221. package/src/surfaceImageChannel.test.ts +0 -19
  222. package/src/surfaceMedian.test.ts +0 -45
  223. package/src/surfaceMorphological.test.ts +0 -75
  224. package/src/surfaceNoise.test.ts +0 -169
  225. package/src/surfacePaletteMap.test.ts +0 -55
  226. package/src/surfacePixel.test.ts +0 -117
  227. package/src/surfacePixelate.test.ts +0 -46
  228. package/src/surfaceQuery.test.ts +0 -48
  229. package/src/surfaceRegion.test.ts +0 -34
  230. package/src/surfaceResize.test.ts +0 -112
  231. package/src/surfaceRotate.test.ts +0 -119
  232. package/src/surfaceShadow.test.ts +0 -165
  233. package/src/surfaceSharpen.test.ts +0 -50
  234. package/src/surfaceTone.test.ts +0 -104
  235. package/src/surfaceTransform.test.ts +0 -134
  236. package/src/surfaceWarp.test.ts +0 -124
@@ -0,0 +1,99 @@
1
+ import { finishEntity } from '@flighthq/entity/contract';
2
+ import type { AppWindow, Entity, GlContext, GlSurface, HostGlCapability } from '@flighthq/types/contract';
3
+
4
+ import { createGlSurface, createGlSurfaceFromNativeHandle, destroyGlSurface } from './glSurface';
5
+ import { allocateSurface, getSurfaceHandle } from './surface';
6
+
7
+ function glCapability(fields: HostGlCapability): HostGlCapability {
8
+ return finishEntity(Object.assign(allocateSurface(null), fields) as never) as unknown as HostGlCapability;
9
+ }
10
+
11
+ const appWindow = {} as AppWindow;
12
+ const context = {} as GlContext;
13
+ const defaults = { release() {}, subscribe: () => () => {} };
14
+
15
+ describe('createGlSurface', () => {
16
+ it('allocates a drawable in the window and acquires a context on the surface it built', () => {
17
+ const create = vi.fn(() => 'canvas');
18
+ const acquire = vi.fn(() => context);
19
+ const surface = createGlSurface(glCapability({ acquire, create, ...defaults }), appWindow, 800, 500);
20
+
21
+ expect(surface).not.toBeNull();
22
+ expect(surface!.__brand).toBe('GlSurface');
23
+ expect(surface!.context).toBe(context);
24
+ expect(getSurfaceHandle(surface!)).toBe('canvas');
25
+ expect(create).toHaveBeenCalledExactlyOnceWith(appWindow, 800, 500, undefined);
26
+ });
27
+
28
+ it('hands acquire the surface, so the host resolves the drawable it just allocated', () => {
29
+ const acquire = vi.fn(() => context);
30
+ const surface = createGlSurface(
31
+ glCapability({ acquire, create: () => 'canvas', ...defaults }),
32
+ appWindow,
33
+ 800,
34
+ 500,
35
+ );
36
+
37
+ expect(acquire).toHaveBeenCalledExactlyOnceWith(surface, undefined);
38
+ });
39
+
40
+ it('passes options to both create and acquire', () => {
41
+ const create = vi.fn(() => 'canvas');
42
+ const acquire = vi.fn(() => context);
43
+ const options = { antialias: true };
44
+ createGlSurface(glCapability({ acquire, create, ...defaults }), appWindow, 800, 500, options);
45
+
46
+ expect(create).toHaveBeenCalledExactlyOnceWith(appWindow, 800, 500, options);
47
+ expect(acquire).toHaveBeenCalledWith(expect.anything(), options);
48
+ });
49
+
50
+ it('returns null without acquiring when the window cannot yield a drawable', () => {
51
+ const acquire = vi.fn(() => context);
52
+ expect(createGlSurface(glCapability({ acquire, create: () => null, ...defaults }), appWindow, 8, 8)).toBeNull();
53
+ expect(acquire).not.toHaveBeenCalled();
54
+ });
55
+
56
+ it('returns null when the drawable exists but no context can be acquired', () => {
57
+ expect(
58
+ createGlSurface(glCapability({ acquire: () => null, create: () => 'canvas', ...defaults }), appWindow, 8, 8),
59
+ ).toBeNull();
60
+ });
61
+ });
62
+
63
+ describe('createGlSurfaceFromNativeHandle', () => {
64
+ it('adopts a drawable the caller owns without allocating one', () => {
65
+ const create = vi.fn(() => 'unused');
66
+ const surface = createGlSurfaceFromNativeHandle(
67
+ glCapability({ acquire: () => context, create, ...defaults }),
68
+ 'adopted',
69
+ );
70
+
71
+ expect(getSurfaceHandle(surface!)).toBe('adopted');
72
+ expect(create).not.toHaveBeenCalled();
73
+ });
74
+
75
+ it('returns null when the adopted drawable yields no context', () => {
76
+ expect(
77
+ createGlSurfaceFromNativeHandle(
78
+ glCapability({ acquire: () => null, create: () => null, ...defaults }),
79
+ 'adopted',
80
+ ),
81
+ ).toBeNull();
82
+ });
83
+ });
84
+
85
+ describe('destroyGlSurface', () => {
86
+ it('releases the surface through the capability', () => {
87
+ const release = vi.fn();
88
+ const capability = glCapability({
89
+ acquire: () => context,
90
+ create: () => 'canvas',
91
+ release,
92
+ subscribe: () => () => {},
93
+ });
94
+ const surface = createGlSurface(capability, appWindow, 8, 8) as GlSurface;
95
+ destroyGlSurface(capability, surface);
96
+
97
+ expect(release).toHaveBeenCalledExactlyOnceWith(surface);
98
+ });
99
+ });
@@ -1,78 +1,47 @@
1
- import { cloneSurface, convertSurfaceAlphaType, createSurface } from './surface';
1
+ import { finishEntity } from '@flighthq/entity/contract';
2
+ import type { Surface } from '@flighthq/types/contract';
3
+ import { EntityRuntimeKey } from '@flighthq/types/contract';
2
4
 
3
- describe('cloneSurface', () => {
4
- it('produces identical values', () => {
5
- const img = createSurface(2, 2, 0x102030ff);
6
- const clone = cloneSurface(img);
7
- expect(clone.width).toBe(img.width);
8
- expect(clone.height).toBe(img.height);
9
- expect(clone.data).toEqual(img.data);
10
- });
5
+ import { allocateSurface, getSurfaceHandle, getSurfaceRuntime } from './surface';
11
6
 
12
- it('is a deep copy', () => {
13
- const img = createSurface(2, 2, 0x102030ff);
14
- const clone = cloneSurface(img);
15
- clone.data[0] = 0;
16
- expect(img.data[0]).toBe(0x10);
17
- });
18
- });
7
+ describe('allocateSurface', () => {
8
+ it('puts the drawable on the runtime and nothing on the entity', () => {
9
+ const handle = { drawable: true };
10
+ const surface = finishEntity(allocateSurface<Surface>(handle));
19
11
 
20
- describe('convertSurfaceAlphaType', () => {
21
- it('premultiplies straight alpha', () => {
22
- const img = createSurface(1, 1, 0x80808080);
23
- img.alphaType = 'straight';
24
- convertSurfaceAlphaType(img, 'premultiplied');
25
- expect(img.alphaType).toBe('premultiplied');
26
- // R = round(0x80 * (0x80/255)) ≈ round(128 * 0.502) ≈ 64
27
- expect(img.data[0]).toBe(64);
28
- expect(img.data[3]).toBe(0x80); // alpha unchanged
12
+ // The whole point of the runtime tier: a portable caller holding this surface can see no trace of the
13
+ // platform object, so no portable layer can grow a dependency on it.
14
+ expect(Object.keys(surface)).toEqual([]);
15
+ expect(getSurfaceHandle(surface)).toBe(handle);
29
16
  });
30
17
 
31
- it('unpremultiplies premultiplied alpha', () => {
32
- // Pre-build a premultiplied surface manually.
33
- const img = createSurface(1, 1, 0x00000000);
34
- img.alphaType = 'premultiplied';
35
- img.data[0] = 64;
36
- img.data[1] = 64;
37
- img.data[2] = 64;
38
- img.data[3] = 128;
39
- convertSurfaceAlphaType(img, 'straight');
40
- expect(img.alphaType).toBe('straight');
41
- // R = round(64 * 255/128) = round(127.5) = 128
42
- expect(img.data[0]).toBe(128);
43
- });
18
+ it('gives each surface its own runtime rather than a shared side table', () => {
19
+ const first = finishEntity(allocateSurface<Surface>({ id: 1 }));
20
+ const second = finishEntity(allocateSurface<Surface>({ id: 2 }));
44
21
 
45
- it('is a no-op when target matches current alphaType', () => {
46
- const img = createSurface(1, 1, 0xff0000ff);
47
- img.alphaType = 'straight';
48
- const before = Array.from(img.data);
49
- convertSurfaceAlphaType(img, 'straight');
50
- expect(Array.from(img.data)).toEqual(before);
22
+ expect(getSurfaceRuntime(first)).not.toBe(getSurfaceRuntime(second));
23
+ expect(getSurfaceHandle(first)).toEqual({ id: 1 });
24
+ expect(getSurfaceHandle(second)).toEqual({ id: 2 });
51
25
  });
52
26
 
53
- it('handles zero-alpha pixels (unpremultiply)', () => {
54
- const img = createSurface(1, 1, 0x00000000);
55
- img.alphaType = 'premultiplied';
56
- convertSurfaceAlphaType(img, 'straight');
57
- expect(img.data[0]).toBe(0);
58
- expect(img.data[3]).toBe(0);
27
+ it('accepts any host representation, including a non-object handle', () => {
28
+ // A lower-level host may identify its drawable by an integer; NativeSurfaceHandle does not narrow it.
29
+ expect(getSurfaceHandle(finishEntity(allocateSurface<Surface>(7)))).toBe(7);
59
30
  });
60
31
  });
61
32
 
62
- describe('createSurface', () => {
63
- it('creates zeroed image data when no color provided', () => {
64
- const img = createSurface(2, 2);
65
- expect(img.width).toBe(2);
66
- expect(img.height).toBe(2);
67
- expect(img.data.length).toBe(16);
68
- expect(img.data.every((v) => v === 0)).toBe(true);
33
+ describe('getSurfaceHandle', () => {
34
+ it('reads through the runtime the surface was allocated with', () => {
35
+ const surface = finishEntity(allocateSurface<Surface>('handle'));
36
+
37
+ expect(getSurfaceHandle(surface)).toBe(getSurfaceRuntime(surface).handle);
69
38
  });
39
+ });
40
+
41
+ describe('getSurfaceRuntime', () => {
42
+ it('returns the runtime attached under the entity runtime key', () => {
43
+ const surface = finishEntity(allocateSurface<Surface>(null));
70
44
 
71
- it('fills with the given color', () => {
72
- const img = createSurface(2, 2, 0x112233ff);
73
- expect(img.data[0]).toBe(0x11);
74
- expect(img.data[1]).toBe(0x22);
75
- expect(img.data[2]).toBe(0x33);
76
- expect(img.data[3]).toBe(0xff);
45
+ expect(getSurfaceRuntime(surface)).toBe(surface[EntityRuntimeKey]);
77
46
  });
78
47
  });
@@ -0,0 +1,45 @@
1
+ import { finishEntity } from '@flighthq/entity/contract';
2
+ import type {
3
+ Entity,
4
+ HostSurfaceDisplayCapability,
5
+ HostSurfaceResizeCapability,
6
+ Surface,
7
+ } from '@flighthq/types/contract';
8
+
9
+ import { allocateSurface } from './surface';
10
+ import { resizeSurface, setSurfaceDisplaySize } from './surfaceDisplay';
11
+
12
+ function capabilityOf<T>(fields: Omit<T, keyof Entity>): T {
13
+ return finishEntity(Object.assign(allocateSurface<Surface>(null), fields) as never) as T;
14
+ }
15
+
16
+ const surface = finishEntity(allocateSurface<Surface>({}));
17
+
18
+ describe('resizeSurface', () => {
19
+ it('routes the device-pixel size to the surface through the capability', () => {
20
+ const resize = vi.fn();
21
+ resizeSurface(capabilityOf<HostSurfaceResizeCapability>({ resize }), surface, 1600, 1000);
22
+
23
+ expect(resize).toHaveBeenCalledExactlyOnceWith(surface, 1600, 1000);
24
+ });
25
+ });
26
+
27
+ describe('setSurfaceDisplaySize', () => {
28
+ it('routes the logical size to the surface through the capability', () => {
29
+ const setDisplaySize = vi.fn();
30
+ setSurfaceDisplaySize(capabilityOf<HostSurfaceDisplayCapability>({ setDisplaySize }), surface, 800, 500);
31
+
32
+ expect(setDisplaySize).toHaveBeenCalledExactlyOnceWith(surface, 800, 500);
33
+ });
34
+
35
+ it('passes the logical size through unscaled, never derived from the backing store', () => {
36
+ // A 2x supersampled surface: display and backing are deliberately unrelated, so the call must carry
37
+ // exactly what the caller passed.
38
+ const setDisplaySize = vi.fn();
39
+ const resize = vi.fn();
40
+ resizeSurface(capabilityOf<HostSurfaceResizeCapability>({ resize }), surface, 1600, 1000);
41
+ setSurfaceDisplaySize(capabilityOf<HostSurfaceDisplayCapability>({ setDisplaySize }), surface, 800, 500);
42
+
43
+ expect(setDisplaySize).toHaveBeenCalledExactlyOnceWith(surface, 800, 500);
44
+ });
45
+ });
@@ -0,0 +1,74 @@
1
+ import { finishEntity } from '@flighthq/entity/contract';
2
+ import type { AppWindow, Entity, HostWgpuCapability, WgpuHostAcquisition, WgpuSurface } from '@flighthq/types/contract';
3
+
4
+ import { allocateSurface, getSurfaceHandle } from './surface';
5
+ import { createWgpuSurface, createWgpuSurfaceFromNativeHandle, destroyWgpuSurface } from './wgpuSurface';
6
+
7
+ function wgpuCapability(fields: HostWgpuCapability): HostWgpuCapability {
8
+ return finishEntity(Object.assign(allocateSurface(null), fields) as never) as unknown as HostWgpuCapability;
9
+ }
10
+
11
+ const appWindow = {} as AppWindow;
12
+ const acquisition = {} as WgpuHostAcquisition;
13
+ const defaults = { attachSurface: () => null, isSupported: () => true, release() {} };
14
+
15
+ describe('createWgpuSurface', () => {
16
+ it('allocates a drawable in the window and acquires a device for the surface it built', async () => {
17
+ const create = vi.fn(() => 'canvas');
18
+ const acquire = vi.fn(async () => acquisition);
19
+ const surface = await createWgpuSurface(wgpuCapability({ acquire, create, ...defaults }), appWindow, 800, 500);
20
+
21
+ expect(surface!.__brand).toBe('WgpuSurface');
22
+ expect(surface!.acquisition).toBe(acquisition);
23
+ expect(getSurfaceHandle(surface!)).toBe('canvas');
24
+ expect(create).toHaveBeenCalledExactlyOnceWith(appWindow, 800, 500);
25
+ expect(acquire).toHaveBeenCalledExactlyOnceWith(surface, {});
26
+ });
27
+
28
+ it('returns null without acquiring when the window cannot yield a drawable', async () => {
29
+ const acquire = vi.fn(async () => acquisition);
30
+ expect(
31
+ await createWgpuSurface(wgpuCapability({ acquire, create: () => null, ...defaults }), appWindow, 8, 8),
32
+ ).toBeNull();
33
+ expect(acquire).not.toHaveBeenCalled();
34
+ });
35
+
36
+ // ★ NULL, NOT REJECT. "This machine has no WebGPU" is an expected outcome, not API misuse.
37
+ it('returns null when device acquisition rejects', async () => {
38
+ const acquire = async (): Promise<WgpuHostAcquisition> => {
39
+ throw new Error('no adapter');
40
+ };
41
+ expect(
42
+ await createWgpuSurface(wgpuCapability({ acquire, create: () => 'canvas', ...defaults }), appWindow, 8, 8),
43
+ ).toBeNull();
44
+ });
45
+ });
46
+
47
+ describe('createWgpuSurfaceFromNativeHandle', () => {
48
+ it('adopts a drawable the caller owns without allocating one', async () => {
49
+ const create = vi.fn(() => 'unused');
50
+ const surface = await createWgpuSurfaceFromNativeHandle(
51
+ wgpuCapability({ acquire: async () => acquisition, create, ...defaults }),
52
+ 'adopted',
53
+ );
54
+
55
+ expect(getSurfaceHandle(surface!)).toBe('adopted');
56
+ expect(create).not.toHaveBeenCalled();
57
+ });
58
+ });
59
+
60
+ describe('destroyWgpuSurface', () => {
61
+ it('releases the acquisition through the capability', async () => {
62
+ const release = vi.fn();
63
+ const capability = wgpuCapability({
64
+ acquire: async () => acquisition,
65
+ attachSurface: () => null,
66
+ create: () => 'canvas',
67
+ isSupported: () => true,
68
+ release,
69
+ });
70
+ destroyWgpuSurface(capability, (await createWgpuSurface(capability, appWindow, 8, 8)) as WgpuSurface);
71
+
72
+ expect(release).toHaveBeenCalledExactlyOnceWith(acquisition);
73
+ });
74
+ });
@@ -1,27 +0,0 @@
1
- import type { SurfaceEdgeMode, SurfaceRegion, SurfaceResizeMode } from '@flighthq/types/contract';
2
- /**
3
- * Applies a full 2×3 affine transform to the `source` region, writing into
4
- * `dest`. The `matrix` is a 6-element array `[a, b, c, d, e, f]` representing:
5
- *
6
- * ```
7
- * [ a c e ]
8
- * [ b d f ]
9
- * ```
10
- *
11
- * Maps each `dest` pixel `(x, y)` back to source coordinates by the inverse
12
- * transform:
13
- *
14
- * ```
15
- * srcX = a * x + c * y + e
16
- * srcY = b * x + d * y + f
17
- * ```
18
- *
19
- * This is a forward-mapping: for each output pixel the source position is
20
- * computed, then sampled according to `sampleMode` (default `'bilinear'`).
21
- * Out-of-bounds source positions are resolved with `edgeMode` (default
22
- * `'transparent'`).
23
- *
24
- * `dest` must not alias `source` when their regions overlap.
25
- */
26
- export declare function transformSurface(dest: Readonly<SurfaceRegion>, source: Readonly<SurfaceRegion>, matrix: Readonly<[number, number, number, number, number, number]>, edgeMode?: SurfaceEdgeMode, sampleMode?: SurfaceResizeMode): void;
27
- //# sourceMappingURL=surfaceAffine.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"surfaceAffine.d.ts","sourceRoot":"","sources":["../src/surfaceAffine.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElG;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC7B,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC/B,MAAM,EAAE,QAAQ,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,EAClE,QAAQ,GAAE,eAA+B,EACzC,UAAU,GAAE,iBAA8B,GACzC,IAAI,CAuCN"}
@@ -1,159 +0,0 @@
1
- import { invalidateImageResource } from '@flighthq/image/contract';
2
- /**
3
- * Applies a full 2×3 affine transform to the `source` region, writing into
4
- * `dest`. The `matrix` is a 6-element array `[a, b, c, d, e, f]` representing:
5
- *
6
- * ```
7
- * [ a c e ]
8
- * [ b d f ]
9
- * ```
10
- *
11
- * Maps each `dest` pixel `(x, y)` back to source coordinates by the inverse
12
- * transform:
13
- *
14
- * ```
15
- * srcX = a * x + c * y + e
16
- * srcY = b * x + d * y + f
17
- * ```
18
- *
19
- * This is a forward-mapping: for each output pixel the source position is
20
- * computed, then sampled according to `sampleMode` (default `'bilinear'`).
21
- * Out-of-bounds source positions are resolved with `edgeMode` (default
22
- * `'transparent'`).
23
- *
24
- * `dest` must not alias `source` when their regions overlap.
25
- */
26
- export function transformSurface(dest, source, matrix, edgeMode = 'transparent', sampleMode = 'bilinear') {
27
- const dw = dest.width;
28
- const dh = dest.height;
29
- const sw = source.width;
30
- const sh = source.height;
31
- if (dw === 0 || dh === 0 || sw === 0 || sh === 0)
32
- return;
33
- const [a, b, c, d, e, f] = matrix;
34
- const sd = source.surface.data;
35
- const dd = dest.surface.data;
36
- const sStride = source.surface.width;
37
- const dStride = dest.surface.width;
38
- for (let dy = 0; dy < dh; dy++) {
39
- const oy = dest.y + dy;
40
- if (oy < 0 || oy >= dest.surface.height)
41
- continue;
42
- for (let dx = 0; dx < dw; dx++) {
43
- const ox = dest.x + dx;
44
- if (ox < 0 || ox >= dStride)
45
- continue;
46
- // Map dest pixel to source coordinates.
47
- const sx = a * dx + c * dy + e;
48
- const sy = b * dx + d * dy + f;
49
- const di = (oy * dStride + ox) * 4;
50
- sampleSurface(dd, di, sd, sw, sh, source.x, source.y, sStride, source.surface.height, sx, sy, sampleMode, edgeMode);
51
- }
52
- }
53
- invalidateImageResource(dest.surface);
54
- }
55
- /**
56
- * Samples the source surface at fractional coordinates `(sx, sy)` in
57
- * source-region-local space, writing the result into `dd[di..di+3]`. Edge
58
- * behaviour is controlled by `edgeMode`; sampling quality by `sampleMode`.
59
- */
60
- function sampleSurface(dd, di, sd, sw, sh, originX, originY, sStride, sHeight, sx, sy, sampleMode, edgeMode) {
61
- if (sampleMode === 'nearest') {
62
- const ix = Math.round(sx);
63
- const iy = Math.round(sy);
64
- const cx = resolveEdge(ix, sw, edgeMode);
65
- const cy = resolveEdge(iy, sh, edgeMode);
66
- if (cx === null || cy === null) {
67
- writeTransparent(dd, di);
68
- return;
69
- }
70
- const si = ((originY + cy) * sStride + (originX + cx)) * 4;
71
- dd[di] = sd[si];
72
- dd[di + 1] = sd[si + 1];
73
- dd[di + 2] = sd[si + 2];
74
- dd[di + 3] = sd[si + 3];
75
- return;
76
- }
77
- if (sampleMode === 'bicubic') {
78
- sampleBicubic(dd, di, sd, sw, sh, originX, originY, sStride, sHeight, sx, sy, edgeMode);
79
- return;
80
- }
81
- // bilinear (default)
82
- sampleBilinear(dd, di, sd, sw, sh, originX, originY, sStride, sHeight, sx, sy, edgeMode);
83
- }
84
- function sampleBilinear(dd, di, sd, sw, sh, originX, originY, sStride, _sHeight, sx, sy, edgeMode) {
85
- const x0 = Math.floor(sx);
86
- const y0 = Math.floor(sy);
87
- const tx = sx - x0;
88
- const ty = sy - y0;
89
- const cx00 = resolveEdge(x0, sw, edgeMode);
90
- const cx10 = resolveEdge(x0 + 1, sw, edgeMode);
91
- const cy00 = resolveEdge(y0, sh, edgeMode);
92
- const cy10 = resolveEdge(y0 + 1, sh, edgeMode);
93
- for (let c = 0; c < 4; c++) {
94
- const v00 = cx00 !== null && cy00 !== null ? sd[((originY + cy00) * sStride + originX + cx00) * 4 + c] : 0;
95
- const v10 = cx10 !== null && cy00 !== null ? sd[((originY + cy00) * sStride + originX + cx10) * 4 + c] : 0;
96
- const v01 = cx00 !== null && cy10 !== null ? sd[((originY + cy10) * sStride + originX + cx00) * 4 + c] : 0;
97
- const v11 = cx10 !== null && cy10 !== null ? sd[((originY + cy10) * sStride + originX + cx10) * 4 + c] : 0;
98
- const top = v00 * (1 - tx) + v10 * tx;
99
- const bottom = v01 * (1 - tx) + v11 * tx;
100
- dd[di + c] = Math.round(top * (1 - ty) + bottom * ty);
101
- }
102
- }
103
- function sampleBicubic(dd, di, sd, sw, sh, originX, originY, sStride, _sHeight, sx, sy, edgeMode) {
104
- const x1 = Math.floor(sx);
105
- const y1 = Math.floor(sy);
106
- const tx = sx - x1;
107
- const ty = sy - y1;
108
- for (let c = 0; c < 4; c++) {
109
- let sum = 0;
110
- for (let m = -1; m <= 2; m++) {
111
- const wy = catmullRomWeight(ty - m);
112
- const ry = resolveEdge(y1 + m, sh, edgeMode);
113
- for (let n = -1; n <= 2; n++) {
114
- const wx = catmullRomWeight(tx - n);
115
- const rx = resolveEdge(x1 + n, sw, edgeMode);
116
- const v = rx !== null && ry !== null ? sd[((originY + ry) * sStride + originX + rx) * 4 + c] : 0;
117
- sum += v * wy * wx;
118
- }
119
- }
120
- dd[di + c] = Math.max(0, Math.min(255, Math.round(sum)));
121
- }
122
- }
123
- /**
124
- * Maps a local coordinate `v` in `[0, size)` using the edge mode.
125
- * Returns `null` for `'transparent'` when out of bounds.
126
- */
127
- function resolveEdge(v, size, mode) {
128
- if (v >= 0 && v < size)
129
- return v;
130
- switch (mode) {
131
- case 'clamp':
132
- return Math.max(0, Math.min(size - 1, v));
133
- case 'wrap':
134
- return ((v % size) + size) % size;
135
- case 'mirror': {
136
- const period = 2 * size;
137
- const wrapped = ((v % period) + period) % period;
138
- return wrapped < size ? wrapped : period - 1 - wrapped;
139
- }
140
- default:
141
- // 'transparent'
142
- return null;
143
- }
144
- }
145
- function catmullRomWeight(t) {
146
- const a = Math.abs(t);
147
- if (a >= 2)
148
- return 0;
149
- if (a >= 1)
150
- return -0.5 * a * a * a + 2.5 * a * a - 4 * a + 2;
151
- return 1.5 * a * a * a - 2.5 * a * a + 1;
152
- }
153
- function writeTransparent(dd, di) {
154
- dd[di] = 0;
155
- dd[di + 1] = 0;
156
- dd[di + 2] = 0;
157
- dd[di + 3] = 0;
158
- }
159
- //# sourceMappingURL=surfaceAffine.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"surfaceAffine.js","sourceRoot":"","sources":["../src/surfaceAffine.ts"],"names":[],"mappings":"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"}
@@ -1,27 +0,0 @@
1
- import type { SurfaceRegion } from '@flighthq/types/contract';
2
- /**
3
- * Copies only the alpha channel from the `source` region into the `dest`
4
- * region. RGB channels of `dest` are left unchanged. The copied size is the
5
- * overlap of the two regions.
6
- *
7
- * Safe to pass the same surface and region in `dest` and `source` (no-op on
8
- * alpha since each value is read and immediately written to the same location).
9
- */
10
- export declare function copySurfaceAlpha(dest: Readonly<SurfaceRegion>, source: Readonly<SurfaceRegion>): void;
11
- /**
12
- * Scales every alpha value in the `out` region by `factor` (0–1). RGB channels
13
- * are unchanged. A `factor` of 0 makes the region fully transparent; a `factor`
14
- * of 1 leaves it unchanged; values in between fade it proportionally.
15
- *
16
- * `factor` is clamped to [0, 1].
17
- */
18
- export declare function multiplySurfaceAlpha(out: Readonly<SurfaceRegion>, factor: number): void;
19
- /**
20
- * Writes a constant `alpha` value (0–255) to every pixel in the `out` region.
21
- * RGB channels are unchanged. Useful for making a region fully opaque or
22
- * transparent in a single call.
23
- *
24
- * `alpha` is clamped to [0, 255].
25
- */
26
- export declare function setSurfaceAlpha(out: Readonly<SurfaceRegion>, alpha: number): void;
27
- //# sourceMappingURL=surfaceAlpha.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"surfaceAlpha.d.ts","sourceRoot":"","sources":["../src/surfaceAlpha.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,GAAG,IAAI,CAqBrG;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAevF;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAcjF"}
@@ -1,83 +0,0 @@
1
- import { invalidateImageResource } from '@flighthq/image/contract';
2
- /**
3
- * Copies only the alpha channel from the `source` region into the `dest`
4
- * region. RGB channels of `dest` are left unchanged. The copied size is the
5
- * overlap of the two regions.
6
- *
7
- * Safe to pass the same surface and region in `dest` and `source` (no-op on
8
- * alpha since each value is read and immediately written to the same location).
9
- */
10
- export function copySurfaceAlpha(dest, source) {
11
- const w = Math.min(dest.width, source.width);
12
- const h = Math.min(dest.height, source.height);
13
- const sd = source.surface.data;
14
- const dd = dest.surface.data;
15
- for (let py = 0; py < h; py++) {
16
- const sy = source.y + py;
17
- const dy = dest.y + py;
18
- if (sy < 0 || sy >= source.surface.height || dy < 0 || dy >= dest.surface.height)
19
- continue;
20
- for (let px = 0; px < w; px++) {
21
- const sx = source.x + px;
22
- const dx = dest.x + px;
23
- if (sx < 0 || sx >= source.surface.width || dx < 0 || dx >= dest.surface.width)
24
- continue;
25
- const si = (sy * source.surface.width + sx) * 4;
26
- const di = (dy * dest.surface.width + dx) * 4;
27
- // Read alpha before writing — safe for the aliased case.
28
- const alpha = sd[si + 3];
29
- dd[di + 3] = alpha;
30
- }
31
- }
32
- invalidateImageResource(dest.surface);
33
- }
34
- /**
35
- * Scales every alpha value in the `out` region by `factor` (0–1). RGB channels
36
- * are unchanged. A `factor` of 0 makes the region fully transparent; a `factor`
37
- * of 1 leaves it unchanged; values in between fade it proportionally.
38
- *
39
- * `factor` is clamped to [0, 1].
40
- */
41
- export function multiplySurfaceAlpha(out, factor) {
42
- const f = Math.max(0, Math.min(1, factor));
43
- const data = out.surface.data;
44
- const surfaceWidth = out.surface.width;
45
- for (let py = 0; py < out.height; py++) {
46
- const y = out.y + py;
47
- if (y < 0 || y >= out.surface.height)
48
- continue;
49
- for (let px = 0; px < out.width; px++) {
50
- const x = out.x + px;
51
- if (x < 0 || x >= surfaceWidth)
52
- continue;
53
- const i = (y * surfaceWidth + x) * 4 + 3;
54
- data[i] = Math.round(data[i] * f);
55
- }
56
- }
57
- invalidateImageResource(out.surface);
58
- }
59
- /**
60
- * Writes a constant `alpha` value (0–255) to every pixel in the `out` region.
61
- * RGB channels are unchanged. Useful for making a region fully opaque or
62
- * transparent in a single call.
63
- *
64
- * `alpha` is clamped to [0, 255].
65
- */
66
- export function setSurfaceAlpha(out, alpha) {
67
- const a = Math.max(0, Math.min(255, Math.round(alpha)));
68
- const data = out.surface.data;
69
- const surfaceWidth = out.surface.width;
70
- for (let py = 0; py < out.height; py++) {
71
- const y = out.y + py;
72
- if (y < 0 || y >= out.surface.height)
73
- continue;
74
- for (let px = 0; px < out.width; px++) {
75
- const x = out.x + px;
76
- if (x < 0 || x >= surfaceWidth)
77
- continue;
78
- data[(y * surfaceWidth + x) * 4 + 3] = a;
79
- }
80
- }
81
- invalidateImageResource(out.surface);
82
- }
83
- //# sourceMappingURL=surfaceAlpha.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"surfaceAlpha.js","sourceRoot":"","sources":["../src/surfaceAlpha.ts"],"names":[],"mappings":"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"}