Add a stack-based Boolean Operation layer node (#1813)

* Multiple boolean operation node

* Change boolean operation ordering

* Complete layer boolean operation node

* Automatically insert new boolean operation node

* Remove divide operation

* Fix subtract operations

* Remove stack data from boolean operation properties

* Fix images and custom vectors

* Code cleanup

* Use slice instead of iter to avoid infinite type recursion

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
adamgerhant
2024-07-10 02:12:55 -07:00
committed by GitHub
parent f4e3e5ab2a
commit 9d749c49fb
14 changed files with 319 additions and 153 deletions

View File

@@ -57,7 +57,7 @@ impl core::hash::Hash for GraphicGroup {
}
/// The possible forms of graphical content held in a Vec by the `elements` field of [`GraphicElement`].
/// Can be another recursively nested [`GraphicGroup`], [`VectorData`], an [`ImageFrame`], text (not yet implemented), or an [`Artboard`].
/// Can be another recursively nested [`GraphicGroup`], a [`VectorData`] shape, an [`ImageFrame`], or an [`Artboard`].
#[derive(Clone, Debug, Hash, PartialEq, DynAny)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum GraphicElement {
@@ -67,10 +67,6 @@ pub enum GraphicElement {
VectorData(Box<VectorData>),
/// A bitmap image with a finite position and extent, equivalent to the SVG <image> tag: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/image
ImageFrame(ImageFrame<Color>),
// TODO: Switch from `String` to a proper formatted typography type
/// Text, equivalent to the SVG <text> tag: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/text
/// (Not yet implemented.)
Text(String),
/// The bounds for displaying a page of contained content
Artboard(Artboard),
}
@@ -366,28 +362,6 @@ impl GraphicElement {
bounding_box: None,
}))
}
GraphicElement::Text(text) => usvg::Node::Text(Box::new(usvg::Text {
id: String::new(),
abs_transform: usvg::Transform::identity(),
rendering_mode: usvg::TextRendering::OptimizeSpeed,
writing_mode: usvg::WritingMode::LeftToRight,
chunks: vec![usvg::TextChunk {
text: text.clone(),
x: None,
y: None,
anchor: usvg::TextAnchor::Start,
spans: vec![],
text_flow: usvg::TextFlow::Linear,
}],
dx: Vec::new(),
dy: Vec::new(),
rotate: Vec::new(),
bounding_box: None,
abs_bounding_box: None,
stroke_bounding_box: None,
abs_stroke_bounding_box: None,
flattened: None,
})),
GraphicElement::GraphicGroup(group) => {
let mut group_element = usvg::Group::default();

View File

@@ -554,7 +554,6 @@ impl GraphicElementRendered for GraphicElement {
match self {
GraphicElement::VectorData(vector_data) => vector_data.render_svg(render, render_params),
GraphicElement::ImageFrame(image_frame) => image_frame.render_svg(render, render_params),
GraphicElement::Text(_) => todo!("Render a text GraphicElement"),
GraphicElement::GraphicGroup(graphic_group) => graphic_group.render_svg(render, render_params),
GraphicElement::Artboard(artboard) => artboard.render_svg(render, render_params),
}
@@ -564,7 +563,6 @@ impl GraphicElementRendered for GraphicElement {
match self {
GraphicElement::VectorData(vector_data) => GraphicElementRendered::bounding_box(&**vector_data, transform),
GraphicElement::ImageFrame(image_frame) => image_frame.bounding_box(transform),
GraphicElement::Text(_) => todo!("Bounds of a text GraphicElement"),
GraphicElement::GraphicGroup(graphic_group) => graphic_group.bounding_box(transform),
GraphicElement::Artboard(artboard) => artboard.bounding_box(transform),
}
@@ -574,7 +572,6 @@ impl GraphicElementRendered for GraphicElement {
match self {
GraphicElement::VectorData(vector_data) => vector_data.add_click_targets(click_targets),
GraphicElement::ImageFrame(image_frame) => image_frame.add_click_targets(click_targets),
GraphicElement::Text(_) => todo!("click target for text GraphicElement"),
GraphicElement::GraphicGroup(graphic_group) => graphic_group.add_click_targets(click_targets),
GraphicElement::Artboard(artboard) => artboard.add_click_targets(click_targets),
}
@@ -584,7 +581,6 @@ impl GraphicElementRendered for GraphicElement {
match self {
GraphicElement::VectorData(vector_data) => vector_data.to_usvg_node(),
GraphicElement::ImageFrame(image_frame) => image_frame.to_usvg_node(),
GraphicElement::Text(text) => text.to_usvg_node(),
GraphicElement::GraphicGroup(graphic_group) => graphic_group.to_usvg_node(),
GraphicElement::Artboard(artboard) => artboard.to_usvg_node(),
}
@@ -594,7 +590,6 @@ impl GraphicElementRendered for GraphicElement {
match self {
GraphicElement::VectorData(vector_data) => vector_data.contains_artboard(),
GraphicElement::ImageFrame(image_frame) => image_frame.contains_artboard(),
GraphicElement::Text(text) => text.contains_artboard(),
GraphicElement::GraphicGroup(graphic_group) => graphic_group.contains_artboard(),
GraphicElement::Artboard(artboard) => artboard.contains_artboard(),
}

View File

@@ -75,7 +75,6 @@ impl Transform for GraphicElement {
match self {
GraphicElement::VectorData(vector_shape) => vector_shape.transform(),
GraphicElement::ImageFrame(image_frame) => image_frame.transform(),
GraphicElement::Text(_) => todo!("Transform of text"),
GraphicElement::GraphicGroup(graphic_group) => graphic_group.transform(),
GraphicElement::Artboard(artboard) => artboard.transform(),
}
@@ -84,7 +83,6 @@ impl Transform for GraphicElement {
match self {
GraphicElement::VectorData(vector_shape) => vector_shape.local_pivot(pivot),
GraphicElement::ImageFrame(image_frame) => image_frame.local_pivot(pivot),
GraphicElement::Text(_) => todo!("Transform of text"),
GraphicElement::GraphicGroup(graphic_group) => graphic_group.local_pivot(pivot),
GraphicElement::Artboard(artboard) => artboard.local_pivot(pivot),
}
@@ -93,7 +91,6 @@ impl Transform for GraphicElement {
match self {
GraphicElement::VectorData(vector_shape) => vector_shape.decompose_scale(),
GraphicElement::ImageFrame(image_frame) => image_frame.decompose_scale(),
GraphicElement::Text(_) => todo!("Transform of text"),
GraphicElement::GraphicGroup(graphic_group) => graphic_group.decompose_scale(),
GraphicElement::Artboard(artboard) => artboard.decompose_scale(),
}
@@ -104,7 +101,6 @@ impl TransformMut for GraphicElement {
match self {
GraphicElement::VectorData(vector_shape) => vector_shape.transform_mut(),
GraphicElement::ImageFrame(image_frame) => image_frame.transform_mut(),
GraphicElement::Text(_) => todo!("Transform of text"),
GraphicElement::GraphicGroup(graphic_group) => graphic_group.transform_mut(),
GraphicElement::Artboard(_) => todo!("Transform of artboard"),
}

View File

@@ -18,23 +18,21 @@ pub enum BooleanOperation {
SubtractBack,
Intersect,
Difference,
Divide,
}
impl BooleanOperation {
pub fn list() -> [BooleanOperation; 6] {
pub fn list() -> [BooleanOperation; 5] {
[
BooleanOperation::Union,
BooleanOperation::SubtractFront,
BooleanOperation::SubtractBack,
BooleanOperation::Intersect,
BooleanOperation::Difference,
BooleanOperation::Divide,
]
}
pub fn icons() -> [&'static str; 6] {
["BooleanUnion", "BooleanSubtractFront", "BooleanSubtractBack", "BooleanIntersect", "BooleanDifference", "BooleanDivide"]
pub fn icons() -> [&'static str; 5] {
["BooleanUnion", "BooleanSubtractFront", "BooleanSubtractBack", "BooleanIntersect", "BooleanDifference"]
}
}
@@ -46,7 +44,6 @@ impl core::fmt::Display for BooleanOperation {
BooleanOperation::SubtractBack => write!(f, "Subtract Back"),
BooleanOperation::Intersect => write!(f, "Intersect"),
BooleanOperation::Difference => write!(f, "Difference"),
BooleanOperation::Divide => write!(f, "Divide"),
}
}
}