@swf2es/player 0.1.0 → 0.1.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 (277) hide show
  1. package/package.json +7 -7
  2. package/dist/audio.d.ts +0 -22
  3. package/dist/audio.d.ts.map +0 -1
  4. package/dist/audio.js +0 -106
  5. package/dist/audio.js.map +0 -1
  6. package/dist/bitmap-filters.d.ts +0 -29
  7. package/dist/bitmap-filters.d.ts.map +0 -1
  8. package/dist/bitmap-filters.js +0 -906
  9. package/dist/bitmap-filters.js.map +0 -1
  10. package/dist/bitmap-ops.d.ts +0 -113
  11. package/dist/bitmap-ops.d.ts.map +0 -1
  12. package/dist/bitmap-ops.js +0 -725
  13. package/dist/bitmap-ops.js.map +0 -1
  14. package/dist/bitmap.d.ts +0 -98
  15. package/dist/bitmap.d.ts.map +0 -1
  16. package/dist/bitmap.js +0 -314
  17. package/dist/bitmap.js.map +0 -1
  18. package/dist/bounds.d.ts +0 -26
  19. package/dist/bounds.d.ts.map +0 -1
  20. package/dist/bounds.js +0 -300
  21. package/dist/bounds.js.map +0 -1
  22. package/dist/color.d.ts +0 -7
  23. package/dist/color.d.ts.map +0 -1
  24. package/dist/color.js +0 -42
  25. package/dist/color.js.map +0 -1
  26. package/dist/display.d.ts +0 -425
  27. package/dist/display.d.ts.map +0 -1
  28. package/dist/display.js +0 -1274
  29. package/dist/display.js.map +0 -1
  30. package/dist/drawing.d.ts +0 -52
  31. package/dist/drawing.d.ts.map +0 -1
  32. package/dist/drawing.js +0 -204
  33. package/dist/drawing.js.map +0 -1
  34. package/dist/filters.d.ts +0 -54
  35. package/dist/filters.d.ts.map +0 -1
  36. package/dist/filters.js +0 -155
  37. package/dist/filters.js.map +0 -1
  38. package/dist/fonts.d.ts +0 -23
  39. package/dist/fonts.d.ts.map +0 -1
  40. package/dist/fonts.js +0 -91
  41. package/dist/fonts.js.map +0 -1
  42. package/dist/geometry.d.ts +0 -21
  43. package/dist/geometry.d.ts.map +0 -1
  44. package/dist/geometry.js +0 -76
  45. package/dist/geometry.js.map +0 -1
  46. package/dist/gradients.d.ts +0 -29
  47. package/dist/gradients.d.ts.map +0 -1
  48. package/dist/gradients.js +0 -116
  49. package/dist/gradients.js.map +0 -1
  50. package/dist/images.d.ts +0 -22
  51. package/dist/images.d.ts.map +0 -1
  52. package/dist/images.js +0 -147
  53. package/dist/images.js.map +0 -1
  54. package/dist/input.d.ts +0 -79
  55. package/dist/input.d.ts.map +0 -1
  56. package/dist/input.js +0 -366
  57. package/dist/input.js.map +0 -1
  58. package/dist/keyboard.d.ts +0 -97
  59. package/dist/keyboard.d.ts.map +0 -1
  60. package/dist/keyboard.js +0 -583
  61. package/dist/keyboard.js.map +0 -1
  62. package/dist/morph.d.ts +0 -17
  63. package/dist/morph.d.ts.map +0 -1
  64. package/dist/morph.js +0 -218
  65. package/dist/morph.js.map +0 -1
  66. package/dist/pixi-blend.d.ts +0 -7
  67. package/dist/pixi-blend.d.ts.map +0 -1
  68. package/dist/pixi-blend.js +0 -253
  69. package/dist/pixi-blend.js.map +0 -1
  70. package/dist/pixi-color.d.ts +0 -54
  71. package/dist/pixi-color.d.ts.map +0 -1
  72. package/dist/pixi-color.js +0 -336
  73. package/dist/pixi-color.js.map +0 -1
  74. package/dist/pixi-filters.d.ts +0 -40
  75. package/dist/pixi-filters.d.ts.map +0 -1
  76. package/dist/pixi-filters.js +0 -953
  77. package/dist/pixi-filters.js.map +0 -1
  78. package/dist/pixi-resolve.d.ts +0 -4
  79. package/dist/pixi-resolve.d.ts.map +0 -1
  80. package/dist/pixi-resolve.js +0 -76
  81. package/dist/pixi-resolve.js.map +0 -1
  82. package/dist/pixi.d.ts +0 -219
  83. package/dist/pixi.d.ts.map +0 -1
  84. package/dist/pixi.js +0 -2169
  85. package/dist/pixi.js.map +0 -1
  86. package/dist/playerglobal/flash/filters/filters.d.ts +0 -26
  87. package/dist/playerglobal/flash/filters/filters.d.ts.map +0 -1
  88. package/dist/playerglobal/flash/filters/filters.js +0 -287
  89. package/dist/playerglobal/flash/filters/filters.js.map +0 -1
  90. package/dist/playerglobal/flash/system/FSCommand.d.ts +0 -4
  91. package/dist/playerglobal/flash/system/FSCommand.d.ts.map +0 -1
  92. package/dist/playerglobal/flash/system/FSCommand.js +0 -18
  93. package/dist/playerglobal/flash/system/FSCommand.js.map +0 -1
  94. package/dist/playerglobal/natives.d.ts +0 -10
  95. package/dist/playerglobal/natives.d.ts.map +0 -1
  96. package/dist/playerglobal/natives.js +0 -53
  97. package/dist/playerglobal/natives.js.map +0 -1
  98. package/dist/png.d.ts +0 -4
  99. package/dist/png.d.ts.map +0 -1
  100. package/dist/png.js +0 -140
  101. package/dist/png.js.map +0 -1
  102. package/dist/render/art.d.ts +0 -148
  103. package/dist/render/art.d.ts.map +0 -1
  104. package/dist/render/art.js +0 -575
  105. package/dist/render/art.js.map +0 -1
  106. package/dist/render/batchers.d.ts +0 -23
  107. package/dist/render/batchers.d.ts.map +0 -1
  108. package/dist/render/batchers.js +0 -52
  109. package/dist/render/batchers.js.map +0 -1
  110. package/dist/render/bitmaps.d.ts +0 -117
  111. package/dist/render/bitmaps.d.ts.map +0 -1
  112. package/dist/render/bitmaps.js +0 -422
  113. package/dist/render/bitmaps.js.map +0 -1
  114. package/dist/render/blend.d.ts +0 -37
  115. package/dist/render/blend.d.ts.map +0 -1
  116. package/dist/render/blend.js +0 -195
  117. package/dist/render/blend.js.map +0 -1
  118. package/dist/render/color.d.ts +0 -111
  119. package/dist/render/color.d.ts.map +0 -1
  120. package/dist/render/color.js +0 -533
  121. package/dist/render/color.js.map +0 -1
  122. package/dist/render/compositing.d.ts +0 -77
  123. package/dist/render/compositing.d.ts.map +0 -1
  124. package/dist/render/compositing.js +0 -188
  125. package/dist/render/compositing.js.map +0 -1
  126. package/dist/render/filters.d.ts +0 -98
  127. package/dist/render/filters.d.ts.map +0 -1
  128. package/dist/render/filters.js +0 -1326
  129. package/dist/render/filters.js.map +0 -1
  130. package/dist/render/hooks.d.ts +0 -4
  131. package/dist/render/hooks.d.ts.map +0 -1
  132. package/dist/render/hooks.js +0 -48
  133. package/dist/render/hooks.js.map +0 -1
  134. package/dist/render/node.d.ts +0 -139
  135. package/dist/render/node.d.ts.map +0 -1
  136. package/dist/render/node.js +0 -59
  137. package/dist/render/node.js.map +0 -1
  138. package/dist/render/patches.d.ts +0 -54
  139. package/dist/render/patches.d.ts.map +0 -1
  140. package/dist/render/patches.js +0 -154
  141. package/dist/render/patches.js.map +0 -1
  142. package/dist/render/planes.d.ts +0 -74
  143. package/dist/render/planes.d.ts.map +0 -1
  144. package/dist/render/planes.js +0 -267
  145. package/dist/render/planes.js.map +0 -1
  146. package/dist/render/pointer.d.ts +0 -5
  147. package/dist/render/pointer.d.ts.map +0 -1
  148. package/dist/render/pointer.js +0 -279
  149. package/dist/render/pointer.js.map +0 -1
  150. package/dist/render/pools.d.ts +0 -122
  151. package/dist/render/pools.d.ts.map +0 -1
  152. package/dist/render/pools.js +0 -238
  153. package/dist/render/pools.js.map +0 -1
  154. package/dist/render/resolve.d.ts +0 -4
  155. package/dist/render/resolve.d.ts.map +0 -1
  156. package/dist/render/resolve.js +0 -76
  157. package/dist/render/resolve.js.map +0 -1
  158. package/dist/render/saffron.d.ts +0 -135
  159. package/dist/render/saffron.d.ts.map +0 -1
  160. package/dist/render/saffron.js +0 -725
  161. package/dist/render/saffron.js.map +0 -1
  162. package/dist/render/settle.d.ts +0 -60
  163. package/dist/render/settle.d.ts.map +0 -1
  164. package/dist/render/settle.js +0 -128
  165. package/dist/render/settle.js.map +0 -1
  166. package/dist/render/shared.d.ts +0 -25
  167. package/dist/render/shared.d.ts.map +0 -1
  168. package/dist/render/shared.js +0 -33
  169. package/dist/render/shared.js.map +0 -1
  170. package/dist/render/snapshot.d.ts +0 -21
  171. package/dist/render/snapshot.d.ts.map +0 -1
  172. package/dist/render/snapshot.js +0 -91
  173. package/dist/render/snapshot.js.map +0 -1
  174. package/dist/render/spares.d.ts +0 -56
  175. package/dist/render/spares.d.ts.map +0 -1
  176. package/dist/render/spares.js +0 -160
  177. package/dist/render/spares.js.map +0 -1
  178. package/dist/render/strokes.d.ts +0 -107
  179. package/dist/render/strokes.d.ts.map +0 -1
  180. package/dist/render/strokes.js +0 -448
  181. package/dist/render/strokes.js.map +0 -1
  182. package/dist/render/table.d.ts +0 -213
  183. package/dist/render/table.d.ts.map +0 -1
  184. package/dist/render/table.js +0 -795
  185. package/dist/render/table.js.map +0 -1
  186. package/dist/render/tessellate.d.ts +0 -89
  187. package/dist/render/tessellate.d.ts.map +0 -1
  188. package/dist/render/tessellate.js +0 -386
  189. package/dist/render/tessellate.js.map +0 -1
  190. package/dist/render/text.d.ts +0 -40
  191. package/dist/render/text.d.ts.map +0 -1
  192. package/dist/render/text.js +0 -309
  193. package/dist/render/text.js.map +0 -1
  194. package/dist/render/three.d.ts +0 -83
  195. package/dist/render/three.d.ts.map +0 -1
  196. package/dist/render/three.js +0 -511
  197. package/dist/render/three.js.map +0 -1
  198. package/dist/render/triangles.d.ts +0 -28
  199. package/dist/render/triangles.d.ts.map +0 -1
  200. package/dist/render/triangles.js +0 -189
  201. package/dist/render/triangles.js.map +0 -1
  202. package/dist/render/view.d.ts +0 -238
  203. package/dist/render/view.d.ts.map +0 -1
  204. package/dist/render/view.js +0 -1173
  205. package/dist/render/view.js.map +0 -1
  206. package/dist/render/worker/bitmaps.d.ts +0 -43
  207. package/dist/render/worker/bitmaps.d.ts.map +0 -1
  208. package/dist/render/worker/bitmaps.js +0 -151
  209. package/dist/render/worker/bitmaps.js.map +0 -1
  210. package/dist/render/worker/drawing.d.ts +0 -21
  211. package/dist/render/worker/drawing.d.ts.map +0 -1
  212. package/dist/render/worker/drawing.js +0 -356
  213. package/dist/render/worker/drawing.js.map +0 -1
  214. package/dist/render/worker/filters.d.ts +0 -7
  215. package/dist/render/worker/filters.d.ts.map +0 -1
  216. package/dist/render/worker/filters.js +0 -125
  217. package/dist/render/worker/filters.js.map +0 -1
  218. package/dist/render/worker/frames.d.ts +0 -32
  219. package/dist/render/worker/frames.d.ts.map +0 -1
  220. package/dist/render/worker/frames.js +0 -124
  221. package/dist/render/worker/frames.js.map +0 -1
  222. package/dist/render/worker/host.d.ts +0 -60
  223. package/dist/render/worker/host.d.ts.map +0 -1
  224. package/dist/render/worker/host.js +0 -297
  225. package/dist/render/worker/host.js.map +0 -1
  226. package/dist/render/worker/libraries.d.ts +0 -36
  227. package/dist/render/worker/libraries.d.ts.map +0 -1
  228. package/dist/render/worker/libraries.js +0 -153
  229. package/dist/render/worker/libraries.js.map +0 -1
  230. package/dist/render/worker/presentation.d.ts +0 -18
  231. package/dist/render/worker/presentation.d.ts.map +0 -1
  232. package/dist/render/worker/presentation.js +0 -47
  233. package/dist/render/worker/presentation.js.map +0 -1
  234. package/dist/render/worker/renderer.d.ts +0 -4
  235. package/dist/render/worker/renderer.d.ts.map +0 -1
  236. package/dist/render/worker/renderer.js +0 -21
  237. package/dist/render/worker/renderer.js.map +0 -1
  238. package/dist/render/worker/scene.d.ts +0 -32
  239. package/dist/render/worker/scene.d.ts.map +0 -1
  240. package/dist/render/worker/scene.js +0 -611
  241. package/dist/render/worker/scene.js.map +0 -1
  242. package/dist/render/worker/text.d.ts +0 -47
  243. package/dist/render/worker/text.d.ts.map +0 -1
  244. package/dist/render/worker/text.js +0 -261
  245. package/dist/render/worker/text.js.map +0 -1
  246. package/dist/render/worker/thread.d.ts +0 -23
  247. package/dist/render/worker/thread.d.ts.map +0 -1
  248. package/dist/render/worker/thread.js +0 -107
  249. package/dist/render/worker/thread.js.map +0 -1
  250. package/dist/render/worker/values.d.ts +0 -18
  251. package/dist/render/worker/values.d.ts.map +0 -1
  252. package/dist/render/worker/values.js +0 -64
  253. package/dist/render/worker/values.js.map +0 -1
  254. package/dist/sha256.d.ts +0 -5
  255. package/dist/sha256.d.ts.map +0 -1
  256. package/dist/sha256.js +0 -96
  257. package/dist/sha256.js.map +0 -1
  258. package/dist/shapes.d.ts +0 -71
  259. package/dist/shapes.d.ts.map +0 -1
  260. package/dist/shapes.js +0 -340
  261. package/dist/shapes.js.map +0 -1
  262. package/dist/static-text.d.ts +0 -33
  263. package/dist/static-text.d.ts.map +0 -1
  264. package/dist/static-text.js +0 -105
  265. package/dist/static-text.js.map +0 -1
  266. package/dist/text-layout.d.ts +0 -66
  267. package/dist/text-layout.d.ts.map +0 -1
  268. package/dist/text-layout.js +0 -315
  269. package/dist/text-layout.js.map +0 -1
  270. package/dist/text.d.ts +0 -67
  271. package/dist/text.d.ts.map +0 -1
  272. package/dist/text.js +0 -383
  273. package/dist/text.js.map +0 -1
  274. package/dist/timeline.d.ts +0 -150
  275. package/dist/timeline.d.ts.map +0 -1
  276. package/dist/timeline.js +0 -266
  277. package/dist/timeline.js.map +0 -1
@@ -1,725 +0,0 @@
1
- // The pixel operations of BitmapData that read and write its store alone
2
- // (bitmap.ts): each on unmultiplied ARGB as Flash's results show it works,
3
- // the store premultiplying again as it writes. The rules are the ones
4
- // Flash traces under adl and records in Ruffle's corpus.
5
- import { unmultiply } from "./bitmap.js";
6
- const M = 2147483647;
7
- /**
8
- * Flash's noise generator: Park-Miller's minimal standard, x * 16807 mod
9
- * 2^31 - 1, a seed of 0 taken as 1 and one under 0 as -seed + 1 (all 25
10
- * pixels Ruffle's bitmapdata_getvector records of noise(0) match).
11
- */
12
- export class ParkMiller {
13
- x;
14
- constructor(seed) {
15
- let s = seed | 0;
16
- if (s <= 0) {
17
- s = -s + 1;
18
- }
19
- this.x = s % M || 1;
20
- }
21
- next() {
22
- // 16807 * x stays below 2^46: exact in a double.
23
- this.x = (this.x * 16807) % M;
24
- return this.x;
25
- }
26
- }
27
- /**
28
- * noise: each pixel's channels drawn in R, G, B order, then alpha, which
29
- * only a transparent bitmap draws; a grayscale draw is one for all three
30
- * colours, then alpha. A value is low + r % (high - low + 1), high capped
31
- * at 255 and a range upside down giving low. A colour left out is 0, an
32
- * alpha left out 255.
33
- */
34
- export function noise(store, seed, low, high, channels, gray) {
35
- const rng = new ParkMiller(seed);
36
- const lo = Math.max(0, Math.min(255, low));
37
- const hi = Math.max(0, Math.min(255, high));
38
- const span = hi - lo + 1;
39
- const draw = () => (span <= 0 ? lo : lo + (rng.next() % span));
40
- const alpha = (channels & 8) !== 0 && store.transparent;
41
- for (let i = 0; i < store.pixels.length; i++) {
42
- let r = 0;
43
- let g = 0;
44
- let b = 0;
45
- if (gray) {
46
- r = g = b = draw();
47
- }
48
- else {
49
- if (channels & 1) {
50
- r = draw();
51
- }
52
- if (channels & 2) {
53
- g = draw();
54
- }
55
- if (channels & 4) {
56
- b = draw();
57
- }
58
- }
59
- const a = alpha ? draw() : 255;
60
- store.pixels[i] = store.premultiplied(((a << 24) | (r << 16) | (g << 8) | b) >>> 0);
61
- }
62
- store.changed();
63
- }
64
- /** The channel's shift in ARGB: 1 red, 2 green, 4 blue, 8 alpha; -1 for another value. */
65
- function shiftOf(channel) {
66
- switch (channel) {
67
- case 1:
68
- return 16;
69
- case 2:
70
- return 8;
71
- case 4:
72
- return 0;
73
- case 8:
74
- return 24;
75
- default:
76
- return -1;
77
- }
78
- }
79
- /** Each destination pixel's channel set from the source pixel's channel, both unmultiplied. */
80
- export function copyChannel(store, source, rect, dx, dy, from, to) {
81
- const fromShift = shiftOf(from);
82
- const toShift = shiftOf(to);
83
- if (toShift < 0 || (toShift === 24 && !store.transparent)) {
84
- return;
85
- }
86
- // A source of more than one channel, or none, copies 0, as Flash does.
87
- forEachCopied(store, source, rect, dx, dy, (s, d) => {
88
- const v = fromShift < 0 ? 0 : (s >>> fromShift) & 0xff;
89
- return ((d & ~(0xff << toShift)) | (v << toShift)) >>> 0;
90
- });
91
- }
92
- /**
93
- * colorTransform as Flash computes it, fitted under adl: each channel read
94
- * back as p * 255 / a, floored; then (c * floor(mul * 256) >> 8) +
95
- * trunc(offset), clamped to 0..255, the alpha alike; and written
96
- * premultiplied as c * (a + 1) >> 8, not as setPixel32 rounds. A pixel
97
- * of alpha 0 is left as it is; an opaque bitmap's alpha is transformed
98
- * like a transparent one's.
99
- */
100
- export function colorTransform(store, rect, ct) {
101
- const c = store.clip(rect);
102
- if (!c) {
103
- return;
104
- }
105
- const fixed = (m) => Math.trunc(m * 256);
106
- const [rm, gm, bm, am] = [ct.rMul, ct.gMul, ct.bMul, ct.aMul].map(fixed);
107
- const [ro, go, bo, ao] = [ct.rAdd, ct.gAdd, ct.bAdd, ct.aAdd].map(Math.trunc);
108
- const ch = (v, m, o) => Math.max(0, Math.min(255, Math.floor((v * m) / 256) + o));
109
- for (let y = c.y; y < c.y + c.height; y++) {
110
- for (let x = c.x; x < c.x + c.width; x++) {
111
- const i = y * store.width + x;
112
- const p = store.pixels[i];
113
- const a0 = p >>> 24;
114
- // A pixel of alpha 0 is left as it is, offsets and all.
115
- if (a0 === 0) {
116
- continue;
117
- }
118
- const straight = (shift) => a0 === 0 ? 0 : Math.min(255, Math.floor((((p >>> shift) & 0xff) * 255) / a0));
119
- // An opaque bitmap's alpha is transformed too: down to 0, the pixel reads 0.
120
- const a = ch(a0, am, ao);
121
- const r = ch(straight(16), rm, ro);
122
- const g = ch(straight(8), gm, go);
123
- const b = ch(straight(0), bm, bo);
124
- const out = (v) => (a === 255 ? v : (v * (a + 1)) >> 8);
125
- store.pixels[i] = ((a << 24) | (out(r) << 16) | (out(g) << 8) | out(b)) >>> 0;
126
- }
127
- }
128
- store.changed();
129
- }
130
- /**
131
- * merge: each channel ((s * m + d * (256 - m)) >> 8) & 0xFF, unmultiplied,
132
- * the multiplier a uint and nothing clamped, as 18 multipliers from -257
133
- * to 2^32 - 1 show Flash computing it under adl; a double holds the
134
- * product, so the shift is a division.
135
- */
136
- export function merge(store, source, rect, dx, dy, muls) {
137
- const [rm, gm, bm, am] = muls;
138
- const mix = (s, d, shift, m) => Math.floor((((s >>> shift) & 0xff) * m + ((d >>> shift) & 0xff) * (256 - m)) / 256) & 0xff;
139
- forEachCopied(store, source, rect, dx, dy, (s, d) => ((mix(s, d, 24, am) << 24) |
140
- (mix(s, d, 16, rm) << 16) |
141
- (mix(s, d, 8, gm) << 8) |
142
- mix(s, d, 0, bm)) >>>
143
- 0);
144
- }
145
- /**
146
- * The source rect's pixels against the destination's at the point, both
147
- * clipped and unmultiplied, each destination pixel set to what `f` makes
148
- * of the pair; from a copy where the source is the destination.
149
- */
150
- function forEachCopied(store, source, rect, dx, dy, f) {
151
- const s = source.clip(rect);
152
- if (!s) {
153
- return;
154
- }
155
- dx += s.x - rect.x;
156
- dy += s.y - rect.y;
157
- const d = store.clip({ x: dx, y: dy, width: s.width, height: s.height });
158
- if (!d) {
159
- return;
160
- }
161
- const sx = s.x + (d.x - dx);
162
- const sy = s.y + (d.y - dy);
163
- const [pixels, pw, ox, oy] = readFrom(source, store, sx, sy, d.width, d.height);
164
- for (let row = 0; row < d.height; row++) {
165
- for (let i = 0; i < d.width; i++) {
166
- const to = (d.y + row) * store.width + d.x + i;
167
- const p = unmultiply(pixels[(sy - oy + row) * pw + sx - ox + i]);
168
- store.pixels[to] = store.premultiplied(f(p, unmultiply(store.pixels[to])));
169
- }
170
- }
171
- store.changed();
172
- }
173
- /** scroll: the pixels moved by (x, y); what nothing moved onto keeps its old pixels. */
174
- export function scroll(store, x, y) {
175
- const { width, height } = store;
176
- const old = store.pixels.slice();
177
- for (let row = 0; row < height; row++) {
178
- const sy = row - y;
179
- if (sy < 0 || sy >= height) {
180
- continue;
181
- }
182
- for (let col = 0; col < width; col++) {
183
- const sx = col - x;
184
- if (sx >= 0 && sx < width) {
185
- store.pixels[row * width + col] = old[sy * width + sx];
186
- }
187
- }
188
- }
189
- store.changed();
190
- }
191
- const OPERATIONS = {
192
- "<": (a, b) => a < b,
193
- "<=": (a, b) => a <= b,
194
- ">": (a, b) => a > b,
195
- ">=": (a, b) => a >= b,
196
- "==": (a, b) => a === b,
197
- "!=": (a, b) => a !== b,
198
- };
199
- /** Whether `op` is one threshold takes. */
200
- export function isThresholdOperation(op) {
201
- // Its own keys only: "constructor" and the rest of Object's are not operations.
202
- return Object.hasOwn(OPERATIONS, op);
203
- }
204
- /**
205
- * threshold: each source pixel, unmultiplied and masked, compared with the
206
- * masked threshold as unsigned numbers; where the test holds the
207
- * destination pixel becomes `color`, elsewhere the source pixel if
208
- * `copySource`; how many held.
209
- */
210
- export function threshold(store, source, rect, dx, dy, op, value, color, mask, copySource) {
211
- const test = OPERATIONS[op];
212
- const target = (value & mask) >>> 0;
213
- let count = 0;
214
- const s = source.clip(rect);
215
- if (!s) {
216
- return 0;
217
- }
218
- dx += s.x - rect.x;
219
- dy += s.y - rect.y;
220
- const d = store.clip({ x: dx, y: dy, width: s.width, height: s.height });
221
- if (!d) {
222
- return 0;
223
- }
224
- const sx = s.x + (d.x - dx);
225
- const sy = s.y + (d.y - dy);
226
- const [pixels, pw, ox, oy] = readFrom(source, store, sx, sy, d.width, d.height);
227
- const fill = store.premultiplied(color >>> 0);
228
- for (let row = 0; row < d.height; row++) {
229
- for (let i = 0; i < d.width; i++) {
230
- const to = (d.y + row) * store.width + d.x + i;
231
- const raw = pixels[(sy - oy + row) * pw + sx - ox + i];
232
- if (test((unmultiply(raw) & mask) >>> 0, target)) {
233
- store.pixels[to] = fill;
234
- count++;
235
- }
236
- else if (copySource) {
237
- store.pixels[to] = store.transparent ? raw : (raw | 0xff000000) >>> 0;
238
- }
239
- }
240
- }
241
- store.changed();
242
- return count;
243
- }
244
- /**
245
- * getColorBoundsRect: the smallest rect holding every pixel whose
246
- * unmultiplied value, masked, is `color` (or is not, without findColor);
247
- * empty where none is, and where the one found is the pixel at the
248
- * origin alone, as Flash has it (Ruffle's bitmap_data).
249
- */
250
- export function colorBounds(store, mask, color, find) {
251
- let x0 = store.width;
252
- let y0 = store.height;
253
- let x1 = -1;
254
- let y1 = -1;
255
- const target = (color & mask) >>> 0;
256
- for (let y = 0; y < store.height; y++) {
257
- for (let x = 0; x < store.width; x++) {
258
- const hit = (unmultiply(store.pixels[y * store.width + x]) & mask) >>> 0 === target;
259
- if (hit === find) {
260
- x0 = Math.min(x0, x);
261
- y0 = Math.min(y0, y);
262
- x1 = Math.max(x1, x);
263
- y1 = Math.max(y1, y);
264
- }
265
- }
266
- }
267
- // Flash takes extents that end at the origin for none found: a lone hit at (0, 0) gives an empty rect.
268
- return x1 <= 0 && y1 <= 0
269
- ? { x: 0, y: 0, width: 0, height: 0 }
270
- : { x: x0, y: y0, width: x1 - x0 + 1, height: y1 - y0 + 1 };
271
- }
272
- /** floodFill: the 4-connected region of the start pixel's exact value set to `color`. */
273
- export function floodFill(store, x, y, color) {
274
- const { width, height } = store;
275
- if (x < 0 || y < 0 || x >= width || y >= height) {
276
- return;
277
- }
278
- const from = store.pixels[y * width + x];
279
- const to = store.premultiplied(color >>> 0);
280
- if (from === to) {
281
- return;
282
- }
283
- const stack = [y * width + x];
284
- while (stack.length) {
285
- const i = stack.pop();
286
- if (store.pixels[i] !== from) {
287
- continue;
288
- }
289
- store.pixels[i] = to;
290
- const px = i % width;
291
- if (px > 0) {
292
- stack.push(i - 1);
293
- }
294
- if (px < width - 1) {
295
- stack.push(i + 1);
296
- }
297
- if (i >= width) {
298
- stack.push(i - width);
299
- }
300
- if (i + width < width * height) {
301
- stack.push(i + width);
302
- }
303
- }
304
- store.changed();
305
- }
306
- /** histogram: four arrays of 256 counts, red, green, blue and alpha, of the rect's unmultiplied pixels. */
307
- export function histogram(store, rect) {
308
- const counts = [0, 1, 2, 3].map(() => new Array(256).fill(0));
309
- const c = store.clip(rect);
310
- if (!c) {
311
- return counts;
312
- }
313
- for (let y = c.y; y < c.y + c.height; y++) {
314
- for (let x = c.x; x < c.x + c.width; x++) {
315
- const p = unmultiply(store.pixels[y * store.width + x]);
316
- counts[0][(p >>> 16) & 0xff]++;
317
- counts[1][(p >>> 8) & 0xff]++;
318
- counts[2][p & 0xff]++;
319
- counts[3][p >>> 24]++;
320
- }
321
- }
322
- return counts;
323
- }
324
- /** The unmultiplied alpha at (x, y), or -1 outside. */
325
- export function alphaAt(store, x, y) {
326
- if (x < 0 || y < 0 || x >= store.width || y >= store.height) {
327
- return -1;
328
- }
329
- return store.pixels[y * store.width + x] >>> 24;
330
- }
331
- /**
332
- * Flash's pixelDissolve taps, by the state's width in bits: a Galois LFSR,
333
- * s >> 1, xor the tap where s was odd, read off adl for every width a
334
- * BitmapData can have (2 to 26 bits).
335
- */
336
- const DISSOLVE_TAPS = [
337
- 0, 0, 3, 6, 12, 20, 48, 96, 184, 272, 576, 1280, 3232, 6912, 13568, 24576, 46080, 73728, 132096,
338
- 466944, 589824, 1310720, 3145728, 4325376, 14155776, 18874368, 59244544,
339
- ];
340
- /** Bits to number 0..n - 1: ceil(log2(n)). */
341
- function bitsFor(n) {
342
- return n <= 1 ? 0 : 32 - Math.clz32(n - 1);
343
- }
344
- /**
345
- * pixelDissolve as Flash does it, fitted under adl: a state of
346
- * ceil(log2 w) + ceil(log2 h) bits stands for the pixel (s & (2^bw - 1),
347
- * s >> bw) of the rect, a state outside it skipped; each call writes
348
- * numPixels pixels, from the seed on, and returns the state after the
349
- * last, raw, so the next call goes on from there. Every call writes the
350
- * pixel at the origin too, which no state stands for, and so n calls of
351
- * 1 write n + 1 (Ruffle's bitmapdata_pixeldissolve); a seed past the
352
- * generator's states is taken modulo 2^bits - 1, and 0 starts at the tap. A
353
- * pixel takes the fill colour where the source is the destination, else
354
- * the source's; a rect a pixel high or wide dissolves nothing.
355
- */
356
- export function pixelDissolve(store, source, rect, dx, dy, seed, count, fill) {
357
- // Over the rect clipped to the source and then to the destination, as the copies are.
358
- const sc = source.clip(rect);
359
- if (!sc) {
360
- return 0;
361
- }
362
- const ox = dx + (sc.x - rect.x);
363
- const oy = dy + (sc.y - rect.y);
364
- const dc = store.clip({ x: ox, y: oy, width: sc.width, height: sc.height });
365
- if (!dc) {
366
- return 0;
367
- }
368
- const rx = sc.x + (dc.x - ox);
369
- const ry = sc.y + (dc.y - oy);
370
- dx = dc.x;
371
- dy = dc.y;
372
- const { width: w, height: h } = dc;
373
- if (w <= 1 || h <= 1) {
374
- return 0;
375
- }
376
- const bw = bitsFor(w);
377
- const bits = bw + bitsFor(h);
378
- const tap = DISSOLVE_TAPS[bits] ?? 0;
379
- const mask = 2 ** bits - 1;
380
- const xMask = (1 << bw) - 1;
381
- const color = store.premultiplied(fill >>> 0);
382
- const next = (s) => (s & 1 ? Math.floor(s / 2) ^ tap : Math.floor(s / 2));
383
- // A position of the rect, written where it lies in both bitmaps.
384
- const write = (state) => {
385
- const px = state & xMask;
386
- const py = Math.floor(state / 2 ** bw);
387
- const sx = rx + px;
388
- const sy = ry + py;
389
- const tx = dx + px;
390
- const ty = dy + py;
391
- if (sx < 0 ||
392
- sy < 0 ||
393
- sx >= source.width ||
394
- sy >= source.height ||
395
- tx < 0 ||
396
- ty < 0 ||
397
- tx >= store.width ||
398
- ty >= store.height) {
399
- return;
400
- }
401
- store.pixels[ty * store.width + tx] =
402
- source === store ? color : source.pixels[sy * source.width + sx];
403
- };
404
- const inside = (state) => (state & xMask) < w && Math.floor(state / 2 ** bw) < h;
405
- // The origin is written on every call; the seed is reduced to the
406
- // generator's period, and 0, which it never reaches, starts at the tap.
407
- write(0);
408
- const start = Math.abs(Math.trunc(seed));
409
- let s = start > mask ? start % mask : start;
410
- if (s === 0) {
411
- s = tap;
412
- }
413
- // The states inside the rect come round every w * h - 1 writes (state 0
414
- // is the origin's, reached from seed 0 alone), so a count past that is
415
- // one full round, which writes every pixel, and the remainder: the same
416
- // pixels and the seed Flash returns, without its seconds-long loop.
417
- const round = w * h - 1;
418
- const steps = count > round ? round + (count % round) : count;
419
- for (let k = 0; k < steps; k++) {
420
- // Every state but 0 comes round within 2^bits steps, so this ends.
421
- while (!inside(s)) {
422
- s = next(s);
423
- }
424
- write(s);
425
- s = next(s);
426
- }
427
- store.changed();
428
- return s;
429
- }
430
- /**
431
- * The pixels a copy reads, with their row width and origin: the source's
432
- * own, or where the source is the destination, a copy of the rect alone,
433
- * so a one-pixel operation does not copy the whole store.
434
- */
435
- function readFrom(source, store, x, y, w, h) {
436
- if (source !== store) {
437
- return [source.pixels, source.width, 0, 0];
438
- }
439
- const copy = new Uint32Array(w * h);
440
- for (let row = 0; row < h; row++) {
441
- const from = (y + row) * source.width + x;
442
- copy.set(source.pixels.subarray(from, from + w), row * w);
443
- }
444
- return [copy, w, x, y];
445
- }
446
- /** The blend modes draw composites with; alpha and erase need a layer, which a bitmap drawn has not, and do nothing. */
447
- const BLENDS = new Set([
448
- "normal",
449
- "layer",
450
- "multiply",
451
- "screen",
452
- "lighten",
453
- "darken",
454
- "difference",
455
- "add",
456
- "subtract",
457
- "invert",
458
- "overlay",
459
- "hardlight",
460
- ]);
461
- /**
462
- * draw of a bitmap source: each destination pixel in the clip takes the
463
- * source pixel under its centre, through the matrix's inverse, clamped to
464
- * the source's edges (bilinear when smoothing), scaled by how much of the
465
- * pixel the transformed source covers (a 4 x 4 sample grid), passed
466
- * through the colour transform as colorTransform does, and composited by
467
- * the blend mode. Flash's own pixels, under adl: nearest at the centre,
468
- * normal as the store's source-over, alpha and erase as nothing.
469
- */
470
- export function drawBitmap(store, source, m, ct, mode, clip, smooth, rows = false) {
471
- if (!BLENDS.has(mode)) {
472
- return;
473
- }
474
- // Flash rasterises the translation snapped down to quarter pixels, which
475
- // its 4 x 4 coverage then reads exactly (a move of 0.49 covers 3/4 and
476
- // 1/4 of the edge pixels under adl).
477
- m = { ...m, tx: Math.floor(m.tx * 4) / 4, ty: Math.floor(m.ty * 4) / 4 };
478
- const det = m.a * m.d - m.b * m.c;
479
- if (det === 0) {
480
- return;
481
- }
482
- // The destination pixels the source can reach: its corners through the matrix.
483
- const corners = [
484
- [0, 0],
485
- [source.width, 0],
486
- [0, source.height],
487
- [source.width, source.height],
488
- ].map(([x, y]) => [m.a * x + m.c * y + m.tx, m.b * x + m.d * y + m.ty]);
489
- const xs = corners.map((p) => p[0]);
490
- const ys = corners.map((p) => p[1]);
491
- let area = store.clip({
492
- x: Math.floor(Math.min(...xs)),
493
- y: Math.floor(Math.min(...ys)),
494
- width: Math.ceil(Math.max(...xs)) - Math.floor(Math.min(...xs)),
495
- height: Math.ceil(Math.max(...ys)) - Math.floor(Math.min(...ys)),
496
- });
497
- if (area && clip) {
498
- area = store.clip({
499
- x: Math.max(area.x, clip.x),
500
- y: Math.max(area.y, clip.y),
501
- width: Math.min(area.x + area.width, clip.x + clip.width) - Math.max(area.x, clip.x),
502
- height: Math.min(area.y + area.height, clip.y + clip.height) - Math.max(area.y, clip.y),
503
- });
504
- }
505
- if (!area) {
506
- return;
507
- }
508
- // Unscaled at a whole pixel, as every snapshot of a display object is
509
- // composited: each covered pixel is covered whole and is the source's
510
- // own, so it is copied straight, as the general path below would.
511
- if (m.a === 1 &&
512
- m.b === 0 &&
513
- m.c === 0 &&
514
- m.d === 1 &&
515
- Number.isInteger(m.tx) &&
516
- Number.isInteger(m.ty) &&
517
- source !== store) {
518
- composite(store, source, area, m.tx, m.ty, ct, mode);
519
- store.changed();
520
- return;
521
- }
522
- // The inverse: from a destination point to the source's.
523
- const ia = m.d / det;
524
- const ib = -m.b / det;
525
- const ic = -m.c / det;
526
- const id = m.a / det;
527
- const itx = -(ia * m.tx + ic * m.ty);
528
- const ity = -(ib * m.tx + id * m.ty);
529
- const inside = (x, y) => {
530
- const sx = ia * x + ic * y + itx;
531
- const sy = ib * x + id * y + ity;
532
- return sx >= 0 && sy >= 0 && sx < source.width && sy < source.height;
533
- };
534
- // Drawn into itself, a BitmapData goes a row at a time, top down, every
535
- // pixel of the row read before one is written, as Flash does: a move
536
- // right keeps the pixels, a move down smears rows. Through a Bitmap of
537
- // itself it is plain scan order, which smears both ways (adl).
538
- const row = rows && source === store ? new Uint32Array(area.width) : null;
539
- const written = row ? new Uint8Array(area.width) : null;
540
- for (let y = area.y; y < area.y + area.height; y++) {
541
- if (row && written) {
542
- written.fill(0);
543
- }
544
- for (let x = area.x; x < area.x + area.width; x++) {
545
- let hits = 0;
546
- for (let k = 0; k < 16; k++) {
547
- if (inside(x + ((k & 3) + 0.5) / 4, y + ((k >> 2) + 0.5) / 4)) {
548
- hits++;
549
- }
550
- }
551
- if (hits === 0) {
552
- continue;
553
- }
554
- const cx = x + 0.5;
555
- const cy = y + 0.5;
556
- const sx = ia * cx + ic * cy + itx;
557
- const sy = ib * cx + id * cy + ity;
558
- let p = smooth ? bilinear(source, sx - 0.5, sy - 0.5) : nearest(source, sx, sy);
559
- if (ct) {
560
- p = transformed(p, ct);
561
- }
562
- if (hits < 16) {
563
- p = scaleBy(p, hits / 16);
564
- }
565
- if (row && written) {
566
- row[x - area.x] = p;
567
- written[x - area.x] = 1;
568
- continue;
569
- }
570
- put(store, y * store.width + x, mode, p);
571
- }
572
- if (row && written) {
573
- for (let k = 0; k < area.width; k++) {
574
- if (written[k]) {
575
- put(store, y * store.width + area.x + k, mode, row[k]);
576
- }
577
- }
578
- }
579
- }
580
- store.changed();
581
- }
582
- /** `source` at (tx, ty) composited into `area` of the store, a pixel each. */
583
- function composite(store, source, area, tx, ty, ct, mode) {
584
- const into = store.pixels;
585
- const from = source.pixels;
586
- const opaque = store.transparent ? 0 : 0xff000000;
587
- const plain = !ct && mode === "normal";
588
- for (let y = area.y; y < area.y + area.height; y++) {
589
- let i = y * store.width + area.x;
590
- let j = (y - ty) * source.width + (area.x - tx);
591
- for (let x = 0; x < area.width; x++, i++, j++) {
592
- const p = from[j];
593
- if (plain) {
594
- // Source over, inline: what blend("normal") computes.
595
- const sa = p >>> 24;
596
- if (sa === 0) {
597
- continue;
598
- }
599
- if (sa === 255) {
600
- into[i] = p;
601
- continue;
602
- }
603
- into[i] = (sourceOver(p, into[i]) | opaque) >>> 0;
604
- continue;
605
- }
606
- put(store, i, mode, ct ? transformed(p, ct) : p);
607
- }
608
- }
609
- }
610
- /** A drawn pixel composited into the store by the blend mode, opaque where the store is. */
611
- function put(store, i, mode, p) {
612
- const out = blend(mode, p, store.pixels[i]);
613
- store.pixels[i] = store.transparent ? out : (out | 0xff000000) >>> 0;
614
- }
615
- function nearest(source, x, y) {
616
- const px = Math.min(source.width - 1, Math.max(0, Math.floor(x)));
617
- const py = Math.min(source.height - 1, Math.max(0, Math.floor(y)));
618
- return source.pixels[py * source.width + px];
619
- }
620
- /** Bilinear between the four premultiplied pixels round (x, y), clamped to the edges. */
621
- function bilinear(source, x, y) {
622
- const x0 = Math.floor(x);
623
- const y0 = Math.floor(y);
624
- const fx = x - x0;
625
- const fy = y - y0;
626
- const at = (px, py) => source.pixels[Math.min(source.height - 1, Math.max(0, py)) * source.width +
627
- Math.min(source.width - 1, Math.max(0, px))];
628
- const p00 = at(x0, y0);
629
- const p10 = at(x0 + 1, y0);
630
- const p01 = at(x0, y0 + 1);
631
- const p11 = at(x0 + 1, y0 + 1);
632
- let out = 0;
633
- for (const shift of [24, 16, 8, 0]) {
634
- const v = (p) => (p >>> shift) & 0xff;
635
- const top = v(p00) * (1 - fx) + v(p10) * fx;
636
- const bottom = v(p01) * (1 - fx) + v(p11) * fx;
637
- out |= Math.round(top * (1 - fy) + bottom * fy) << shift;
638
- }
639
- return out >>> 0;
640
- }
641
- /** A premultiplied pixel through a colour transform, as colorTransform computes it. */
642
- function transformed(p, ct) {
643
- const a0 = p >>> 24;
644
- if (a0 === 0 && ct.aAdd <= 0) {
645
- return 0;
646
- }
647
- const fixed = (v) => Math.trunc(v * 256);
648
- const ch = (v, mul, add) => Math.max(0, Math.min(255, Math.floor((v * fixed(mul)) / 256) + Math.trunc(add)));
649
- const straight = (shift) => a0 === 0 ? 0 : Math.min(255, Math.floor((((p >>> shift) & 0xff) * 255) / a0));
650
- const a = ch(a0, ct.aMul, ct.aAdd);
651
- const out = (v) => (a === 255 ? v : (v * (a + 1)) >> 8);
652
- return (((a << 24) |
653
- (out(ch(straight(16), ct.rMul, ct.rAdd)) << 16) |
654
- (out(ch(straight(8), ct.gMul, ct.gAdd)) << 8) |
655
- out(ch(straight(0), ct.bMul, ct.bAdd))) >>>
656
- 0);
657
- }
658
- /** A premultiplied pixel with all four channels scaled by a coverage. */
659
- function scaleBy(p, f) {
660
- let out = 0;
661
- for (const shift of [24, 16, 8, 0]) {
662
- out |= Math.round(((p >>> shift) & 0xff) * f) << shift;
663
- }
664
- return out >>> 0;
665
- }
666
- /** Premultiplied s over d by a blend mode, the W3C's compositing with each mode's mix. */
667
- function blend(mode, s, d) {
668
- const sa = s >>> 24;
669
- if (mode === "normal" || mode === "layer") {
670
- return sourceOver(s, d);
671
- }
672
- const da = d >>> 24;
673
- const mul = (x, y) => (x * y + 127) / 255;
674
- const channel = (shift) => {
675
- const cs = (s >>> shift) & 0xff;
676
- const cd = (d >>> shift) & 0xff;
677
- let b;
678
- switch (mode) {
679
- case "multiply":
680
- b = mul(cs, cd);
681
- break;
682
- case "screen":
683
- b = (cs * da) / 255 + (cd * sa) / 255 - mul(cs, cd);
684
- break;
685
- case "lighten":
686
- b = Math.max(mul(cs, da), mul(cd, sa));
687
- break;
688
- case "darken":
689
- b = Math.min(mul(cs, da), mul(cd, sa));
690
- break;
691
- case "difference":
692
- b = Math.abs(mul(cs, da) - mul(cd, sa));
693
- break;
694
- case "add":
695
- return Math.min(255, cs + cd);
696
- case "subtract":
697
- return Math.max(0, cd - cs);
698
- case "invert":
699
- // The destination inverted, the source's colour unused.
700
- return Math.max(0, Math.min(255, Math.floor(mul(255 - cd, sa) + mul(cd, 255 - sa))));
701
- case "overlay":
702
- b = 2 * cd <= da ? 2 * mul(cs, cd) : mul(sa, da) - 2 * mul(da - cd, sa - cs);
703
- break;
704
- default:
705
- b = 2 * cs <= sa ? 2 * mul(cs, cd) : mul(sa, da) - 2 * mul(da - cd, sa - cs);
706
- break;
707
- }
708
- return Math.max(0, Math.min(255, Math.floor(b + mul(cs, 255 - da) + mul(cd, 255 - sa))));
709
- };
710
- const a = mode === "add" || mode === "subtract"
711
- ? Math.min(255, sa + da)
712
- : Math.min(255, Math.round(sa + da - mul(sa, da)));
713
- return ((a << 24) | (channel(16) << 16) | (channel(8) << 8) | channel(0)) >>> 0;
714
- }
715
- /** Source over destination, both premultiplied, as Flash composites: s + ((d * (256 - sa)) >> 8). */
716
- function sourceOver(s, d) {
717
- const sa = s >>> 24;
718
- if (sa === 255) {
719
- return s >>> 0;
720
- }
721
- const k = 256 - sa;
722
- const ch = (shift) => Math.min(255, ((s >>> shift) & 0xff) + ((((d >>> shift) & 0xff) * k) >> 8));
723
- return ((ch(24) << 24) | (ch(16) << 16) | (ch(8) << 8) | ch(0)) >>> 0;
724
- }
725
- //# sourceMappingURL=bitmap-ops.js.map