Integrate Vello for vector rendering (#1802)

* Start integrating vello into render pipeline

Cache vello render creation

Implement viewport navigation

Close vello path

Add transform parameter to vello render pass

* Fix render node types

* Fix a bunch of bugs in the path translation

* Avoid panic on empty document

* Fix rendering of holes

* Implement image rendering

* Implement graph recompilation afer editor api change

* Implement preferences toggle for using vello as the renderer

* Make surface creation optional

* Feature gate vello usages

* Implement skeleton for radial gradient

* Rename vello preference

* Fix some gradients

* Only update monitor nodes on graph recompile

* Fix warnings + remove dead code

* Update everything except for thumbnails after a node graph evaluation

* Fix missing click targets for Image frames

* Improve perfamance by removing unecessary widget updates

* Fix node graph paning

* Fix thumbnail loading

* Implement proper hash for vector modification

* Fix test and warnings

* Code review

* Fix dep

* Remove warning

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Dennis Kobert
2024-07-22 10:56:29 +02:00
committed by GitHub
parent 8e774efe9d
commit ab71d26d84
41 changed files with 807 additions and 760 deletions

View File

@@ -277,7 +277,7 @@ impl ManipulatorPointId {
}
/// The type of handle found on a bézier curve.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, DynAny)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, DynAny)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum HandleType {
/// The first handle on a cubic bézier or the only handle on a quadratic bézier.
@@ -287,7 +287,7 @@ pub enum HandleType {
}
/// Represents a primary or end handle found in a particular segment.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, DynAny)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, DynAny)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct HandleId {
pub ty: HandleType,

View File

@@ -9,7 +9,7 @@ use std::collections::HashMap;
macro_rules! create_ids {
($($id:ident),*) => {
$(
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, DynAny)]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, DynAny)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// A strongly typed ID
pub struct $id(u64);

View File

@@ -16,6 +16,20 @@ pub struct PointModification {
delta: HashMap<PointId, DVec2>,
}
impl Hash for PointModification {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.add.hash(state);
let mut remove = self.remove.iter().collect::<Vec<_>>();
remove.sort_unstable();
remove.hash(state);
let mut delta = self.delta.iter().map(|(&a, &b)| (a, [b.x.to_bits(), b.y.to_bits()])).collect::<Vec<_>>();
delta.sort_unstable();
delta.hash(state);
}
}
impl PointModification {
/// Apply this modification to the specified [`PointDomain`].
pub fn apply(&self, point_domain: &mut PointDomain, segment_domain: &mut SegmentDomain) {
@@ -90,6 +104,36 @@ pub struct SegmentModification {
stroke: HashMap<SegmentId, StrokeId>,
}
impl Hash for SegmentModification {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.add.hash(state);
let mut remove = self.remove.iter().collect::<Vec<_>>();
remove.sort_unstable();
remove.hash(state);
let mut start_point = self.start_point.iter().map(|(&a, &b)| (a, b)).collect::<Vec<_>>();
start_point.sort_unstable();
start_point.hash(state);
let mut end_point = self.end_point.iter().map(|(&a, &b)| (a, b)).collect::<Vec<_>>();
end_point.sort_unstable();
end_point.hash(state);
let mut handle_primary = self.handle_primary.iter().map(|(&a, &b)| (a, b.map(|b| [b.x.to_bits(), b.y.to_bits()]))).collect::<Vec<_>>();
handle_primary.sort_unstable();
handle_primary.hash(state);
let mut handle_end = self.handle_end.iter().map(|(&a, &b)| (a, b.map(|b| [b.x.to_bits(), b.y.to_bits()]))).collect::<Vec<_>>();
handle_end.sort_unstable();
handle_end.hash(state);
let mut stroke = self.stroke.iter().map(|(&a, &b)| (a, b)).collect::<Vec<_>>();
stroke.sort_unstable();
stroke.hash(state);
}
}
impl SegmentModification {
/// Apply this modification to the specified [`SegmentDomain`].
pub fn apply(&self, segment_domain: &mut SegmentDomain, point_domain: &PointDomain) {
@@ -245,6 +289,24 @@ pub struct RegionModification {
fill: HashMap<RegionId, FillId>,
}
impl Hash for RegionModification {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.add.hash(state);
let mut remove = self.remove.iter().collect::<Vec<_>>();
remove.sort_unstable();
remove.hash(state);
let mut segment_range = self.segment_range.iter().map(|(&a, b)| (a, (*b.start(), *b.end()))).collect::<Vec<_>>();
segment_range.sort_unstable();
segment_range.hash(state);
let mut fill = self.fill.iter().map(|(&a, &b)| (a, b)).collect::<Vec<_>>();
fill.sort_unstable();
fill.hash(state);
}
}
impl RegionModification {
/// Apply this modification to the specified [`RegionDomain`].
pub fn apply(&self, region_domain: &mut RegionDomain) {
@@ -398,8 +460,19 @@ impl VectorModification {
impl core::hash::Hash for VectorModification {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
// TODO: properly implement (hashing a hashset is difficult because ordering is unstable)
PointId::generate().hash(state);
self.points.hash(state);
self.segments.hash(state);
self.regions.hash(state);
let mut add_g1_continuous = self.add_g1_continuous.iter().copied().collect::<Vec<_>>();
add_g1_continuous.sort_unstable();
add_g1_continuous.hash(state);
let mut remove_g1_continuous = self.remove_g1_continuous.iter().copied().collect::<Vec<_>>();
remove_g1_continuous.sort_unstable();
remove_g1_continuous.hash(state);
}
}