1 | #pragma once |
2 | |
3 | /* Generated with cbindgen:0.26.0 */ |
4 | |
5 | #include <cstdarg> |
6 | #include <cstdint> |
7 | #include <cstdlib> |
8 | #include <ostream> |
9 | #include <new> |
10 | #include "slint_enums_internal.h" |
11 | namespace slint::cbindgen_private { struct ParsedSVG{}; struct HTMLImage{}; using namespace vtable; namespace types{ struct NineSliceImage{}; } } |
12 | |
13 | namespace slint { |
14 | namespace cbindgen_private { |
15 | namespace types { |
16 | |
17 | /// This enum describes the origin to use when rendering a borrowed OpenGL texture. |
18 | /// Use this with [`BorrowedOpenGLTextureBuilder::origin`]. |
19 | enum class BorrowedOpenGLTextureOrigin : uint8_t { |
20 | /// The top-left of the texture is the top-left of the texture drawn on the screen. |
21 | TopLeft, |
22 | /// The bottom-left of the texture is the top-left of the texture draw on the screen, |
23 | /// flipping it vertically. |
24 | BottomLeft, |
25 | }; |
26 | |
27 | /// The pixel format of a StaticTexture |
28 | enum class PixelFormat : uint8_t { |
29 | /// red, green, blue. 24bits. |
30 | Rgb, |
31 | /// Red, green, blue, alpha. 32bits. |
32 | Rgba, |
33 | /// Red, green, blue, alpha. 32bits. The color are premultiplied by alpha |
34 | RgbaPremultiplied, |
35 | /// Alpha map. 8bits. Each pixel is an alpha value. The color is specified separately. |
36 | AlphaMap, |
37 | }; |
38 | |
39 | /// Represent a nine-slice image with the base image and the 4 borders |
40 | struct NineSliceImage; |
41 | |
42 | /// ImageCacheKey encapsulates the different ways of indexing images in the |
43 | /// cache of decoded images. |
44 | union ImageCacheKey { |
45 | enum class Tag : uint8_t { |
46 | /// This variant indicates that no image cache key can be created for the image. |
47 | /// For example this is the case for programmatically created images. |
48 | Invalid = 0, |
49 | /// The image is identified by its path on the file system. |
50 | Path = 1, |
51 | #if defined(SLINT_TARGET_WASM) |
52 | /// The image is identified by a URL. |
53 | URL = 2, |
54 | #endif |
55 | /// The image is identified by the static address of its encoded data. |
56 | EmbeddedData = 3, |
57 | }; |
58 | |
59 | struct Path_Body { |
60 | Tag tag; |
61 | SharedString _0; |
62 | |
63 | bool operator==(const Path_Body& other) const { |
64 | return _0 == other._0; |
65 | } |
66 | bool operator!=(const Path_Body& other) const { |
67 | return _0 != other._0; |
68 | } |
69 | }; |
70 | |
71 | #if defined(SLINT_TARGET_WASM) |
72 | struct URL_Body { |
73 | Tag tag; |
74 | SharedString _0; |
75 | |
76 | bool operator==(const URL_Body& other) const { |
77 | return _0 == other._0; |
78 | } |
79 | bool operator!=(const URL_Body& other) const { |
80 | return _0 != other._0; |
81 | } |
82 | }; |
83 | #endif |
84 | |
85 | struct EmbeddedData_Body { |
86 | Tag tag; |
87 | uintptr_t _0; |
88 | |
89 | bool operator==(const EmbeddedData_Body& other) const { |
90 | return _0 == other._0; |
91 | } |
92 | bool operator!=(const EmbeddedData_Body& other) const { |
93 | return _0 != other._0; |
94 | } |
95 | }; |
96 | |
97 | struct { |
98 | Tag tag; |
99 | }; |
100 | Path_Body path; |
101 | #if defined(SLINT_TARGET_WASM) |
102 | URL_Body url; |
103 | #endif |
104 | EmbeddedData_Body embedded_data; |
105 | |
106 | static ImageCacheKey Invalid() { |
107 | ImageCacheKey result; |
108 | result.tag = Tag::Invalid; |
109 | return result; |
110 | } |
111 | |
112 | bool IsInvalid() const { |
113 | return tag == Tag::Invalid; |
114 | } |
115 | |
116 | static ImageCacheKey Path(const SharedString &_0) { |
117 | ImageCacheKey result; |
118 | ::new (&result.path._0) (SharedString)(_0); |
119 | result.tag = Tag::Path; |
120 | return result; |
121 | } |
122 | |
123 | bool IsPath() const { |
124 | return tag == Tag::Path; |
125 | } |
126 | |
127 | #if defined(SLINT_TARGET_WASM) |
128 | static ImageCacheKey URL(const SharedString &_0) { |
129 | ImageCacheKey result; |
130 | ::new (&result.url._0) (SharedString)(_0); |
131 | result.tag = Tag::URL; |
132 | return result; |
133 | } |
134 | |
135 | bool IsURL() const { |
136 | return tag == Tag::URL; |
137 | } |
138 | #endif |
139 | |
140 | static ImageCacheKey EmbeddedData(const uintptr_t &_0) { |
141 | ImageCacheKey result; |
142 | ::new (&result.embedded_data._0) (uintptr_t)(_0); |
143 | result.tag = Tag::EmbeddedData; |
144 | return result; |
145 | } |
146 | |
147 | bool IsEmbeddedData() const { |
148 | return tag == Tag::EmbeddedData; |
149 | } |
150 | |
151 | bool operator==(const ImageCacheKey& other) const { |
152 | if (tag != other.tag) { |
153 | return false; |
154 | } |
155 | switch (tag) { |
156 | case Tag::Path: return path == other.path; |
157 | #if defined(SLINT_TARGET_WASM) |
158 | case Tag::URL: return url == other.url; |
159 | #endif |
160 | case Tag::EmbeddedData: return embedded_data == other.embedded_data; |
161 | default: break; |
162 | } |
163 | return true; |
164 | } |
165 | |
166 | bool operator!=(const ImageCacheKey& other) const { |
167 | return !(*this == other); |
168 | } |
169 | |
170 | private: |
171 | ImageCacheKey() { |
172 | |
173 | } |
174 | public: |
175 | |
176 | |
177 | ~ImageCacheKey() { |
178 | switch (tag) { |
179 | case Tag::Path: path.~Path_Body(); break; |
180 | #if defined(SLINT_TARGET_WASM) |
181 | case Tag::URL: url.~URL_Body(); break; |
182 | #endif |
183 | case Tag::EmbeddedData: embedded_data.~EmbeddedData_Body(); break; |
184 | default: break; |
185 | } |
186 | } |
187 | |
188 | ImageCacheKey(const ImageCacheKey& other) |
189 | : tag(other.tag) { |
190 | switch (tag) { |
191 | case Tag::Path: ::new (&path) (Path_Body)(other.path); break; |
192 | #if defined(SLINT_TARGET_WASM) |
193 | case Tag::URL: ::new (&url) (URL_Body)(other.url); break; |
194 | #endif |
195 | case Tag::EmbeddedData: ::new (&embedded_data) (EmbeddedData_Body)(other.embedded_data); break; |
196 | default: break; |
197 | } |
198 | } |
199 | ImageCacheKey& operator=(const ImageCacheKey& other) { |
200 | if (this != &other) { |
201 | this->~ImageCacheKey(); |
202 | new (this) ImageCacheKey(other); |
203 | } |
204 | return *this; |
205 | } |
206 | }; |
207 | |
208 | /// SharedPixelBuffer is a container for storing image data as pixels. It is |
209 | /// internally reference counted and cheap to clone. |
210 | /// |
211 | /// You can construct a new empty shared pixel buffer with [`SharedPixelBuffer::new`], |
212 | /// or you can clone it from an existing contiguous buffer that you might already have, using |
213 | /// [`SharedPixelBuffer::clone_from_slice`]. |
214 | /// |
215 | /// See the documentation for [`Image`] for examples how to use this type to integrate |
216 | /// Slint with external rendering functions. |
217 | template<typename Pixel> |
218 | struct SharedPixelBuffer { |
219 | uint32_t width; |
220 | uint32_t height; |
221 | SharedVector<Pixel> data; |
222 | |
223 | bool operator==(const SharedPixelBuffer& other) const { |
224 | return width == other.width && |
225 | height == other.height && |
226 | data == other.data; |
227 | } |
228 | bool operator!=(const SharedPixelBuffer& other) const { |
229 | return width != other.width || |
230 | height != other.height || |
231 | data != other.data; |
232 | } |
233 | }; |
234 | |
235 | /// SharedImageBuffer is a container for images that are stored in CPU accessible memory. |
236 | /// |
237 | /// The SharedImageBuffer's variants represent the different common formats for encoding |
238 | /// images in pixels. |
239 | struct SharedImageBuffer { |
240 | enum class Tag { |
241 | /// This variant holds the data for an image where each pixel has three color channels (red, green, |
242 | /// and blue) and each channel is encoded as unsigned byte. |
243 | RGB8, |
244 | /// This variant holds the data for an image where each pixel has four color channels (red, green, |
245 | /// blue and alpha) and each channel is encoded as unsigned byte. |
246 | RGBA8, |
247 | /// This variant holds the data for an image where each pixel has four color channels (red, green, |
248 | /// blue and alpha) and each channel is encoded as unsigned byte. In contrast to [`Self::RGBA8`], |
249 | /// this variant assumes that the alpha channel is also already multiplied to each red, green and blue |
250 | /// component of each pixel. |
251 | /// Only construct this format if you know that your pixels are encoded this way. It is more efficient |
252 | /// for rendering. |
253 | RGBA8Premultiplied, |
254 | }; |
255 | |
256 | struct RGB8_Body { |
257 | SharedPixelBuffer<Rgb8Pixel> _0; |
258 | |
259 | bool operator==(const RGB8_Body& other) const { |
260 | return _0 == other._0; |
261 | } |
262 | bool operator!=(const RGB8_Body& other) const { |
263 | return _0 != other._0; |
264 | } |
265 | }; |
266 | |
267 | struct RGBA8_Body { |
268 | SharedPixelBuffer<Rgba8Pixel> _0; |
269 | |
270 | bool operator==(const RGBA8_Body& other) const { |
271 | return _0 == other._0; |
272 | } |
273 | bool operator!=(const RGBA8_Body& other) const { |
274 | return _0 != other._0; |
275 | } |
276 | }; |
277 | |
278 | struct RGBA8Premultiplied_Body { |
279 | SharedPixelBuffer<Rgba8Pixel> _0; |
280 | |
281 | bool operator==(const RGBA8Premultiplied_Body& other) const { |
282 | return _0 == other._0; |
283 | } |
284 | bool operator!=(const RGBA8Premultiplied_Body& other) const { |
285 | return _0 != other._0; |
286 | } |
287 | }; |
288 | |
289 | Tag tag; |
290 | union { |
291 | RGB8_Body rgb8; |
292 | RGBA8_Body rgba8; |
293 | RGBA8Premultiplied_Body rgba8_premultiplied; |
294 | }; |
295 | |
296 | static SharedImageBuffer RGB8(const SharedPixelBuffer<Rgb8Pixel> &_0) { |
297 | SharedImageBuffer result; |
298 | ::new (&result.rgb8._0) (SharedPixelBuffer<Rgb8Pixel>)(_0); |
299 | result.tag = Tag::RGB8; |
300 | return result; |
301 | } |
302 | |
303 | bool IsRGB8() const { |
304 | return tag == Tag::RGB8; |
305 | } |
306 | |
307 | static SharedImageBuffer RGBA8(const SharedPixelBuffer<Rgba8Pixel> &_0) { |
308 | SharedImageBuffer result; |
309 | ::new (&result.rgba8._0) (SharedPixelBuffer<Rgba8Pixel>)(_0); |
310 | result.tag = Tag::RGBA8; |
311 | return result; |
312 | } |
313 | |
314 | bool IsRGBA8() const { |
315 | return tag == Tag::RGBA8; |
316 | } |
317 | |
318 | static SharedImageBuffer RGBA8Premultiplied(const SharedPixelBuffer<Rgba8Pixel> &_0) { |
319 | SharedImageBuffer result; |
320 | ::new (&result.rgba8_premultiplied._0) (SharedPixelBuffer<Rgba8Pixel>)(_0); |
321 | result.tag = Tag::RGBA8Premultiplied; |
322 | return result; |
323 | } |
324 | |
325 | bool IsRGBA8Premultiplied() const { |
326 | return tag == Tag::RGBA8Premultiplied; |
327 | } |
328 | |
329 | bool operator==(const SharedImageBuffer& other) const { |
330 | if (tag != other.tag) { |
331 | return false; |
332 | } |
333 | switch (tag) { |
334 | case Tag::RGB8: return rgb8 == other.rgb8; |
335 | case Tag::RGBA8: return rgba8 == other.rgba8; |
336 | case Tag::RGBA8Premultiplied: return rgba8_premultiplied == other.rgba8_premultiplied; |
337 | |
338 | } |
339 | return true; |
340 | } |
341 | |
342 | bool operator!=(const SharedImageBuffer& other) const { |
343 | return !(*this == other); |
344 | } |
345 | |
346 | private: |
347 | SharedImageBuffer() { |
348 | |
349 | } |
350 | public: |
351 | |
352 | |
353 | ~SharedImageBuffer() { |
354 | switch (tag) { |
355 | case Tag::RGB8: rgb8.~RGB8_Body(); break; |
356 | case Tag::RGBA8: rgba8.~RGBA8_Body(); break; |
357 | case Tag::RGBA8Premultiplied: rgba8_premultiplied.~RGBA8Premultiplied_Body(); break; |
358 | |
359 | } |
360 | } |
361 | |
362 | SharedImageBuffer(const SharedImageBuffer& other) |
363 | : tag(other.tag) { |
364 | switch (tag) { |
365 | case Tag::RGB8: ::new (&rgb8) (RGB8_Body)(other.rgb8); break; |
366 | case Tag::RGBA8: ::new (&rgba8) (RGBA8_Body)(other.rgba8); break; |
367 | case Tag::RGBA8Premultiplied: ::new (&rgba8_premultiplied) (RGBA8Premultiplied_Body)(other.rgba8_premultiplied); break; |
368 | |
369 | } |
370 | } |
371 | SharedImageBuffer& operator=(const SharedImageBuffer& other) { |
372 | if (this != &other) { |
373 | this->~SharedImageBuffer(); |
374 | new (this) SharedImageBuffer(other); |
375 | } |
376 | return *this; |
377 | } |
378 | }; |
379 | |
380 | /// 2D Size in integer coordinates |
381 | using IntSize = Size2D<uint32_t>; |
382 | |
383 | struct OpaqueImageVTable { |
384 | Layout (*drop_in_place)(VRefMut<OpaqueImageVTable>); |
385 | void (*dealloc)(const OpaqueImageVTable*, uint8_t *ptr, Layout layout); |
386 | /// Returns the image size |
387 | IntSize (*size)(VRef<OpaqueImageVTable>); |
388 | /// Returns a cache key |
389 | ImageCacheKey (*cache_key)(VRef<OpaqueImageVTable>); |
390 | |
391 | bool operator==(const OpaqueImageVTable& other) const { |
392 | return drop_in_place == other.drop_in_place && |
393 | dealloc == other.dealloc && |
394 | size == other.size && |
395 | cache_key == other.cache_key; |
396 | } |
397 | bool operator!=(const OpaqueImageVTable& other) const { |
398 | return drop_in_place != other.drop_in_place || |
399 | dealloc != other.dealloc || |
400 | size != other.size || |
401 | cache_key != other.cache_key; |
402 | } |
403 | }; |
404 | |
405 | /// Expand IntRect so that cbindgen can see it. ( is in fact euclid::default::Rect<i32>) |
406 | struct IntRect { |
407 | int32_t x; |
408 | int32_t y; |
409 | int32_t width; |
410 | int32_t height; |
411 | |
412 | bool operator==(const IntRect& other) const { |
413 | return x == other.x && |
414 | y == other.y && |
415 | width == other.width && |
416 | height == other.height; |
417 | } |
418 | bool operator!=(const IntRect& other) const { |
419 | return x != other.x || |
420 | y != other.y || |
421 | width != other.width || |
422 | height != other.height; |
423 | } |
424 | }; |
425 | |
426 | /// Some raw pixel data which is typically stored in the binary |
427 | struct StaticTexture { |
428 | /// The position and size of the texture within the image |
429 | IntRect rect; |
430 | /// The pixel format of this texture |
431 | PixelFormat format; |
432 | /// The color, for the alpha map ones |
433 | Color color; |
434 | /// index in the data array |
435 | uintptr_t index; |
436 | |
437 | bool operator==(const StaticTexture& other) const { |
438 | return rect == other.rect && |
439 | format == other.format && |
440 | color == other.color && |
441 | index == other.index; |
442 | } |
443 | bool operator!=(const StaticTexture& other) const { |
444 | return rect != other.rect || |
445 | format != other.format || |
446 | color != other.color || |
447 | index != other.index; |
448 | } |
449 | }; |
450 | |
451 | /// A texture is stored in read-only memory and may be composed of sub-textures. |
452 | struct StaticTextures { |
453 | /// The total size of the image (this might not be the size of the full image |
454 | /// as some transparent part are not part of any texture) |
455 | IntSize size; |
456 | /// The size of the image before the compiler applied any scaling |
457 | IntSize original_size; |
458 | /// The pixel data referenced by the textures |
459 | Slice<uint8_t> data; |
460 | /// The list of textures |
461 | Slice<StaticTexture> textures; |
462 | |
463 | bool operator==(const StaticTextures& other) const { |
464 | return size == other.size && |
465 | original_size == other.original_size && |
466 | data == other.data && |
467 | textures == other.textures; |
468 | } |
469 | bool operator!=(const StaticTextures& other) const { |
470 | return size != other.size || |
471 | original_size != other.original_size || |
472 | data != other.data || |
473 | textures != other.textures; |
474 | } |
475 | }; |
476 | |
477 | #if !defined(SLINT_TARGET_WASM) |
478 | /// This structure contains fields to identify and render an OpenGL texture that Slint borrows from the application code. |
479 | /// Use this to embed a native OpenGL texture into a Slint scene. |
480 | /// |
481 | /// The ownership of the texture remains with the application. It is the application's responsibility to delete the texture |
482 | /// when it is not used anymore. |
483 | /// |
484 | /// Note that only 2D RGBA textures are supported. |
485 | struct BorrowedOpenGLTexture { |
486 | /// The id or name of the texture, as created by [`glGenTextures`](https://registry.khronos.org/OpenGL-Refpages/gl4/html/glGenTextures.xhtml). |
487 | uint32_t texture_id; |
488 | /// The size of the texture in pixels. |
489 | IntSize size; |
490 | /// Origin of the texture when rendering. |
491 | BorrowedOpenGLTextureOrigin origin; |
492 | |
493 | bool operator==(const BorrowedOpenGLTexture& other) const { |
494 | return texture_id == other.texture_id && |
495 | size == other.size && |
496 | origin == other.origin; |
497 | } |
498 | bool operator!=(const BorrowedOpenGLTexture& other) const { |
499 | return texture_id != other.texture_id || |
500 | size != other.size || |
501 | origin != other.origin; |
502 | } |
503 | }; |
504 | #endif |
505 | |
506 | /// A resource is a reference to binary data, for example images. They can be accessible on the file |
507 | /// system or embedded in the resulting binary. Or they might be URLs to a web server and a downloaded |
508 | /// is necessary before they can be used. |
509 | union ImageInner { |
510 | enum class Tag : uint8_t { |
511 | /// A resource that does not represent any data. |
512 | ImageInner_None = 0, |
513 | ImageInner_EmbeddedImage = 1, |
514 | ImageInner_Svg = 2, |
515 | ImageInner_StaticTextures = 3, |
516 | #if defined(SLINT_TARGET_WASM) |
517 | ImageInner_HTMLImage = 4, |
518 | #endif |
519 | ImageInner_BackendStorage = 5, |
520 | #if !defined(SLINT_TARGET_WASM) |
521 | ImageInner_BorrowedOpenGLTexture = 6, |
522 | #endif |
523 | ImageInner_NineSlice = 7, |
524 | }; |
525 | |
526 | struct ImageInner_EmbeddedImage_Body { |
527 | Tag tag; |
528 | ImageCacheKey cache_key; |
529 | SharedImageBuffer buffer; |
530 | |
531 | bool operator==(const ImageInner_EmbeddedImage_Body& other) const { |
532 | return cache_key == other.cache_key && |
533 | buffer == other.buffer; |
534 | } |
535 | bool operator!=(const ImageInner_EmbeddedImage_Body& other) const { |
536 | return cache_key != other.cache_key || |
537 | buffer != other.buffer; |
538 | } |
539 | }; |
540 | |
541 | struct ImageInner_Svg_Body { |
542 | Tag tag; |
543 | VRc<OpaqueImageVTable, ParsedSVG> _0; |
544 | |
545 | bool operator==(const ImageInner_Svg_Body& other) const { |
546 | return _0 == other._0; |
547 | } |
548 | bool operator!=(const ImageInner_Svg_Body& other) const { |
549 | return _0 != other._0; |
550 | } |
551 | }; |
552 | |
553 | struct ImageInner_StaticTextures_Body { |
554 | Tag tag; |
555 | const StaticTextures *_0; |
556 | |
557 | bool operator==(const ImageInner_StaticTextures_Body& other) const { |
558 | return _0 == other._0; |
559 | } |
560 | bool operator!=(const ImageInner_StaticTextures_Body& other) const { |
561 | return _0 != other._0; |
562 | } |
563 | }; |
564 | |
565 | #if defined(SLINT_TARGET_WASM) |
566 | struct ImageInner_HTMLImage_Body { |
567 | Tag tag; |
568 | VRc<OpaqueImageVTable, HTMLImage> _0; |
569 | |
570 | bool operator==(const ImageInner_HTMLImage_Body& other) const { |
571 | return _0 == other._0; |
572 | } |
573 | bool operator!=(const ImageInner_HTMLImage_Body& other) const { |
574 | return _0 != other._0; |
575 | } |
576 | }; |
577 | #endif |
578 | |
579 | struct ImageInner_BackendStorage_Body { |
580 | Tag tag; |
581 | VRc<OpaqueImageVTable> _0; |
582 | |
583 | bool operator==(const ImageInner_BackendStorage_Body& other) const { |
584 | return _0 == other._0; |
585 | } |
586 | bool operator!=(const ImageInner_BackendStorage_Body& other) const { |
587 | return _0 != other._0; |
588 | } |
589 | }; |
590 | |
591 | #if !defined(SLINT_TARGET_WASM) |
592 | struct ImageInner_BorrowedOpenGLTexture_Body { |
593 | Tag tag; |
594 | BorrowedOpenGLTexture _0; |
595 | |
596 | bool operator==(const ImageInner_BorrowedOpenGLTexture_Body& other) const { |
597 | return _0 == other._0; |
598 | } |
599 | bool operator!=(const ImageInner_BorrowedOpenGLTexture_Body& other) const { |
600 | return _0 != other._0; |
601 | } |
602 | }; |
603 | #endif |
604 | |
605 | struct ImageInner_NineSlice_Body { |
606 | Tag tag; |
607 | VRc<OpaqueImageVTable, NineSliceImage> _0; |
608 | |
609 | bool operator==(const ImageInner_NineSlice_Body& other) const { |
610 | return _0 == other._0; |
611 | } |
612 | bool operator!=(const ImageInner_NineSlice_Body& other) const { |
613 | return _0 != other._0; |
614 | } |
615 | }; |
616 | |
617 | struct { |
618 | Tag tag; |
619 | }; |
620 | ImageInner_EmbeddedImage_Body embedded_image; |
621 | ImageInner_Svg_Body svg; |
622 | ImageInner_StaticTextures_Body static_textures; |
623 | #if defined(SLINT_TARGET_WASM) |
624 | ImageInner_HTMLImage_Body html_image; |
625 | #endif |
626 | ImageInner_BackendStorage_Body backend_storage; |
627 | #if !defined(SLINT_TARGET_WASM) |
628 | ImageInner_BorrowedOpenGLTexture_Body borrowed_open_gl_texture; |
629 | #endif |
630 | ImageInner_NineSlice_Body nine_slice; |
631 | |
632 | static ImageInner ImageInner_None() { |
633 | ImageInner result; |
634 | result.tag = Tag::ImageInner_None; |
635 | return result; |
636 | } |
637 | |
638 | bool IsImageInner_None() const { |
639 | return tag == Tag::ImageInner_None; |
640 | } |
641 | |
642 | static ImageInner ImageInner_EmbeddedImage(const ImageCacheKey &cache_key, |
643 | const SharedImageBuffer &buffer) { |
644 | ImageInner result; |
645 | ::new (&result.embedded_image.cache_key) (ImageCacheKey)(cache_key); |
646 | ::new (&result.embedded_image.buffer) (SharedImageBuffer)(buffer); |
647 | result.tag = Tag::ImageInner_EmbeddedImage; |
648 | return result; |
649 | } |
650 | |
651 | bool IsImageInner_EmbeddedImage() const { |
652 | return tag == Tag::ImageInner_EmbeddedImage; |
653 | } |
654 | |
655 | static ImageInner ImageInner_Svg(const VRc<OpaqueImageVTable, ParsedSVG> &_0) { |
656 | ImageInner result; |
657 | ::new (&result.svg._0) (VRc<OpaqueImageVTable, ParsedSVG>)(_0); |
658 | result.tag = Tag::ImageInner_Svg; |
659 | return result; |
660 | } |
661 | |
662 | bool IsImageInner_Svg() const { |
663 | return tag == Tag::ImageInner_Svg; |
664 | } |
665 | |
666 | static ImageInner ImageInner_StaticTextures(const StaticTextures *const &_0) { |
667 | ImageInner result; |
668 | ::new (&result.static_textures._0) (const StaticTextures*)(_0); |
669 | result.tag = Tag::ImageInner_StaticTextures; |
670 | return result; |
671 | } |
672 | |
673 | bool IsImageInner_StaticTextures() const { |
674 | return tag == Tag::ImageInner_StaticTextures; |
675 | } |
676 | |
677 | #if defined(SLINT_TARGET_WASM) |
678 | static ImageInner ImageInner_HTMLImage(const VRc<OpaqueImageVTable, HTMLImage> &_0) { |
679 | ImageInner result; |
680 | ::new (&result.html_image._0) (VRc<OpaqueImageVTable, HTMLImage>)(_0); |
681 | result.tag = Tag::ImageInner_HTMLImage; |
682 | return result; |
683 | } |
684 | |
685 | bool IsImageInner_HTMLImage() const { |
686 | return tag == Tag::ImageInner_HTMLImage; |
687 | } |
688 | #endif |
689 | |
690 | static ImageInner ImageInner_BackendStorage(const VRc<OpaqueImageVTable> &_0) { |
691 | ImageInner result; |
692 | ::new (&result.backend_storage._0) (VRc<OpaqueImageVTable>)(_0); |
693 | result.tag = Tag::ImageInner_BackendStorage; |
694 | return result; |
695 | } |
696 | |
697 | bool IsImageInner_BackendStorage() const { |
698 | return tag == Tag::ImageInner_BackendStorage; |
699 | } |
700 | |
701 | #if !defined(SLINT_TARGET_WASM) |
702 | static ImageInner ImageInner_BorrowedOpenGLTexture(const BorrowedOpenGLTexture &_0) { |
703 | ImageInner result; |
704 | ::new (&result.borrowed_open_gl_texture._0) (BorrowedOpenGLTexture)(_0); |
705 | result.tag = Tag::ImageInner_BorrowedOpenGLTexture; |
706 | return result; |
707 | } |
708 | |
709 | bool IsImageInner_BorrowedOpenGLTexture() const { |
710 | return tag == Tag::ImageInner_BorrowedOpenGLTexture; |
711 | } |
712 | #endif |
713 | |
714 | static ImageInner ImageInner_NineSlice(const VRc<OpaqueImageVTable, NineSliceImage> &_0) { |
715 | ImageInner result; |
716 | ::new (&result.nine_slice._0) (VRc<OpaqueImageVTable, NineSliceImage>)(_0); |
717 | result.tag = Tag::ImageInner_NineSlice; |
718 | return result; |
719 | } |
720 | |
721 | bool IsImageInner_NineSlice() const { |
722 | return tag == Tag::ImageInner_NineSlice; |
723 | } |
724 | |
725 | bool operator==(const ImageInner& other) const { |
726 | if (tag != other.tag) { |
727 | return false; |
728 | } |
729 | switch (tag) { |
730 | case Tag::ImageInner_EmbeddedImage: return embedded_image == other.embedded_image; |
731 | case Tag::ImageInner_Svg: return svg == other.svg; |
732 | case Tag::ImageInner_StaticTextures: return static_textures == other.static_textures; |
733 | #if defined(SLINT_TARGET_WASM) |
734 | case Tag::ImageInner_HTMLImage: return html_image == other.html_image; |
735 | #endif |
736 | case Tag::ImageInner_BackendStorage: return backend_storage == other.backend_storage; |
737 | #if !defined(SLINT_TARGET_WASM) |
738 | case Tag::ImageInner_BorrowedOpenGLTexture: return borrowed_open_gl_texture == other.borrowed_open_gl_texture; |
739 | #endif |
740 | case Tag::ImageInner_NineSlice: return nine_slice == other.nine_slice; |
741 | default: break; |
742 | } |
743 | return true; |
744 | } |
745 | |
746 | bool operator!=(const ImageInner& other) const { |
747 | return !(*this == other); |
748 | } |
749 | |
750 | private: |
751 | ImageInner() { |
752 | |
753 | } |
754 | public: |
755 | |
756 | |
757 | ~ImageInner() { |
758 | switch (tag) { |
759 | case Tag::ImageInner_EmbeddedImage: embedded_image.~ImageInner_EmbeddedImage_Body(); break; |
760 | case Tag::ImageInner_Svg: svg.~ImageInner_Svg_Body(); break; |
761 | case Tag::ImageInner_StaticTextures: static_textures.~ImageInner_StaticTextures_Body(); break; |
762 | #if defined(SLINT_TARGET_WASM) |
763 | case Tag::ImageInner_HTMLImage: html_image.~ImageInner_HTMLImage_Body(); break; |
764 | #endif |
765 | case Tag::ImageInner_BackendStorage: backend_storage.~ImageInner_BackendStorage_Body(); break; |
766 | #if !defined(SLINT_TARGET_WASM) |
767 | case Tag::ImageInner_BorrowedOpenGLTexture: borrowed_open_gl_texture.~ImageInner_BorrowedOpenGLTexture_Body(); break; |
768 | #endif |
769 | case Tag::ImageInner_NineSlice: nine_slice.~ImageInner_NineSlice_Body(); break; |
770 | default: break; |
771 | } |
772 | } |
773 | |
774 | ImageInner(const ImageInner& other) |
775 | : tag(other.tag) { |
776 | switch (tag) { |
777 | case Tag::ImageInner_EmbeddedImage: ::new (&embedded_image) (ImageInner_EmbeddedImage_Body)(other.embedded_image); break; |
778 | case Tag::ImageInner_Svg: ::new (&svg) (ImageInner_Svg_Body)(other.svg); break; |
779 | case Tag::ImageInner_StaticTextures: ::new (&static_textures) (ImageInner_StaticTextures_Body)(other.static_textures); break; |
780 | #if defined(SLINT_TARGET_WASM) |
781 | case Tag::ImageInner_HTMLImage: ::new (&html_image) (ImageInner_HTMLImage_Body)(other.html_image); break; |
782 | #endif |
783 | case Tag::ImageInner_BackendStorage: ::new (&backend_storage) (ImageInner_BackendStorage_Body)(other.backend_storage); break; |
784 | #if !defined(SLINT_TARGET_WASM) |
785 | case Tag::ImageInner_BorrowedOpenGLTexture: ::new (&borrowed_open_gl_texture) (ImageInner_BorrowedOpenGLTexture_Body)(other.borrowed_open_gl_texture); break; |
786 | #endif |
787 | case Tag::ImageInner_NineSlice: ::new (&nine_slice) (ImageInner_NineSlice_Body)(other.nine_slice); break; |
788 | default: break; |
789 | } |
790 | } |
791 | ImageInner& operator=(const ImageInner& other) { |
792 | if (this != &other) { |
793 | this->~ImageInner(); |
794 | new (this) ImageInner(other); |
795 | } |
796 | return *this; |
797 | } |
798 | }; |
799 | |
800 | /// An image type that can be displayed by the Image element. You can construct |
801 | /// Image objects from a path to an image file on disk, using [`Self::load_from_path`]. |
802 | /// |
803 | /// Another typical use-case is to render the image content with Rust code. |
804 | /// For this it's most efficient to create a new SharedPixelBuffer with the known dimensions |
805 | /// and pass the mutable slice to your rendering function. Afterwards you can create an |
806 | /// Image. |
807 | /// |
808 | /// The following example creates a 320x200 RGB pixel buffer and calls an external |
809 | /// low_level_render() function to draw a shape into it. Finally the result is |
810 | /// stored in an Image with [`Self::from_rgb8()`]: |
811 | /// ``` |
812 | /// # use i_slint_core::graphics::{SharedPixelBuffer, Image, Rgb8Pixel}; |
813 | /// |
814 | /// fn low_level_render(width: u32, height: u32, buffer: &mut [u8]) { |
815 | /// // render beautiful circle or other shapes here |
816 | /// } |
817 | /// |
818 | /// let mut pixel_buffer = SharedPixelBuffer::<Rgb8Pixel>::new(320, 200); |
819 | /// |
820 | /// low_level_render(pixel_buffer.width(), pixel_buffer.height(), |
821 | /// pixel_buffer.make_mut_bytes()); |
822 | /// |
823 | /// let image = Image::from_rgb8(pixel_buffer); |
824 | /// ``` |
825 | /// |
826 | /// Another use-case is to import existing image data into Slint, by |
827 | /// creating a new Image through cloning of another image type. |
828 | /// |
829 | /// The following example uses the popular [image crate](https://docs.rs/image/) to |
830 | /// load a `.png` file from disk, apply brightening filter on it and then import |
831 | /// it into an [`Image`]: |
832 | /// ```no_run |
833 | /// # use i_slint_core::graphics::{SharedPixelBuffer, Image, Rgba8Pixel}; |
834 | /// let mut cat_image = image::open("cat.png").expect("Error loading cat image").into_rgba8(); |
835 | /// |
836 | /// image::imageops::colorops::brighten_in_place(&mut cat_image, 20); |
837 | /// |
838 | /// let buffer = SharedPixelBuffer::<Rgba8Pixel>::clone_from_slice( |
839 | /// cat_image.as_raw(), |
840 | /// cat_image.width(), |
841 | /// cat_image.height(), |
842 | /// ); |
843 | /// let image = Image::from_rgba8(buffer); |
844 | /// ``` |
845 | /// |
846 | /// A popular software (CPU) rendering library in Rust is tiny-skia. The following example shows |
847 | /// how to use tiny-skia to render into a [`SharedPixelBuffer`]: |
848 | /// ``` |
849 | /// # use i_slint_core::graphics::{SharedPixelBuffer, Image, Rgba8Pixel}; |
850 | /// let mut pixel_buffer = SharedPixelBuffer::<Rgba8Pixel>::new(640, 480); |
851 | /// let width = pixel_buffer.width(); |
852 | /// let height = pixel_buffer.height(); |
853 | /// let mut pixmap = tiny_skia::PixmapMut::from_bytes( |
854 | /// pixel_buffer.make_mut_bytes(), width, height |
855 | /// ).unwrap(); |
856 | /// pixmap.fill(tiny_skia::Color::TRANSPARENT); |
857 | /// |
858 | /// let circle = tiny_skia::PathBuilder::from_circle(320., 240., 150.).unwrap(); |
859 | /// |
860 | /// let mut paint = tiny_skia::Paint::default(); |
861 | /// paint.shader = tiny_skia::LinearGradient::new( |
862 | /// tiny_skia::Point::from_xy(100.0, 100.0), |
863 | /// tiny_skia::Point::from_xy(400.0, 400.0), |
864 | /// vec![ |
865 | /// tiny_skia::GradientStop::new(0.0, tiny_skia::Color::from_rgba8(50, 127, 150, 200)), |
866 | /// tiny_skia::GradientStop::new(1.0, tiny_skia::Color::from_rgba8(220, 140, 75, 180)), |
867 | /// ], |
868 | /// tiny_skia::SpreadMode::Pad, |
869 | /// tiny_skia::Transform::identity(), |
870 | /// ).unwrap(); |
871 | /// |
872 | /// pixmap.fill_path(&circle, &paint, tiny_skia::FillRule::Winding, Default::default(), None); |
873 | /// |
874 | /// let image = Image::from_rgba8_premultiplied(pixel_buffer); |
875 | /// ``` |
876 | /// |
877 | /// ### Sending Image to a thread |
878 | /// |
879 | /// `Image` is not [`Send`], because it uses internal cache that are local to the Slint thread. |
880 | /// If you want to create image data in a thread and send that to slint, construct the |
881 | /// [`SharedPixelBuffer`] in a thread, and send that to Slint's UI thread. |
882 | /// |
883 | /// ```rust,no_run |
884 | /// # use i_slint_core::graphics::{SharedPixelBuffer, Image, Rgba8Pixel}; |
885 | /// std::thread::spawn(move || { |
886 | /// let mut pixel_buffer = SharedPixelBuffer::<Rgba8Pixel>::new(640, 480); |
887 | /// // ... fill the pixel_buffer with data as shown in the previous example ... |
888 | /// slint::invoke_from_event_loop(move || { |
889 | /// // this will run in the Slint's UI thread |
890 | /// let image = Image::from_rgba8_premultiplied(pixel_buffer); |
891 | /// // ... use the image, eg: |
892 | /// // my_ui_handle.upgrade().unwrap().set_image(image); |
893 | /// }); |
894 | /// }); |
895 | /// ``` |
896 | using Image = ImageInner; |
897 | |
898 | /// 2D Size |
899 | using Size = Size2D<float>; |
900 | |
901 | extern "C" { |
902 | |
903 | void slint_image_load_from_path(const SharedString *path, Image *image); |
904 | |
905 | void slint_image_load_from_embedded_data(Slice<uint8_t> data, Slice<uint8_t> format, Image *image); |
906 | |
907 | IntSize slint_image_size(const Image *image); |
908 | |
909 | const SharedString *slint_image_path(const Image *image); |
910 | |
911 | void slint_image_from_embedded_textures(const StaticTextures *textures, Image *image); |
912 | |
913 | bool slint_image_compare_equal(const Image *image1, const Image *image2); |
914 | |
915 | /// Call [`Image::set_nine_slice_edges`] |
916 | void slint_image_set_nine_slice_edges(Image *image, |
917 | uint16_t top, |
918 | uint16_t right, |
919 | uint16_t bottom, |
920 | uint16_t left); |
921 | |
922 | } // extern "C" |
923 | |
924 | } // namespace types |
925 | } // namespace cbindgen_private |
926 | } // namespace slint |
927 | |