elit 3.6.6 → 3.6.7

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 (153) hide show
  1. package/Cargo.lock +1 -1
  2. package/Cargo.toml +1 -1
  3. package/dist/build.cjs +421 -331
  4. package/dist/build.d.ts +1 -19
  5. package/dist/build.js +420 -330
  6. package/dist/build.mjs +420 -330
  7. package/dist/chokidar.cjs +219 -182
  8. package/dist/chokidar.d.ts +25 -10
  9. package/dist/chokidar.js +217 -182
  10. package/dist/chokidar.mjs +218 -183
  11. package/dist/cli.cjs +22439 -21563
  12. package/dist/cli.d.ts +19 -37
  13. package/dist/cli.mjs +24113 -23252
  14. package/dist/config.cjs +357 -350
  15. package/dist/config.d.ts +17 -245
  16. package/dist/config.js +520 -515
  17. package/dist/config.mjs +346 -341
  18. package/dist/contracts-BeW9k0yZ.d.ts +54 -0
  19. package/dist/contracts-D7KIS-TK.d.ts +36 -0
  20. package/dist/coverage.cjs +448 -485
  21. package/dist/coverage.d.ts +13 -62
  22. package/dist/coverage.js +447 -484
  23. package/dist/coverage.mjs +447 -484
  24. package/dist/database.cjs +819 -828
  25. package/dist/database.d.ts +8 -24
  26. package/dist/database.js +818 -829
  27. package/dist/database.mjs +818 -829
  28. package/dist/desktop-auto-render.cjs +1700 -1523
  29. package/dist/desktop-auto-render.d.ts +4 -12
  30. package/dist/desktop-auto-render.js +1695 -1518
  31. package/dist/desktop-auto-render.mjs +1696 -1519
  32. package/dist/desktop.cjs +3 -1
  33. package/dist/desktop.d.ts +4 -1
  34. package/dist/desktop.js +1 -1
  35. package/dist/desktop.mjs +1 -1
  36. package/dist/dev-build.cjs +830 -0
  37. package/dist/dev-build.d.ts +53 -0
  38. package/dist/dev-build.js +3318 -0
  39. package/dist/dev-build.mjs +797 -0
  40. package/dist/dom.cjs +717 -591
  41. package/dist/dom.d.ts +2 -17
  42. package/dist/dom.js +714 -588
  43. package/dist/dom.mjs +716 -590
  44. package/dist/el.cjs +62 -52
  45. package/dist/el.d.ts +5 -12
  46. package/dist/el.js +60 -52
  47. package/dist/el.mjs +60 -52
  48. package/dist/fs.cjs +72 -63
  49. package/dist/fs.d.ts +22 -19
  50. package/dist/fs.js +71 -62
  51. package/dist/fs.mjs +71 -62
  52. package/dist/hmr.cjs +40 -14
  53. package/dist/hmr.d.ts +11 -23
  54. package/dist/hmr.js +38 -14
  55. package/dist/hmr.mjs +38 -14
  56. package/dist/http.cjs +251 -99
  57. package/dist/http.d.ts +38 -104
  58. package/dist/http.js +249 -99
  59. package/dist/http.mjs +249 -99
  60. package/dist/https.cjs +524 -228
  61. package/dist/https.d.ts +44 -36
  62. package/dist/https.js +520 -226
  63. package/dist/https.mjs +522 -228
  64. package/dist/index.cjs +7502 -7691
  65. package/dist/index.d.ts +6 -3
  66. package/dist/index.js +7486 -7677
  67. package/dist/index.mjs +7497 -7687
  68. package/dist/mime-types.cjs +10 -4
  69. package/dist/mime-types.d.ts +8 -11
  70. package/dist/mime-types.js +9 -3
  71. package/dist/mime-types.mjs +9 -3
  72. package/dist/native.cjs +8616 -8870
  73. package/dist/native.d.ts +7 -10
  74. package/dist/native.js +8682 -8936
  75. package/dist/native.mjs +8615 -8869
  76. package/dist/path.cjs +83 -77
  77. package/dist/path.d.ts +29 -29
  78. package/dist/path.js +82 -76
  79. package/dist/path.mjs +82 -76
  80. package/dist/pm.cjs +3300 -0
  81. package/dist/pm.d.ts +256 -0
  82. package/dist/pm.js +5638 -0
  83. package/dist/pm.mjs +3196 -0
  84. package/dist/preview-build.cjs +712 -0
  85. package/dist/preview-build.d.ts +59 -0
  86. package/dist/preview-build.js +3194 -0
  87. package/dist/preview-build.mjs +676 -0
  88. package/dist/render-context.cjs +13 -2
  89. package/dist/render-context.d.ts +9 -34
  90. package/dist/render-context.js +11 -2
  91. package/dist/render-context.mjs +11 -2
  92. package/dist/router.cjs +787 -646
  93. package/dist/router.d.ts +8 -14
  94. package/dist/router.js +786 -645
  95. package/dist/router.mjs +786 -645
  96. package/dist/runtime.cjs +1 -1
  97. package/dist/runtime.js +1 -1
  98. package/dist/runtime.mjs +1 -1
  99. package/dist/server.cjs +3254 -2684
  100. package/dist/server.d.ts +47 -5
  101. package/dist/server.js +3427 -2859
  102. package/dist/server.mjs +3397 -2829
  103. package/dist/smtp-server.cjs +16 -3
  104. package/dist/smtp-server.d.ts +12 -26
  105. package/dist/smtp-server.js +18 -5
  106. package/dist/smtp-server.mjs +16 -3
  107. package/dist/state-DvEkDehk.d.ts +195 -0
  108. package/dist/state.cjs +768 -659
  109. package/dist/state.d.ts +11 -71
  110. package/dist/state.js +760 -651
  111. package/dist/state.mjs +767 -658
  112. package/dist/style.cjs +1011 -968
  113. package/dist/style.d.ts +13 -127
  114. package/dist/style.js +1009 -970
  115. package/dist/style.mjs +1011 -971
  116. package/dist/test-reporter.cjs +332 -316
  117. package/dist/test-reporter.d.ts +28 -33
  118. package/dist/test-reporter.js +328 -312
  119. package/dist/test-reporter.mjs +328 -312
  120. package/dist/test-runtime.cjs +927 -968
  121. package/dist/test-runtime.d.ts +24 -99
  122. package/dist/test-runtime.js +922 -965
  123. package/dist/test-runtime.mjs +922 -965
  124. package/dist/test.cjs +4428 -4273
  125. package/dist/test.d.ts +2 -8
  126. package/dist/test.js +4307 -4154
  127. package/dist/test.mjs +4419 -4267
  128. package/dist/types-BONVzPtp.d.ts +59 -0
  129. package/dist/types-BR4wMiVx.d.ts +32 -0
  130. package/dist/types-C4gKykuG.d.ts +23 -0
  131. package/dist/types-CIhpN1-K.d.ts +64 -0
  132. package/dist/types-Ckj8md_j.d.ts +84 -0
  133. package/dist/types-CpjQTAkX.d.ts +24 -0
  134. package/dist/types-D0LjrYjS.d.ts +14 -0
  135. package/dist/types-DAisuVr5.d.ts +75 -0
  136. package/dist/types-tJn88E1N.d.ts +242 -0
  137. package/dist/types.d.ts +50 -237
  138. package/dist/universal.cjs +1 -1
  139. package/dist/universal.d.ts +1 -7
  140. package/dist/universal.js +1 -1
  141. package/dist/universal.mjs +1 -1
  142. package/dist/websocket-XfyK23zD.d.ts +119 -0
  143. package/dist/ws.cjs +129 -108
  144. package/dist/ws.d.ts +21 -131
  145. package/dist/ws.js +128 -109
  146. package/dist/ws.mjs +128 -109
  147. package/dist/wss.cjs +757 -479
  148. package/dist/wss.d.ts +31 -28
  149. package/dist/wss.js +755 -479
  150. package/dist/wss.mjs +758 -482
  151. package/package.json +8 -1
  152. package/vendor/epaint-0.31.1/src/image.rs +418 -0
  153. package/dist/server-uMQvZAll.d.ts +0 -458
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "elit",
3
- "version": "3.6.6",
3
+ "version": "3.6.7",
4
4
  "description": "Optimized lightweight library for creating DOM elements with reactive state",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -143,6 +143,12 @@
143
143
  "import": "./dist/runtime.mjs",
144
144
  "require": "./dist/runtime.cjs"
145
145
  },
146
+ "./pm": {
147
+ "types": "./dist/pm.d.ts",
148
+ "browser": "./dist/pm.js",
149
+ "import": "./dist/pm.mjs",
150
+ "require": "./dist/pm.cjs"
151
+ },
146
152
  "./database": {
147
153
  "types": "./dist/database.d.ts",
148
154
  "browser": "./dist/database.js",
@@ -285,6 +291,7 @@
285
291
  "dist/*.d.ts",
286
292
  "dist/*.js",
287
293
  "desktop",
294
+ "vendor",
288
295
  "Cargo.toml",
289
296
  "Cargo.lock",
290
297
  "README.md",
@@ -0,0 +1,418 @@
1
+ use crate::{textures::TextureOptions, Color32};
2
+ use std::sync::Arc;
3
+
4
+ /// An image stored in RAM.
5
+ ///
6
+ /// To load an image file, see [`ColorImage::from_rgba_unmultiplied`].
7
+ ///
8
+ /// In order to paint the image on screen, you first need to convert it to
9
+ ///
10
+ /// See also: [`ColorImage`], [`FontImage`].
11
+ #[derive(Clone, PartialEq)]
12
+ #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
13
+ pub enum ImageData {
14
+ /// RGBA image.
15
+ Color(Arc<ColorImage>),
16
+
17
+ /// Used for the font texture.
18
+ Font(FontImage),
19
+ }
20
+
21
+ impl ImageData {
22
+ pub fn size(&self) -> [usize; 2] {
23
+ match self {
24
+ Self::Color(image) => image.size,
25
+ Self::Font(image) => image.size,
26
+ }
27
+ }
28
+
29
+ pub fn width(&self) -> usize {
30
+ self.size()[0]
31
+ }
32
+
33
+ pub fn height(&self) -> usize {
34
+ self.size()[1]
35
+ }
36
+
37
+ pub fn bytes_per_pixel(&self) -> usize {
38
+ match self {
39
+ Self::Color(_) | Self::Font(_) => 4,
40
+ }
41
+ }
42
+ }
43
+
44
+ // ----------------------------------------------------------------------------
45
+
46
+ /// A 2D RGBA color image in RAM.
47
+ #[derive(Clone, Default, PartialEq, Eq)]
48
+ #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
49
+ pub struct ColorImage {
50
+ /// width, height.
51
+ pub size: [usize; 2],
52
+
53
+ /// The pixels, row by row, from top to bottom.
54
+ pub pixels: Vec<Color32>,
55
+ }
56
+
57
+ impl ColorImage {
58
+ /// Create an image filled with the given color.
59
+ pub fn new(size: [usize; 2], color: Color32) -> Self {
60
+ Self {
61
+ size,
62
+ pixels: vec![color; size[0] * size[1]],
63
+ }
64
+ }
65
+
66
+ /// Create a [`ColorImage`] from flat un-multiplied RGBA data.
67
+ ///
68
+ /// This is usually what you want to use after having loaded an image file.
69
+ ///
70
+ /// Panics if `size[0] * size[1] * 4 != rgba.len()`.
71
+ ///
72
+ /// ## Example using the [`image`](crates.io/crates/image) crate:
73
+ /// ``` ignore
74
+ /// fn load_image_from_path(path: &std::path::Path) -> Result<egui::ColorImage, image::ImageError> {
75
+ /// let image = image::io::Reader::open(path)?.decode()?;
76
+ /// let size = [image.width() as _, image.height() as _];
77
+ /// let image_buffer = image.to_rgba8();
78
+ /// let pixels = image_buffer.as_flat_samples();
79
+ /// Ok(egui::ColorImage::from_rgba_unmultiplied(
80
+ /// size,
81
+ /// pixels.as_slice(),
82
+ /// ))
83
+ /// }
84
+ ///
85
+ /// fn load_image_from_memory(image_data: &[u8]) -> Result<ColorImage, image::ImageError> {
86
+ /// let image = image::load_from_memory(image_data)?;
87
+ /// let size = [image.width() as _, image.height() as _];
88
+ /// let image_buffer = image.to_rgba8();
89
+ /// let pixels = image_buffer.as_flat_samples();
90
+ /// Ok(ColorImage::from_rgba_unmultiplied(
91
+ /// size,
92
+ /// pixels.as_slice(),
93
+ /// ))
94
+ /// }
95
+ /// ```
96
+ pub fn from_rgba_unmultiplied(size: [usize; 2], rgba: &[u8]) -> Self {
97
+ assert_eq!(size[0] * size[1] * 4, rgba.len());
98
+ let pixels = rgba
99
+ .chunks_exact(4)
100
+ .map(|p| Color32::from_rgba_unmultiplied(p[0], p[1], p[2], p[3]))
101
+ .collect();
102
+ Self { size, pixels }
103
+ }
104
+
105
+ pub fn from_rgba_premultiplied(size: [usize; 2], rgba: &[u8]) -> Self {
106
+ assert_eq!(size[0] * size[1] * 4, rgba.len());
107
+ let pixels = rgba
108
+ .chunks_exact(4)
109
+ .map(|p| Color32::from_rgba_premultiplied(p[0], p[1], p[2], p[3]))
110
+ .collect();
111
+ Self { size, pixels }
112
+ }
113
+
114
+ /// Create a [`ColorImage`] from flat opaque gray data.
115
+ ///
116
+ /// Panics if `size[0] * size[1] != gray.len()`.
117
+ pub fn from_gray(size: [usize; 2], gray: &[u8]) -> Self {
118
+ assert_eq!(size[0] * size[1], gray.len());
119
+ let pixels = gray.iter().map(|p| Color32::from_gray(*p)).collect();
120
+ Self { size, pixels }
121
+ }
122
+
123
+ /// Alternative method to `from_gray`.
124
+ /// Create a [`ColorImage`] from iterator over flat opaque gray data.
125
+ ///
126
+ /// Panics if `size[0] * size[1] != gray_iter.len()`.
127
+ #[doc(alias = "from_grey_iter")]
128
+ pub fn from_gray_iter(size: [usize; 2], gray_iter: impl Iterator<Item = u8>) -> Self {
129
+ let pixels: Vec<_> = gray_iter.map(Color32::from_gray).collect();
130
+ assert_eq!(size[0] * size[1], pixels.len());
131
+ Self { size, pixels }
132
+ }
133
+
134
+ /// A view of the underlying data as `&[u8]`
135
+ #[cfg(feature = "bytemuck")]
136
+ pub fn as_raw(&self) -> &[u8] {
137
+ bytemuck::cast_slice(&self.pixels)
138
+ }
139
+
140
+ /// A view of the underlying data as `&mut [u8]`
141
+ #[cfg(feature = "bytemuck")]
142
+ pub fn as_raw_mut(&mut self) -> &mut [u8] {
143
+ bytemuck::cast_slice_mut(&mut self.pixels)
144
+ }
145
+
146
+ /// Create a [`ColorImage`] from flat RGB data.
147
+ ///
148
+ /// This is what you want to use after having loaded an image file (and if
149
+ /// you are ignoring the alpha channel - considering it to always be 0xff)
150
+ ///
151
+ /// Panics if `size[0] * size[1] * 3 != rgb.len()`.
152
+ pub fn from_rgb(size: [usize; 2], rgb: &[u8]) -> Self {
153
+ assert_eq!(size[0] * size[1] * 3, rgb.len());
154
+ let pixels = rgb
155
+ .chunks_exact(3)
156
+ .map(|p| Color32::from_rgb(p[0], p[1], p[2]))
157
+ .collect();
158
+ Self { size, pixels }
159
+ }
160
+
161
+ /// An example color image, useful for tests.
162
+ pub fn example() -> Self {
163
+ let width = 128;
164
+ let height = 64;
165
+ let mut img = Self::new([width, height], Color32::TRANSPARENT);
166
+ for y in 0..height {
167
+ for x in 0..width {
168
+ let h = x as f32 / width as f32;
169
+ let s = 1.0;
170
+ let v = 1.0;
171
+ let a = y as f32 / height as f32;
172
+ img[(x, y)] = crate::Hsva { h, s, v, a }.into();
173
+ }
174
+ }
175
+ img
176
+ }
177
+
178
+ #[inline]
179
+ pub fn width(&self) -> usize {
180
+ self.size[0]
181
+ }
182
+
183
+ #[inline]
184
+ pub fn height(&self) -> usize {
185
+ self.size[1]
186
+ }
187
+
188
+ /// Create a new image from a patch of the current image.
189
+ ///
190
+ /// This method is especially convenient for screenshotting a part of the app
191
+ /// since `region` can be interpreted as screen coordinates of the entire screenshot if `pixels_per_point` is provided for the native application.
192
+ /// The floats of [`emath::Rect`] are cast to usize, rounding them down in order to interpret them as indices to the image data.
193
+ ///
194
+ /// Panics if `region.min.x > region.max.x || region.min.y > region.max.y`, or if a region larger than the image is passed.
195
+ pub fn region(&self, region: &emath::Rect, pixels_per_point: Option<f32>) -> Self {
196
+ let pixels_per_point = pixels_per_point.unwrap_or(1.0);
197
+ let min_x = (region.min.x * pixels_per_point) as usize;
198
+ let max_x = (region.max.x * pixels_per_point) as usize;
199
+ let min_y = (region.min.y * pixels_per_point) as usize;
200
+ let max_y = (region.max.y * pixels_per_point) as usize;
201
+ assert!(
202
+ min_x <= max_x && min_y <= max_y,
203
+ "Screenshot region is invalid: {region:?}"
204
+ );
205
+ let width = max_x - min_x;
206
+ let height = max_y - min_y;
207
+ let mut output = Vec::with_capacity(width * height);
208
+ let row_stride = self.size[0];
209
+
210
+ for row in min_y..max_y {
211
+ output.extend_from_slice(
212
+ &self.pixels[row * row_stride + min_x..row * row_stride + max_x],
213
+ );
214
+ }
215
+ Self {
216
+ size: [width, height],
217
+ pixels: output,
218
+ }
219
+ }
220
+ }
221
+
222
+ impl std::ops::Index<(usize, usize)> for ColorImage {
223
+ type Output = Color32;
224
+
225
+ #[inline]
226
+ fn index(&self, (x, y): (usize, usize)) -> &Color32 {
227
+ let [w, h] = self.size;
228
+ assert!(x < w && y < h);
229
+ &self.pixels[y * w + x]
230
+ }
231
+ }
232
+
233
+ impl std::ops::IndexMut<(usize, usize)> for ColorImage {
234
+ #[inline]
235
+ fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut Color32 {
236
+ let [w, h] = self.size;
237
+ assert!(x < w && y < h);
238
+ &mut self.pixels[y * w + x]
239
+ }
240
+ }
241
+
242
+ impl From<ColorImage> for ImageData {
243
+ #[inline(always)]
244
+ fn from(image: ColorImage) -> Self {
245
+ Self::Color(Arc::new(image))
246
+ }
247
+ }
248
+
249
+ impl From<Arc<ColorImage>> for ImageData {
250
+ #[inline]
251
+ fn from(image: Arc<ColorImage>) -> Self {
252
+ Self::Color(image)
253
+ }
254
+ }
255
+
256
+ impl std::fmt::Debug for ColorImage {
257
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
258
+ f.debug_struct("ColorImage")
259
+ .field("size", &self.size)
260
+ .field("pixel-count", &self.pixels.len())
261
+ .finish_non_exhaustive()
262
+ }
263
+ }
264
+
265
+ // ----------------------------------------------------------------------------
266
+
267
+ /// A single-channel image designed for the font texture.
268
+ ///
269
+ /// Each value represents "coverage", i.e. how much a texel is covered by a character.
270
+ ///
271
+ /// This is roughly interpreted as the opacity of a white image.
272
+ #[derive(Clone, Default, PartialEq)]
273
+ #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
274
+ pub struct FontImage {
275
+ /// width, height
276
+ pub size: [usize; 2],
277
+
278
+ /// The coverage value.
279
+ ///
280
+ /// Often you want to use [`Self::srgba_pixels`] instead.
281
+ pub pixels: Vec<f32>,
282
+ }
283
+
284
+ impl FontImage {
285
+ pub fn new(size: [usize; 2]) -> Self {
286
+ Self {
287
+ size,
288
+ pixels: vec![0.0; size[0] * size[1]],
289
+ }
290
+ }
291
+
292
+ #[inline]
293
+ pub fn width(&self) -> usize {
294
+ self.size[0]
295
+ }
296
+
297
+ #[inline]
298
+ pub fn height(&self) -> usize {
299
+ self.size[1]
300
+ }
301
+
302
+ /// Returns the textures as `sRGBA` premultiplied pixels, row by row, top to bottom.
303
+ ///
304
+ /// `gamma` should normally be set to `None`.
305
+ ///
306
+ /// If you are having problems with text looking skinny and pixelated, try using a low gamma, e.g. `0.4`.
307
+ #[inline]
308
+ pub fn srgba_pixels(&self, gamma: Option<f32>) -> impl ExactSizeIterator<Item = Color32> + '_ {
309
+ // Tuned slightly lower than upstream's 0.55 default so text coverage lands a bit closer
310
+ // to browser-rendered output in Elit's desktop-native parity checks.
311
+ let gamma = gamma.unwrap_or(0.50);
312
+ self.pixels.iter().map(move |coverage| {
313
+ let alpha = coverage.powf(gamma);
314
+ // We want to multiply with `vec4(alpha)` in the fragment shader:
315
+ let a = fast_round(alpha * 255.0);
316
+ Color32::from_rgba_premultiplied(a, a, a, a)
317
+ })
318
+ }
319
+
320
+ /// Clone a sub-region as a new image.
321
+ pub fn region(&self, [x, y]: [usize; 2], [w, h]: [usize; 2]) -> Self {
322
+ assert!(x + w <= self.width());
323
+ assert!(y + h <= self.height());
324
+
325
+ let mut pixels = Vec::with_capacity(w * h);
326
+ for y in y..y + h {
327
+ let offset = y * self.width() + x;
328
+ pixels.extend(&self.pixels[offset..(offset + w)]);
329
+ }
330
+ assert_eq!(pixels.len(), w * h);
331
+ Self {
332
+ size: [w, h],
333
+ pixels,
334
+ }
335
+ }
336
+ }
337
+
338
+ impl std::ops::Index<(usize, usize)> for FontImage {
339
+ type Output = f32;
340
+
341
+ #[inline]
342
+ fn index(&self, (x, y): (usize, usize)) -> &f32 {
343
+ let [w, h] = self.size;
344
+ assert!(x < w && y < h);
345
+ &self.pixels[y * w + x]
346
+ }
347
+ }
348
+
349
+ impl std::ops::IndexMut<(usize, usize)> for FontImage {
350
+ #[inline]
351
+ fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut f32 {
352
+ let [w, h] = self.size;
353
+ assert!(x < w && y < h);
354
+ &mut self.pixels[y * w + x]
355
+ }
356
+ }
357
+
358
+ impl From<FontImage> for ImageData {
359
+ #[inline(always)]
360
+ fn from(image: FontImage) -> Self {
361
+ Self::Font(image)
362
+ }
363
+ }
364
+
365
+ #[inline]
366
+ fn fast_round(r: f32) -> u8 {
367
+ (r + 0.5) as _ // rust does a saturating cast since 1.45
368
+ }
369
+
370
+ // ----------------------------------------------------------------------------
371
+
372
+ /// A change to an image.
373
+ ///
374
+ /// Either a whole new image, or an update to a rectangular region of it.
375
+ #[derive(Clone, PartialEq)]
376
+ #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
377
+ #[must_use = "The painter must take care of this"]
378
+ pub struct ImageDelta {
379
+ /// What to set the texture to.
380
+ ///
381
+ /// If [`Self::pos`] is `None`, this describes the whole texture.
382
+ ///
383
+ /// If [`Self::pos`] is `Some`, this describes a patch of the whole image starting at [`Self::pos`].
384
+ pub image: ImageData,
385
+
386
+ pub options: TextureOptions,
387
+
388
+ /// If `None`, set the whole texture to [`Self::image`].
389
+ ///
390
+ /// If `Some(pos)`, update a sub-region of an already allocated texture with the patch in [`Self::image`].
391
+ pub pos: Option<[usize; 2]>,
392
+ }
393
+
394
+ impl ImageDelta {
395
+ /// Update the whole texture.
396
+ pub fn full(image: impl Into<ImageData>, options: TextureOptions) -> Self {
397
+ Self {
398
+ image: image.into(),
399
+ options,
400
+ pos: None,
401
+ }
402
+ }
403
+
404
+ /// Update a sub-region of an existing texture.
405
+ pub fn partial(pos: [usize; 2], image: impl Into<ImageData>, options: TextureOptions) -> Self {
406
+ Self {
407
+ image: image.into(),
408
+ options,
409
+ pos: Some(pos),
410
+ }
411
+ }
412
+
413
+ /// Is this affecting the whole texture?
414
+ /// If `false`, this is a partial (sub-region) update.
415
+ pub fn is_whole(&self) -> bool {
416
+ self.pos.is_none()
417
+ }
418
+ }