mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-30 13:51:13 +00:00
Added ArcTo element for paths
This commit is contained in:
parent
a83127ace8
commit
f646809ff4
8 changed files with 124 additions and 11 deletions
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
namespace sixtyfps {
|
namespace sixtyfps {
|
||||||
|
|
||||||
|
using internal::types::PathArcTo;
|
||||||
using internal::types::PathElement;
|
using internal::types::PathElement;
|
||||||
using internal::types::PathLineTo;
|
using internal::types::PathLineTo;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +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::{PathElement, PathLineTo, Resource};
|
use sixtyfps_corelib::abi::datastructures::{PathArcTo, PathElement, PathLineTo, Resource};
|
||||||
use sixtyfps_corelib::{ComponentRefPin, EvaluationContext};
|
use sixtyfps_corelib::{ComponentRefPin, EvaluationContext};
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -122,6 +122,30 @@ fn to_eval_value<'cx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_float_property<'cx>(
|
||||||
|
cx: &mut impl Context<'cx>,
|
||||||
|
object: &Handle<JsObject>,
|
||||||
|
name: &str,
|
||||||
|
value: f32,
|
||||||
|
) -> NeonResult<()> {
|
||||||
|
let value = JsNumber::new(cx, value);
|
||||||
|
let value = value.as_value(cx);
|
||||||
|
object.set(cx, name, value)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_bool_property<'cx>(
|
||||||
|
cx: &mut impl Context<'cx>,
|
||||||
|
object: &Handle<JsObject>,
|
||||||
|
name: &str,
|
||||||
|
value: bool,
|
||||||
|
) -> NeonResult<()> {
|
||||||
|
let value = JsBoolean::new(cx, value);
|
||||||
|
let value = value.as_value(cx);
|
||||||
|
object.set(cx, name, value)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn to_js_value<'cx>(
|
fn to_js_value<'cx>(
|
||||||
val: sixtyfps_interpreter::Value,
|
val: sixtyfps_interpreter::Value,
|
||||||
cx: &mut impl Context<'cx>,
|
cx: &mut impl Context<'cx>,
|
||||||
|
@ -162,13 +186,28 @@ fn to_js_value<'cx>(
|
||||||
|
|
||||||
match element {
|
match element {
|
||||||
PathElement::LineTo(PathLineTo { x, y }) => {
|
PathElement::LineTo(PathLineTo { x, y }) => {
|
||||||
let x = JsNumber::new(cx, *x);
|
set_float_property(cx, &element_object, "x", *x)?;
|
||||||
let x = x.as_value(cx);
|
set_float_property(cx, &element_object, "y", *y)?;
|
||||||
element_object.set(cx, "x", x)?;
|
}
|
||||||
|
PathElement::ArcTo(PathArcTo {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
radius_x,
|
||||||
|
radius_y,
|
||||||
|
x_rotation,
|
||||||
|
large_arc,
|
||||||
|
sweep,
|
||||||
|
}) => {
|
||||||
|
set_float_property(cx, &element_object, "x", *x)?;
|
||||||
|
set_float_property(cx, &element_object, "y", *y)?;
|
||||||
|
|
||||||
let y = JsNumber::new(cx, *y);
|
set_float_property(cx, &element_object, "radius_x", *radius_x)?;
|
||||||
let y = y.as_value(cx);
|
set_float_property(cx, &element_object, "radius_y", *radius_y)?;
|
||||||
element_object.set(cx, "y", y)?;
|
|
||||||
|
set_float_property(cx, &element_object, "x_rotation", *x_rotation)?;
|
||||||
|
|
||||||
|
set_bool_property(cx, &element_object, "large_arc", *large_arc)?;
|
||||||
|
set_bool_property(cx, &element_object, "sweep", *sweep)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ TestCase := Rectangle {
|
||||||
LineTo { x: 100; y: 0; }
|
LineTo { x: 100; y: 0; }
|
||||||
LineTo { x: 100; y: 0; }
|
LineTo { x: 100; y: 0; }
|
||||||
Rectangle {}
|
Rectangle {}
|
||||||
// ^error{Rectangle is not allowed within Path. Only LineTo are valid children}
|
// ^error{Rectangle is not allowed within Path. Only LineTo ArcTo are valid children}
|
||||||
}
|
}
|
||||||
|
|
||||||
LineTo { x: 100; y: 0; }
|
LineTo { x: 100; y: 0; }
|
||||||
|
|
|
@ -289,6 +289,20 @@ impl TypeRegister {
|
||||||
path.additional_accepted_child_types
|
path.additional_accepted_child_types
|
||||||
.insert("LineTo".to_owned(), Type::Builtin(Rc::new(line_to)));
|
.insert("LineTo".to_owned(), Type::Builtin(Rc::new(line_to)));
|
||||||
|
|
||||||
|
let mut arc_to = BuiltinElement::new("ArcTo");
|
||||||
|
arc_to.properties.insert("x".to_owned(), Type::Float32);
|
||||||
|
arc_to.properties.insert("y".to_owned(), Type::Float32);
|
||||||
|
arc_to.properties.insert("radius_x".to_owned(), Type::Float32);
|
||||||
|
arc_to.properties.insert("radius_y".to_owned(), Type::Float32);
|
||||||
|
arc_to.properties.insert("x_rotation".to_owned(), Type::Float32);
|
||||||
|
arc_to.properties.insert("large_arc".to_owned(), Type::Bool);
|
||||||
|
arc_to.properties.insert("sweep".to_owned(), Type::Bool);
|
||||||
|
arc_to.rust_type_constructor =
|
||||||
|
Some("sixtyfps::re_exports::PathElement::ArcTo(PathArcTo{{}})".into());
|
||||||
|
arc_to.cpp_type = Some("sixtyfps::PathArcTo".into());
|
||||||
|
path.additional_accepted_child_types
|
||||||
|
.insert("ArcTo".to_owned(), Type::Builtin(Rc::new(arc_to)));
|
||||||
|
|
||||||
r.types.insert("Path".to_owned(), Type::Builtin(Rc::new(path)));
|
r.types.insert("Path".to_owned(), Type::Builtin(Rc::new(path)));
|
||||||
|
|
||||||
let mut property_animation =
|
let mut property_animation =
|
||||||
|
|
|
@ -266,12 +266,44 @@ pub struct PathLineTo {
|
||||||
pub y: f32,
|
pub y: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(FieldOffsets, Default, BuiltinItem, Clone, Debug, PartialEq)]
|
||||||
|
#[pin]
|
||||||
|
/// PathArcTo describes the event of moving the cursor on the path across an arc to the specified
|
||||||
|
/// x/y coordinates, with the specified x/y radius and additional properties.
|
||||||
|
pub struct PathArcTo {
|
||||||
|
#[rtti_field]
|
||||||
|
/// The x coordinate where the arc should end up.
|
||||||
|
pub x: f32,
|
||||||
|
#[rtti_field]
|
||||||
|
/// The y coordinate where the arc should end up.
|
||||||
|
pub y: f32,
|
||||||
|
#[rtti_field]
|
||||||
|
/// The radius on the x-axis of the arc.
|
||||||
|
pub radius_x: f32,
|
||||||
|
#[rtti_field]
|
||||||
|
/// The radius on the y-axis of the arc.
|
||||||
|
pub radius_y: f32,
|
||||||
|
#[rtti_field]
|
||||||
|
/// The rotation along the x-axis of the arc in degress.
|
||||||
|
pub x_rotation: f32,
|
||||||
|
#[rtti_field]
|
||||||
|
/// large_arc indicates whether to take the long or the shorter path to complete the arc.
|
||||||
|
pub large_arc: bool,
|
||||||
|
#[rtti_field]
|
||||||
|
/// sweep indicates the direction of the arc. If true, a clockwise direction is chosen,
|
||||||
|
/// otherwise counter-clockwise.
|
||||||
|
pub sweep: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
/// PathElement describes a single element on a path, such as move-to, line-to, etc.
|
/// PathElement describes a single element on a path, such as move-to, line-to, etc.
|
||||||
pub enum PathElement {
|
pub enum PathElement {
|
||||||
/// The LineTo variant describes a line.
|
/// The LineTo variant describes a line.
|
||||||
LineTo(PathLineTo),
|
LineTo(PathLineTo),
|
||||||
|
/// The PathArcTo variant describes an arc.
|
||||||
|
ArcTo(PathArcTo),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
|
@ -377,6 +377,9 @@ fn convert_path_element(
|
||||||
"LineTo" => sixtyfps_corelib::abi::datastructures::PathElement::LineTo(
|
"LineTo" => sixtyfps_corelib::abi::datastructures::PathElement::LineTo(
|
||||||
new_struct_with_bindings(&expr_element.bindings, component_type, eval_context),
|
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),
|
||||||
|
),
|
||||||
_ => panic!(
|
_ => panic!(
|
||||||
"Cannot create unsupported path element {}",
|
"Cannot create unsupported path element {}",
|
||||||
expr_element.element_type.class_name
|
expr_element.element_type.class_name
|
||||||
|
|
|
@ -5,7 +5,7 @@ use itertools::Itertools;
|
||||||
use lyon::tessellation::geometry_builder::{BuffersBuilder, VertexBuffers};
|
use lyon::tessellation::geometry_builder::{BuffersBuilder, VertexBuffers};
|
||||||
use lyon::tessellation::{FillAttributes, FillOptions, FillTessellator};
|
use lyon::tessellation::{FillAttributes, FillOptions, FillTessellator};
|
||||||
use sixtyfps_corelib::abi::datastructures::{
|
use sixtyfps_corelib::abi::datastructures::{
|
||||||
Color, ComponentWindow, ComponentWindowOpaque, PathElement, PathLineTo, Point, Rect,
|
Color, ComponentWindow, ComponentWindowOpaque, PathArcTo, PathElement, PathLineTo, Point, Rect,
|
||||||
RenderingPrimitive, Resource, Size,
|
RenderingPrimitive, Resource, Size,
|
||||||
};
|
};
|
||||||
use sixtyfps_corelib::graphics::{
|
use sixtyfps_corelib::graphics::{
|
||||||
|
@ -336,8 +336,11 @@ impl RenderingPrimitivesBuilder for GLRenderingPrimitivesBuilder {
|
||||||
Some(self.create_glyph_runs(text, font_family, pixel_size, *color))
|
Some(self.create_glyph_runs(text, font_family, pixel_size, *color))
|
||||||
}
|
}
|
||||||
RenderingPrimitive::Path { x: _, y: _, elements, fill_color } => {
|
RenderingPrimitive::Path { x: _, y: _, elements, fill_color } => {
|
||||||
use lyon::math::Point;
|
use lyon::math::{Angle, Point, Vector};
|
||||||
use lyon::path::builder::{Build, FlatPathBuilder};
|
use lyon::path::{
|
||||||
|
builder::{Build, FlatPathBuilder, SvgBuilder},
|
||||||
|
ArcFlags,
|
||||||
|
};
|
||||||
|
|
||||||
let mut path_builder = lyon::path::Path::builder().with_svg();
|
let mut path_builder = lyon::path::Path::builder().with_svg();
|
||||||
for element in elements.iter() {
|
for element in elements.iter() {
|
||||||
|
@ -345,6 +348,20 @@ impl RenderingPrimitivesBuilder for GLRenderingPrimitivesBuilder {
|
||||||
PathElement::LineTo(PathLineTo { x, y }) => {
|
PathElement::LineTo(PathLineTo { x, y }) => {
|
||||||
path_builder.line_to(Point::new(*x, *y))
|
path_builder.line_to(Point::new(*x, *y))
|
||||||
}
|
}
|
||||||
|
PathElement::ArcTo(PathArcTo {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
radius_x,
|
||||||
|
radius_y,
|
||||||
|
x_rotation,
|
||||||
|
large_arc,
|
||||||
|
sweep,
|
||||||
|
}) => path_builder.arc_to(
|
||||||
|
Vector::new(*radius_x, *radius_y),
|
||||||
|
Angle::degrees(*x_rotation),
|
||||||
|
ArcFlags { large_arc: *large_arc, sweep: *sweep },
|
||||||
|
Point::new(*x, *y),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,13 @@ Hello := Rectangle {
|
||||||
x: 0;
|
x: 0;
|
||||||
y: 100;
|
y: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArcTo {
|
||||||
|
x: 0;
|
||||||
|
y: 0;
|
||||||
|
radius_x: 10;
|
||||||
|
radius_y: 10;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue