WIP: API to expose image loading from C++ and Rust

This commit is contained in:
Olivier Goffart 2021-05-28 12:13:49 +02:00 committed by Olivier Goffart
parent 4584c40544
commit 0b3fecf300
15 changed files with 140 additions and 68 deletions

View file

@ -11,26 +11,39 @@ LICENSE END */
#include <string_view> #include <string_view>
#include "sixtyfps_image_internal.h" #include "sixtyfps_image_internal.h"
#include "sixtyfps_string.h" #include "sixtyfps_string.h"
#include "sixtyfps_sharedvector.h"
namespace sixtyfps { namespace sixtyfps {
struct ImageReference /// An image type that can be displayed by the Image element
struct Image
{ {
public: public:
ImageReference() : data(Data::None()) { } Image() : data(Data::None()) { }
ImageReference(const SharedString &file_path) : data(Data::AbsoluteFilePath(file_path)) { }
friend bool operator==(const ImageReference &a, const ImageReference &b) { static Image load_from_path(const SharedString &file_path) {
Image img;
img.data = Data::AbsoluteFilePath(file_path);
return img;
}
static Image load_from_argb(int width, int height, const SharedVector<uint32_t> &data) {
Image img;
img.data = Data::EmbeddedRgbaImage(width, height, data);
return img;
}
friend bool operator==(const Image &a, const Image &b) {
return a.data == b.data; return a.data == b.data;
} }
friend bool operator!=(const ImageReference &a, const ImageReference &b) { friend bool operator!=(const Image &a, const Image &b) {
return a.data != b.data; return a.data != b.data;
} }
private: private:
using Tag = cbindgen_private::types::ImageReference::Tag; using Tag = cbindgen_private::types::ImageReference::Tag;
using Data = cbindgen_private::types::ImageReference; using Data = cbindgen_private::types::Image;
Data data; Data data;
}; };

View file

@ -195,7 +195,11 @@ fn to_eval_value<'cx>(
} }
}, },
Type::Image => { Type::Image => {
Ok(Value::Image(ImageReference::AbsoluteFilePath(val.to_string(cx)?.value().into()))) let path = val.to_string(cx)?.value();
Ok(Value::Image(
sixtyfps_corelib::graphics::Image::load_from_path(std::path::Path::new(&path))
.or_else(|_| cx.throw_error(format!("cannot load image {:?}", path)))?,
))
} }
Type::Bool => Ok(Value::Bool(val.downcast_or_throw::<JsBoolean, _>(cx)?.value())), Type::Bool => Ok(Value::Bool(val.downcast_or_throw::<JsBoolean, _>(cx)?.value())),
Type::Struct { fields, .. } => { Type::Struct { fields, .. } => {
@ -243,7 +247,7 @@ fn to_js_value<'cx>(
Value::Number(n) => JsNumber::new(cx, n).as_value(cx), Value::Number(n) => JsNumber::new(cx, n).as_value(cx),
Value::String(s) => JsString::new(cx, s.as_str()).as_value(cx), Value::String(s) => JsString::new(cx, s.as_str()).as_value(cx),
Value::Bool(b) => JsBoolean::new(cx, b).as_value(cx), Value::Bool(b) => JsBoolean::new(cx, b).as_value(cx),
Value::Image(r) => match r { Value::Image(r) => match r.0 {
ImageReference::None => JsUndefined::new().as_value(cx), ImageReference::None => JsUndefined::new().as_value(cx),
ImageReference::AbsoluteFilePath(path) => JsString::new(cx, path.as_str()).as_value(cx), ImageReference::AbsoluteFilePath(path) => JsString::new(cx, path.as_str()).as_value(cx),
ImageReference::EmbeddedData { .. } | ImageReference::EmbeddedRgbaImage { .. } => { ImageReference::EmbeddedData { .. } | ImageReference::EmbeddedRgbaImage { .. } => {

View file

@ -224,8 +224,9 @@ pub mod re_exports {
init_component_items, Component, ComponentRefPin, ComponentVTable, init_component_items, Component, ComponentRefPin, ComponentVTable,
}; };
pub use sixtyfps_corelib::graphics::{ pub use sixtyfps_corelib::graphics::{
Brush, GradientStop, LinearGradientBrush, PathArcTo, PathCubicTo, PathData, PathElement, Brush, GradientStop, Image, ImageReference, LinearGradientBrush, PathArcTo, PathCubicTo,
PathEvent, PathLineTo, PathMoveTo, PathQuadraticTo, Point, Rect, Size, PathData, PathElement, PathEvent, PathLineTo, PathMoveTo, PathQuadraticTo, Point, Rect,
Size,
}; };
pub use sixtyfps_corelib::input::{ pub use sixtyfps_corelib::input::{
FocusEvent, InputEventResult, KeyEvent, KeyEventResult, KeyboardModifiers, MouseEvent, FocusEvent, InputEventResult, KeyEvent, KeyEventResult, KeyboardModifiers, MouseEvent,
@ -242,7 +243,6 @@ pub mod re_exports {
pub use sixtyfps_corelib::window::ComponentWindow; pub use sixtyfps_corelib::window::ComponentWindow;
pub use sixtyfps_corelib::Color; pub use sixtyfps_corelib::Color;
pub use sixtyfps_corelib::ComponentVTable_static; pub use sixtyfps_corelib::ComponentVTable_static;
pub use sixtyfps_corelib::ImageReference;
pub use sixtyfps_corelib::SharedString; pub use sixtyfps_corelib::SharedString;
pub use sixtyfps_corelib::SharedVector; pub use sixtyfps_corelib::SharedVector;
pub use sixtyfps_rendering_backend_default::native_widgets::*; pub use sixtyfps_rendering_backend_default::native_widgets::*;

View file

@ -255,7 +255,7 @@ impl CppType for Type {
} }
Type::Array(i) => Some(format!("std::shared_ptr<sixtyfps::Model<{}>>", i.cpp_type()?)), Type::Array(i) => Some(format!("std::shared_ptr<sixtyfps::Model<{}>>", i.cpp_type()?)),
Type::Image => Some("sixtyfps::ImageReference".to_owned()), Type::Image => Some("sixtyfps::Image".to_owned()),
Type::Builtin(elem) => elem.native_class.cpp_type.clone(), Type::Builtin(elem) => elem.native_class.cpp_type.clone(),
Type::Enumeration(enumeration) => Some(format!("sixtyfps::{}", enumeration.name)), Type::Enumeration(enumeration) => Some(format!("sixtyfps::{}", enumeration.name)),
Type::Brush => Some("sixtyfps::Brush".to_owned()), Type::Brush => Some("sixtyfps::Brush".to_owned()),
@ -1613,8 +1613,8 @@ fn compile_expression(
} }
Expression::ImageReference(resource_ref) => { Expression::ImageReference(resource_ref) => {
match resource_ref { match resource_ref {
crate::expression_tree::ImageReference::None => format!(r#"sixtyfps::ImageReference()"#), crate::expression_tree::ImageReference::None => format!(r#"sixtyfps::Image()"#),
crate::expression_tree::ImageReference::AbsolutePath(path) => format!(r#"sixtyfps::ImageReference(sixtyfps::SharedString(u8"{}"))"#, escape_string(path.as_str())), crate::expression_tree::ImageReference::AbsolutePath(path) => format!(r#"sixtyfps::Image::load_from_path(sixtyfps::SharedString(u8"{}"))"#, escape_string(path.as_str())),
crate::expression_tree::ImageReference::EmbeddedData(_) => unimplemented!("The C++ generator does not support resource embedding yet") crate::expression_tree::ImageReference::EmbeddedData(_) => unimplemented!("The C++ generator does not support resource embedding yet")
} }
} }

View file

@ -39,7 +39,7 @@ fn rust_type(ty: &Type) -> Option<proc_macro2::TokenStream> {
Type::LogicalLength => Some(quote!(f32)), Type::LogicalLength => Some(quote!(f32)),
Type::Percent => Some(quote!(f32)), Type::Percent => Some(quote!(f32)),
Type::Bool => Some(quote!(bool)), Type::Bool => Some(quote!(bool)),
Type::Image => Some(quote!(sixtyfps::re_exports::ImageReference)), Type::Image => Some(quote!(sixtyfps::re_exports::Image)),
Type::Struct { fields, name: None, .. } => { Type::Struct { fields, name: None, .. } => {
let elem = fields.values().map(|v| rust_type(v)).collect::<Option<Vec<_>>>()?; let elem = fields.values().map(|v| rust_type(v)).collect::<Option<Vec<_>>>()?;
// This will produce a tuple // This will produce a tuple
@ -1335,14 +1335,18 @@ fn compile_expression(expr: &Expression, component: &Rc<Component>) -> TokenStre
Expression::ImageReference(resource_ref) => { Expression::ImageReference(resource_ref) => {
match resource_ref { match resource_ref {
crate::expression_tree::ImageReference::None => { crate::expression_tree::ImageReference::None => {
quote!(sixtyfps::re_exports::ImageReference::None) quote!(sixtyfps::re_exports::Image::default())
} }
crate::expression_tree::ImageReference::AbsolutePath(path) => { crate::expression_tree::ImageReference::AbsolutePath(path) => {
quote!(sixtyfps::re_exports::ImageReference::AbsoluteFilePath(sixtyfps::re_exports::SharedString::from(#path))) quote!(sixtyfps::re_exports::Image::load_from_path(sixtyfps::re_exports::SharedString::from(#path)))
}, },
crate::expression_tree::ImageReference::EmbeddedData(resource_id) => { crate::expression_tree::ImageReference::EmbeddedData(resource_id) => {
let symbol = format_ident!("SFPS_EMBEDDED_RESOURCE_{}", resource_id); let symbol = format_ident!("SFPS_EMBEDDED_RESOURCE_{}", resource_id);
quote!(sixtyfps::re_exports::ImageReference::EmbeddedData(#symbol.into())) quote!(
sixtyfps::re_exports::Image(
sixtyfps::re_exports::ImageReference::EmbeddedData(#symbol.into())
)
)
} }
} }
} }

View file

@ -42,31 +42,8 @@ pub use path::*;
mod brush; mod brush;
pub use brush::*; pub use brush::*;
/// A resource is a reference to binary data, for example images. They can be accessible on the file mod image;
/// system or embedded in the resulting binary. Or they might be URLs to a web server and a downloaded pub use self::image::*;
/// is necessary before they can be used.
///
/// TODO! If we want to make this type public API, we should not make it an enum, but an opaque type instead
#[derive(Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum ImageReference {
/// A resource that does not represent any data.
None,
/// A resource that points to a file in the file system
AbsoluteFilePath(crate::SharedString),
/// A resource that is embedded in the program and accessible via pointer
/// The format is the same as in a file
EmbeddedData(super::slice::Slice<'static, u8>),
/// Raw ARGB
#[allow(missing_docs)]
EmbeddedRgbaImage { width: u32, height: u32, data: super::sharedvector::SharedVector<u32> },
}
impl Default for ImageReference {
fn default() -> Self {
ImageReference::None
}
}
/// CachedGraphicsData allows the graphics backend to store an arbitrary piece of data associated with /// CachedGraphicsData allows the graphics backend to store an arbitrary piece of data associated with
/// an item, which is typically computed by accessing properties. The dependency_tracker is used to allow /// an item, which is typically computed by accessing properties. The dependency_tracker is used to allow

View file

@ -0,0 +1,65 @@
/* LICENSE BEGIN
This file is part of the SixtyFPS Project -- https://sixtyfps.io
Copyright (c) 2020 Olivier Goffart <olivier.goffart@sixtyfps.io>
Copyright (c) 2020 Simon Hausmann <simon.hausmann@sixtyfps.io>
SPDX-License-Identifier: GPL-3.0-only
This file is also available under commercial licensing terms.
Please contact info@sixtyfps.io for more information.
LICENSE END */
use crate::slice::Slice;
use crate::{SharedString, SharedVector};
/// A resource is a reference to binary data, for example images. They can be accessible on the file
/// system or embedded in the resulting binary. Or they might be URLs to a web server and a downloaded
/// is necessary before they can be used.
#[derive(Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum ImageReference {
/// A resource that does not represent any data.
None,
/// A resource that points to a file in the file system
AbsoluteFilePath(SharedString),
/// A resource that is embedded in the program and accessible via pointer
/// The format is the same as in a file
EmbeddedData(Slice<'static, u8>),
/// Raw ARGB
#[allow(missing_docs)]
EmbeddedRgbaImage { width: u32, height: u32, data: SharedVector<u32> },
}
impl Default for ImageReference {
fn default() -> Self {
ImageReference::None
}
}
/// Error generated if an image cannot be loaded for any reasons.
#[derive(Default, Debug, PartialEq)]
pub struct LoadImageError(());
/// An image type that can be displayed by the Image element
#[repr(transparent)]
#[derive(Default, Clone, Debug, PartialEq)]
// FIXME: the inner should be private
pub struct Image(pub ImageReference);
impl Image {
/// Create an Image from a path to a file containing an image
pub fn load_from_path(path: &std::path::Path) -> Result<Self, LoadImageError> {
Ok(Image(ImageReference::AbsoluteFilePath(path.to_str().ok_or(LoadImageError(()))?.into())))
}
/// Create an image from argb pixels
pub fn load_from_argb(
width: u32,
height: u32,
data: SharedVector<u32>,
) -> Result<Self, LoadImageError> {
if data.len() != width as usize * height as usize {
Err(LoadImageError(()))
} else {
Ok(Image(ImageReference::EmbeddedRgbaImage { width, height, data }))
}
}
}

View file

@ -20,7 +20,7 @@ When adding an item or a property, it needs to be kept in sync with different pl
- Don't forget to update the documentation - Don't forget to update the documentation
*/ */
use super::{Item, ItemConsts, ItemRc}; use super::{Item, ItemConsts, ItemRc};
use crate::graphics::{ImageReference, Rect}; use crate::graphics::Rect;
use crate::input::{ use crate::input::{
FocusEvent, InputEventFilterResult, InputEventResult, KeyEvent, KeyEventResult, MouseEvent, FocusEvent, InputEventFilterResult, InputEventResult, KeyEvent, KeyEventResult, MouseEvent,
}; };
@ -55,7 +55,7 @@ impl Default for ImageFit {
#[pin] #[pin]
/// The implementation of the `Image` element /// The implementation of the `Image` element
pub struct ImageItem { pub struct ImageItem {
pub source: Property<ImageReference>, pub source: Property<crate::graphics::Image>,
pub x: Property<f32>, pub x: Property<f32>,
pub y: Property<f32>, pub y: Property<f32>,
pub width: Property<f32>, pub width: Property<f32>,
@ -72,7 +72,7 @@ impl Item for ImageItem {
} }
fn layouting_info(self: Pin<&Self>, window: &ComponentWindow) -> LayoutInfo { fn layouting_info(self: Pin<&Self>, window: &ComponentWindow) -> LayoutInfo {
let natural_size = window.0.image_size(&self.source()); let natural_size = window.0.image_size(&self.source().0);
LayoutInfo { LayoutInfo {
preferred_width: natural_size.width, preferred_width: natural_size.width,
preferred_height: natural_size.height, preferred_height: natural_size.height,
@ -121,7 +121,7 @@ impl ItemConsts for ImageItem {
#[pin] #[pin]
/// The implementation of the `ClippedImage` element /// The implementation of the `ClippedImage` element
pub struct ClippedImage { pub struct ClippedImage {
pub source: Property<ImageReference>, pub source: Property<crate::graphics::Image>,
pub x: Property<f32>, pub x: Property<f32>,
pub y: Property<f32>, pub y: Property<f32>,
pub width: Property<f32>, pub width: Property<f32>,
@ -143,7 +143,7 @@ impl Item for ClippedImage {
} }
fn layouting_info(self: Pin<&Self>, window: &ComponentWindow) -> LayoutInfo { fn layouting_info(self: Pin<&Self>, window: &ComponentWindow) -> LayoutInfo {
let natural_size = window.0.image_size(&self.source()); let natural_size = window.0.image_size(&self.source().0);
LayoutInfo { LayoutInfo {
preferred_width: natural_size.width, preferred_width: natural_size.width,
preferred_height: natural_size.height, preferred_height: natural_size.height,

View file

@ -32,7 +32,7 @@ declare_ValueType![
f32, f32,
f64, f64,
crate::SharedString, crate::SharedString,
crate::ImageReference, crate::graphics::Image,
crate::Color, crate::Color,
crate::PathData, crate::PathData,
crate::animations::EasingCurve, crate::animations::EasingCurve,

View file

@ -10,7 +10,8 @@ LICENSE END */
use core::convert::TryInto; use core::convert::TryInto;
use sixtyfps_compilerlib::langtype::Type as LangType; use sixtyfps_compilerlib::langtype::Type as LangType;
use sixtyfps_corelib::{Brush, ImageReference, PathData, SharedString, SharedVector}; use sixtyfps_corelib::graphics::Image;
use sixtyfps_corelib::{Brush, PathData, SharedString, SharedVector};
use std::collections::HashMap; use std::collections::HashMap;
use std::iter::FromIterator; use std::iter::FromIterator;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -40,6 +41,8 @@ pub enum ValueType {
Struct, Struct,
/// Correspond to `brush` or `color` type in .60. For color, this is then a [`Brush::SolidColor`] /// Correspond to `brush` or `color` type in .60. For color, this is then a [`Brush::SolidColor`]
Brush, Brush,
/// Correspond to `image` type in .60.
Image,
/// The type is not a public type but something internal. /// The type is not a public type but something internal.
Other = -1, Other = -1,
} }
@ -92,7 +95,7 @@ pub enum Value {
Bool(bool), Bool(bool),
#[doc(hidden)] #[doc(hidden)]
/// Correspond to the `image` type in .60 /// Correspond to the `image` type in .60
Image(ImageReference), Image(Image),
/// An Array in the .60 language. /// An Array in the .60 language.
Array(SharedVector<Value>), Array(SharedVector<Value>),
/// A more complex model which is not created by the interpreter itself (Value::Array can also be used for model) /// A more complex model which is not created by the interpreter itself (Value::Array can also be used for model)
@ -212,7 +215,7 @@ macro_rules! declare_value_conversion {
declare_value_conversion!(Number => [u32, u64, i32, i64, f32, f64, usize, isize] ); declare_value_conversion!(Number => [u32, u64, i32, i64, f32, f64, usize, isize] );
declare_value_conversion!(String => [SharedString] ); declare_value_conversion!(String => [SharedString] );
declare_value_conversion!(Bool => [bool] ); declare_value_conversion!(Bool => [bool] );
declare_value_conversion!(Image => [ImageReference] ); declare_value_conversion!(Image => [Image] );
declare_value_conversion!(Struct => [Struct] ); declare_value_conversion!(Struct => [Struct] );
declare_value_conversion!(Brush => [Brush] ); declare_value_conversion!(Brush => [Brush] );
declare_value_conversion!(PathElements => [PathData]); declare_value_conversion!(PathElements => [PathData]);

View file

@ -18,7 +18,6 @@ use sixtyfps_compilerlib::object_tree::{Element, ElementRc};
use sixtyfps_compilerlib::*; use sixtyfps_compilerlib::*;
use sixtyfps_compilerlib::{diagnostics::BuildDiagnostics, object_tree::PropertyDeclaration}; use sixtyfps_compilerlib::{diagnostics::BuildDiagnostics, object_tree::PropertyDeclaration};
use sixtyfps_corelib::component::{Component, ComponentRef, ComponentRefPin, ComponentVTable}; use sixtyfps_corelib::component::{Component, ComponentRef, ComponentRefPin, ComponentVTable};
use sixtyfps_corelib::graphics::ImageReference;
use sixtyfps_corelib::item_tree::{ use sixtyfps_corelib::item_tree::{
ItemTreeNode, ItemVisitorRefMut, ItemVisitorVTable, TraversalOrder, VisitChildrenResult, ItemTreeNode, ItemVisitorRefMut, ItemVisitorVTable, TraversalOrder, VisitChildrenResult,
}; };
@ -750,7 +749,7 @@ pub(crate) fn generate_component<'id>(
Type::Angle => animated_property_info::<f32>(), Type::Angle => animated_property_info::<f32>(),
Type::PhysicalLength => animated_property_info::<f32>(), Type::PhysicalLength => animated_property_info::<f32>(),
Type::LogicalLength => animated_property_info::<f32>(), Type::LogicalLength => animated_property_info::<f32>(),
Type::Image => property_info::<ImageReference>(), Type::Image => property_info::<sixtyfps_corelib::graphics::Image>(),
Type::Bool => property_info::<bool>(), Type::Bool => property_info::<bool>(),
Type::Callback { .. } => { Type::Callback { .. } => {
custom_callbacks.insert(name.clone(), builder.add_field_type::<Callback>()); custom_callbacks.insert(name.clone(), builder.add_field_type::<Callback>());

View file

@ -16,7 +16,7 @@ use corelib::graphics::{GradientStop, LinearGradientBrush, PathElement};
use corelib::items::{ItemRef, PropertyAnimation}; use corelib::items::{ItemRef, PropertyAnimation};
use corelib::rtti::AnimatedBindingKind; use corelib::rtti::AnimatedBindingKind;
use corelib::window::ComponentWindow; use corelib::window::ComponentWindow;
use corelib::{Brush, Color, ImageReference, PathData, SharedString, SharedVector}; use corelib::{Brush, Color, PathData, SharedString, SharedVector};
use sixtyfps_compilerlib::expression_tree::{ use sixtyfps_compilerlib::expression_tree::{
BindingExpression, BuiltinFunction, EasingCurve, Expression, Path as ExprPath, BindingExpression, BuiltinFunction, EasingCurve, Expression, Path as ExprPath,
PathElement as ExprPathElement, PathElement as ExprPathElement,
@ -468,15 +468,18 @@ pub fn eval_expression(e: &Expression, local_context: &mut EvalLocalContext) ->
} }
} }
Expression::ImageReference(resource_ref) => { Expression::ImageReference(resource_ref) => {
match resource_ref { Value::Image(match resource_ref {
sixtyfps_compilerlib::expression_tree::ImageReference::None => { sixtyfps_compilerlib::expression_tree::ImageReference::None => {
Value::Image(ImageReference::None) Ok(Default::default())
} }
sixtyfps_compilerlib::expression_tree::ImageReference::AbsolutePath(path) => { sixtyfps_compilerlib::expression_tree::ImageReference::AbsolutePath(path) => {
Value::Image(ImageReference::AbsoluteFilePath(path.into())) corelib::graphics::Image::load_from_path(std::path::Path::new(path))
} }
sixtyfps_compilerlib::expression_tree::ImageReference::EmbeddedData(_) => panic!("Resource embedding is not supported by the interpreter") sixtyfps_compilerlib::expression_tree::ImageReference::EmbeddedData(_) => panic!("Resource embedding is not supported by the interpreter")
} }.unwrap_or_else(|_| {
eprintln!("Could not load image {:?}",resource_ref );
Default::default()
}))
} }
Expression::Condition { condition, true_expr, false_expr } => { Expression::Condition { condition, true_expr, false_expr } => {
match eval_expression(&**condition, local_context).try_into() match eval_expression(&**condition, local_context).try_into()

View file

@ -22,7 +22,7 @@ use std::pin::Pin;
use std::rc::Rc; use std::rc::Rc;
use sixtyfps_corelib::graphics::{ use sixtyfps_corelib::graphics::{
Brush, Color, FontRequest, ImageReference, IntRect, Point, Rect, RenderingCache, Size, Brush, Color, FontRequest, Image, IntRect, Point, Rect, RenderingCache, Size,
}; };
use sixtyfps_corelib::item_rendering::{CachedRenderingData, ItemRenderer}; use sixtyfps_corelib::item_rendering::{CachedRenderingData, ItemRenderer};
use sixtyfps_corelib::items::{ use sixtyfps_corelib::items::{
@ -30,7 +30,8 @@ use sixtyfps_corelib::items::{
}; };
use sixtyfps_corelib::properties::Property; use sixtyfps_corelib::properties::Property;
use sixtyfps_corelib::window::ComponentWindow; use sixtyfps_corelib::window::ComponentWindow;
use sixtyfps_corelib::SharedString;
use sixtyfps_corelib::{ImageReference, SharedString};
mod graphics_window; mod graphics_window;
use graphics_window::*; use graphics_window::*;
@ -241,6 +242,7 @@ impl OpenGLContext {
(Self::Current(windowed_context), renderer) (Self::Current(windowed_context), renderer)
} }
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
{ {
use wasm_bindgen::JsCast; use wasm_bindgen::JsCast;
@ -1353,7 +1355,7 @@ impl GLItemRenderer {
fn draw_image_impl( fn draw_image_impl(
&mut self, &mut self,
item_cache: &CachedRenderingData, item_cache: &CachedRenderingData,
source_property: std::pin::Pin<&Property<ImageReference>>, source_property: std::pin::Pin<&Property<Image>>,
source_clip_rect: IntRect, source_clip_rect: IntRect,
target_width: std::pin::Pin<&Property<f32>>, target_width: std::pin::Pin<&Property<f32>>,
target_height: std::pin::Pin<&Property<f32>>, target_height: std::pin::Pin<&Property<f32>>,
@ -1374,7 +1376,7 @@ impl GLItemRenderer {
.borrow_mut() .borrow_mut()
.load_item_graphics_cache_with_function(item_cache, || { .load_item_graphics_cache_with_function(item_cache, || {
self.shared_data self.shared_data
.load_image_resource(&source_property.get()) .load_image_resource(&source_property.get().0)
.and_then(|cached_image| { .and_then(|cached_image| {
cached_image.as_renderable( cached_image.as_renderable(
// The condition at the entry of the function ensures that width/height are positive // The condition at the entry of the function ensures that width/height are positive

View file

@ -10,7 +10,7 @@ LICENSE END */
use cpp::*; use cpp::*;
use items::{ImageFit, TextHorizontalAlignment, TextVerticalAlignment}; use items::{ImageFit, TextHorizontalAlignment, TextVerticalAlignment};
use sixtyfps_corelib::graphics::{Brush, FontRequest, Point, Rect, RenderingCache, Size}; use sixtyfps_corelib::graphics::{Brush, FontRequest, Image, Point, Rect, RenderingCache, Size};
use sixtyfps_corelib::input::{InternalKeyCode, KeyEvent, KeyEventType, MouseEvent}; use sixtyfps_corelib::input::{InternalKeyCode, KeyEvent, KeyEventType, MouseEvent};
use sixtyfps_corelib::item_rendering::{CachedRenderingData, ItemRenderer}; use sixtyfps_corelib::item_rendering::{CachedRenderingData, ItemRenderer};
use sixtyfps_corelib::items::{self, FillRule, ItemRef, TextOverflow, TextWrap}; use sixtyfps_corelib::items::{self, FillRule, ItemRef, TextOverflow, TextWrap};
@ -820,7 +820,7 @@ impl QtItemRenderer<'_> {
fn draw_image_impl( fn draw_image_impl(
&mut self, &mut self,
item_cache: &CachedRenderingData, item_cache: &CachedRenderingData,
source_property: Pin<&Property<ImageReference>>, source_property: Pin<&Property<Image>>,
dest_rect: qttypes::QRectF, dest_rect: qttypes::QRectF,
source_rect: Option<qttypes::QRectF>, source_rect: Option<qttypes::QRectF>,
target_width: std::pin::Pin<&Property<f32>>, target_width: std::pin::Pin<&Property<f32>>,
@ -851,7 +851,7 @@ impl QtItemRenderer<'_> {
None None
}; };
load_image_from_resource(&source_property.get(), source_size, image_fit).map_or( load_image_from_resource(&source_property.get().0, source_size, image_fit).map_or(
QtRenderingCacheItem::Invalid, QtRenderingCacheItem::Invalid,
|mut pixmap: qttypes::QPixmap| { |mut pixmap: qttypes::QPixmap| {
let colorize = colorize_property.map_or(Brush::default(), |c| c.get()); let colorize = colorize_property.map_or(Brush::default(), |c| c.get());

View file

@ -110,6 +110,7 @@ fn gen_corelib(root_dir: &Path, include_dir: &Path) -> anyhow::Result<()> {
"SharedString", "SharedString",
"SharedVector", "SharedVector",
"ImageReference", "ImageReference",
"Image",
"Color", "Color",
"PathData", "PathData",
"PathElement", "PathElement",
@ -179,7 +180,7 @@ fn gen_corelib(root_dir: &Path, include_dir: &Path) -> anyhow::Result<()> {
.write_to_file(include_dir.join("sixtyfps_properties_internal.h")); .write_to_file(include_dir.join("sixtyfps_properties_internal.h"));
for (rust_types, extra_excluded_types, internal_header) in [ for (rust_types, extra_excluded_types, internal_header) in [
(vec!["ImageReference"], vec![], "sixtyfps_image_internal.h"), (vec!["ImageReference", "Image"], vec![], "sixtyfps_image_internal.h"),
( (
vec!["Color", "sixtyfps_color_brighter", "sixtyfps_color_darker"], vec!["Color", "sixtyfps_color_brighter", "sixtyfps_color_darker"],
vec![], vec![],
@ -248,6 +249,7 @@ fn gen_corelib(root_dir: &Path, include_dir: &Path) -> anyhow::Result<()> {
.with_src(crate_dir.join("graphics/color.rs")) .with_src(crate_dir.join("graphics/color.rs"))
.with_src(crate_dir.join("graphics/path.rs")) .with_src(crate_dir.join("graphics/path.rs"))
.with_src(crate_dir.join("graphics/brush.rs")) .with_src(crate_dir.join("graphics/brush.rs"))
.with_src(crate_dir.join("graphics/image.rs"))
.with_src(crate_dir.join("animations.rs")) .with_src(crate_dir.join("animations.rs"))
// .with_src(crate_dir.join("input.rs")) // .with_src(crate_dir.join("input.rs"))
.with_src(crate_dir.join("item_rendering.rs")) .with_src(crate_dir.join("item_rendering.rs"))