mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 22:31:14 +00:00
Simplify compiled path data structure
Use two arrays, one for events and one for coordinates. That simplifies the code generator and the generated code, and it also provides for a more compact memory representation.
This commit is contained in:
parent
264b1f650f
commit
4b6e549b96
7 changed files with 254 additions and 313 deletions
|
@ -8,12 +8,8 @@ namespace sixtyfps {
|
||||||
using internal::types::PathArcTo;
|
using internal::types::PathArcTo;
|
||||||
using internal::types::PathElement;
|
using internal::types::PathElement;
|
||||||
using internal::types::PathEvent;
|
using internal::types::PathEvent;
|
||||||
using internal::types::PathEventBegin;
|
|
||||||
using internal::types::PathEventCubic;
|
|
||||||
using internal::types::PathEventEnd;
|
|
||||||
using internal::types::PathEventLine;
|
|
||||||
using internal::types::PathEventQuadratic;
|
|
||||||
using internal::types::PathLineTo;
|
using internal::types::PathLineTo;
|
||||||
|
using internal::types::Point;
|
||||||
|
|
||||||
struct PathElements
|
struct PathElements
|
||||||
{
|
{
|
||||||
|
@ -26,8 +22,9 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PathElements(const PathEvent *firstEvent, size_t count)
|
PathElements(const PathEvent *firstEvent, size_t event_count, const Point *firstCoordinate,
|
||||||
: data(Data::PathEvents(events_from_array(firstEvent, count)))
|
size_t coordinate_count)
|
||||||
|
: data(events_from_array(firstEvent, event_count, firstCoordinate, coordinate_count))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,11 +37,16 @@ private:
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SharedArray<PathEvent> events_from_array(const PathEvent *firstEvent, size_t count)
|
static internal::types::PathElements events_from_array(const PathEvent *firstEvent,
|
||||||
|
size_t event_count,
|
||||||
|
const Point *firstCoordinate,
|
||||||
|
size_t coordinate_count)
|
||||||
{
|
{
|
||||||
SharedArray<PathEvent> tmp;
|
SharedArray<PathEvent> events;
|
||||||
sixtyfps_new_path_events(&tmp, firstEvent, count);
|
SharedArray<Point> coordinates;
|
||||||
return tmp;
|
sixtyfps_new_path_events(&events, &coordinates, firstEvent, event_count, firstCoordinate,
|
||||||
|
coordinate_count);
|
||||||
|
return Data::PathEvents(events, coordinates);
|
||||||
}
|
}
|
||||||
|
|
||||||
using Data = internal::types::PathElements;
|
using Data = internal::types::PathElements;
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
use neon::prelude::*;
|
use neon::prelude::*;
|
||||||
use sixtyfps_compilerlib::typeregister::Type;
|
use sixtyfps_compilerlib::typeregister::Type;
|
||||||
use sixtyfps_corelib::abi::datastructures::{
|
use sixtyfps_corelib::abi::datastructures::{PathArcTo, PathElement, PathLineTo, Resource};
|
||||||
PathArcTo, PathElement, PathEvent, PathEventBegin, PathEventCubic, PathEventEnd, PathEventLine,
|
|
||||||
PathEventQuadratic, PathLineTo, Resource,
|
|
||||||
};
|
|
||||||
use sixtyfps_corelib::{ComponentRefPin, EvaluationContext};
|
use sixtyfps_corelib::{ComponentRefPin, EvaluationContext};
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -235,79 +232,7 @@ fn to_js_value<'cx>(
|
||||||
}
|
}
|
||||||
js_array.as_value(cx)
|
js_array.as_value(cx)
|
||||||
} else {
|
} else {
|
||||||
let events_iter = elements.events_iter().unwrap();
|
todo!()
|
||||||
let js_array = JsArray::new(cx, events_iter.len() as _);
|
|
||||||
for (i, event) in events_iter.enumerate() {
|
|
||||||
let element_object = JsObject::new(cx);
|
|
||||||
|
|
||||||
match event {
|
|
||||||
PathEvent::Begin(PathEventBegin { x, y }) => {
|
|
||||||
set_string_property(cx, &element_object, "type", "event_begin")?;
|
|
||||||
set_float_property(cx, &element_object, "x", *x)?;
|
|
||||||
set_float_property(cx, &element_object, "y", *y)?;
|
|
||||||
}
|
|
||||||
PathEvent::Line(PathEventLine { from_x, from_y, to_x, to_y }) => {
|
|
||||||
set_string_property(cx, &element_object, "type", "event_line")?;
|
|
||||||
set_float_property(cx, &element_object, "from_x", *from_x)?;
|
|
||||||
set_float_property(cx, &element_object, "from_y", *from_y)?;
|
|
||||||
set_float_property(cx, &element_object, "to_x", *to_x)?;
|
|
||||||
set_float_property(cx, &element_object, "to_y", *to_y)?;
|
|
||||||
}
|
|
||||||
PathEvent::Quadratic(PathEventQuadratic {
|
|
||||||
from_x,
|
|
||||||
from_y,
|
|
||||||
control_x,
|
|
||||||
control_y,
|
|
||||||
to_x,
|
|
||||||
to_y,
|
|
||||||
}) => {
|
|
||||||
set_string_property(cx, &element_object, "type", "event_quadratic")?;
|
|
||||||
set_float_property(cx, &element_object, "from_x", *from_x)?;
|
|
||||||
set_float_property(cx, &element_object, "from_y", *from_y)?;
|
|
||||||
set_float_property(cx, &element_object, "control_x", *control_x)?;
|
|
||||||
set_float_property(cx, &element_object, "control_y", *control_y)?;
|
|
||||||
set_float_property(cx, &element_object, "to_x", *to_x)?;
|
|
||||||
set_float_property(cx, &element_object, "to_y", *to_y)?;
|
|
||||||
}
|
|
||||||
PathEvent::Cubic(PathEventCubic {
|
|
||||||
from_x,
|
|
||||||
from_y,
|
|
||||||
control1_x,
|
|
||||||
control1_y,
|
|
||||||
control2_x,
|
|
||||||
control2_y,
|
|
||||||
to_x,
|
|
||||||
to_y,
|
|
||||||
}) => {
|
|
||||||
set_string_property(cx, &element_object, "type", "event_cubic")?;
|
|
||||||
set_float_property(cx, &element_object, "from_x", *from_x)?;
|
|
||||||
set_float_property(cx, &element_object, "from_y", *from_y)?;
|
|
||||||
set_float_property(cx, &element_object, "control1_x", *control1_x)?;
|
|
||||||
set_float_property(cx, &element_object, "control1_y", *control1_y)?;
|
|
||||||
set_float_property(cx, &element_object, "control2_x", *control2_x)?;
|
|
||||||
set_float_property(cx, &element_object, "control2_y", *control2_y)?;
|
|
||||||
set_float_property(cx, &element_object, "to_x", *to_x)?;
|
|
||||||
set_float_property(cx, &element_object, "to_y", *to_y)?;
|
|
||||||
}
|
|
||||||
PathEvent::End(PathEventEnd {
|
|
||||||
first_x,
|
|
||||||
first_y,
|
|
||||||
last_x,
|
|
||||||
last_y,
|
|
||||||
close,
|
|
||||||
}) => {
|
|
||||||
set_string_property(cx, &element_object, "type", "event_end")?;
|
|
||||||
set_float_property(cx, &element_object, "first_x", *first_x)?;
|
|
||||||
set_float_property(cx, &element_object, "first_y", *first_y)?;
|
|
||||||
set_float_property(cx, &element_object, "last_x", *last_x)?;
|
|
||||||
set_float_property(cx, &element_object, "last_y", *last_y)?;
|
|
||||||
set_bool_property(cx, &element_object, "close", *close)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
js_array.set(cx, i as u32, element_object)?;
|
|
||||||
}
|
|
||||||
js_array.as_value(cx)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -931,23 +931,6 @@ fn compute_layout(component: &Rc<Component>) -> Vec<String> {
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_path_event(event_name: &str, fields: &[(&str, String)]) -> String {
|
|
||||||
let fields_initialization: Vec<String> = fields
|
|
||||||
.iter()
|
|
||||||
.map(|(prop, initializer)| format!("var.{} = {};", prop, initializer))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
format!(
|
|
||||||
r#"[&](){{
|
|
||||||
{} var{{}};
|
|
||||||
{}
|
|
||||||
return var;
|
|
||||||
}}()"#,
|
|
||||||
event_name,
|
|
||||||
fields_initialization.join("\n")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compile_path(path: &crate::expression_tree::Path, component: &Rc<Component>) -> String {
|
fn compile_path(path: &crate::expression_tree::Path, component: &Rc<Component>) -> String {
|
||||||
match path {
|
match path {
|
||||||
crate::expression_tree::Path::Elements(elements) => {
|
crate::expression_tree::Path::Elements(elements) => {
|
||||||
|
@ -980,89 +963,73 @@ fn compile_path(path: &crate::expression_tree::Path, component: &Rc<Component>)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
crate::expression_tree::Path::Events(events) => {
|
crate::expression_tree::Path::Events(events) => {
|
||||||
let converted_elements: Vec<String> = compile_path_events(events);
|
let (converted_events, converted_coordinates) = compile_path_events(events);
|
||||||
format!(
|
format!(
|
||||||
r#"[&](){{
|
r#"[&](){{
|
||||||
sixtyfps::PathEvent events[{}] = {{
|
sixtyfps::PathEvent events[{}] = {{
|
||||||
{}
|
{}
|
||||||
}};
|
}};
|
||||||
return sixtyfps::PathElements(&events[0], std::size(events));
|
sixtyfps::Point coordinates[{}] = {{
|
||||||
|
{}
|
||||||
|
}};
|
||||||
|
return sixtyfps::PathElements(&events[0], std::size(events), &coordinates[0], std::size(coordinates));
|
||||||
}}()"#,
|
}}()"#,
|
||||||
converted_elements.len(),
|
converted_events.len(),
|
||||||
converted_elements.join(",")
|
converted_events.join(","),
|
||||||
|
converted_coordinates.len(),
|
||||||
|
converted_coordinates.join(",")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_path_events(events: &crate::expression_tree::PathEvents) -> Vec<String> {
|
fn compile_path_events(events: &crate::expression_tree::PathEvents) -> (Vec<String>, Vec<String>) {
|
||||||
use lyon::path::Event;
|
use lyon::path::Event;
|
||||||
|
|
||||||
events
|
let mut coordinates = Vec::new();
|
||||||
|
|
||||||
|
let events = events
|
||||||
.iter()
|
.iter()
|
||||||
.map(|event| match event {
|
.map(|event| match event {
|
||||||
Event::Begin { at } => format!(
|
Event::Begin { at } => {
|
||||||
"sixtyfps::PathEvent::Begin({})",
|
coordinates.push(at);
|
||||||
new_path_event(
|
"sixtyfps::PathEvent::Begin"
|
||||||
"sixtyfps::PathEventBegin",
|
}
|
||||||
&[("x", at.x.to_string()), ("y", at.y.to_string())]
|
Event::Line { from, to } => {
|
||||||
)
|
coordinates.push(from);
|
||||||
),
|
coordinates.push(to);
|
||||||
Event::Line { from, to } => format!(
|
"sixtyfps::PathEvent::Line"
|
||||||
"sixtyfps::PathEvent::Line({})",
|
}
|
||||||
new_path_event(
|
Event::Quadratic { from, ctrl, to } => {
|
||||||
"sixtyfps::PathEventLine",
|
coordinates.push(from);
|
||||||
&[
|
coordinates.push(ctrl);
|
||||||
("from_x", from.x.to_string()),
|
coordinates.push(to);
|
||||||
("from_y", from.y.to_string()),
|
"sixtyfps::PathEvent::Quadratic"
|
||||||
("to_x", to.x.to_string()),
|
}
|
||||||
("to_y", to.y.to_string())
|
Event::Cubic { from, ctrl1, ctrl2, to } => {
|
||||||
]
|
coordinates.push(from);
|
||||||
)
|
coordinates.push(ctrl1);
|
||||||
),
|
coordinates.push(ctrl2);
|
||||||
Event::Quadratic { from, ctrl, to } => format!(
|
coordinates.push(to);
|
||||||
"sixtyfps::PathEvent::Quadratic({})",
|
"sixtyfps::PathEvent::Cubic"
|
||||||
new_path_event(
|
}
|
||||||
"sixtyfps::PathEventQuadratic",
|
Event::End { last, first, close } => {
|
||||||
&[
|
debug_assert_eq!(coordinates.first(), Some(&first));
|
||||||
("from_x", from.x.to_string()),
|
debug_assert_eq!(coordinates.last(), Some(&last));
|
||||||
("from_y", from.y.to_string()),
|
if *close {
|
||||||
("control_x", ctrl.x.to_string()),
|
"sixtyfps::PathEvent::EndClosed"
|
||||||
("control_y", ctrl.y.to_string()),
|
} else {
|
||||||
("to_x", to.x.to_string()),
|
"sixtyfps::PathEvent::EndOpen"
|
||||||
("to_y", to.y.to_string())
|
}
|
||||||
]
|
}
|
||||||
)
|
})
|
||||||
),
|
.map(String::from)
|
||||||
Event::Cubic { from, ctrl1, ctrl2, to } => format!(
|
.collect();
|
||||||
"sixtyfps::PathEvent::Cubic({})",
|
|
||||||
new_path_event(
|
let coordinates = coordinates
|
||||||
"sixtyfps::PathEventCubic",
|
.into_iter()
|
||||||
&[
|
.map(|pt| format!("sixtyfps::Point{{{}, {}}}", pt.x, pt.y))
|
||||||
("from_x", from.x.to_string()),
|
.collect();
|
||||||
("from_y", from.y.to_string()),
|
|
||||||
("control1_x", ctrl1.x.to_string()),
|
(events, coordinates)
|
||||||
("control1_y", ctrl1.y.to_string()),
|
|
||||||
("control2_x", ctrl2.x.to_string()),
|
|
||||||
("control2_y", ctrl2.y.to_string()),
|
|
||||||
("to_x", to.x.to_string()),
|
|
||||||
("to_y", to.y.to_string())
|
|
||||||
]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Event::End { last, first, close } => format!(
|
|
||||||
"sixtyfps::PathEvent::End({})",
|
|
||||||
new_path_event(
|
|
||||||
"sixtyfps::PathEventEnd",
|
|
||||||
&[
|
|
||||||
("first_x", first.x.to_string()),
|
|
||||||
("first_y", first.y.to_string()),
|
|
||||||
("last_x", last.x.to_string()),
|
|
||||||
("last_y", last.y.to_string()),
|
|
||||||
("close", close.to_string())
|
|
||||||
]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -791,52 +791,56 @@ fn compute_layout(component: &Rc<Component>) -> TokenStream {
|
||||||
fn compile_path_events(events: &crate::expression_tree::PathEvents) -> TokenStream {
|
fn compile_path_events(events: &crate::expression_tree::PathEvents) -> TokenStream {
|
||||||
use lyon::path::Event;
|
use lyon::path::Event;
|
||||||
|
|
||||||
|
let mut coordinates = Vec::new();
|
||||||
|
|
||||||
let converted_events: Vec<proc_macro2::TokenStream> = events
|
let converted_events: Vec<proc_macro2::TokenStream> = events
|
||||||
.iter()
|
.iter()
|
||||||
.map(|event| match event {
|
.map(|event| match event {
|
||||||
Event::Begin { at } => {
|
Event::Begin { at } => {
|
||||||
let x = at.x;
|
coordinates.push(at);
|
||||||
let y = at.y;
|
quote!(sixtyfps::re_exports::PathEvent::Begin)
|
||||||
quote!(sixtyfps::re_exports::PathEvent::Begin(sixtyfps::re_exports::PathEventBegin{x: #x, y: #y}))
|
|
||||||
}
|
}
|
||||||
Event::Line { from, to } => {
|
Event::Line { from, to } => {
|
||||||
let from_x = from.x;
|
coordinates.push(from);
|
||||||
let from_y = from.y;
|
coordinates.push(to);
|
||||||
let to_x = to.x;
|
quote!(sixtyfps::re_exports::PathEvent::Line)
|
||||||
let to_y = to.y;
|
|
||||||
quote!(sixtyfps::re_exports::PathEvent::Line(sixtyfps::re_exports::PathEventLine{from_x: #from_x, from_y: #from_y, to_x: #to_x, to_y: #to_y}))
|
|
||||||
}
|
}
|
||||||
Event::Quadratic { from, ctrl, to } => {
|
Event::Quadratic { from, ctrl, to } => {
|
||||||
let from_x = from.x;
|
coordinates.push(from);
|
||||||
let from_y = from.y;
|
coordinates.push(ctrl);
|
||||||
let control_x = ctrl.x;
|
coordinates.push(to);
|
||||||
let control_y = ctrl.y;
|
quote!(sixtyfps::re_exports::PathEvent::Quadratic)
|
||||||
let to_x = to.x;
|
|
||||||
let to_y = to.y;
|
|
||||||
quote!(sixtyfps::re_exports::PathEvent::Quadratic(sixtyfps::re_exports::PathEventQuadratic{from_x: #from_x, from_y: #from_y, control_x: #control_x, control_y: #control_y, to_x: #to_x, to_y: #to_y}))
|
|
||||||
}
|
}
|
||||||
Event::Cubic { from, ctrl1, ctrl2, to } => {
|
Event::Cubic { from, ctrl1, ctrl2, to } => {
|
||||||
let from_x = from.x;
|
coordinates.push(from);
|
||||||
let from_y = from.y;
|
coordinates.push(ctrl1);
|
||||||
let control1_x = ctrl1.x;
|
coordinates.push(ctrl2);
|
||||||
let control1_y = ctrl1.y;
|
coordinates.push(to);
|
||||||
let control2_x = ctrl2.x;
|
quote!(sixtyfps::re_exports::PathEvent::Cubic)
|
||||||
let control2_y = ctrl2.y;
|
|
||||||
let to_x = to.x;
|
|
||||||
let to_y = to.y;
|
|
||||||
quote!(sixtyfps::re_exports::PathEvent::Cubic(sixtyfps::re_exports::PathEventCubic{from_x: #from_x, from_y: #from_y, control1_x: #control1_x, control1_y: #control1_y, control2_x: #control2_x, control2_y: #control2_y, to_x: #to_x, to_y: #to_y}))
|
|
||||||
}
|
}
|
||||||
Event::End { last, first, close } => {
|
Event::End { last, first, close } => {
|
||||||
let first_x = first.x;
|
debug_assert_eq!(coordinates.first(), Some(&first));
|
||||||
let first_y = first.y;
|
debug_assert_eq!(coordinates.last(), Some(&last));
|
||||||
let last_x = last.x;
|
if *close {
|
||||||
let last_y = last.y;
|
quote!(sixtyfps::re_exports::PathEvent::EndClosed)
|
||||||
quote!(sixtyfps::re_exports::PathEvent::End(sixtyfps::re_exports::PathEventEnd{first_x: #first_x, first_y: #first_y, last_x: #last_x, last_y: #last_y, close: #close}))
|
} else {
|
||||||
|
quote!(sixtyfps::re_exports::PathEvent::EndOpen)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
quote!(sixtyfps::re_exports::SharedArray::<sixtyfps::re_exports::PathEvent>::from(&[#(#converted_events),*]))
|
let coordinates: Vec<TokenStream> = coordinates
|
||||||
|
.into_iter()
|
||||||
|
.map(|pt| {
|
||||||
|
let x = pt.x;
|
||||||
|
let y = pt.y;
|
||||||
|
quote!(sixtyfps::re_exports::Point::new(#x, #y))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
quote!(sixtyfps::re_exports::SharedArray::<sixtyfps::re_exports::PathEvent>::from(&[#(#converted_events),*]),
|
||||||
|
sixtyfps::re_exports::SharedArray::<sixtyfps::re_exports::Point>::from(&[#(#coordinates),*]))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_path(path: &Path, component: &Rc<Component>) -> TokenStream {
|
fn compile_path(path: &Path, component: &Rc<Component>) -> TokenStream {
|
||||||
|
|
|
@ -426,86 +426,67 @@ pub struct PathEventEnd {
|
||||||
/// generated at compile time from a higher-level description, such as SVG commands.
|
/// generated at compile time from a higher-level description, such as SVG commands.
|
||||||
pub enum PathEvent {
|
pub enum PathEvent {
|
||||||
/// The beginning of the path.
|
/// The beginning of the path.
|
||||||
Begin(PathEventBegin),
|
Begin,
|
||||||
/// A straight line on the path.
|
/// A straight line on the path.
|
||||||
Line(PathEventLine),
|
Line,
|
||||||
/// A quadratic bezier curve on the path.
|
/// A quadratic bezier curve on the path.
|
||||||
Quadratic(PathEventQuadratic),
|
Quadratic,
|
||||||
/// A cubic bezier curve on the path.
|
/// A cubic bezier curve on the path.
|
||||||
Cubic(PathEventCubic),
|
Cubic,
|
||||||
/// The end of the path.
|
/// The end of the path that remains open.
|
||||||
End(PathEventEnd),
|
EndOpen,
|
||||||
|
/// The end of a path that is closed.
|
||||||
|
EndClosed,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&PathEvent> for lyon::path::Event<lyon::math::Point, lyon::math::Point> {
|
struct ToLyonPathEventIterator<'a> {
|
||||||
fn from(event: &PathEvent) -> Self {
|
events_it: std::slice::Iter<'a, PathEvent>,
|
||||||
use lyon::math::Point;
|
coordinates_it: std::slice::Iter<'a, Point>,
|
||||||
use lyon::path::Event;
|
first: Option<&'a Point>,
|
||||||
match event {
|
last: Option<&'a Point>,
|
||||||
PathEvent::Begin(begin) => Event::Begin { at: Point::new(begin.x, begin.y) },
|
|
||||||
PathEvent::Line(line) => Event::Line {
|
|
||||||
from: Point::new(line.from_x, line.from_y),
|
|
||||||
to: Point::new(line.to_x, line.to_y),
|
|
||||||
},
|
|
||||||
PathEvent::Quadratic(curve) => Event::Quadratic {
|
|
||||||
from: Point::new(curve.from_x, curve.from_y),
|
|
||||||
ctrl: Point::new(curve.control_x, curve.control_y),
|
|
||||||
to: Point::new(curve.to_x, curve.to_y),
|
|
||||||
},
|
|
||||||
PathEvent::Cubic(curve) => Event::Cubic {
|
|
||||||
from: Point::new(curve.from_x, curve.from_y),
|
|
||||||
ctrl1: Point::new(curve.control1_x, curve.control1_y),
|
|
||||||
ctrl2: Point::new(curve.control2_x, curve.control2_y),
|
|
||||||
to: Point::new(curve.to_x, curve.to_y),
|
|
||||||
},
|
|
||||||
PathEvent::End(end) => Event::End {
|
|
||||||
first: Point::new(end.first_x, end.first_y),
|
|
||||||
last: Point::new(end.last_x, end.last_y),
|
|
||||||
close: end.close,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for ToLyonPathEventIterator<'a> {
|
||||||
|
type Item = lyon::path::Event<lyon::math::Point, lyon::math::Point>;
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
use lyon::path::Event;
|
||||||
|
|
||||||
|
self.events_it.next().map(|event| match event {
|
||||||
|
PathEvent::Begin => Event::Begin { at: self.coordinates_it.next().unwrap().clone() },
|
||||||
|
PathEvent::Line => Event::Line {
|
||||||
|
from: self.coordinates_it.next().unwrap().clone(),
|
||||||
|
to: self.coordinates_it.next().unwrap().clone(),
|
||||||
|
},
|
||||||
|
PathEvent::Quadratic => Event::Quadratic {
|
||||||
|
from: self.coordinates_it.next().unwrap().clone(),
|
||||||
|
ctrl: self.coordinates_it.next().unwrap().clone(),
|
||||||
|
to: self.coordinates_it.next().unwrap().clone(),
|
||||||
|
},
|
||||||
|
PathEvent::Cubic => Event::Cubic {
|
||||||
|
from: self.coordinates_it.next().unwrap().clone(),
|
||||||
|
ctrl1: self.coordinates_it.next().unwrap().clone(),
|
||||||
|
ctrl2: self.coordinates_it.next().unwrap().clone(),
|
||||||
|
to: self.coordinates_it.next().unwrap().clone(),
|
||||||
|
},
|
||||||
|
PathEvent::EndOpen => Event::End {
|
||||||
|
first: self.first.unwrap().clone(),
|
||||||
|
last: self.last.unwrap().clone(),
|
||||||
|
close: false,
|
||||||
|
},
|
||||||
|
PathEvent::EndClosed => Event::End {
|
||||||
|
first: self.first.unwrap().clone(),
|
||||||
|
last: self.last.unwrap().clone(),
|
||||||
|
close: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
self.events_it.size_hint()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&lyon::path::Event<lyon::math::Point, lyon::math::Point>> for PathEvent {
|
impl<'a> ExactSizeIterator for ToLyonPathEventIterator<'a> {}
|
||||||
fn from(event: &lyon::path::Event<lyon::math::Point, lyon::math::Point>) -> Self {
|
|
||||||
use lyon::path::Event;
|
|
||||||
match event {
|
|
||||||
Event::Begin { at } => PathEvent::Begin(PathEventBegin { x: at.x, y: at.y }),
|
|
||||||
Event::Line { from, to } => PathEvent::Line(PathEventLine {
|
|
||||||
from_x: from.x,
|
|
||||||
from_y: from.y,
|
|
||||||
to_x: to.x,
|
|
||||||
to_y: to.y,
|
|
||||||
}),
|
|
||||||
Event::Quadratic { from, ctrl, to } => PathEvent::Quadratic(PathEventQuadratic {
|
|
||||||
from_x: from.x,
|
|
||||||
from_y: from.y,
|
|
||||||
control_x: ctrl.x,
|
|
||||||
control_y: ctrl.y,
|
|
||||||
to_x: to.x,
|
|
||||||
to_y: to.y,
|
|
||||||
}),
|
|
||||||
Event::Cubic { from, ctrl1, ctrl2, to } => PathEvent::Cubic(PathEventCubic {
|
|
||||||
from_x: from.x,
|
|
||||||
from_y: from.y,
|
|
||||||
control1_x: ctrl1.x,
|
|
||||||
control1_y: ctrl1.y,
|
|
||||||
control2_x: ctrl2.x,
|
|
||||||
control2_y: ctrl2.y,
|
|
||||||
to_x: to.x,
|
|
||||||
to_y: to.y,
|
|
||||||
}),
|
|
||||||
Event::End { last, first, close } => PathEvent::End(PathEventEnd {
|
|
||||||
first_x: first.x,
|
|
||||||
first_y: first.y,
|
|
||||||
last_x: last.x,
|
|
||||||
last_y: last.y,
|
|
||||||
close: *close,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
@ -518,7 +499,7 @@ pub enum PathElements {
|
||||||
/// SharedElements is used to make PathElements from shared arrays of elements.
|
/// SharedElements is used to make PathElements from shared arrays of elements.
|
||||||
SharedElements(crate::SharedArray<PathElement>),
|
SharedElements(crate::SharedArray<PathElement>),
|
||||||
/// PathEvents describe the elements of the path as a series of low-level events.
|
/// PathEvents describe the elements of the path as a series of low-level events.
|
||||||
PathEvents(crate::SharedArray<PathEvent>),
|
PathEvents(crate::SharedArray<PathEvent>, crate::SharedArray<Point>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PathElements {
|
impl Default for PathElements {
|
||||||
|
@ -540,9 +521,14 @@ impl PathElements {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator over all events if the elements are represented as low-level events.
|
/// Returns an iterator over all events if the elements are represented as low-level events.
|
||||||
pub fn events_iter(&self) -> Option<std::slice::Iter<PathEvent>> {
|
fn events_iter(&self) -> Option<ToLyonPathEventIterator> {
|
||||||
match self {
|
match &self {
|
||||||
PathElements::PathEvents(events) => Some(events.as_slice().iter()),
|
PathElements::PathEvents(events, coordinates) => Some(ToLyonPathEventIterator {
|
||||||
|
events_it: events.iter(),
|
||||||
|
coordinates_it: coordinates.iter(),
|
||||||
|
first: coordinates.first(),
|
||||||
|
last: coordinates.last(),
|
||||||
|
}),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -615,12 +601,18 @@ pub unsafe extern "C" fn sixtyfps_new_path_elements(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
/// This function is used for the low-level C++ interface to allocate the backing vector for a shared path event array.
|
/// This function is used for the low-level C++ interface to allocate the backing vector for a shared path event array.
|
||||||
pub unsafe extern "C" fn sixtyfps_new_path_events(
|
pub unsafe extern "C" fn sixtyfps_new_path_events(
|
||||||
out: *mut c_void,
|
out_events: *mut c_void,
|
||||||
|
out_coordinates: *mut c_void,
|
||||||
first_event: *const PathEvent,
|
first_event: *const PathEvent,
|
||||||
count: usize,
|
event_count: usize,
|
||||||
|
first_coordinate: *const Point,
|
||||||
|
coordinate_count: usize,
|
||||||
) {
|
) {
|
||||||
let arr = crate::SharedArray::from(std::slice::from_raw_parts(first_event, count));
|
let events = crate::SharedArray::from(std::slice::from_raw_parts(first_event, event_count));
|
||||||
core::ptr::write(out as *mut crate::SharedArray<PathEvent>, arr.clone());
|
core::ptr::write(out_events as *mut crate::SharedArray<PathEvent>, events.clone());
|
||||||
|
let coordinates =
|
||||||
|
crate::SharedArray::from(std::slice::from_raw_parts(first_coordinate, coordinate_count));
|
||||||
|
core::ptr::write(out_coordinates as *mut crate::SharedArray<Point>, coordinates.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Each item return a RenderingPrimitive to the backend with information about what to draw.
|
/// Each item return a RenderingPrimitive to the backend with information about what to draw.
|
||||||
|
|
|
@ -11,4 +11,5 @@ path = "lib.rs"
|
||||||
sixtyfps_corelib = { path = "../corelib", features = ["rtti"] }
|
sixtyfps_corelib = { path = "../corelib", features = ["rtti"] }
|
||||||
vtable = { path="../../helper_crates/vtable" }
|
vtable = { path="../../helper_crates/vtable" }
|
||||||
sixtyfps_compilerlib = { path = "../../sixtyfps_compiler", features = ["display-diagnostics"] }
|
sixtyfps_compilerlib = { path = "../../sixtyfps_compiler", features = ["display-diagnostics"] }
|
||||||
|
lyon = { version = "0.15.8" }
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,9 @@ use sixtyfps_compilerlib::expression_tree::{
|
||||||
use sixtyfps_compilerlib::{object_tree::ElementRc, typeregister::Type};
|
use sixtyfps_compilerlib::{object_tree::ElementRc, typeregister::Type};
|
||||||
use sixtyfps_corelib as corelib;
|
use sixtyfps_corelib as corelib;
|
||||||
use sixtyfps_corelib::{
|
use sixtyfps_corelib::{
|
||||||
abi::datastructures::ItemRef, abi::primitives::PropertyAnimation, Color, EvaluationContext,
|
abi::datastructures::ItemRef, abi::datastructures::PathElement,
|
||||||
PathElements, Resource, SharedString,
|
abi::primitives::PropertyAnimation, Color, EvaluationContext, PathElements, Resource,
|
||||||
|
SharedArray, SharedString,
|
||||||
};
|
};
|
||||||
use std::{collections::HashMap, rc::Rc};
|
use std::{collections::HashMap, rc::Rc};
|
||||||
|
|
||||||
|
@ -363,26 +364,71 @@ pub fn new_struct_with_bindings<
|
||||||
element
|
element
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn convert_from_lyon_path<'a>(
|
||||||
|
it: impl IntoIterator<Item = &'a lyon::path::Event<lyon::math::Point, lyon::math::Point>>,
|
||||||
|
) -> PathElements {
|
||||||
|
use lyon::path::Event;
|
||||||
|
use sixtyfps_corelib::abi::datastructures::PathEvent;
|
||||||
|
|
||||||
|
let mut coordinates = Vec::new();
|
||||||
|
|
||||||
|
let events = it
|
||||||
|
.into_iter()
|
||||||
|
.map(|event| match event {
|
||||||
|
Event::Begin { at } => {
|
||||||
|
coordinates.push(at);
|
||||||
|
PathEvent::Begin
|
||||||
|
}
|
||||||
|
Event::Line { from, to } => {
|
||||||
|
coordinates.push(from);
|
||||||
|
coordinates.push(to);
|
||||||
|
PathEvent::Line
|
||||||
|
}
|
||||||
|
Event::Quadratic { from, ctrl, to } => {
|
||||||
|
coordinates.push(from);
|
||||||
|
coordinates.push(ctrl);
|
||||||
|
coordinates.push(to);
|
||||||
|
PathEvent::Quadratic
|
||||||
|
}
|
||||||
|
Event::Cubic { from, ctrl1, ctrl2, to } => {
|
||||||
|
coordinates.push(from);
|
||||||
|
coordinates.push(ctrl1);
|
||||||
|
coordinates.push(ctrl2);
|
||||||
|
coordinates.push(to);
|
||||||
|
PathEvent::Cubic
|
||||||
|
}
|
||||||
|
Event::End { last, first, close } => {
|
||||||
|
debug_assert_eq!(coordinates.first(), Some(&first));
|
||||||
|
debug_assert_eq!(coordinates.last(), Some(&last));
|
||||||
|
if *close {
|
||||||
|
PathEvent::EndClosed
|
||||||
|
} else {
|
||||||
|
PathEvent::EndOpen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
PathElements::PathEvents(
|
||||||
|
SharedArray::from(&events),
|
||||||
|
SharedArray::from_iter(coordinates.into_iter().cloned()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn convert_path(
|
pub fn convert_path(
|
||||||
path: &ExprPath,
|
path: &ExprPath,
|
||||||
component_type: &crate::ComponentDescription,
|
component_type: &crate::ComponentDescription,
|
||||||
eval_context: &corelib::EvaluationContext,
|
eval_context: &corelib::EvaluationContext,
|
||||||
) -> sixtyfps_corelib::abi::datastructures::PathElements {
|
) -> PathElements {
|
||||||
match path {
|
match path {
|
||||||
ExprPath::Elements(elements) => {
|
ExprPath::Elements(elements) => {
|
||||||
PathElements::SharedElements(sixtyfps_corelib::SharedArray::<
|
PathElements::SharedElements(SharedArray::<PathElement>::from_iter(
|
||||||
sixtyfps_corelib::abi::datastructures::PathElement,
|
|
||||||
>::from_iter(
|
|
||||||
elements
|
elements
|
||||||
.iter()
|
.iter()
|
||||||
.map(|element| convert_path_element(element, component_type, eval_context)),
|
.map(|element| convert_path_element(element, component_type, eval_context)),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
ExprPath::Events(events) => PathElements::PathEvents(sixtyfps_corelib::SharedArray::<
|
ExprPath::Events(events) => convert_from_lyon_path(events.iter()),
|
||||||
sixtyfps_corelib::abi::datastructures::PathEvent,
|
|
||||||
>::from_iter(
|
|
||||||
events.iter().map(|event| event.into()),
|
|
||||||
)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,15 +436,19 @@ fn convert_path_element(
|
||||||
expr_element: &ExprPathElement,
|
expr_element: &ExprPathElement,
|
||||||
component_type: &crate::ComponentDescription,
|
component_type: &crate::ComponentDescription,
|
||||||
eval_context: &corelib::EvaluationContext,
|
eval_context: &corelib::EvaluationContext,
|
||||||
) -> sixtyfps_corelib::abi::datastructures::PathElement {
|
) -> PathElement {
|
||||||
match expr_element.element_type.class_name.as_str() {
|
match expr_element.element_type.class_name.as_str() {
|
||||||
"LineTo" => sixtyfps_corelib::abi::datastructures::PathElement::LineTo(
|
"LineTo" => PathElement::LineTo(new_struct_with_bindings(
|
||||||
new_struct_with_bindings(&expr_element.bindings, component_type, eval_context),
|
&expr_element.bindings,
|
||||||
),
|
component_type,
|
||||||
"ArcTo" => sixtyfps_corelib::abi::datastructures::PathElement::ArcTo(
|
eval_context,
|
||||||
new_struct_with_bindings(&expr_element.bindings, component_type, eval_context),
|
)),
|
||||||
),
|
"ArcTo" => PathElement::ArcTo(new_struct_with_bindings(
|
||||||
"Close" => sixtyfps_corelib::abi::datastructures::PathElement::Close,
|
&expr_element.bindings,
|
||||||
|
component_type,
|
||||||
|
eval_context,
|
||||||
|
)),
|
||||||
|
"Close" => PathElement::Close,
|
||||||
_ => panic!(
|
_ => panic!(
|
||||||
"Cannot create unsupported path element {}",
|
"Cannot create unsupported path element {}",
|
||||||
expr_element.element_type.class_name
|
expr_element.element_type.class_name
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue