@pibbl/core 0.0.2 → 0.0.3-alpha.85.1

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 (233) hide show
  1. package/THIRD_PARTY_NOTICES.txt +81 -0
  2. package/dist/features/textures/index.d.ts +12 -2
  3. package/dist/features/textures/index.js +33 -1
  4. package/dist/features/textures/index.js.map +2 -2
  5. package/dist/features/textures/lib/chemical-field.d.ts +56 -0
  6. package/dist/features/textures/lib/chemical-field.js +154 -0
  7. package/dist/features/textures/lib/chemical-field.js.map +7 -0
  8. package/dist/features/textures/lib/chemical-recipes.d.ts +119 -0
  9. package/dist/features/textures/lib/chemical-recipes.js +275 -0
  10. package/dist/features/textures/lib/chemical-recipes.js.map +7 -0
  11. package/dist/features/textures/lib/definitions.d.ts +3 -18
  12. package/dist/features/textures/lib/definitions.js +15 -20
  13. package/dist/features/textures/lib/definitions.js.map +2 -2
  14. package/dist/features/textures/lib/geometric-patterns.d.ts +149 -0
  15. package/dist/features/textures/lib/geometric-patterns.js +305 -0
  16. package/dist/features/textures/lib/geometric-patterns.js.map +7 -0
  17. package/dist/features/textures/lib/gray-scott.d.ts +55 -0
  18. package/dist/features/textures/lib/gray-scott.js +39 -0
  19. package/dist/features/textures/lib/gray-scott.js.map +7 -0
  20. package/dist/features/textures/lib/patterns.d.ts +123 -0
  21. package/dist/features/textures/lib/patterns.js +344 -0
  22. package/dist/features/textures/lib/patterns.js.map +7 -0
  23. package/dist/features/textures/lib/reaction-diffusion.d.ts +3 -2
  24. package/dist/features/textures/lib/reaction-diffusion.js +9 -20
  25. package/dist/features/textures/lib/reaction-diffusion.js.map +2 -2
  26. package/dist/features/textures/lib/simulation.d.ts +10 -4
  27. package/dist/features/textures/lib/simulation.js +23 -13
  28. package/dist/features/textures/lib/simulation.js.map +2 -2
  29. package/dist/features/viz/index.d.ts +55 -6
  30. package/dist/features/viz/index.js +107 -2
  31. package/dist/features/viz/index.js.map +2 -2
  32. package/dist/features/viz/inspection/bar.d.ts +79 -0
  33. package/dist/features/viz/inspection/bar.js +49 -0
  34. package/dist/features/viz/inspection/bar.js.map +7 -0
  35. package/dist/features/viz/inspection/candle.d.ts +156 -0
  36. package/dist/features/viz/inspection/candle.js +120 -0
  37. package/dist/features/viz/inspection/candle.js.map +7 -0
  38. package/dist/features/viz/inspection/capture-types.d.ts +65 -0
  39. package/dist/features/viz/inspection/capture.d.ts +16 -0
  40. package/dist/features/viz/inspection/capture.js +49 -0
  41. package/dist/features/viz/inspection/capture.js.map +7 -0
  42. package/dist/features/viz/inspection/handler.d.ts +36 -0
  43. package/dist/features/viz/inspection/handler.js +91 -0
  44. package/dist/features/viz/inspection/handler.js.map +7 -0
  45. package/dist/features/viz/inspection/ohlc-bar.d.ts +132 -0
  46. package/dist/features/viz/inspection/ohlc-bar.js +118 -0
  47. package/dist/features/viz/inspection/ohlc-bar.js.map +7 -0
  48. package/dist/features/viz/inspection/owned-ref.d.ts +16 -0
  49. package/dist/features/viz/inspection/owned-ref.js +99 -0
  50. package/dist/features/viz/inspection/owned-ref.js.map +7 -0
  51. package/dist/features/viz/inspection/painted-point.d.ts +22 -0
  52. package/dist/features/viz/inspection/painted-point.js +29 -0
  53. package/dist/features/viz/inspection/painted-point.js.map +7 -0
  54. package/dist/features/viz/inspection/queries.d.ts +100 -0
  55. package/dist/features/viz/inspection/queries.js +192 -0
  56. package/dist/features/viz/inspection/queries.js.map +7 -0
  57. package/dist/features/viz/inspection/query-types.d.ts +177 -0
  58. package/dist/features/viz/inspection/volume.d.ts +104 -0
  59. package/dist/features/viz/inspection/volume.js +95 -0
  60. package/dist/features/viz/inspection/volume.js.map +7 -0
  61. package/dist/features/viz/inspection.d.ts +19 -0
  62. package/dist/features/viz/inspection.js +54 -0
  63. package/dist/features/viz/inspection.js.map +7 -0
  64. package/dist/features/viz/inspection.mjs +1 -0
  65. package/dist/features/viz/lib/area-series.d.ts +62 -0
  66. package/dist/features/viz/lib/area-series.js +120 -0
  67. package/dist/features/viz/lib/area-series.js.map +7 -0
  68. package/dist/features/viz/lib/axis.js +1 -1
  69. package/dist/features/viz/lib/axis.js.map +2 -2
  70. package/dist/features/viz/lib/bar-series.d.ts +3 -1
  71. package/dist/features/viz/lib/bar-series.js +16 -1
  72. package/dist/features/viz/lib/bar-series.js.map +2 -2
  73. package/dist/features/viz/lib/baseline-series.d.ts +55 -0
  74. package/dist/features/viz/lib/baseline-series.js +136 -0
  75. package/dist/features/viz/lib/baseline-series.js.map +7 -0
  76. package/dist/features/viz/lib/candlestick-series.d.ts +62 -0
  77. package/dist/features/viz/lib/candlestick-series.js +150 -0
  78. package/dist/features/viz/lib/candlestick-series.js.map +7 -0
  79. package/dist/features/viz/lib/censored-point-series.d.ts +71 -0
  80. package/dist/features/viz/lib/censored-point-series.js +129 -0
  81. package/dist/features/viz/lib/censored-point-series.js.map +7 -0
  82. package/dist/features/viz/lib/color-context.d.ts +4 -0
  83. package/dist/features/viz/lib/color-context.js +41 -0
  84. package/dist/features/viz/lib/color-context.js.map +7 -0
  85. package/dist/features/viz/lib/color-math.d.ts +4 -0
  86. package/dist/features/viz/lib/color-math.js +31 -0
  87. package/dist/features/viz/lib/color-math.js.map +7 -0
  88. package/dist/features/viz/lib/color-types.d.ts +53 -0
  89. package/dist/features/viz/lib/curve-definition.d.ts +49 -0
  90. package/dist/features/viz/lib/curve-definition.js +148 -0
  91. package/dist/features/viz/lib/curve-definition.js.map +7 -0
  92. package/dist/features/viz/lib/diverging-color-scale.d.ts +11 -0
  93. package/dist/features/viz/lib/diverging-color-scale.js +51 -0
  94. package/dist/features/viz/lib/diverging-color-scale.js.map +7 -0
  95. package/dist/features/viz/lib/domain-navigation.d.ts +40 -0
  96. package/dist/features/viz/lib/domain-navigation.js +77 -0
  97. package/dist/features/viz/lib/domain-navigation.js.map +7 -0
  98. package/dist/features/viz/lib/editable-chart-elements.d.ts +178 -0
  99. package/dist/features/viz/lib/editable-chart-elements.js +733 -0
  100. package/dist/features/viz/lib/editable-chart-elements.js.map +7 -0
  101. package/dist/features/viz/lib/financial-aggregation.d.ts +127 -0
  102. package/dist/features/viz/lib/financial-aggregation.js +116 -0
  103. package/dist/features/viz/lib/financial-aggregation.js.map +7 -0
  104. package/dist/features/viz/lib/financial-autoscale.d.ts +64 -0
  105. package/dist/features/viz/lib/financial-autoscale.js +61 -0
  106. package/dist/features/viz/lib/financial-autoscale.js.map +7 -0
  107. package/dist/features/viz/lib/financial-comparison.d.ts +62 -0
  108. package/dist/features/viz/lib/financial-comparison.js +98 -0
  109. package/dist/features/viz/lib/financial-comparison.js.map +7 -0
  110. package/dist/features/viz/lib/financial-geometry.d.ts +77 -0
  111. package/dist/features/viz/lib/financial-geometry.js +67 -0
  112. package/dist/features/viz/lib/financial-geometry.js.map +7 -0
  113. package/dist/features/viz/lib/financial-indicators.d.ts +114 -0
  114. package/dist/features/viz/lib/financial-indicators.js +135 -0
  115. package/dist/features/viz/lib/financial-indicators.js.map +7 -0
  116. package/dist/features/viz/lib/financial-oscillators.d.ts +171 -0
  117. package/dist/features/viz/lib/financial-oscillators.js +265 -0
  118. package/dist/features/viz/lib/financial-oscillators.js.map +7 -0
  119. package/dist/features/viz/lib/hover-data.d.ts +1 -1
  120. package/dist/features/viz/lib/hover-data.js +5 -2
  121. package/dist/features/viz/lib/hover-data.js.map +2 -2
  122. package/dist/features/viz/lib/interval-band-series.d.ts +49 -0
  123. package/dist/features/viz/lib/interval-band-series.js +136 -0
  124. package/dist/features/viz/lib/interval-band-series.js.map +7 -0
  125. package/dist/features/viz/lib/interval-diamond-series.d.ts +43 -0
  126. package/dist/features/viz/lib/interval-diamond-series.js +124 -0
  127. package/dist/features/viz/lib/interval-diamond-series.js.map +7 -0
  128. package/dist/features/viz/lib/interval-series.d.ts +79 -0
  129. package/dist/features/viz/lib/interval-series.js +158 -0
  130. package/dist/features/viz/lib/interval-series.js.map +7 -0
  131. package/dist/features/viz/lib/line-series.d.ts +1 -1
  132. package/dist/features/viz/lib/line-series.js +47 -28
  133. package/dist/features/viz/lib/line-series.js.map +2 -2
  134. package/dist/features/viz/lib/linear-scale.js +1 -1
  135. package/dist/features/viz/lib/linear-scale.js.map +2 -2
  136. package/dist/features/viz/lib/monotone-curve.d.ts +11 -0
  137. package/dist/features/viz/lib/monotone-curve.js +63 -0
  138. package/dist/features/viz/lib/monotone-curve.js.map +7 -0
  139. package/dist/features/viz/lib/numeric-range-interpolation.d.ts +15 -0
  140. package/dist/features/viz/lib/numeric-range-interpolation.js +36 -0
  141. package/dist/features/viz/lib/numeric-range-interpolation.js.map +7 -0
  142. package/dist/features/viz/lib/ohlc-bar-series.d.ts +55 -0
  143. package/dist/features/viz/lib/ohlc-bar-series.js +168 -0
  144. package/dist/features/viz/lib/ohlc-bar-series.js.map +7 -0
  145. package/dist/features/viz/lib/paired-series.d.ts +44 -0
  146. package/dist/features/viz/lib/paired-series.js +93 -0
  147. package/dist/features/viz/lib/paired-series.js.map +7 -0
  148. package/dist/features/viz/lib/plot-series.js +11 -6
  149. package/dist/features/viz/lib/plot-series.js.map +2 -2
  150. package/dist/features/viz/lib/plot-types.d.ts +4 -3
  151. package/dist/features/viz/lib/point-series.d.ts +1 -1
  152. package/dist/features/viz/lib/point-series.js +36 -9
  153. package/dist/features/viz/lib/point-series.js.map +2 -2
  154. package/dist/features/viz/lib/point-types.d.ts +5 -2
  155. package/dist/features/viz/lib/scale-context.d.ts +1 -1
  156. package/dist/features/viz/lib/scale-ticks.js +21 -6
  157. package/dist/features/viz/lib/scale-ticks.js.map +2 -2
  158. package/dist/features/viz/lib/sequential-color-scale.d.ts +11 -0
  159. package/dist/features/viz/lib/sequential-color-scale.js +49 -0
  160. package/dist/features/viz/lib/sequential-color-scale.js.map +7 -0
  161. package/dist/features/viz/lib/series-position.d.ts +12 -0
  162. package/dist/features/viz/lib/series-position.js +44 -0
  163. package/dist/features/viz/lib/series-position.js.map +7 -0
  164. package/dist/features/viz/lib/step-curves.d.ts +19 -0
  165. package/dist/features/viz/lib/step-curves.js +53 -0
  166. package/dist/features/viz/lib/step-curves.js.map +7 -0
  167. package/dist/features/viz/lib/threshold-color-scale.d.ts +43 -0
  168. package/dist/features/viz/lib/threshold-color-scale.js +59 -0
  169. package/dist/features/viz/lib/threshold-color-scale.js.map +7 -0
  170. package/dist/features/viz/lib/trading-time-mapping.d.ts +32 -0
  171. package/dist/features/viz/lib/trading-time-mapping.js +89 -0
  172. package/dist/features/viz/lib/trading-time-mapping.js.map +7 -0
  173. package/dist/features/viz/lib/trading-time-scale.d.ts +83 -0
  174. package/dist/features/viz/lib/trading-time-scale.js +96 -0
  175. package/dist/features/viz/lib/trading-time-scale.js.map +7 -0
  176. package/dist/features/viz/lib/trajectory-series.d.ts +71 -0
  177. package/dist/features/viz/lib/trajectory-series.js +111 -0
  178. package/dist/features/viz/lib/trajectory-series.js.map +7 -0
  179. package/dist/features/viz/lib/types.d.ts +20 -4
  180. package/dist/features/viz/lib/use-continuous-scale.js +6 -1
  181. package/dist/features/viz/lib/use-continuous-scale.js.map +2 -2
  182. package/dist/features/viz/lib/volume-series.d.ts +59 -0
  183. package/dist/features/viz/lib/volume-series.js +117 -0
  184. package/dist/features/viz/lib/volume-series.js.map +7 -0
  185. package/dist/features/viz/lib/weighted-point-series.d.ts +71 -0
  186. package/dist/features/viz/lib/weighted-point-series.js +169 -0
  187. package/dist/features/viz/lib/weighted-point-series.js.map +7 -0
  188. package/dist/filters/emboss-gpu.d.ts +4 -0
  189. package/dist/filters/emboss-gpu.js +39 -0
  190. package/dist/filters/emboss-gpu.js.map +7 -0
  191. package/dist/filters/emboss.d.ts +32 -0
  192. package/dist/filters/emboss.js +106 -0
  193. package/dist/filters/emboss.js.map +7 -0
  194. package/dist/filters/reflection-gpu.d.ts +3 -1
  195. package/dist/filters/reflection-gpu.js +5 -2
  196. package/dist/filters/reflection-gpu.js.map +2 -2
  197. package/dist/filters/render-emboss-boundary.d.ts +13 -0
  198. package/dist/filters/render-emboss-boundary.js +131 -0
  199. package/dist/filters/render-emboss-boundary.js.map +7 -0
  200. package/dist/filters.d.ts +2 -0
  201. package/dist/filters.js +2 -0
  202. package/dist/filters.js.map +2 -2
  203. package/dist/index.d.ts +2 -0
  204. package/dist/index.js +3 -0
  205. package/dist/index.js.map +2 -2
  206. package/dist/internal.d.ts +2 -0
  207. package/dist/internal.js +4 -0
  208. package/dist/internal.js.map +2 -2
  209. package/dist/lib/events/event-facade.d.ts +13 -0
  210. package/dist/lib/events/event-facade.js +23 -0
  211. package/dist/lib/events/event-facade.js.map +2 -2
  212. package/dist/lib/events/propagation.js +19 -14
  213. package/dist/lib/events/propagation.js.map +2 -2
  214. package/dist/lib/execute-render.js +13 -0
  215. package/dist/lib/execute-render.js.map +2 -2
  216. package/dist/lib/recording/recording.d.ts +43 -0
  217. package/dist/lib/recording/recording.js +555 -0
  218. package/dist/lib/recording/recording.js.map +7 -0
  219. package/dist/lib/recording/types.d.ts +118 -0
  220. package/dist/lib/recording/wasm-bytes.d.ts +1 -0
  221. package/dist/lib/recording/wasm-bytes.js +5 -0
  222. package/dist/lib/recording/wasm-bytes.js.map +7 -0
  223. package/dist/lib/recording/worker-source.d.ts +1 -0
  224. package/dist/lib/recording/worker-source.js +5 -0
  225. package/dist/lib/recording/worker-source.js.map +7 -0
  226. package/dist/lib/render-transaction.d.ts +5 -2
  227. package/dist/lib/render-transaction.js +23 -1
  228. package/dist/lib/render-transaction.js.map +2 -2
  229. package/dist/lib/series-inspection-frame.d.ts +18 -0
  230. package/dist/lib/series-inspection-frame.js +70 -0
  231. package/dist/lib/series-inspection-frame.js.map +7 -0
  232. package/dist/lib/types.d.ts +6 -0
  233. package/package.json +10 -2
@@ -0,0 +1,169 @@
1
+ import { jsx } from "@pibbl/core/jsx-runtime";
2
+ import { resolveTexturePaint } from "@pibbl/core/internal";
3
+ import { Path, resolveSignalValue, useCanvasContext } from "@pibbl/core";
4
+ import { validateTexturePaint, withHooksForbidden } from "@pibbl/core/internal";
5
+ import { pointAccessor, pointData } from "./point-data.js";
6
+ import { appendPointTarget, pointPath } from "./point-geometry.js";
7
+ import { opacity, width } from "./paint.js";
8
+ import {
9
+ mapSeriesPosition,
10
+ seriesAccessor,
11
+ useSeriesPosition
12
+ } from "./series-position.js";
13
+ const fields = ["fill", "stroke", "strokeWidth", "opacity", "cursor"];
14
+ function paint(value, name) {
15
+ if (value === void 0 || typeof value === "string" || value instanceof CanvasGradient || value instanceof CanvasPattern)
16
+ return value;
17
+ try {
18
+ validateTexturePaint(value);
19
+ return value;
20
+ } catch {
21
+ }
22
+ throw new TypeError(`WeightedPointSeries: invalid ${name}.`);
23
+ }
24
+ function styleObject(input) {
25
+ if (input === null || typeof input !== "object" || Array.isArray(input))
26
+ throw new TypeError("WeightedPointSeries: style must be an object.");
27
+ const result = {};
28
+ for (const key of Object.keys(input)) {
29
+ if (!fields.includes(key))
30
+ throw new TypeError(
31
+ `WeightedPointSeries: unsupported style field ${key}.`
32
+ );
33
+ result[key] = resolveSignalValue(input[key]);
34
+ }
35
+ return result;
36
+ }
37
+ function normalized(style) {
38
+ if (style.cursor !== void 0 && typeof style.cursor !== "string")
39
+ throw new TypeError("WeightedPointSeries: cursor must be a string.");
40
+ return {
41
+ fill: paint(style.fill ?? "#087f8c", "fill"),
42
+ stroke: paint(style.stroke, "stroke"),
43
+ strokeWidth: width(
44
+ style.strokeWidth ?? 1,
45
+ "WeightedPointSeries strokeWidth"
46
+ ),
47
+ opacity: opacity(style.opacity ?? 1, "WeightedPointSeries opacity"),
48
+ cursor: style.cursor
49
+ };
50
+ }
51
+ function range(value) {
52
+ const actual = value ?? [0, 6];
53
+ if (!Array.isArray(actual) || actual.length !== 2 || actual[0] !== 0 || !Number.isFinite(actual[1]) || actual[1] < 0)
54
+ throw new RangeError(
55
+ "WeightedPointSeries: radiusRange must be [0, a finite nonnegative maximum]."
56
+ );
57
+ return actual;
58
+ }
59
+ function domain(value) {
60
+ if (!Array.isArray(value) || value.length !== 2 || value[0] !== 0 || !Number.isFinite(value[1]) || value[1] <= 0)
61
+ throw new RangeError(
62
+ "WeightedPointSeries: weightDomain must be [0, a finite positive maximum]."
63
+ );
64
+ return value;
65
+ }
66
+ function WeightedPointSeries({
67
+ data: input,
68
+ x: xInput,
69
+ y: yInput,
70
+ weight: weightInput,
71
+ xScale: xId,
72
+ yScale: yId,
73
+ weightDomain,
74
+ radiusRange,
75
+ defined,
76
+ style: styleInput,
77
+ ...events
78
+ }) {
79
+ const xs = useSeriesPosition(xId);
80
+ const ys = useSeriesPosition(yId);
81
+ const data = pointData(resolveSignalValue(input), "WeightedPointSeries");
82
+ const x = seriesAccessor(xInput);
83
+ const y = seriesAccessor(yInput);
84
+ const weight = pointAccessor(weightInput);
85
+ const [, maximumWeight] = domain(weightDomain);
86
+ const [, maximumRadius] = range(radiusRange);
87
+ const style = normalized(styleObject(resolveSignalValue(styleInput) ?? {}));
88
+ const ctx = useCanvasContext();
89
+ const target = new Path2D();
90
+ const marks = [];
91
+ for (let i = 0; i < data.length; i++) {
92
+ const datum = data[i];
93
+ const values = withHooksForbidden(
94
+ "WeightedPointSeries: accessors cannot call hooks.",
95
+ () => {
96
+ if (defined && !defined(datum, i, data)) return void 0;
97
+ return {
98
+ x: x(datum, i, data),
99
+ y: y(datum, i, data),
100
+ weight: weight(datum, i, data)
101
+ };
102
+ }
103
+ );
104
+ if (!values) continue;
105
+ const mappedX = mapSeriesPosition(xs, values.x);
106
+ const mappedY = mapSeriesPosition(ys, values.y);
107
+ if (mappedX === void 0 || mappedY === void 0) continue;
108
+ const supplied = values.weight;
109
+ if (supplied == null) continue;
110
+ if (typeof supplied !== "number" || !Number.isFinite(supplied))
111
+ throw new TypeError(
112
+ "WeightedPointSeries: weight must be a finite number."
113
+ );
114
+ if (supplied < 0)
115
+ throw new RangeError("WeightedPointSeries: weight must be nonnegative.");
116
+ if (supplied > maximumWeight)
117
+ throw new RangeError("WeightedPointSeries: weight exceeds weightDomain.");
118
+ if (supplied === 0 || maximumRadius === 0) continue;
119
+ const radius = maximumRadius * Math.sqrt(supplied / maximumWeight);
120
+ marks.push({ x: mappedX, y: mappedY, radius });
121
+ }
122
+ for (const { x: x2, y: y2, radius } of marks) {
123
+ appendPointTarget(
124
+ target,
125
+ x2,
126
+ y2,
127
+ radius,
128
+ !!style.fill,
129
+ style.stroke ? style.strokeWidth : 0
130
+ );
131
+ const path = pointPath(x2, y2, radius);
132
+ ctx.save();
133
+ try {
134
+ ctx.globalAlpha *= style.opacity;
135
+ if (style.fill) {
136
+ ctx.fillStyle = resolveTexturePaint(style.fill, ctx, {
137
+ x: x2 - radius,
138
+ y: y2 - radius,
139
+ width: radius * 2,
140
+ height: radius * 2
141
+ });
142
+ ctx.fill(path);
143
+ }
144
+ if (style.stroke && style.strokeWidth > 0) {
145
+ ctx.strokeStyle = resolveTexturePaint(style.stroke, ctx, {
146
+ x: x2 - radius,
147
+ y: y2 - radius,
148
+ width: radius * 2,
149
+ height: radius * 2
150
+ });
151
+ ctx.lineWidth = style.strokeWidth;
152
+ ctx.stroke(path);
153
+ }
154
+ } finally {
155
+ ctx.restore();
156
+ }
157
+ }
158
+ return /* @__PURE__ */ jsx(
159
+ Path,
160
+ {
161
+ ...events,
162
+ style: { d: target, fill: "transparent", cursor: style.cursor }
163
+ }
164
+ );
165
+ }
166
+ export {
167
+ WeightedPointSeries
168
+ };
169
+ //# sourceMappingURL=weighted-point-series.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/features/viz/lib/weighted-point-series.tsx"],
4
+ "sourcesContent": ["import { resolveTexturePaint } from \"@pibbl/core/internal\";\nimport { Path, resolveSignalValue, useCanvasContext } from \"@pibbl/core\";\nimport type {\n FillStyle,\n PibblEventHandlers,\n PibblEventParticipationOptions,\n SignalValue,\n StrokeStyle,\n} from \"@pibbl/core\";\nimport type { SignalStyle } from \"@pibbl/core/internal\";\nimport { validateTexturePaint, withHooksForbidden } from \"@pibbl/core/internal\";\nimport type { LineAccessor, ScaleId, SeriesAccessor } from \"./types.js\";\nimport { pointAccessor, pointData } from \"./point-data.js\";\nimport { appendPointTarget, pointPath } from \"./point-geometry.js\";\nimport { opacity, width } from \"./paint.js\";\nimport {\n mapSeriesPosition,\n seriesAccessor,\n useSeriesPosition,\n} from \"./series-position.js\";\n\nconst fields = [\"fill\", \"stroke\", \"strokeWidth\", \"opacity\", \"cursor\"];\n\n/**\n * A data property or callback extracting a nonnegative research weight.\n *\n * @see {@link WeightedPointSeriesProps}\n */\nexport type WeightAccessor<D> = LineAccessor<D>;\n\n/** Shared presentation for {@link WeightedPointSeries}. */\nexport interface WeightedPointSeriesStyle {\n /** Paint used for point interiors. Defaults to `#087f8c`. */\n readonly fill?: FillStyle;\n /** Paint used for point outlines. Defaults to no outline. */\n readonly stroke?: StrokeStyle;\n /** Outline width in local coordinate units. Defaults to 1. */\n readonly strokeWidth?: number;\n /** Opacity in the inclusive range [0, 1]. Defaults to 1. */\n readonly opacity?: number;\n /** Pointer cursor while the series owns a target. */\n readonly cursor?: string;\n}\n\n/**\n * Authored inputs for {@link WeightedPointSeries}.\n *\n * Weights are supplied data, not calculated precision, sample size, or evidence.\n * The zero baseline and squared-radius interpolation make displayed area linear in\n * the supplied weight.\n */\nexport interface WeightedPointSeriesProps<D>\n extends PibblEventHandlers, PibblEventParticipationOptions {\n /** Readonly data or a signal containing it. */\n readonly data: SignalValue<readonly D[]>;\n /** Horizontal coordinate property or synchronous accessor. */\n readonly x: SeriesAccessor<D>;\n /** Vertical coordinate property or synchronous accessor. */\n readonly y: SeriesAccessor<D>;\n /** Nonnegative supplied weight property or synchronous accessor. */\n readonly weight: WeightAccessor<D>;\n /** Scale used to map x coordinates. */\n readonly xScale: ScaleId;\n /** Scale used to map y coordinates. */\n readonly yScale: ScaleId;\n /** Supplied inclusive weight extent. The lower bound must be zero. */\n readonly weightDomain: readonly [0, number];\n /** Radius extent `[0, maximumRadius]`; defaults to `[0, 6]`. */\n readonly radiusRange?: readonly [0, number];\n /**\n * Excludes a datum before coordinate and weight accessors run.\n * @param datum - Candidate source datum.\n * @param index - Zero-based source index.\n * @param data - Complete source data array.\n * @returns Whether this datum contributes a mark.\n */\n readonly defined?: (datum: D, index: number, data: readonly D[]) => boolean;\n /** Shared presentation. Whole-object and shallow field signals are supported. */\n readonly style?: SignalValue<SignalStyle<WeightedPointSeriesStyle>>;\n}\n\nfunction paint(\n value: unknown,\n name: string,\n): FillStyle | StrokeStyle | undefined {\n if (\n value === undefined ||\n typeof value === \"string\" ||\n value instanceof CanvasGradient ||\n value instanceof CanvasPattern\n )\n return value;\n try {\n validateTexturePaint(value as never);\n return value as FillStyle | StrokeStyle;\n } catch {\n // Normalize all unsupported public paint values to the series error.\n }\n throw new TypeError(`WeightedPointSeries: invalid ${name}.`);\n}\n\nfunction styleObject(input: unknown): WeightedPointSeriesStyle {\n if (input === null || typeof input !== \"object\" || Array.isArray(input))\n throw new TypeError(\"WeightedPointSeries: style must be an object.\");\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(input)) {\n if (!fields.includes(key))\n throw new TypeError(\n `WeightedPointSeries: unsupported style field ${key}.`,\n );\n result[key] = resolveSignalValue((input as Record<string, unknown>)[key]);\n }\n return result as WeightedPointSeriesStyle;\n}\n\nfunction normalized(style: WeightedPointSeriesStyle) {\n if (style.cursor !== undefined && typeof style.cursor !== \"string\")\n throw new TypeError(\"WeightedPointSeries: cursor must be a string.\");\n return {\n fill: paint(style.fill ?? \"#087f8c\", \"fill\"),\n stroke: paint(style.stroke, \"stroke\"),\n strokeWidth: width(\n style.strokeWidth ?? 1,\n \"WeightedPointSeries strokeWidth\",\n ),\n opacity: opacity(style.opacity ?? 1, \"WeightedPointSeries opacity\"),\n cursor: style.cursor,\n };\n}\n\nfunction range(\n value: readonly [number, number] | undefined,\n): readonly [number, number] {\n const actual: readonly [number, number] = value ?? [0, 6];\n if (\n !Array.isArray(actual) ||\n actual.length !== 2 ||\n actual[0] !== 0 ||\n !Number.isFinite(actual[1]) ||\n actual[1] < 0\n )\n throw new RangeError(\n \"WeightedPointSeries: radiusRange must be [0, a finite nonnegative maximum].\",\n );\n return actual;\n}\n\nfunction domain(value: readonly [0, number]): readonly [number, number] {\n if (\n !Array.isArray(value) ||\n value.length !== 2 ||\n value[0] !== 0 ||\n !Number.isFinite(value[1]) ||\n value[1] <= 0\n )\n throw new RangeError(\n \"WeightedPointSeries: weightDomain must be [0, a finite positive maximum].\",\n );\n return value;\n}\n\n/**\n * Draws batched circles whose visible area is proportional to supplied weights.\n *\n * Nullish weights and zero weights omit their marks. Finite positive weights must\n * fall inside `weightDomain`; the component never clamps or infers weights.\n * `data` and shared style signals schedule ordinary Pibbl updates. The component\n * owns no retained resources and returns one ordinary Pibbl pointer target.\n *\n * @param props - Supplied observations, coordinate and weight accessors, scales, and paint.\n * See {@link WeightedPointSeriesProps}.\n * @returns One batched Pibbl Path whose mark area is proportional to each supplied weight.\n * @see {@link WeightedPointSeriesProps}\n */\nexport function WeightedPointSeries<D>({\n data: input,\n x: xInput,\n y: yInput,\n weight: weightInput,\n xScale: xId,\n yScale: yId,\n weightDomain,\n radiusRange,\n defined,\n style: styleInput,\n ...events\n}: WeightedPointSeriesProps<D>) {\n const xs = useSeriesPosition(xId);\n const ys = useSeriesPosition(yId);\n const data = pointData(resolveSignalValue(input), \"WeightedPointSeries\");\n const x = seriesAccessor(xInput);\n const y = seriesAccessor(yInput);\n const weight = pointAccessor(weightInput);\n const [, maximumWeight] = domain(weightDomain);\n const [, maximumRadius] = range(radiusRange);\n const style = normalized(styleObject(resolveSignalValue(styleInput) ?? {}));\n const ctx = useCanvasContext();\n const target = new Path2D();\n const marks: {\n readonly x: number;\n readonly y: number;\n readonly radius: number;\n }[] = [];\n for (let i = 0; i < data.length; i++) {\n const datum = data[i];\n const values = withHooksForbidden(\n \"WeightedPointSeries: accessors cannot call hooks.\",\n () => {\n if (defined && !defined(datum, i, data)) return undefined;\n return {\n x: x(datum, i, data),\n y: y(datum, i, data),\n weight: weight(datum, i, data),\n };\n },\n );\n if (!values) continue;\n const mappedX = mapSeriesPosition(xs, values.x);\n const mappedY = mapSeriesPosition(ys, values.y);\n if (mappedX === undefined || mappedY === undefined) continue;\n const supplied = values.weight;\n if (supplied == null) continue;\n if (typeof supplied !== \"number\" || !Number.isFinite(supplied))\n throw new TypeError(\n \"WeightedPointSeries: weight must be a finite number.\",\n );\n if (supplied < 0)\n throw new RangeError(\"WeightedPointSeries: weight must be nonnegative.\");\n if (supplied > maximumWeight)\n throw new RangeError(\"WeightedPointSeries: weight exceeds weightDomain.\");\n if (supplied === 0 || maximumRadius === 0) continue;\n const radius = maximumRadius * Math.sqrt(supplied / maximumWeight);\n marks.push({ x: mappedX, y: mappedY, radius });\n }\n for (const { x, y, radius } of marks) {\n appendPointTarget(\n target,\n x,\n y,\n radius,\n !!style.fill,\n style.stroke ? style.strokeWidth : 0,\n );\n const path = pointPath(x, y, radius);\n ctx.save();\n try {\n ctx.globalAlpha *= style.opacity;\n if (style.fill) {\n ctx.fillStyle = resolveTexturePaint(style.fill, ctx, {\n x: x - radius,\n y: y - radius,\n width: radius * 2,\n height: radius * 2,\n });\n ctx.fill(path);\n }\n if (style.stroke && style.strokeWidth > 0) {\n ctx.strokeStyle = resolveTexturePaint(style.stroke, ctx, {\n x: x - radius,\n y: y - radius,\n width: radius * 2,\n height: radius * 2,\n });\n ctx.lineWidth = style.strokeWidth;\n ctx.stroke(path);\n }\n } finally {\n ctx.restore();\n }\n }\n return (\n <Path\n {...events}\n style={{ d: target, fill: \"transparent\", cursor: style.cursor }}\n />\n );\n}\n"],
5
+ "mappings": "AA+QI;AA/QJ,SAAS,2BAA2B;AACpC,SAAS,MAAM,oBAAoB,wBAAwB;AAS3D,SAAS,sBAAsB,0BAA0B;AAEzD,SAAS,eAAe,iBAAiB;AACzC,SAAS,mBAAmB,iBAAiB;AAC7C,SAAS,SAAS,aAAa;AAC/B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,MAAM,SAAS,CAAC,QAAQ,UAAU,eAAe,WAAW,QAAQ;AA4DpE,SAAS,MACP,OACA,MACqC;AACrC,MACE,UAAU,UACV,OAAO,UAAU,YACjB,iBAAiB,kBACjB,iBAAiB;AAEjB,WAAO;AACT,MAAI;AACF,yBAAqB,KAAc;AACnC,WAAO;AAAA,EACT,QAAQ;AAAA,EAER;AACA,QAAM,IAAI,UAAU,gCAAgC,IAAI,GAAG;AAC7D;AAEA,SAAS,YAAY,OAA0C;AAC7D,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK;AACpE,UAAM,IAAI,UAAU,+CAA+C;AACrE,QAAM,SAAkC,CAAC;AACzC,aAAW,OAAO,OAAO,KAAK,KAAK,GAAG;AACpC,QAAI,CAAC,OAAO,SAAS,GAAG;AACtB,YAAM,IAAI;AAAA,QACR,gDAAgD,GAAG;AAAA,MACrD;AACF,WAAO,GAAG,IAAI,mBAAoB,MAAkC,GAAG,CAAC;AAAA,EAC1E;AACA,SAAO;AACT;AAEA,SAAS,WAAW,OAAiC;AACnD,MAAI,MAAM,WAAW,UAAa,OAAO,MAAM,WAAW;AACxD,UAAM,IAAI,UAAU,+CAA+C;AACrE,SAAO;AAAA,IACL,MAAM,MAAM,MAAM,QAAQ,WAAW,MAAM;AAAA,IAC3C,QAAQ,MAAM,MAAM,QAAQ,QAAQ;AAAA,IACpC,aAAa;AAAA,MACX,MAAM,eAAe;AAAA,MACrB;AAAA,IACF;AAAA,IACA,SAAS,QAAQ,MAAM,WAAW,GAAG,6BAA6B;AAAA,IAClE,QAAQ,MAAM;AAAA,EAChB;AACF;AAEA,SAAS,MACP,OAC2B;AAC3B,QAAM,SAAoC,SAAS,CAAC,GAAG,CAAC;AACxD,MACE,CAAC,MAAM,QAAQ,MAAM,KACrB,OAAO,WAAW,KAClB,OAAO,CAAC,MAAM,KACd,CAAC,OAAO,SAAS,OAAO,CAAC,CAAC,KAC1B,OAAO,CAAC,IAAI;AAEZ,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AACF,SAAO;AACT;AAEA,SAAS,OAAO,OAAwD;AACtE,MACE,CAAC,MAAM,QAAQ,KAAK,KACpB,MAAM,WAAW,KACjB,MAAM,CAAC,MAAM,KACb,CAAC,OAAO,SAAS,MAAM,CAAC,CAAC,KACzB,MAAM,CAAC,KAAK;AAEZ,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AACF,SAAO;AACT;AAeO,SAAS,oBAAuB;AAAA,EACrC,MAAM;AAAA,EACN,GAAG;AAAA,EACH,GAAG;AAAA,EACH,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,GAAG;AACL,GAAgC;AAC9B,QAAM,KAAK,kBAAkB,GAAG;AAChC,QAAM,KAAK,kBAAkB,GAAG;AAChC,QAAM,OAAO,UAAU,mBAAmB,KAAK,GAAG,qBAAqB;AACvE,QAAM,IAAI,eAAe,MAAM;AAC/B,QAAM,IAAI,eAAe,MAAM;AAC/B,QAAM,SAAS,cAAc,WAAW;AACxC,QAAM,CAAC,EAAE,aAAa,IAAI,OAAO,YAAY;AAC7C,QAAM,CAAC,EAAE,aAAa,IAAI,MAAM,WAAW;AAC3C,QAAM,QAAQ,WAAW,YAAY,mBAAmB,UAAU,KAAK,CAAC,CAAC,CAAC;AAC1E,QAAM,MAAM,iBAAiB;AAC7B,QAAM,SAAS,IAAI,OAAO;AAC1B,QAAM,QAIA,CAAC;AACP,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,QAAQ,KAAK,CAAC;AACpB,UAAM,SAAS;AAAA,MACb;AAAA,MACA,MAAM;AACJ,YAAI,WAAW,CAAC,QAAQ,OAAO,GAAG,IAAI,EAAG,QAAO;AAChD,eAAO;AAAA,UACL,GAAG,EAAE,OAAO,GAAG,IAAI;AAAA,UACnB,GAAG,EAAE,OAAO,GAAG,IAAI;AAAA,UACnB,QAAQ,OAAO,OAAO,GAAG,IAAI;AAAA,QAC/B;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,OAAQ;AACb,UAAM,UAAU,kBAAkB,IAAI,OAAO,CAAC;AAC9C,UAAM,UAAU,kBAAkB,IAAI,OAAO,CAAC;AAC9C,QAAI,YAAY,UAAa,YAAY,OAAW;AACpD,UAAM,WAAW,OAAO;AACxB,QAAI,YAAY,KAAM;AACtB,QAAI,OAAO,aAAa,YAAY,CAAC,OAAO,SAAS,QAAQ;AAC3D,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AACF,QAAI,WAAW;AACb,YAAM,IAAI,WAAW,kDAAkD;AACzE,QAAI,WAAW;AACb,YAAM,IAAI,WAAW,mDAAmD;AAC1E,QAAI,aAAa,KAAK,kBAAkB,EAAG;AAC3C,UAAM,SAAS,gBAAgB,KAAK,KAAK,WAAW,aAAa;AACjE,UAAM,KAAK,EAAE,GAAG,SAAS,GAAG,SAAS,OAAO,CAAC;AAAA,EAC/C;AACA,aAAW,EAAE,GAAAA,IAAG,GAAAC,IAAG,OAAO,KAAK,OAAO;AACpC;AAAA,MACE;AAAA,MACAD;AAAA,MACAC;AAAA,MACA;AAAA,MACA,CAAC,CAAC,MAAM;AAAA,MACR,MAAM,SAAS,MAAM,cAAc;AAAA,IACrC;AACA,UAAM,OAAO,UAAUD,IAAGC,IAAG,MAAM;AACnC,QAAI,KAAK;AACT,QAAI;AACF,UAAI,eAAe,MAAM;AACzB,UAAI,MAAM,MAAM;AACd,YAAI,YAAY,oBAAoB,MAAM,MAAM,KAAK;AAAA,UACnD,GAAGD,KAAI;AAAA,UACP,GAAGC,KAAI;AAAA,UACP,OAAO,SAAS;AAAA,UAChB,QAAQ,SAAS;AAAA,QACnB,CAAC;AACD,YAAI,KAAK,IAAI;AAAA,MACf;AACA,UAAI,MAAM,UAAU,MAAM,cAAc,GAAG;AACzC,YAAI,cAAc,oBAAoB,MAAM,QAAQ,KAAK;AAAA,UACvD,GAAGD,KAAI;AAAA,UACP,GAAGC,KAAI;AAAA,UACP,OAAO,SAAS;AAAA,UAChB,QAAQ,SAAS;AAAA,QACnB,CAAC;AACD,YAAI,YAAY,MAAM;AACtB,YAAI,OAAO,IAAI;AAAA,MACjB;AAAA,IACF,UAAE;AACA,UAAI,QAAQ;AAAA,IACd;AAAA,EACF;AACA,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,OAAO,EAAE,GAAG,QAAQ,MAAM,eAAe,QAAQ,MAAM,OAAO;AAAA;AAAA,EAChE;AAEJ;",
6
+ "names": ["x", "y"]
7
+ }
@@ -0,0 +1,4 @@
1
+ import { ReflectionGpu, type ReflectionGpuCallbacks } from "./reflection-gpu.js";
2
+ export declare class EmbossGpu extends ReflectionGpu {
3
+ constructor(callbacks?: Readonly<ReflectionGpuCallbacks>);
4
+ }
@@ -0,0 +1,39 @@
1
+ import {
2
+ ReflectionGpu
3
+ } from "./reflection-gpu.js";
4
+ const fragment = `#version 300 es
5
+ precision highp float;
6
+ uniform sampler2D scene, map;
7
+ uniform vec2 logicalOrigin, logicalSize, mapOrigin, tileSize, direction;
8
+ uniform float rotation, opacity, depth;
9
+ in vec2 uv;
10
+ out vec4 outputColor;
11
+ vec2 coordinates(vec2 logical) {
12
+ vec2 p=logical-mapOrigin;
13
+ float c=cos(rotation),s=sin(rotation);
14
+ return vec2(c*p.x+s*p.y,-s*p.x+c*p.y)/tileSize;
15
+ }
16
+ float height(vec2 p) {
17
+ vec4 field=texture(map,coordinates(p));
18
+ return dot(field.rgb,vec3(.2126,.7152,.0722))*field.a;
19
+ }
20
+ void main() {
21
+ vec4 base=texture(scene,uv);
22
+ vec2 p=logicalOrigin+uv*logicalSize;
23
+ vec2 gradient=.5*vec2(height(p+vec2(1,0))-height(p-vec2(1,0)),height(p+vec2(0,1))-height(p-vec2(0,1)));
24
+ vec3 normal=normalize(vec3(-depth*gradient,1.));
25
+ vec3 light=normalize(vec3(direction*.8,1.));
26
+ float shade=max(0.,dot(normal,light))/light.z;
27
+ // A flat map is exactly neutral. Multiply premultiplied color, preserve alpha.
28
+ outputColor=vec4(clamp(base.rgb*mix(1.,shade,opacity),vec3(0),vec3(base.a)),base.a);
29
+ }
30
+ `;
31
+ class EmbossGpu extends ReflectionGpu {
32
+ constructor(callbacks = {}) {
33
+ super(callbacks, fragment);
34
+ }
35
+ }
36
+ export {
37
+ EmbossGpu
38
+ };
39
+ //# sourceMappingURL=emboss-gpu.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/filters/emboss-gpu.ts"],
4
+ "sourcesContent": ["import {\n ReflectionGpu,\n type ReflectionGpuCallbacks,\n} from \"./reflection-gpu.js\";\n\n// Reuses the existing GPU surface/cache ownership; this shader consumes scalar\n// height instead of the reflected-light operation's pre-encoded RG slopes.\nconst fragment = `#version 300 es\nprecision highp float;\nuniform sampler2D scene, map;\nuniform vec2 logicalOrigin, logicalSize, mapOrigin, tileSize, direction;\nuniform float rotation, opacity, depth;\nin vec2 uv;\nout vec4 outputColor;\nvec2 coordinates(vec2 logical) {\n vec2 p=logical-mapOrigin;\n float c=cos(rotation),s=sin(rotation);\n return vec2(c*p.x+s*p.y,-s*p.x+c*p.y)/tileSize;\n}\nfloat height(vec2 p) {\n vec4 field=texture(map,coordinates(p));\n return dot(field.rgb,vec3(.2126,.7152,.0722))*field.a;\n}\nvoid main() {\n vec4 base=texture(scene,uv);\n vec2 p=logicalOrigin+uv*logicalSize;\n vec2 gradient=.5*vec2(height(p+vec2(1,0))-height(p-vec2(1,0)),height(p+vec2(0,1))-height(p-vec2(0,1)));\n vec3 normal=normalize(vec3(-depth*gradient,1.));\n vec3 light=normalize(vec3(direction*.8,1.));\n float shade=max(0.,dot(normal,light))/light.z;\n // A flat map is exactly neutral. Multiply premultiplied color, preserve alpha.\n outputColor=vec4(clamp(base.rgb*mix(1.,shade,opacity),vec3(0),vec3(base.a)),base.a);\n}\n`;\nexport class EmbossGpu extends ReflectionGpu {\n constructor(callbacks: Readonly<ReflectionGpuCallbacks> = {}) {\n super(callbacks, fragment);\n }\n}\n"],
5
+ "mappings": "AAAA;AAAA,EACE;AAAA,OAEK;AAIP,MAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2BV,MAAM,kBAAkB,cAAc;AAAA,EAC3C,YAAY,YAA8C,CAAC,GAAG;AAC5D,UAAM,WAAW,QAAQ;AAAA,EAC3B;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,32 @@
1
+ import type { SignalValue } from "../lib/signals/types.js";
2
+ import { type PibblFilter } from "../lib/style/filter-types.js";
3
+ import { type TexturePaint } from "../lib/textures/texture-protocol.js";
4
+ /** Directional lighting of grayscale texture height. See {@link emboss}. */
5
+ export interface PibblEmbossFilterOptions {
6
+ /** Local texture placement region with finite coordinates and positive dimensions. See {@link TexturePaint}. */
7
+ readonly region: Readonly<{
8
+ /** Horizontal origin in local logical coordinates. See {@link PibblEmbossFilterOptions}. */
9
+ x: number;
10
+ /** Vertical origin in local logical coordinates. See {@link PibblEmbossFilterOptions}. */
11
+ y: number;
12
+ /** Positive logical region width. See {@link PibblEmbossFilterOptions}. */
13
+ width: number;
14
+ /** Positive logical region height. See {@link PibblEmbossFilterOptions}. */
15
+ height: number;
16
+ }>;
17
+ /** Height range in logical pixels, finite 0–32; default 3. See {@link emboss}. */
18
+ readonly depth?: SignalValue<number>;
19
+ /** Lighting strength, finite 0–1; default 1. Zero bypasses processing. See {@link emboss}. */
20
+ readonly strength?: SignalValue<number>;
21
+ /** Nonzero finite direction toward the light in local coordinates; default [-0.6, -0.8]. See {@link emboss}. */
22
+ readonly direction?: readonly [number, number];
23
+ }
24
+ /**
25
+ * Lights captured pixels using normals derived from a grayscale texture height map.
26
+ * Flat heights are neutral; opposing slopes brighten and darken without changing alpha or geometry.
27
+ * @param map - Mounted height texture, luminance times alpha; white is high. See {@link TexturePaint}.
28
+ * @param options - Local placement, height depth, strength, and light direction. See {@link PibblEmbossFilterOptions}.
29
+ * @returns A filter descriptor for style.filter. See {@link PibblFilter}.
30
+ * @see {@link PibblEmbossFilterOptions}
31
+ */
32
+ export declare function emboss(map: SignalValue<TexturePaint>, options: PibblEmbossFilterOptions): PibblFilter;
@@ -0,0 +1,106 @@
1
+ import { isSignal } from "../lib/signals/graph.js";
2
+ import { layoutDiagnostic } from "../lib/style/diagnostics.js";
3
+ import {
4
+ PIBBL_FILTER_EXECUTOR
5
+ } from "../lib/style/filter-types.js";
6
+ import {
7
+ borrowTextureRaster,
8
+ validateTexturePaint
9
+ } from "../lib/textures/texture-protocol.js";
10
+ import {
11
+ filterBoundaryExecutor
12
+ } from "./filter-executor.js";
13
+ import { processEmboss } from "./render-emboss-boundary.js";
14
+ const definitions = /* @__PURE__ */ new WeakMap();
15
+ const executor = {
16
+ prepare(value, property, context) {
17
+ const definition = definitions.get(value);
18
+ if (!definition)
19
+ throw new Error(
20
+ "An emboss filter was created by an incompatible Pibbl runtime."
21
+ );
22
+ const { options } = definition;
23
+ const fail = (key, value2, reason) => layoutDiagnostic({
24
+ component: context.component,
25
+ property: `${property}.${key}`,
26
+ value: value2,
27
+ algorithm: context.algorithm,
28
+ constraints: context.constraints,
29
+ reason
30
+ });
31
+ const numeric = (key, fallback, maximum) => {
32
+ const input = options[key];
33
+ const value2 = input === void 0 ? fallback : isSignal(input) ? input.get() : input;
34
+ if (typeof value2 !== "number" || !Number.isFinite(value2) || value2 < 0 || value2 > maximum)
35
+ throw fail(key, value2, `must be finite within 0..${maximum}`);
36
+ return value2;
37
+ };
38
+ const depth = numeric("depth", 3, 32), strength = numeric("strength", 1, 1);
39
+ const direction = options.direction ?? [-0.6, -0.8];
40
+ if (!Array.isArray(direction) || direction.length !== 2 || !direction.every(
41
+ (value2) => typeof value2 === "number" && Number.isFinite(value2)
42
+ ) || Math.hypot(...direction) === 0)
43
+ throw fail(
44
+ "direction",
45
+ direction,
46
+ "must contain two finite components with nonzero length"
47
+ );
48
+ const length = Math.hypot(...direction);
49
+ const candidate = options.region;
50
+ if (!candidate || typeof candidate !== "object")
51
+ throw fail(
52
+ "region",
53
+ candidate,
54
+ "must contain finite coordinates and positive dimensions"
55
+ );
56
+ const { x, y, width, height } = candidate;
57
+ if (![x, y, width, height].every(
58
+ (value2) => typeof value2 === "number" && Number.isFinite(value2)
59
+ ) || width <= 0 || height <= 0)
60
+ throw fail(
61
+ "region",
62
+ candidate,
63
+ "must contain finite coordinates and positive dimensions"
64
+ );
65
+ const region = { x, y, width, height };
66
+ const map = isSignal(definition.map) ? definition.map.get() : definition.map;
67
+ try {
68
+ validateTexturePaint(map);
69
+ if (strength !== 0 && depth !== 0)
70
+ borrowTextureRaster(map, () => void 0);
71
+ } catch (error) {
72
+ throw fail(
73
+ "map",
74
+ map,
75
+ error instanceof Error ? error.message : String(error)
76
+ );
77
+ }
78
+ const settings = {
79
+ opacity: strength,
80
+ depth,
81
+ threshold: 0,
82
+ softness: 1,
83
+ direction: [direction[0] / length, direction[1] / length]
84
+ };
85
+ return Object.freeze({
86
+ executor: filterBoundaryExecutor,
87
+ reverseInfluence: (output) => ({ ...output }),
88
+ process: strength === 0 || depth === 0 ? void 0 : (source, windows) => processEmboss(source, windows, map, settings, region)
89
+ });
90
+ },
91
+ render: filterBoundaryExecutor.render
92
+ };
93
+ function emboss(map, options) {
94
+ const frozen = Object.freeze({
95
+ ...options,
96
+ region: Object.freeze({ ...options.region }),
97
+ direction: options.direction && Object.freeze([...options.direction])
98
+ });
99
+ const value = Object.freeze({ [PIBBL_FILTER_EXECUTOR]: executor });
100
+ definitions.set(value, { map, options: frozen });
101
+ return value;
102
+ }
103
+ export {
104
+ emboss
105
+ };
106
+ //# sourceMappingURL=emboss.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/filters/emboss.ts"],
4
+ "sourcesContent": ["import { isSignal } from \"../lib/signals/graph.js\";\nimport type { SignalValue } from \"../lib/signals/types.js\";\nimport { layoutDiagnostic } from \"../lib/style/diagnostics.js\";\nimport {\n PIBBL_FILTER_EXECUTOR,\n type PibblFilter,\n type PibblFilterExecutor,\n} from \"../lib/style/filter-types.js\";\nimport {\n borrowTextureRaster,\n validateTexturePaint,\n type TexturePaint,\n} from \"../lib/textures/texture-protocol.js\";\nimport {\n filterBoundaryExecutor,\n type CustomPreparedFilter,\n} from \"./filter-executor.js\";\nimport { processEmboss } from \"./render-emboss-boundary.js\";\n\n/** Directional lighting of grayscale texture height. See {@link emboss}. */\nexport interface PibblEmbossFilterOptions {\n /** Local texture placement region with finite coordinates and positive dimensions. See {@link TexturePaint}. */\n readonly region: Readonly<{\n /** Horizontal origin in local logical coordinates. See {@link PibblEmbossFilterOptions}. */\n x: number;\n /** Vertical origin in local logical coordinates. See {@link PibblEmbossFilterOptions}. */\n y: number;\n /** Positive logical region width. See {@link PibblEmbossFilterOptions}. */\n width: number;\n /** Positive logical region height. See {@link PibblEmbossFilterOptions}. */\n height: number;\n }>;\n /** Height range in logical pixels, finite 0\u201332; default 3. See {@link emboss}. */\n readonly depth?: SignalValue<number>;\n /** Lighting strength, finite 0\u20131; default 1. Zero bypasses processing. See {@link emboss}. */\n readonly strength?: SignalValue<number>;\n /** Nonzero finite direction toward the light in local coordinates; default [-0.6, -0.8]. See {@link emboss}. */\n readonly direction?: readonly [number, number];\n}\nconst definitions = new WeakMap<\n PibblFilter,\n {\n map: SignalValue<TexturePaint>;\n options: Readonly<PibblEmbossFilterOptions>;\n }\n>();\nconst executor: PibblFilterExecutor = {\n prepare(value, property, context) {\n const definition = definitions.get(value);\n if (!definition)\n throw new Error(\n \"An emboss filter was created by an incompatible Pibbl runtime.\",\n );\n const { options } = definition;\n const fail = (key: string, value: unknown, reason: string) =>\n layoutDiagnostic({\n component: context.component,\n property: `${property}.${key}`,\n value,\n algorithm: context.algorithm,\n constraints: context.constraints,\n reason,\n });\n const numeric = (\n key: \"depth\" | \"strength\",\n fallback: number,\n maximum: number,\n ) => {\n const input = options[key];\n const value =\n input === undefined ? fallback : isSignal(input) ? input.get() : input;\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value) ||\n value < 0 ||\n value > maximum\n )\n throw fail(key, value, `must be finite within 0..${maximum}`);\n return value;\n };\n const depth = numeric(\"depth\", 3, 32),\n strength = numeric(\"strength\", 1, 1);\n const direction: unknown = options.direction ?? [-0.6, -0.8];\n if (\n !Array.isArray(direction) ||\n direction.length !== 2 ||\n !direction.every(\n (value) => typeof value === \"number\" && Number.isFinite(value),\n ) ||\n Math.hypot(...direction) === 0\n )\n throw fail(\n \"direction\",\n direction,\n \"must contain two finite components with nonzero length\",\n );\n const length = Math.hypot(...direction);\n const candidate: unknown = options.region;\n if (!candidate || typeof candidate !== \"object\")\n throw fail(\n \"region\",\n candidate,\n \"must contain finite coordinates and positive dimensions\",\n );\n const { x, y, width, height } = candidate as {\n x: number;\n y: number;\n width: number;\n height: number;\n };\n if (\n ![x, y, width, height].every(\n (value) => typeof value === \"number\" && Number.isFinite(value),\n ) ||\n width <= 0 ||\n height <= 0\n )\n throw fail(\n \"region\",\n candidate,\n \"must contain finite coordinates and positive dimensions\",\n );\n const region = { x, y, width, height };\n const map = isSignal(definition.map)\n ? definition.map.get()\n : definition.map;\n try {\n validateTexturePaint(map);\n if (strength !== 0 && depth !== 0)\n borrowTextureRaster(map, () => undefined);\n } catch (error) {\n throw fail(\n \"map\",\n map,\n error instanceof Error ? error.message : String(error),\n );\n }\n const settings = {\n opacity: strength,\n depth,\n threshold: 0,\n softness: 1,\n direction: [direction[0] / length, direction[1] / length] as const,\n };\n return Object.freeze({\n executor: filterBoundaryExecutor,\n reverseInfluence: (output) => ({ ...output }),\n process:\n strength === 0 || depth === 0\n ? undefined\n : (source, windows) =>\n processEmboss(source, windows, map, settings, region),\n } satisfies CustomPreparedFilter);\n },\n render: filterBoundaryExecutor.render,\n};\n/**\n * Lights captured pixels using normals derived from a grayscale texture height map.\n * Flat heights are neutral; opposing slopes brighten and darken without changing alpha or geometry.\n * @param map - Mounted height texture, luminance times alpha; white is high. See {@link TexturePaint}.\n * @param options - Local placement, height depth, strength, and light direction. See {@link PibblEmbossFilterOptions}.\n * @returns A filter descriptor for style.filter. See {@link PibblFilter}.\n * @see {@link PibblEmbossFilterOptions}\n */\nexport function emboss(\n map: SignalValue<TexturePaint>,\n options: PibblEmbossFilterOptions,\n): PibblFilter {\n const frozen = Object.freeze({\n ...options,\n region: Object.freeze({ ...options.region }),\n direction:\n options.direction &&\n (Object.freeze([...options.direction]) as readonly [number, number]),\n });\n const value = Object.freeze({ [PIBBL_FILTER_EXECUTOR]: executor });\n definitions.set(value, { map, options: frozen });\n return value;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["value"]
7
+ }
@@ -19,6 +19,7 @@ export interface ReflectionSettings {
19
19
  readonly threshold: number;
20
20
  readonly softness: number;
21
21
  readonly direction: readonly [number, number];
22
+ readonly depth?: number;
22
23
  }
23
24
  export type ReflectionLight = {
24
25
  readonly color: string;
@@ -35,6 +36,7 @@ export interface ReflectionWarp {
35
36
  /** Optional synchronous image processor; scene pixels are never read back. */
36
37
  export declare class ReflectionGpu {
37
38
  private readonly callbacks;
39
+ private readonly fragment;
38
40
  private readonly canvas;
39
41
  private gl;
40
42
  private resources;
@@ -46,7 +48,7 @@ export declare class ReflectionGpu {
46
48
  private lost;
47
49
  private readonly onContextLost;
48
50
  private readonly onContextRestored;
49
- constructor(callbacks?: Readonly<ReflectionGpuCallbacks>);
51
+ constructor(callbacks?: Readonly<ReflectionGpuCallbacks>, fragment?: string);
50
52
  get isContextLost(): boolean;
51
53
  private acquireResources;
52
54
  apply(source: OffscreenCanvas, map: BorrowedTextureRaster, light: ReflectionLight, settings: ReflectionSettings, coordinates: ReflectionCoordinates, warp?: ReflectionWarp): ImageBitmap;
@@ -38,12 +38,14 @@ void main() {
38
38
  }
39
39
  `;
40
40
  class ReflectionGpu {
41
- constructor(callbacks = {}) {
41
+ constructor(callbacks = {}, fragment = fragmentSource) {
42
42
  this.callbacks = callbacks;
43
+ this.fragment = fragment;
43
44
  this.canvas.addEventListener("webglcontextlost", this.onContextLost);
44
45
  this.canvas.addEventListener("webglcontextrestored", this.onContextRestored);
45
46
  }
46
47
  callbacks;
48
+ fragment;
47
49
  canvas = new OffscreenCanvas(1, 1);
48
50
  gl;
49
51
  resources;
@@ -80,7 +82,7 @@ class ReflectionGpu {
80
82
  let fragment;
81
83
  let program = null;
82
84
  try {
83
- fragment = compile(gl, gl.FRAGMENT_SHADER, fragmentSource);
85
+ fragment = compile(gl, gl.FRAGMENT_SHADER, this.fragment);
84
86
  program = gl.createProgram();
85
87
  if (!program) throw new Error("Could not allocate reflection program.");
86
88
  gl.attachShader(program, vertex);
@@ -186,6 +188,7 @@ class ReflectionGpu {
186
188
  placement("warpOrigin", "warpSize", "warpRotation", warp?.map.placement ?? map.placement, warp?.region ?? coordinates.region, warp?.map.width ?? map.width, warp?.map.height ?? map.height);
187
189
  gl.uniform2f(uniform("warpStrength"), (warp?.strength ?? 0) * coordinates.density / source.width, (warp?.strength ?? 0) * coordinates.density / source.height);
188
190
  gl.uniform2f(uniform("direction"), settings.direction[0], settings.direction[1]);
191
+ gl.uniform1f(uniform("depth"), settings.depth ?? 0);
189
192
  gl.uniform1f(uniform("opacity"), settings.opacity);
190
193
  gl.uniform1f(uniform("threshold"), settings.threshold);
191
194
  gl.uniform1f(uniform("softness"), settings.softness);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/filters/reflection-gpu.ts"],
4
- "sourcesContent": ["import type { BorrowedTextureRaster, TexturePlacement } from '../lib/textures/texture-protocol.js';\n\nexport interface ReflectionCoordinates {\n readonly originX: number;\n readonly originY: number;\n readonly density: number;\n readonly region: Readonly<{ x: number; y: number; width: number; height: number }>;\n}\nexport interface ReflectionGpuCallbacks {\n readonly onContextLost?: () => void;\n readonly onContextRestored?: () => void;\n}\nconst vertexSource = `#version 300 es\nin vec2 p;\nout vec2 uv;\nvoid main() { uv = vec2((p.x + 1.) * .5, 1. - (p.y + 1.) * .5); gl_Position = vec4(p, 0, 1); }\n`;\nexport interface ReflectionSettings {\n readonly opacity: number; readonly threshold: number; readonly softness: number;\n readonly direction: readonly [number, number];\n}\nexport type ReflectionLight = { readonly color: string } | { readonly image: HTMLImageElement | ImageBitmap } | { readonly raster: BorrowedTextureRaster };\nexport interface ReflectionWarp { readonly map: BorrowedTextureRaster; readonly strength: number; readonly region: ReflectionCoordinates['region']; }\nconst fragmentSource = `#version 300 es\nprecision highp float;\nuniform sampler2D scene, map, lightMap, warpMap;\nuniform vec2 logicalOrigin, logicalSize, mapOrigin, tileSize, lightOrigin, lightSize, warpOrigin, warpSize, warpStrength, direction;\nuniform float rotation, lightRotation, warpRotation, opacity, threshold, softness;\nin vec2 uv;\nout vec4 outputColor;\nfloat decode(float c) { float b=c*255.; return (b-128.)/(b<128.?128.:127.); }\nvec2 coordinates(vec2 origin, vec2 size, float angle) {\n vec2 p=logicalOrigin+uv*logicalSize-origin;\n float c=cos(angle),s=sin(angle);\n return vec2(c*p.x+s*p.y,-s*p.x+c*p.y)/size;\n}\nvec4 sourcePixel(ivec2 p) {\n ivec2 size=textureSize(scene,0);\n if(any(lessThan(p,ivec2(0)))||any(greaterThanEqual(p,size))) return vec4(0);\n return texelFetch(scene,p,0);\n}\nvec4 sourceSample(vec2 p) {\n vec2 pixel=p*vec2(textureSize(scene,0))-.5;\n ivec2 base=ivec2(floor(pixel)); vec2 f=fract(pixel);\n return mix(mix(sourcePixel(base),sourcePixel(base+ivec2(1,0)),f.x),mix(sourcePixel(base+ivec2(0,1)),sourcePixel(base+ivec2(1,1)),f.x),f.y);\n}\nvoid main() {\n vec4 warp=texture(warpMap,coordinates(warpOrigin,warpSize,warpRotation));\n vec4 base=sourceSample(uv+vec2(decode(warp.r),decode(warp.g))*warp.a*warpStrength);\n vec4 field=texture(map,coordinates(mapOrigin,tileSize,rotation));\n vec2 slope=vec2(decode(field.r),decode(field.g));\n float coverage=smoothstep(threshold,threshold+softness,dot(slope,direction))*field.a*opacity;\n vec4 light=texture(lightMap,coordinates(lightOrigin,lightSize,lightRotation)+slope*.035);\n float amount=coverage*light.a;\n outputColor=vec4(base.rgb*(1.-amount)+base.a*light.rgb*amount,base.a);\n}\n`;\n\n/** Optional synchronous image processor; scene pixels are never read back. */\nexport class ReflectionGpu {\n private readonly canvas = new OffscreenCanvas(1, 1);\n private gl: WebGL2RenderingContext | undefined;\n private resources: ReflectionResources | undefined;\n private readonly maps = new Map<object, { texture: WebGLTexture; revision: number }>();\n private readonly directKey = {};\n private colorCanvas: OffscreenCanvas | undefined;\n private directRevision = 0;\n private disposed = false;\n private lost = false;\n private readonly onContextLost = (event: Event): void => {\n event.preventDefault();\n if (this.disposed || this.lost) return;\n this.lost = true;\n this.releaseResources(false);\n this.callbacks.onContextLost?.();\n };\n private readonly onContextRestored = (): void => {\n if (this.disposed || !this.lost) return;\n this.lost = false;\n this.callbacks.onContextRestored?.();\n };\n\n constructor(private readonly callbacks: Readonly<ReflectionGpuCallbacks> = {}) {\n this.canvas.addEventListener('webglcontextlost', this.onContextLost);\n this.canvas.addEventListener('webglcontextrestored', this.onContextRestored);\n }\n\n get isContextLost(): boolean {\n return this.lost || this.gl?.isContextLost() === true;\n }\n\n private acquireResources(): ReflectionResources {\n if (this.disposed) throw new Error('Cannot use a disposed reflection processor.');\n if (this.isContextLost) throw new Error('Reflection WebGL2 context was lost.');\n if (this.resources) return this.resources;\n const gl = this.canvas.getContext('webgl2', { premultipliedAlpha: true, preserveDrawingBuffer: false });\n if (!gl) throw new Error('Reflection requires OffscreenCanvas WebGL2 support.');\n if (gl.isContextLost()) throw new Error('Reflection WebGL2 context was lost.');\n this.gl = gl;\n const vertex = compile(gl, gl.VERTEX_SHADER, vertexSource);\n let fragment: WebGLShader | undefined;\n let program: WebGLProgram | null = null;\n try {\n fragment = compile(gl, gl.FRAGMENT_SHADER, fragmentSource);\n program = gl.createProgram();\n if (!program) throw new Error('Could not allocate reflection program.');\n gl.attachShader(program, vertex); gl.attachShader(program, fragment); gl.linkProgram(program);\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) throw new Error(`Reflection shader link failed: ${gl.getProgramInfoLog(program)}`);\n } catch (error) { if (program) gl.deleteProgram(program); throw error; }\n finally { gl.deleteShader(vertex); if (fragment) gl.deleteShader(fragment); }\n const vao = gl.createVertexArray(), buffer = gl.createBuffer();\n if (!vao || !buffer) { if (vao) gl.deleteVertexArray(vao); if (buffer) gl.deleteBuffer(buffer); gl.deleteProgram(program); throw new Error('Could not allocate reflection geometry.'); }\n gl.bindVertexArray(vao); gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);\n const location = gl.getAttribLocation(program, 'p');\n gl.enableVertexAttribArray(location); gl.vertexAttribPointer(location, 2, gl.FLOAT, false, 0, 0);\n const source = gl.createTexture();\n if (!source) {\n if (source) gl.deleteTexture(source);\n gl.deleteBuffer(buffer); gl.deleteVertexArray(vao); gl.deleteProgram(program);\n throw new Error('Could not allocate reflection textures.');\n }\n const resources: ReflectionResources = { program, vao, buffer, source };\n gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);\n this.resources = resources;\n return resources;\n }\n\n apply(source: OffscreenCanvas, map: BorrowedTextureRaster, light: ReflectionLight, settings: ReflectionSettings, coordinates: ReflectionCoordinates, warp?: ReflectionWarp): ImageBitmap {\n const { gl, program, vao, source: sourceTexture } = this.acquireResourcesWithContext();\n const maximum = gl.getParameter(gl.MAX_TEXTURE_SIZE) as number;\n if (Math.max(source.width, source.height, map.width, map.height, warp?.map.width ?? 0, warp?.map.height ?? 0) > maximum) throw new RangeError('Reflection target exceeds WebGL2 maximum texture size.');\n if (this.canvas.width !== source.width) this.canvas.width = source.width;\n if (this.canvas.height !== source.height) this.canvas.height = source.height;\n gl.viewport(0, 0, source.width, source.height); gl.useProgram(program); gl.bindVertexArray(vao);\n this.upload(gl, 0, sourceTexture, source, true, false);\n const uploaded = new Map<object, number>();\n const bind = (unit: number, raster: {source: TexImageSource; width:number; height:number; resource:object; revision:number; placement:Readonly<TexturePlacement>}) => {\n if (Math.max(raster.width,raster.height)>maximum) throw new RangeError('Reflection light exceeds WebGL2 maximum texture size.');\n let cached=this.maps.get(raster.resource);\n if (!cached) {\n const texture=gl.createTexture(); if(!texture) throw new Error('Could not allocate reflection input texture.');\n cached={texture,revision:-1}; this.maps.set(raster.resource,cached);\n }\n this.upload(gl,unit,cached.texture,raster.source,false,raster.placement.mode!=='stretch',cached.revision!==raster.revision && uploaded.get(raster.resource)!==raster.revision);\n uploaded.set(raster.resource,raster.revision);\n };\n bind(1,map); bind(3,warp?.map ?? map);\n let lightPlacement: Readonly<TexturePlacement> = {mode:'stretch'};\n let lightWidth=1,lightHeight=1;\n if ('raster' in light) { bind(2,light.raster); lightPlacement=light.raster.placement; lightWidth=light.raster.width; lightHeight=light.raster.height; }\n else {\n let image: TexImageSource;\n if ('color' in light) {\n const canvas=this.colorCanvas ??= new OffscreenCanvas(1,1);\n const ctx=canvas.getContext('2d'); if(!ctx) throw new Error('Reflection colors require Canvas 2D.');\n ctx.clearRect(0,0,1,1); ctx.fillStyle=light.color; ctx.fillRect(0,0,1,1); image=canvas;\n } else { image=light.image; lightWidth='naturalWidth' in light.image?light.image.naturalWidth:light.image.width; lightHeight='naturalHeight' in light.image?light.image.naturalHeight:light.image.height; }\n bind(2,{source:image,width:lightWidth,height:lightHeight,resource:this.directKey,revision:++this.directRevision,placement:lightPlacement});\n }\n const uniform=(name:string)=>gl.getUniformLocation(program,name);\n const placement=(origin:string,size:string,angle:string,value:Readonly<TexturePlacement>,region:ReflectionCoordinates['region'],width:number,height:number)=>{\n gl.uniform2f(uniform(origin),region.x+(value.offsetX??0),region.y+(value.offsetY??0));\n gl.uniform2f(uniform(size),value.mode==='stretch'?region.width:value.tileWidth??width,value.mode==='stretch'?region.height:value.tileHeight??height);\n gl.uniform1f(uniform(angle),(value.rotation??0)*Math.PI/180);\n };\n gl.uniform1i(uniform('scene'),0); gl.uniform1i(uniform('map'),1); gl.uniform1i(uniform('lightMap'),2); gl.uniform1i(uniform('warpMap'),3);\n gl.uniform2f(uniform('logicalOrigin'),coordinates.originX,coordinates.originY);\n gl.uniform2f(uniform('logicalSize'),source.width/coordinates.density,source.height/coordinates.density);\n placement('mapOrigin','tileSize','rotation',map.placement,coordinates.region,map.width,map.height);\n placement('lightOrigin','lightSize','lightRotation',lightPlacement,coordinates.region,lightWidth,lightHeight);\n placement('warpOrigin','warpSize','warpRotation',warp?.map.placement??map.placement,warp?.region??coordinates.region,warp?.map.width??map.width,warp?.map.height??map.height);\n gl.uniform2f(uniform('warpStrength'),(warp?.strength??0)*coordinates.density/source.width,(warp?.strength??0)*coordinates.density/source.height);\n gl.uniform2f(uniform('direction'),settings.direction[0],settings.direction[1]);\n gl.uniform1f(uniform('opacity'),settings.opacity); gl.uniform1f(uniform('threshold'),settings.threshold); gl.uniform1f(uniform('softness'),settings.softness);\n gl.drawArrays(gl.TRIANGLE_STRIP,0,4);\n if(this.isContextLost) throw new Error('Reflection WebGL2 context was lost.');\n const error=gl.getError(); if(error!==gl.NO_ERROR) throw new Error(`Reflection GPU processing failed (${error}).`);\n for(const [resource,revision] of uploaded) this.maps.get(resource)!.revision=revision;\n return this.canvas.transferToImageBitmap();\n }\n private acquireResourcesWithContext(): ReflectionResources & { gl: WebGL2RenderingContext } {\n const resources = this.acquireResources();\n const gl = this.gl;\n if (!gl || gl.isContextLost()) throw new Error('Reflection WebGL2 context was lost.');\n return { ...resources, gl };\n }\n private upload(gl: WebGL2RenderingContext, unit: number, texture: WebGLTexture, canvas: TexImageSource, premultiply: boolean, repeat: boolean, upload = true): void {\n gl.activeTexture(gl.TEXTURE0 + unit); gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, repeat ? gl.REPEAT : gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, repeat ? gl.REPEAT : gl.CLAMP_TO_EDGE);\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiply);\n if (upload) gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);\n }\n retainMaps(resources: ReadonlySet<object>): void {\n const gl = this.gl;\n for (const [resource, cached] of this.maps) {\n if (resource !== this.directKey && !resources.has(resource)) { if (gl && !gl.isContextLost()) gl.deleteTexture(cached.texture); this.maps.delete(resource); }\n }\n }\n private releaseResources(deleteResources: boolean): void {\n const gl = this.gl;\n const resources = this.resources;\n this.resources = undefined;\n if (gl && !gl.isContextLost() && deleteResources) {\n gl.deleteTexture(resources?.source ?? null);\n for (const cached of this.maps.values()) gl.deleteTexture(cached.texture);\n if (resources) { gl.deleteBuffer(resources.buffer); gl.deleteVertexArray(resources.vao); gl.deleteProgram(resources.program); }\n }\n this.maps.clear();\n }\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n this.canvas.removeEventListener('webglcontextlost', this.onContextLost);\n this.canvas.removeEventListener('webglcontextrestored', this.onContextRestored);\n this.releaseResources(true);\n this.canvas.width = 0; this.canvas.height = 0;\n if(this.colorCanvas) this.colorCanvas.width=this.colorCanvas.height=0;\n this.colorCanvas=undefined;\n }\n}\ninterface ReflectionResources {\n readonly program: WebGLProgram;\n readonly vao: WebGLVertexArrayObject;\n readonly buffer: WebGLBuffer;\n readonly source: WebGLTexture;\n}\nfunction compile(gl: WebGL2RenderingContext, kind: number, source: string): WebGLShader {\n const shader = gl.createShader(kind);\n if (!shader) throw new Error('Could not allocate reflection shader.');\n gl.shaderSource(shader, source); gl.compileShader(shader);\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const error = gl.getShaderInfoLog(shader); gl.deleteShader(shader);\n throw new Error(`Reflection shader compile failed: ${error}`);\n }\n return shader;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { BorrowedTextureRaster, TexturePlacement } from '../lib/textures/texture-protocol.js';\n\nexport interface ReflectionCoordinates {\n readonly originX: number;\n readonly originY: number;\n readonly density: number;\n readonly region: Readonly<{ x: number; y: number; width: number; height: number }>;\n}\nexport interface ReflectionGpuCallbacks {\n readonly onContextLost?: () => void;\n readonly onContextRestored?: () => void;\n}\nconst vertexSource = `#version 300 es\nin vec2 p;\nout vec2 uv;\nvoid main() { uv = vec2((p.x + 1.) * .5, 1. - (p.y + 1.) * .5); gl_Position = vec4(p, 0, 1); }\n`;\nexport interface ReflectionSettings {\n readonly opacity: number; readonly threshold: number; readonly softness: number;\n readonly direction: readonly [number, number];\n readonly depth?: number;\n}\nexport type ReflectionLight = { readonly color: string } | { readonly image: HTMLImageElement | ImageBitmap } | { readonly raster: BorrowedTextureRaster };\nexport interface ReflectionWarp { readonly map: BorrowedTextureRaster; readonly strength: number; readonly region: ReflectionCoordinates['region']; }\nconst fragmentSource = `#version 300 es\nprecision highp float;\nuniform sampler2D scene, map, lightMap, warpMap;\nuniform vec2 logicalOrigin, logicalSize, mapOrigin, tileSize, lightOrigin, lightSize, warpOrigin, warpSize, warpStrength, direction;\nuniform float rotation, lightRotation, warpRotation, opacity, threshold, softness;\nin vec2 uv;\nout vec4 outputColor;\nfloat decode(float c) { float b=c*255.; return (b-128.)/(b<128.?128.:127.); }\nvec2 coordinates(vec2 origin, vec2 size, float angle) {\n vec2 p=logicalOrigin+uv*logicalSize-origin;\n float c=cos(angle),s=sin(angle);\n return vec2(c*p.x+s*p.y,-s*p.x+c*p.y)/size;\n}\nvec4 sourcePixel(ivec2 p) {\n ivec2 size=textureSize(scene,0);\n if(any(lessThan(p,ivec2(0)))||any(greaterThanEqual(p,size))) return vec4(0);\n return texelFetch(scene,p,0);\n}\nvec4 sourceSample(vec2 p) {\n vec2 pixel=p*vec2(textureSize(scene,0))-.5;\n ivec2 base=ivec2(floor(pixel)); vec2 f=fract(pixel);\n return mix(mix(sourcePixel(base),sourcePixel(base+ivec2(1,0)),f.x),mix(sourcePixel(base+ivec2(0,1)),sourcePixel(base+ivec2(1,1)),f.x),f.y);\n}\nvoid main() {\n vec4 warp=texture(warpMap,coordinates(warpOrigin,warpSize,warpRotation));\n vec4 base=sourceSample(uv+vec2(decode(warp.r),decode(warp.g))*warp.a*warpStrength);\n vec4 field=texture(map,coordinates(mapOrigin,tileSize,rotation));\n vec2 slope=vec2(decode(field.r),decode(field.g));\n float coverage=smoothstep(threshold,threshold+softness,dot(slope,direction))*field.a*opacity;\n vec4 light=texture(lightMap,coordinates(lightOrigin,lightSize,lightRotation)+slope*.035);\n float amount=coverage*light.a;\n outputColor=vec4(base.rgb*(1.-amount)+base.a*light.rgb*amount,base.a);\n}\n`;\n\n/** Optional synchronous image processor; scene pixels are never read back. */\nexport class ReflectionGpu {\n private readonly canvas = new OffscreenCanvas(1, 1);\n private gl: WebGL2RenderingContext | undefined;\n private resources: ReflectionResources | undefined;\n private readonly maps = new Map<object, { texture: WebGLTexture; revision: number }>();\n private readonly directKey = {};\n private colorCanvas: OffscreenCanvas | undefined;\n private directRevision = 0;\n private disposed = false;\n private lost = false;\n private readonly onContextLost = (event: Event): void => {\n event.preventDefault();\n if (this.disposed || this.lost) return;\n this.lost = true;\n this.releaseResources(false);\n this.callbacks.onContextLost?.();\n };\n private readonly onContextRestored = (): void => {\n if (this.disposed || !this.lost) return;\n this.lost = false;\n this.callbacks.onContextRestored?.();\n };\n\n constructor(private readonly callbacks: Readonly<ReflectionGpuCallbacks> = {}, private readonly fragment = fragmentSource) {\n this.canvas.addEventListener('webglcontextlost', this.onContextLost);\n this.canvas.addEventListener('webglcontextrestored', this.onContextRestored);\n }\n\n get isContextLost(): boolean {\n return this.lost || this.gl?.isContextLost() === true;\n }\n\n private acquireResources(): ReflectionResources {\n if (this.disposed) throw new Error('Cannot use a disposed reflection processor.');\n if (this.isContextLost) throw new Error('Reflection WebGL2 context was lost.');\n if (this.resources) return this.resources;\n const gl = this.canvas.getContext('webgl2', { premultipliedAlpha: true, preserveDrawingBuffer: false });\n if (!gl) throw new Error('Reflection requires OffscreenCanvas WebGL2 support.');\n if (gl.isContextLost()) throw new Error('Reflection WebGL2 context was lost.');\n this.gl = gl;\n const vertex = compile(gl, gl.VERTEX_SHADER, vertexSource);\n let fragment: WebGLShader | undefined;\n let program: WebGLProgram | null = null;\n try {\n fragment = compile(gl, gl.FRAGMENT_SHADER, this.fragment);\n program = gl.createProgram();\n if (!program) throw new Error('Could not allocate reflection program.');\n gl.attachShader(program, vertex); gl.attachShader(program, fragment); gl.linkProgram(program);\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) throw new Error(`Reflection shader link failed: ${gl.getProgramInfoLog(program)}`);\n } catch (error) { if (program) gl.deleteProgram(program); throw error; }\n finally { gl.deleteShader(vertex); if (fragment) gl.deleteShader(fragment); }\n const vao = gl.createVertexArray(), buffer = gl.createBuffer();\n if (!vao || !buffer) { if (vao) gl.deleteVertexArray(vao); if (buffer) gl.deleteBuffer(buffer); gl.deleteProgram(program); throw new Error('Could not allocate reflection geometry.'); }\n gl.bindVertexArray(vao); gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);\n const location = gl.getAttribLocation(program, 'p');\n gl.enableVertexAttribArray(location); gl.vertexAttribPointer(location, 2, gl.FLOAT, false, 0, 0);\n const source = gl.createTexture();\n if (!source) {\n if (source) gl.deleteTexture(source);\n gl.deleteBuffer(buffer); gl.deleteVertexArray(vao); gl.deleteProgram(program);\n throw new Error('Could not allocate reflection textures.');\n }\n const resources: ReflectionResources = { program, vao, buffer, source };\n gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);\n this.resources = resources;\n return resources;\n }\n\n apply(source: OffscreenCanvas, map: BorrowedTextureRaster, light: ReflectionLight, settings: ReflectionSettings, coordinates: ReflectionCoordinates, warp?: ReflectionWarp): ImageBitmap {\n const { gl, program, vao, source: sourceTexture } = this.acquireResourcesWithContext();\n const maximum = gl.getParameter(gl.MAX_TEXTURE_SIZE) as number;\n if (Math.max(source.width, source.height, map.width, map.height, warp?.map.width ?? 0, warp?.map.height ?? 0) > maximum) throw new RangeError('Reflection target exceeds WebGL2 maximum texture size.');\n if (this.canvas.width !== source.width) this.canvas.width = source.width;\n if (this.canvas.height !== source.height) this.canvas.height = source.height;\n gl.viewport(0, 0, source.width, source.height); gl.useProgram(program); gl.bindVertexArray(vao);\n this.upload(gl, 0, sourceTexture, source, true, false);\n const uploaded = new Map<object, number>();\n const bind = (unit: number, raster: {source: TexImageSource; width:number; height:number; resource:object; revision:number; placement:Readonly<TexturePlacement>}) => {\n if (Math.max(raster.width,raster.height)>maximum) throw new RangeError('Reflection light exceeds WebGL2 maximum texture size.');\n let cached=this.maps.get(raster.resource);\n if (!cached) {\n const texture=gl.createTexture(); if(!texture) throw new Error('Could not allocate reflection input texture.');\n cached={texture,revision:-1}; this.maps.set(raster.resource,cached);\n }\n this.upload(gl,unit,cached.texture,raster.source,false,raster.placement.mode!=='stretch',cached.revision!==raster.revision && uploaded.get(raster.resource)!==raster.revision);\n uploaded.set(raster.resource,raster.revision);\n };\n bind(1,map); bind(3,warp?.map ?? map);\n let lightPlacement: Readonly<TexturePlacement> = {mode:'stretch'};\n let lightWidth=1,lightHeight=1;\n if ('raster' in light) { bind(2,light.raster); lightPlacement=light.raster.placement; lightWidth=light.raster.width; lightHeight=light.raster.height; }\n else {\n let image: TexImageSource;\n if ('color' in light) {\n const canvas=this.colorCanvas ??= new OffscreenCanvas(1,1);\n const ctx=canvas.getContext('2d'); if(!ctx) throw new Error('Reflection colors require Canvas 2D.');\n ctx.clearRect(0,0,1,1); ctx.fillStyle=light.color; ctx.fillRect(0,0,1,1); image=canvas;\n } else { image=light.image; lightWidth='naturalWidth' in light.image?light.image.naturalWidth:light.image.width; lightHeight='naturalHeight' in light.image?light.image.naturalHeight:light.image.height; }\n bind(2,{source:image,width:lightWidth,height:lightHeight,resource:this.directKey,revision:++this.directRevision,placement:lightPlacement});\n }\n const uniform=(name:string)=>gl.getUniformLocation(program,name);\n const placement=(origin:string,size:string,angle:string,value:Readonly<TexturePlacement>,region:ReflectionCoordinates['region'],width:number,height:number)=>{\n gl.uniform2f(uniform(origin),region.x+(value.offsetX??0),region.y+(value.offsetY??0));\n gl.uniform2f(uniform(size),value.mode==='stretch'?region.width:value.tileWidth??width,value.mode==='stretch'?region.height:value.tileHeight??height);\n gl.uniform1f(uniform(angle),(value.rotation??0)*Math.PI/180);\n };\n gl.uniform1i(uniform('scene'),0); gl.uniform1i(uniform('map'),1); gl.uniform1i(uniform('lightMap'),2); gl.uniform1i(uniform('warpMap'),3);\n gl.uniform2f(uniform('logicalOrigin'),coordinates.originX,coordinates.originY);\n gl.uniform2f(uniform('logicalSize'),source.width/coordinates.density,source.height/coordinates.density);\n placement('mapOrigin','tileSize','rotation',map.placement,coordinates.region,map.width,map.height);\n placement('lightOrigin','lightSize','lightRotation',lightPlacement,coordinates.region,lightWidth,lightHeight);\n placement('warpOrigin','warpSize','warpRotation',warp?.map.placement??map.placement,warp?.region??coordinates.region,warp?.map.width??map.width,warp?.map.height??map.height);\n gl.uniform2f(uniform('warpStrength'),(warp?.strength??0)*coordinates.density/source.width,(warp?.strength??0)*coordinates.density/source.height);\n gl.uniform2f(uniform('direction'),settings.direction[0],settings.direction[1]);\n gl.uniform1f(uniform('depth'),settings.depth ?? 0);\n gl.uniform1f(uniform('opacity'),settings.opacity); gl.uniform1f(uniform('threshold'),settings.threshold); gl.uniform1f(uniform('softness'),settings.softness);\n gl.drawArrays(gl.TRIANGLE_STRIP,0,4);\n if(this.isContextLost) throw new Error('Reflection WebGL2 context was lost.');\n const error=gl.getError(); if(error!==gl.NO_ERROR) throw new Error(`Reflection GPU processing failed (${error}).`);\n for(const [resource,revision] of uploaded) this.maps.get(resource)!.revision=revision;\n return this.canvas.transferToImageBitmap();\n }\n private acquireResourcesWithContext(): ReflectionResources & { gl: WebGL2RenderingContext } {\n const resources = this.acquireResources();\n const gl = this.gl;\n if (!gl || gl.isContextLost()) throw new Error('Reflection WebGL2 context was lost.');\n return { ...resources, gl };\n }\n private upload(gl: WebGL2RenderingContext, unit: number, texture: WebGLTexture, canvas: TexImageSource, premultiply: boolean, repeat: boolean, upload = true): void {\n gl.activeTexture(gl.TEXTURE0 + unit); gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, repeat ? gl.REPEAT : gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, repeat ? gl.REPEAT : gl.CLAMP_TO_EDGE);\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiply);\n if (upload) gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);\n }\n retainMaps(resources: ReadonlySet<object>): void {\n const gl = this.gl;\n for (const [resource, cached] of this.maps) {\n if (resource !== this.directKey && !resources.has(resource)) { if (gl && !gl.isContextLost()) gl.deleteTexture(cached.texture); this.maps.delete(resource); }\n }\n }\n private releaseResources(deleteResources: boolean): void {\n const gl = this.gl;\n const resources = this.resources;\n this.resources = undefined;\n if (gl && !gl.isContextLost() && deleteResources) {\n gl.deleteTexture(resources?.source ?? null);\n for (const cached of this.maps.values()) gl.deleteTexture(cached.texture);\n if (resources) { gl.deleteBuffer(resources.buffer); gl.deleteVertexArray(resources.vao); gl.deleteProgram(resources.program); }\n }\n this.maps.clear();\n }\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n this.canvas.removeEventListener('webglcontextlost', this.onContextLost);\n this.canvas.removeEventListener('webglcontextrestored', this.onContextRestored);\n this.releaseResources(true);\n this.canvas.width = 0; this.canvas.height = 0;\n if(this.colorCanvas) this.colorCanvas.width=this.colorCanvas.height=0;\n this.colorCanvas=undefined;\n }\n}\ninterface ReflectionResources {\n readonly program: WebGLProgram;\n readonly vao: WebGLVertexArrayObject;\n readonly buffer: WebGLBuffer;\n readonly source: WebGLTexture;\n}\nfunction compile(gl: WebGL2RenderingContext, kind: number, source: string): WebGLShader {\n const shader = gl.createShader(kind);\n if (!shader) throw new Error('Could not allocate reflection shader.');\n gl.shaderSource(shader, source); gl.compileShader(shader);\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const error = gl.getShaderInfoLog(shader); gl.deleteShader(shader);\n throw new Error(`Reflection shader compile failed: ${error}`);\n }\n return shader;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,13 @@
1
+ import { type TexturePaint } from "../lib/textures/texture-protocol.js";
2
+ import type { PibblInstance } from "../lib/types.js";
3
+ import type { FilterWindows } from "../lib/filter/filter-region.js";
4
+ import { EmbossGpu } from "./emboss-gpu.js";
5
+ import type { ReflectionSettings } from "./reflection-gpu.js";
6
+ /** @internal Test-only read-only access; it never creates a GPU service. */
7
+ export declare function peekEmbossGpu(instance: PibblInstance): EmbossGpu | undefined;
8
+ export declare function processEmboss(source: OffscreenCanvas, windows: FilterWindows, paint: TexturePaint, settings: ReflectionSettings, region: Readonly<{
9
+ x: number;
10
+ y: number;
11
+ width: number;
12
+ height: number;
13
+ }>): ImageBitmap;