mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-30 13:51:13 +00:00
Add a viewer tool
This commit is contained in:
parent
f88d856990
commit
7d1394e349
4 changed files with 199 additions and 3 deletions
|
@ -6,6 +6,7 @@ members = [
|
||||||
'sixtyfps_compiler/parser_test_macro',
|
'sixtyfps_compiler/parser_test_macro',
|
||||||
'api/sixtyfps-rs',
|
'api/sixtyfps-rs',
|
||||||
'api/sixtyfps-rs/sixtyfps-rs-macro',
|
'api/sixtyfps-rs/sixtyfps-rs-macro',
|
||||||
|
'tools/viewer',
|
||||||
'examples/graphicstest',
|
'examples/graphicstest',
|
||||||
'examples/rusttest',
|
'examples/rusttest',
|
||||||
'helper_crates/const-field-offset',
|
'helper_crates/const-field-offset',
|
||||||
|
|
|
@ -66,12 +66,12 @@ pub fn const_field_offset(input: TokenStream) -> TokenStream {
|
||||||
|
|
||||||
// Build the output, possibly using quasi-quotation
|
// Build the output, possibly using quasi-quotation
|
||||||
let expanded = quote! {
|
let expanded = quote! {
|
||||||
struct #field_struct_name {
|
pub struct #field_struct_name {
|
||||||
#(#fields : usize,)*
|
#(pub #fields : usize,)*
|
||||||
}
|
}
|
||||||
|
|
||||||
impl #struct_name {
|
impl #struct_name {
|
||||||
/*pub ??? */ const fn field_offsets() -> #field_struct_name {
|
pub const fn field_offsets() -> #field_struct_name {
|
||||||
let mut len = 0usize;
|
let mut len = 0usize;
|
||||||
#field_struct_name {
|
#field_struct_name {
|
||||||
#( #fields : {
|
#( #fields : {
|
||||||
|
|
20
tools/viewer/Cargo.toml
Normal file
20
tools/viewer/Cargo.toml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
[package]
|
||||||
|
name = "viewer"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Olivier Goffart <ogoffart@sixtyfps.io>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
corelib = { path="../../sixtyfps_runtime/corelib" }
|
||||||
|
sixtyfps_compiler = { path = "../../sixtyfps_compiler", features = ["display-diagnostics"] }
|
||||||
|
# FIXME: make optional and configurable backends
|
||||||
|
gl = { path = "../../sixtyfps_runtime/rendering_backends/gl" }
|
||||||
|
structopt = "0.3.14"
|
||||||
|
codemap-diagnostic = "0.1.1"
|
||||||
|
codemap = "0.1"
|
||||||
|
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "viewer"
|
||||||
|
path = "main.rs"
|
175
tools/viewer/main.rs
Normal file
175
tools/viewer/main.rs
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
use corelib::abi::datastructures::{ComponentImpl, ComponentType};
|
||||||
|
use sixtyfps_compiler::object_tree::Expression;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use structopt::StructOpt;
|
||||||
|
|
||||||
|
#[derive(StructOpt)]
|
||||||
|
struct Cli {
|
||||||
|
#[structopt(name = "path to .60 file", parse(from_os_str))]
|
||||||
|
path: std::path::PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
trait PropertyWriter {
|
||||||
|
unsafe fn write(ptr: *mut u8, value: &Expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PropertyWriter for f32 {
|
||||||
|
unsafe fn write(ptr: *mut u8, value: &Expression) {
|
||||||
|
let val: Self = match value {
|
||||||
|
Expression::NumberLiteral(v) => *v as _,
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
std::ptr::write(ptr as *mut Self, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PropertyWriter for u32 {
|
||||||
|
unsafe fn write(ptr: *mut u8, value: &Expression) {
|
||||||
|
let val: Self = match value {
|
||||||
|
Expression::NumberLiteral(v) => *v as _,
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
std::ptr::write(ptr as *mut Self, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PropertyWriter for *const i8 {
|
||||||
|
unsafe fn write(ptr: *mut u8, value: &Expression) {
|
||||||
|
let val: Self = match value {
|
||||||
|
Expression::StringLiteral(v) => {
|
||||||
|
// FIXME that's a leak
|
||||||
|
std::ffi::CString::new(v.as_str()).unwrap().into_raw() as _
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
std::ptr::write(ptr as *mut Self, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn construct<T: Default>(ptr: *mut corelib::abi::datastructures::ItemImpl) {
|
||||||
|
core::ptr::write(ptr as *mut T, T::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn set_property<T: PropertyWriter>(ptr: *mut u8, e: &Expression) {
|
||||||
|
T::write(ptr, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn dummy_destroy(_: *const ComponentType, _: *mut ComponentImpl) {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
struct MyComponentType {
|
||||||
|
ct: ComponentType,
|
||||||
|
it: Vec<corelib::abi::datastructures::ItemTreeNode>,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn item_tree(
|
||||||
|
c: *const ComponentType,
|
||||||
|
) -> *const corelib::abi::datastructures::ItemTreeNode {
|
||||||
|
(*(c as *const MyComponentType)).it.as_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RuntimeTypeInfo {
|
||||||
|
vtable: *const corelib::abi::datastructures::ItemVTable,
|
||||||
|
construct: unsafe fn(*mut corelib::abi::datastructures::ItemImpl),
|
||||||
|
properties: HashMap<&'static str, (usize, unsafe fn(*mut u8, &Expression))>,
|
||||||
|
size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> std::io::Result<()> {
|
||||||
|
use sixtyfps_compiler::*;
|
||||||
|
let args = Cli::from_args();
|
||||||
|
let source = std::fs::read_to_string(&args.path)?;
|
||||||
|
let (syntax_node, mut diag) = parser::parse(&source);
|
||||||
|
let tr = typeregister::TypeRegister::builtin();
|
||||||
|
let tree = object_tree::Document::from_node(syntax_node, &mut diag, &tr);
|
||||||
|
if !diag.inner.is_empty() {
|
||||||
|
diag.print(args.path.to_string_lossy().into_owned(), source);
|
||||||
|
std::process::exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
use corelib::abi::primitives::{Image, Rectangle};
|
||||||
|
|
||||||
|
// FIXME: thus obviously is unsafe and not great
|
||||||
|
let mut rtti = HashMap::new();
|
||||||
|
rtti.insert(
|
||||||
|
"Rectangle",
|
||||||
|
RuntimeTypeInfo {
|
||||||
|
vtable: &corelib::abi::primitives::RectangleVTable as _,
|
||||||
|
construct: construct::<Rectangle>,
|
||||||
|
properties: [
|
||||||
|
("x", (Rectangle::field_offsets().x, set_property::<f32> as _)),
|
||||||
|
("y", (Rectangle::field_offsets().y, set_property::<f32> as _)),
|
||||||
|
("width", (Rectangle::field_offsets().width, set_property::<f32> as _)),
|
||||||
|
("height", (Rectangle::field_offsets().height, set_property::<f32> as _)),
|
||||||
|
("color", (Rectangle::field_offsets().color, set_property::<u32> as _)),
|
||||||
|
]
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.collect(),
|
||||||
|
size: std::mem::size_of::<Rectangle>(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
rtti.insert(
|
||||||
|
"Image",
|
||||||
|
RuntimeTypeInfo {
|
||||||
|
vtable: &corelib::abi::primitives::ImageVTable as _,
|
||||||
|
construct: construct::<Image>,
|
||||||
|
properties: [
|
||||||
|
("x", (Image::field_offsets().x, set_property::<f32> as _)),
|
||||||
|
("y", (Image::field_offsets().y, set_property::<f32> as _)),
|
||||||
|
("width", (Image::field_offsets().width, set_property::<f32> as _)),
|
||||||
|
("height", (Image::field_offsets().height, set_property::<f32> as _)),
|
||||||
|
("source", (Image::field_offsets().source, set_property::<*const i8> as _)),
|
||||||
|
]
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.collect(),
|
||||||
|
size: std::mem::size_of::<Image>(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let l = lower::LoweredComponent::lower(&*tree.root_component);
|
||||||
|
|
||||||
|
let mut tree_array = vec![];
|
||||||
|
let mut current_offset = 0usize;
|
||||||
|
let mut items_types = vec![];
|
||||||
|
|
||||||
|
generator::build_array_helper(&l, |item, child_offset| {
|
||||||
|
let rt = &rtti[&*item.native_type.class_name];
|
||||||
|
tree_array.push(corelib::abi::datastructures::ItemTreeNode::Item {
|
||||||
|
offset: current_offset as isize,
|
||||||
|
vtable: rt.vtable,
|
||||||
|
children_index: child_offset,
|
||||||
|
chilren_count: item.children.len() as _,
|
||||||
|
});
|
||||||
|
items_types.push((current_offset, rt, item.init_properties.clone()));
|
||||||
|
current_offset += rt.size;
|
||||||
|
});
|
||||||
|
|
||||||
|
let t = ComponentType { create: None, destroy: dummy_destroy, item_tree };
|
||||||
|
let t = MyComponentType { ct: t, it: tree_array };
|
||||||
|
|
||||||
|
let mut my_impl = Vec::<u64>::new();
|
||||||
|
my_impl.resize(current_offset / 8 + 1, 0);
|
||||||
|
let mem = my_impl.as_mut_ptr() as *mut u8;
|
||||||
|
|
||||||
|
for (offset, rtti, properties) in items_types {
|
||||||
|
unsafe {
|
||||||
|
let item = mem.offset(offset as isize);
|
||||||
|
(rtti.construct)(item as _);
|
||||||
|
for (prop, expr) in properties {
|
||||||
|
let (o, set) = rtti.properties[&*prop];
|
||||||
|
set(item.offset(o as isize), &expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gl::sixtyfps_runtime_run_component_with_gl_renderer(
|
||||||
|
&t as *const MyComponentType as *const ComponentType,
|
||||||
|
std::ptr::NonNull::new(mem).unwrap().cast(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue