mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 14:21:16 +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::PathElement;
|
||||
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::Point;
|
||||
|
||||
struct PathElements
|
||||
{
|
||||
|
@ -26,8 +22,9 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
PathElements(const PathEvent *firstEvent, size_t count)
|
||||
: data(Data::PathEvents(events_from_array(firstEvent, count)))
|
||||
PathElements(const PathEvent *firstEvent, size_t event_count, const Point *firstCoordinate,
|
||||
size_t coordinate_count)
|
||||
: data(events_from_array(firstEvent, event_count, firstCoordinate, coordinate_count))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -40,11 +37,16 @@ private:
|
|||
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;
|
||||
sixtyfps_new_path_events(&tmp, firstEvent, count);
|
||||
return tmp;
|
||||
SharedArray<PathEvent> events;
|
||||
SharedArray<Point> coordinates;
|
||||
sixtyfps_new_path_events(&events, &coordinates, firstEvent, event_count, firstCoordinate,
|
||||
coordinate_count);
|
||||
return Data::PathEvents(events, coordinates);
|
||||
}
|
||||
|
||||
using Data = internal::types::PathElements;
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
use core::cell::RefCell;
|
||||
use neon::prelude::*;
|
||||
use sixtyfps_compilerlib::typeregister::Type;
|
||||
use sixtyfps_corelib::abi::datastructures::{
|
||||
PathArcTo, PathElement, PathEvent, PathEventBegin, PathEventCubic, PathEventEnd, PathEventLine,
|
||||
PathEventQuadratic, PathLineTo, Resource,
|
||||
};
|
||||
use sixtyfps_corelib::abi::datastructures::{PathArcTo, PathElement, PathLineTo, Resource};
|
||||
use sixtyfps_corelib::{ComponentRefPin, EvaluationContext};
|
||||
|
||||
use std::rc::Rc;
|
||||
|
@ -235,79 +232,7 @@ fn to_js_value<'cx>(
|
|||
}
|
||||
js_array.as_value(cx)
|
||||
} else {
|
||||
let events_iter = elements.events_iter().unwrap();
|
||||
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)
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -931,23 +931,6 @@ fn compute_layout(component: &Rc<Component>) -> Vec<String> {
|
|||
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 {
|
||||
match path {
|
||||
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) => {
|
||||
let converted_elements: Vec<String> = compile_path_events(events);
|
||||
let (converted_events, converted_coordinates) = compile_path_events(events);
|
||||
format!(
|
||||
r#"[&](){{
|
||||
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_elements.join(",")
|
||||
converted_events.len(),
|
||||
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;
|
||||
|
||||
events
|
||||
let mut coordinates = Vec::new();
|
||||
|
||||
let events = events
|
||||
.iter()
|
||||
.map(|event| match event {
|
||||
Event::Begin { at } => format!(
|
||||
"sixtyfps::PathEvent::Begin({})",
|
||||
new_path_event(
|
||||
"sixtyfps::PathEventBegin",
|
||||
&[("x", at.x.to_string()), ("y", at.y.to_string())]
|
||||
)
|
||||
),
|
||||
Event::Line { from, to } => format!(
|
||||
"sixtyfps::PathEvent::Line({})",
|
||||
new_path_event(
|
||||
"sixtyfps::PathEventLine",
|
||||
&[
|
||||
("from_x", from.x.to_string()),
|
||||
("from_y", from.y.to_string()),
|
||||
("to_x", to.x.to_string()),
|
||||
("to_y", to.y.to_string())
|
||||
]
|
||||
)
|
||||
),
|
||||
Event::Quadratic { from, ctrl, to } => format!(
|
||||
"sixtyfps::PathEvent::Quadratic({})",
|
||||
new_path_event(
|
||||
"sixtyfps::PathEventQuadratic",
|
||||
&[
|
||||
("from_x", from.x.to_string()),
|
||||
("from_y", from.y.to_string()),
|
||||
("control_x", ctrl.x.to_string()),
|
||||
("control_y", ctrl.y.to_string()),
|
||||
("to_x", to.x.to_string()),
|
||||
("to_y", to.y.to_string())
|
||||
]
|
||||
)
|
||||
),
|
||||
Event::Cubic { from, ctrl1, ctrl2, to } => format!(
|
||||
"sixtyfps::PathEvent::Cubic({})",
|
||||
new_path_event(
|
||||
"sixtyfps::PathEventCubic",
|
||||
&[
|
||||
("from_x", from.x.to_string()),
|
||||
("from_y", from.y.to_string()),
|
||||
("control1_x", ctrl1.x.to_string()),
|
||||
("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()
|
||||
Event::Begin { at } => {
|
||||
coordinates.push(at);
|
||||
"sixtyfps::PathEvent::Begin"
|
||||
}
|
||||
Event::Line { from, to } => {
|
||||
coordinates.push(from);
|
||||
coordinates.push(to);
|
||||
"sixtyfps::PathEvent::Line"
|
||||
}
|
||||
Event::Quadratic { from, ctrl, to } => {
|
||||
coordinates.push(from);
|
||||
coordinates.push(ctrl);
|
||||
coordinates.push(to);
|
||||
"sixtyfps::PathEvent::Quadratic"
|
||||
}
|
||||
Event::Cubic { from, ctrl1, ctrl2, to } => {
|
||||
coordinates.push(from);
|
||||
coordinates.push(ctrl1);
|
||||
coordinates.push(ctrl2);
|
||||
coordinates.push(to);
|
||||
"sixtyfps::PathEvent::Cubic"
|
||||
}
|
||||
Event::End { last, first, close } => {
|
||||
debug_assert_eq!(coordinates.first(), Some(&first));
|
||||
debug_assert_eq!(coordinates.last(), Some(&last));
|
||||
if *close {
|
||||
"sixtyfps::PathEvent::EndClosed"
|
||||
} else {
|
||||
"sixtyfps::PathEvent::EndOpen"
|
||||
}
|
||||
}
|
||||
})
|
||||
.map(String::from)
|
||||
.collect();
|
||||
|
||||
let coordinates = coordinates
|
||||
.into_iter()
|
||||
.map(|pt| format!("sixtyfps::Point{{{}, {}}}", pt.x, pt.y))
|
||||
.collect();
|
||||
|
||||
(events, coordinates)
|
||||
}
|
||||
|
|
|
@ -791,52 +791,56 @@ fn compute_layout(component: &Rc<Component>) -> TokenStream {
|
|||
fn compile_path_events(events: &crate::expression_tree::PathEvents) -> TokenStream {
|
||||
use lyon::path::Event;
|
||||
|
||||
let mut coordinates = Vec::new();
|
||||
|
||||
let converted_events: Vec<proc_macro2::TokenStream> = events
|
||||
.iter()
|
||||
.map(|event| match event {
|
||||
Event::Begin { at } => {
|
||||
let x = at.x;
|
||||
let y = at.y;
|
||||
quote!(sixtyfps::re_exports::PathEvent::Begin(sixtyfps::re_exports::PathEventBegin{x: #x, y: #y}))
|
||||
coordinates.push(at);
|
||||
quote!(sixtyfps::re_exports::PathEvent::Begin)
|
||||
}
|
||||
Event::Line { from, to } => {
|
||||
let from_x = from.x;
|
||||
let from_y = from.y;
|
||||
let to_x = to.x;
|
||||
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}))
|
||||
coordinates.push(from);
|
||||
coordinates.push(to);
|
||||
quote!(sixtyfps::re_exports::PathEvent::Line)
|
||||
}
|
||||
Event::Quadratic { from, ctrl, to } => {
|
||||
let from_x = from.x;
|
||||
let from_y = from.y;
|
||||
let control_x = ctrl.x;
|
||||
let control_y = ctrl.y;
|
||||
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}))
|
||||
coordinates.push(from);
|
||||
coordinates.push(ctrl);
|
||||
coordinates.push(to);
|
||||
quote!(sixtyfps::re_exports::PathEvent::Quadratic)
|
||||
}
|
||||
Event::Cubic { from, ctrl1, ctrl2, to } => {
|
||||
let from_x = from.x;
|
||||
let from_y = from.y;
|
||||
let control1_x = ctrl1.x;
|
||||
let control1_y = ctrl1.y;
|
||||
let control2_x = ctrl2.x;
|
||||
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}))
|
||||
coordinates.push(from);
|
||||
coordinates.push(ctrl1);
|
||||
coordinates.push(ctrl2);
|
||||
coordinates.push(to);
|
||||
quote!(sixtyfps::re_exports::PathEvent::Cubic)
|
||||
}
|
||||
Event::End { last, first, close } => {
|
||||
let first_x = first.x;
|
||||
let first_y = first.y;
|
||||
let last_x = last.x;
|
||||
let last_y = last.y;
|
||||
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}))
|
||||
debug_assert_eq!(coordinates.first(), Some(&first));
|
||||
debug_assert_eq!(coordinates.last(), Some(&last));
|
||||
if *close {
|
||||
quote!(sixtyfps::re_exports::PathEvent::EndClosed)
|
||||
} else {
|
||||
quote!(sixtyfps::re_exports::PathEvent::EndOpen)
|
||||
}
|
||||
}
|
||||
})
|
||||
.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 {
|
||||
|
|
|
@ -426,86 +426,67 @@ pub struct PathEventEnd {
|
|||
/// generated at compile time from a higher-level description, such as SVG commands.
|
||||
pub enum PathEvent {
|
||||
/// The beginning of the path.
|
||||
Begin(PathEventBegin),
|
||||
Begin,
|
||||
/// A straight line on the path.
|
||||
Line(PathEventLine),
|
||||
Line,
|
||||
/// A quadratic bezier curve on the path.
|
||||
Quadratic(PathEventQuadratic),
|
||||
Quadratic,
|
||||
/// A cubic bezier curve on the path.
|
||||
Cubic(PathEventCubic),
|
||||
/// The end of the path.
|
||||
End(PathEventEnd),
|
||||
Cubic,
|
||||
/// The end of the path that remains open.
|
||||
EndOpen,
|
||||
/// The end of a path that is closed.
|
||||
EndClosed,
|
||||
}
|
||||
|
||||
impl From<&PathEvent> for lyon::path::Event<lyon::math::Point, lyon::math::Point> {
|
||||
fn from(event: &PathEvent) -> Self {
|
||||
use lyon::math::Point;
|
||||
use lyon::path::Event;
|
||||
match event {
|
||||
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,
|
||||
},
|
||||
struct ToLyonPathEventIterator<'a> {
|
||||
events_it: std::slice::Iter<'a, PathEvent>,
|
||||
coordinates_it: std::slice::Iter<'a, Point>,
|
||||
first: Option<&'a Point>,
|
||||
last: Option<&'a Point>,
|
||||
}
|
||||
|
||||
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 {
|
||||
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,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a> ExactSizeIterator for ToLyonPathEventIterator<'a> {}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
@ -518,7 +499,7 @@ pub enum PathElements {
|
|||
/// SharedElements is used to make PathElements from shared arrays of elements.
|
||||
SharedElements(crate::SharedArray<PathElement>),
|
||||
/// 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 {
|
||||
|
@ -540,9 +521,14 @@ impl PathElements {
|
|||
}
|
||||
|
||||
/// 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>> {
|
||||
match self {
|
||||
PathElements::PathEvents(events) => Some(events.as_slice().iter()),
|
||||
fn events_iter(&self) -> Option<ToLyonPathEventIterator> {
|
||||
match &self {
|
||||
PathElements::PathEvents(events, coordinates) => Some(ToLyonPathEventIterator {
|
||||
events_it: events.iter(),
|
||||
coordinates_it: coordinates.iter(),
|
||||
first: coordinates.first(),
|
||||
last: coordinates.last(),
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -615,12 +601,18 @@ pub unsafe extern "C" fn sixtyfps_new_path_elements(
|
|||
#[no_mangle]
|
||||
/// 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(
|
||||
out: *mut c_void,
|
||||
out_events: *mut c_void,
|
||||
out_coordinates: *mut c_void,
|
||||
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));
|
||||
core::ptr::write(out as *mut crate::SharedArray<PathEvent>, arr.clone());
|
||||
let events = crate::SharedArray::from(std::slice::from_raw_parts(first_event, event_count));
|
||||
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.
|
||||
|
|
|
@ -11,4 +11,5 @@ path = "lib.rs"
|
|||
sixtyfps_corelib = { path = "../corelib", features = ["rtti"] }
|
||||
vtable = { path="../../helper_crates/vtable" }
|
||||
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_corelib as corelib;
|
||||
use sixtyfps_corelib::{
|
||||
abi::datastructures::ItemRef, abi::primitives::PropertyAnimation, Color, EvaluationContext,
|
||||
PathElements, Resource, SharedString,
|
||||
abi::datastructures::ItemRef, abi::datastructures::PathElement,
|
||||
abi::primitives::PropertyAnimation, Color, EvaluationContext, PathElements, Resource,
|
||||
SharedArray, SharedString,
|
||||
};
|
||||
use std::{collections::HashMap, rc::Rc};
|
||||
|
||||
|
@ -363,26 +364,71 @@ pub fn new_struct_with_bindings<
|
|||
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(
|
||||
path: &ExprPath,
|
||||
component_type: &crate::ComponentDescription,
|
||||
eval_context: &corelib::EvaluationContext,
|
||||
) -> sixtyfps_corelib::abi::datastructures::PathElements {
|
||||
) -> PathElements {
|
||||
match path {
|
||||
ExprPath::Elements(elements) => {
|
||||
PathElements::SharedElements(sixtyfps_corelib::SharedArray::<
|
||||
sixtyfps_corelib::abi::datastructures::PathElement,
|
||||
>::from_iter(
|
||||
PathElements::SharedElements(SharedArray::<PathElement>::from_iter(
|
||||
elements
|
||||
.iter()
|
||||
.map(|element| convert_path_element(element, component_type, eval_context)),
|
||||
))
|
||||
}
|
||||
ExprPath::Events(events) => PathElements::PathEvents(sixtyfps_corelib::SharedArray::<
|
||||
sixtyfps_corelib::abi::datastructures::PathEvent,
|
||||
>::from_iter(
|
||||
events.iter().map(|event| event.into()),
|
||||
)),
|
||||
ExprPath::Events(events) => convert_from_lyon_path(events.iter()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -390,15 +436,19 @@ fn convert_path_element(
|
|||
expr_element: &ExprPathElement,
|
||||
component_type: &crate::ComponentDescription,
|
||||
eval_context: &corelib::EvaluationContext,
|
||||
) -> sixtyfps_corelib::abi::datastructures::PathElement {
|
||||
) -> PathElement {
|
||||
match expr_element.element_type.class_name.as_str() {
|
||||
"LineTo" => sixtyfps_corelib::abi::datastructures::PathElement::LineTo(
|
||||
new_struct_with_bindings(&expr_element.bindings, component_type, eval_context),
|
||||
),
|
||||
"ArcTo" => sixtyfps_corelib::abi::datastructures::PathElement::ArcTo(
|
||||
new_struct_with_bindings(&expr_element.bindings, component_type, eval_context),
|
||||
),
|
||||
"Close" => sixtyfps_corelib::abi::datastructures::PathElement::Close,
|
||||
"LineTo" => PathElement::LineTo(new_struct_with_bindings(
|
||||
&expr_element.bindings,
|
||||
component_type,
|
||||
eval_context,
|
||||
)),
|
||||
"ArcTo" => PathElement::ArcTo(new_struct_with_bindings(
|
||||
&expr_element.bindings,
|
||||
component_type,
|
||||
eval_context,
|
||||
)),
|
||||
"Close" => PathElement::Close,
|
||||
_ => panic!(
|
||||
"Cannot create unsupported path element {}",
|
||||
expr_element.element_type.class_name
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue