mirror of
https://github.com/penpot/penpot.git
synced 2025-12-12 06:24:17 +01:00
✨ Removed modifiers from code
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.types.container :as ctn]
|
||||
[app.common.types.modifiers :as ctm]
|
||||
[app.common.types.path :as path]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.types.shape.attrs :refer [editable-attrs]]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
@@ -669,6 +670,8 @@
|
||||
snap-pixel?
|
||||
(and (not ignore-snap-pixel) (contains? (:workspace-layout state) :snap-pixel-grid))
|
||||
|
||||
_ (wasm.api/clean-geometry-modifiers)
|
||||
|
||||
transforms
|
||||
(into {} (wasm.api/propagate-modifiers geometry-entries snap-pixel?))
|
||||
|
||||
@@ -685,12 +688,24 @@
|
||||
modifiers (dm/get-in modif-tree [shape-id :modifiers])]
|
||||
(-> shape
|
||||
(gsh/apply-transform transform)
|
||||
(ctm/apply-structure-modifiers modifiers))))]
|
||||
(ctm/apply-structure-modifiers modifiers))))
|
||||
|
||||
bool-ids
|
||||
(into #{}
|
||||
(comp
|
||||
(mapcat (partial cfh/get-parents-with-self objects))
|
||||
(filter cfh/bool-shape?)
|
||||
(map :id))
|
||||
ids)]
|
||||
(rx/of
|
||||
(clear-local-transform)
|
||||
(ptk/event ::dwg/move-frame-guides {:ids ids :transforms transforms})
|
||||
(ptk/event ::dwcm/move-frame-comment-threads transforms)
|
||||
(dwsh/update-shapes ids update-shape options))))))
|
||||
(dwsh/update-shapes ids update-shape options)
|
||||
|
||||
;; The update to the bool path needs to be in a different operation because it
|
||||
;; needs to have the updated children info
|
||||
(dwsh/update-shapes bool-ids path/update-bool-shape (assoc options :with-objects? true)))))))
|
||||
|
||||
(def ^:private
|
||||
xf-rotation-shape
|
||||
|
||||
@@ -314,8 +314,8 @@
|
||||
:ignore-constraints (contains? layout :scale-text))))))
|
||||
(rx/take-until stopper))
|
||||
|
||||
;; The last event we need to use the old method so the elements are correctly positioned until
|
||||
;; all the logic is implemented in wasm
|
||||
;; The last event we need to use the old method so the elements are correctly
|
||||
;; positioned until all the logic is implemented in wasm
|
||||
(->> resize-events-stream
|
||||
(rx/take-until stopper)
|
||||
(rx/last)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"A WASM based render API"
|
||||
(:require
|
||||
["react-dom/server" :as rds]
|
||||
[app.common.data :as d :refer [not-empty?]]
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.math :as mth]
|
||||
[app.common.types.fills :as types.fills]
|
||||
@@ -850,20 +850,14 @@
|
||||
[pending]
|
||||
(let [event (js/CustomEvent. "wasm:set-objects-finished")
|
||||
pending (-> (d/index-by :key :callback pending) vals)]
|
||||
(if (not-empty? pending)
|
||||
(->> (rx/from pending)
|
||||
(rx/merge-map (fn [callback] (callback)))
|
||||
(rx/tap (fn [_] (request-render "set-objects")))
|
||||
(rx/reduce conj [])
|
||||
(rx/subs! (fn [_]
|
||||
(clear-drawing-cache)
|
||||
(request-render "pending-finished")
|
||||
(h/call wasm/internal-module "_update_shape_text_layout_for_all")
|
||||
(.dispatchEvent ^js js/document event))))
|
||||
(do
|
||||
(clear-drawing-cache)
|
||||
(request-render "pending-finished")
|
||||
(.dispatchEvent ^js js/document event)))))
|
||||
(->> (rx/from pending)
|
||||
(rx/merge-map (fn [callback] (callback)))
|
||||
(rx/reduce conj [])
|
||||
(rx/subs! (fn [_]
|
||||
(clear-drawing-cache)
|
||||
(request-render "pending-finished")
|
||||
(h/call wasm/internal-module "_update_shape_text_layout_for_all")
|
||||
(.dispatchEvent ^js js/document event))))))
|
||||
|
||||
(defn process-object
|
||||
[shape]
|
||||
@@ -988,6 +982,10 @@
|
||||
[]
|
||||
(h/call wasm/internal-module "_clean_modifiers"))
|
||||
|
||||
(defn clean-geometry-modifiers
|
||||
[]
|
||||
(h/call wasm/internal-module "_clean_geometry_modifiers"))
|
||||
|
||||
(defn set-modifiers
|
||||
[modifiers]
|
||||
|
||||
@@ -1116,7 +1114,6 @@
|
||||
|
||||
(defn calculate-bool
|
||||
[bool-type ids]
|
||||
|
||||
(let [size (mem/get-alloc-size ids UUID-U8-SIZE)
|
||||
heap (mem/get-heap-u32)
|
||||
offset (mem/alloc->offset-32 size)]
|
||||
|
||||
@@ -495,11 +495,7 @@ pub extern "C" fn get_selection_rect() -> *mut u8 {
|
||||
with_state_mut!(state, {
|
||||
let bbs: Vec<_> = entries
|
||||
.iter()
|
||||
.flat_map(|id| {
|
||||
let default = Matrix::default();
|
||||
let modifier = state.modifiers.get(id).unwrap_or(&default);
|
||||
state.shapes.get(id).map(|b| b.bounds().transform(modifier))
|
||||
})
|
||||
.flat_map(|id| state.shapes.get(id).map(|b| b.bounds()))
|
||||
.collect();
|
||||
|
||||
let result_bound = if bbs.len() == 1 {
|
||||
@@ -569,9 +565,15 @@ pub extern "C" fn set_structure_modifiers() {
|
||||
#[no_mangle]
|
||||
pub extern "C" fn clean_modifiers() {
|
||||
with_state_mut!(state, {
|
||||
state.structure.clear();
|
||||
state.scale_content.clear();
|
||||
// state.modifiers.clear();
|
||||
state.shapes.clean_modifiers();
|
||||
state.shapes.clean_structure();
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn clean_geometry_modifiers() {
|
||||
with_state_mut!(state, {
|
||||
state.shapes.clean_modifiers();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ pub fn are_close_points(a: impl Into<(f32, f32)>, b: impl Into<(f32, f32)>) -> b
|
||||
is_close_to(a_x, b_x) && is_close_to(a_y, b_y)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn is_close_matrix(m: &Matrix, other: &Matrix) -> bool {
|
||||
is_close_to(m.scale_x(), other.scale_x())
|
||||
&& is_close_to(m.scale_y(), other.scale_y())
|
||||
|
||||
@@ -388,8 +388,6 @@ pub fn bool_from_shapes(
|
||||
bool_type: BoolType,
|
||||
children_ids: &IndexSet<Uuid>,
|
||||
shapes: ShapesPoolRef,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
) -> Path {
|
||||
if children_ids.is_empty() {
|
||||
return Path::default();
|
||||
@@ -399,13 +397,13 @@ pub fn bool_from_shapes(
|
||||
return Path::default();
|
||||
};
|
||||
|
||||
let mut current_path = child.to_path(shapes, modifiers, structure);
|
||||
let mut current_path = child.to_path(shapes);
|
||||
|
||||
for idx in (0..children_ids.len() - 1).rev() {
|
||||
let Some(other) = shapes.get(&children_ids[idx]) else {
|
||||
continue;
|
||||
};
|
||||
let other_path = other.to_path(shapes, modifiers, structure);
|
||||
let other_path = other.to_path(shapes);
|
||||
|
||||
let (segs_a, segs_b) = split_segments(¤t_path, &other_path);
|
||||
|
||||
@@ -422,26 +420,15 @@ pub fn bool_from_shapes(
|
||||
current_path
|
||||
}
|
||||
|
||||
pub fn update_bool_to_path(
|
||||
shape: &Shape,
|
||||
shapes: ShapesPoolRef,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
) -> Shape {
|
||||
let mut shape = shape.clone();
|
||||
let children_ids = shape.modified_children_ids(structure.get(&shape.id), true);
|
||||
#[allow(dead_code)]
|
||||
pub fn update_bool_to_path(shape: &mut Shape, shapes: ShapesPoolRef) {
|
||||
let children_ids = shape.children_ids(true);
|
||||
|
||||
let Type::Bool(bool_data) = &mut shape.shape_type else {
|
||||
return shape;
|
||||
return;
|
||||
};
|
||||
bool_data.path = bool_from_shapes(
|
||||
bool_data.bool_type,
|
||||
&children_ids,
|
||||
shapes,
|
||||
modifiers,
|
||||
structure,
|
||||
);
|
||||
shape
|
||||
|
||||
bool_data.path = bool_from_shapes(bool_data.bool_type, &children_ids, shapes);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@@ -450,14 +437,14 @@ pub fn debug_render_bool_paths(
|
||||
render_state: &mut RenderState,
|
||||
shape: &Shape,
|
||||
shapes: ShapesPoolRef,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
_modifiers: &HashMap<Uuid, Matrix>,
|
||||
_structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
) {
|
||||
let canvas = render_state.surfaces.canvas(SurfaceId::Strokes);
|
||||
|
||||
let mut shape = shape.clone();
|
||||
|
||||
let children_ids = shape.modified_children_ids(structure.get(&shape.id), true);
|
||||
let children_ids = shape.children_ids(true);
|
||||
|
||||
let Type::Bool(bool_data) = &mut shape.shape_type else {
|
||||
return;
|
||||
@@ -471,13 +458,13 @@ pub fn debug_render_bool_paths(
|
||||
return;
|
||||
};
|
||||
|
||||
let mut current_path = child.to_path(shapes, modifiers, structure);
|
||||
let mut current_path = child.to_path(shapes);
|
||||
|
||||
for idx in (0..children_ids.len() - 1).rev() {
|
||||
let Some(other) = shapes.get(&children_ids[idx]) else {
|
||||
continue;
|
||||
};
|
||||
let other_path = other.to_path(shapes, modifiers, structure);
|
||||
let other_path = other.to_path(shapes);
|
||||
|
||||
let (segs_a, segs_b) = split_segments(¤t_path, &other_path);
|
||||
|
||||
|
||||
@@ -22,8 +22,7 @@ pub use surfaces::{SurfaceId, Surfaces};
|
||||
|
||||
use crate::performance;
|
||||
use crate::shapes::{
|
||||
all_with_ancestors, Blur, BlurType, Corners, Fill, Shadow, Shape, SolidColor, Stroke,
|
||||
StructureEntry, Type,
|
||||
all_with_ancestors, Blur, BlurType, Corners, Fill, Shadow, Shape, SolidColor, Stroke, Type,
|
||||
};
|
||||
use crate::state::{ShapesPoolMutRef, ShapesPoolRef};
|
||||
use crate::tiles::{self, PendingTiles, TileRect};
|
||||
@@ -31,8 +30,6 @@ use crate::uuid::Uuid;
|
||||
use crate::view::Viewbox;
|
||||
use crate::wapi;
|
||||
|
||||
use crate::math;
|
||||
use crate::math::bools;
|
||||
use indexmap::IndexSet;
|
||||
|
||||
pub use fonts::*;
|
||||
@@ -63,13 +60,11 @@ impl NodeRenderState {
|
||||
/// Calculates the clip bounds for child elements of a given shape.
|
||||
///
|
||||
/// This function determines the clipping region that should be applied to child elements
|
||||
/// when rendering. It takes into account the element's selection rectangle, transform,
|
||||
/// and any additional modifiers.
|
||||
/// when rendering. It takes into account the element's selection rectangle, transform.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// * `element` - The shape element for which to calculate clip bounds
|
||||
/// * `modifiers` - Optional transformation matrix to apply to the bounds
|
||||
/// * `offset` - Optional offset (x, y) to adjust the bounds position. When provided,
|
||||
/// the bounds are translated by the negative of this offset, effectively moving
|
||||
/// the clipping region to compensate for coordinate system transformations.
|
||||
@@ -78,7 +73,6 @@ impl NodeRenderState {
|
||||
pub fn get_children_clip_bounds(
|
||||
&self,
|
||||
element: &Shape,
|
||||
modifiers: Option<&Matrix>,
|
||||
offset: Option<(f32, f32)>,
|
||||
) -> Option<(Rect, Option<Corners>, Matrix)> {
|
||||
if self.id.is_nil() || !element.clip() {
|
||||
@@ -97,10 +91,6 @@ impl NodeRenderState {
|
||||
transform.post_translate(bounds.center());
|
||||
transform.pre_translate(-bounds.center());
|
||||
|
||||
if let Some(modifier) = modifiers {
|
||||
transform.post_concat(modifier);
|
||||
}
|
||||
|
||||
let corners = match &element.shape_type {
|
||||
Type::Rect(data) => data.corners,
|
||||
Type::Frame(data) => data.corners,
|
||||
@@ -119,12 +109,10 @@ impl NodeRenderState {
|
||||
/// # Parameters
|
||||
///
|
||||
/// * `element` - The shape element for which to calculate shadow clip bounds
|
||||
/// * `modifiers` - Optional transformation matrix to apply to the bounds
|
||||
/// * `shadow` - The shadow configuration containing blur, offset, and other properties
|
||||
pub fn get_nested_shadow_clip_bounds(
|
||||
&self,
|
||||
element: &Shape,
|
||||
modifiers: Option<&Matrix>,
|
||||
shadow: &Shadow,
|
||||
) -> Option<(Rect, Option<Corners>, Matrix)> {
|
||||
if self.id.is_nil() {
|
||||
@@ -142,10 +130,6 @@ impl NodeRenderState {
|
||||
transform.post_translate(element.center());
|
||||
transform.pre_translate(-element.center());
|
||||
|
||||
if let Some(modifier) = modifiers {
|
||||
transform.post_concat(modifier);
|
||||
}
|
||||
|
||||
let corners = match &element.shape_type {
|
||||
Type::Rect(data) => data.corners,
|
||||
Type::Frame(data) => data.corners,
|
||||
@@ -275,28 +259,6 @@ pub fn get_cache_size(viewbox: Viewbox, scale: f32) -> skia::ISize {
|
||||
.into()
|
||||
}
|
||||
|
||||
fn is_modified_child(
|
||||
shape: &Shape,
|
||||
shapes: ShapesPoolRef,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
) -> bool {
|
||||
if modifiers.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let ids = shape.all_children(shapes, true, false);
|
||||
let default = &Matrix::default();
|
||||
let parent_modifier = modifiers.get(&shape.id).unwrap_or(default);
|
||||
|
||||
// Returns true if the transform of any child is different to the parent's
|
||||
ids.iter().any(|id| {
|
||||
!math::is_close_matrix(
|
||||
parent_modifier,
|
||||
modifiers.get(id).unwrap_or(&Matrix::default()),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
impl RenderState {
|
||||
pub fn new(width: i32, height: i32) -> RenderState {
|
||||
// This needs to be done once per WebGL context.
|
||||
@@ -476,9 +438,6 @@ impl RenderState {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn render_shape(
|
||||
&mut self,
|
||||
shapes: ShapesPoolRef,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
shape: &Shape,
|
||||
scale_content: Option<&f32>,
|
||||
clip_bounds: Option<(Rect, Option<Corners>, Matrix)>,
|
||||
@@ -546,10 +505,6 @@ impl RenderState {
|
||||
// We don't want to change the value in the global state
|
||||
let mut shape: Cow<Shape> = Cow::Borrowed(shape);
|
||||
|
||||
if let Some(shape_modifiers) = modifiers.get(&shape.id) {
|
||||
shape.to_mut().apply_transform(shape_modifiers);
|
||||
}
|
||||
|
||||
let mut nested_blur_value = 0.;
|
||||
for nested_blur in self.nested_blurs.iter().flatten() {
|
||||
if !nested_blur.hidden && nested_blur.blur_type == BlurType::LayerBlur {
|
||||
@@ -580,11 +535,6 @@ impl RenderState {
|
||||
|
||||
match &shape.shape_type {
|
||||
Type::SVGRaw(sr) => {
|
||||
if let Some(shape_modifiers) = modifiers.get(&shape.id) {
|
||||
self.surfaces
|
||||
.canvas(fills_surface_id)
|
||||
.concat(shape_modifiers);
|
||||
}
|
||||
self.surfaces.canvas(fills_surface_id).concat(&matrix);
|
||||
if let Some(svg) = shape.svg.as_ref() {
|
||||
svg.render(self.surfaces.canvas(fills_surface_id))
|
||||
@@ -751,20 +701,7 @@ impl RenderState {
|
||||
s.canvas().concat(&matrix);
|
||||
});
|
||||
|
||||
// For boolean shapes, there's no need to calculate children because
|
||||
// when painting the shape, the necessary path is already calculated
|
||||
let shape = if let Type::Bool(_) = &shape.shape_type {
|
||||
// If any child transform doesn't match the parent transform means
|
||||
// that the children is transformed and we need to recalculate the
|
||||
// boolean
|
||||
if is_modified_child(&shape, shapes, modifiers) {
|
||||
&bools::update_bool_to_path(&shape, shapes, modifiers, structure)
|
||||
} else {
|
||||
&shape
|
||||
}
|
||||
} else {
|
||||
&shape
|
||||
};
|
||||
let shape = &shape;
|
||||
|
||||
if shape.fills.is_empty()
|
||||
&& !matches!(shape.shape_type, Type::Group(_))
|
||||
@@ -837,12 +774,7 @@ impl RenderState {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_from_cache(
|
||||
&mut self,
|
||||
shapes: ShapesPoolRef,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
) {
|
||||
pub fn render_from_cache(&mut self, shapes: ShapesPoolRef) {
|
||||
let scale = self.get_cached_scale();
|
||||
if let Some(snapshot) = &self.cached_target_snapshot {
|
||||
let canvas = self.surfaces.canvas(SurfaceId::Target);
|
||||
@@ -875,7 +807,7 @@ impl RenderState {
|
||||
debug::render(self);
|
||||
}
|
||||
|
||||
ui::render(self, shapes, modifiers, structure);
|
||||
ui::render(self, shapes);
|
||||
debug::render_wasm_label(self);
|
||||
|
||||
self.flush_and_submit();
|
||||
@@ -885,8 +817,6 @@ impl RenderState {
|
||||
pub fn start_render_loop(
|
||||
&mut self,
|
||||
tree: ShapesPoolRef,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
scale_content: &HashMap<Uuid, f32>,
|
||||
timestamp: i32,
|
||||
) -> Result<(), String> {
|
||||
@@ -937,7 +867,7 @@ impl RenderState {
|
||||
self.current_tile = None;
|
||||
self.render_in_progress = true;
|
||||
self.apply_drawing_to_render_canvas(None);
|
||||
self.process_animation_frame(tree, modifiers, structure, scale_content, timestamp)?;
|
||||
self.process_animation_frame(tree, scale_content, timestamp)?;
|
||||
performance::end_measure!("start_render_loop");
|
||||
Ok(())
|
||||
}
|
||||
@@ -945,21 +875,13 @@ impl RenderState {
|
||||
pub fn process_animation_frame(
|
||||
&mut self,
|
||||
tree: ShapesPoolRef,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
scale_content: &HashMap<Uuid, f32>,
|
||||
timestamp: i32,
|
||||
) -> Result<(), String> {
|
||||
performance::begin_measure!("process_animation_frame");
|
||||
if self.render_in_progress {
|
||||
if tree.len() != 0 {
|
||||
self.render_shape_tree_partial(
|
||||
tree,
|
||||
modifiers,
|
||||
structure,
|
||||
scale_content,
|
||||
timestamp,
|
||||
)?;
|
||||
self.render_shape_tree_partial(tree, scale_content, timestamp)?;
|
||||
} else {
|
||||
println!("Empty tree");
|
||||
}
|
||||
@@ -1031,9 +953,6 @@ impl RenderState {
|
||||
#[inline]
|
||||
pub fn render_shape_exit(
|
||||
&mut self,
|
||||
tree: ShapesPoolRef,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
element: &Shape,
|
||||
visited_mask: bool,
|
||||
scale_content: Option<&f32>,
|
||||
@@ -1091,9 +1010,6 @@ impl RenderState {
|
||||
element_strokes.to_mut().clear_shadows();
|
||||
element_strokes.to_mut().clip_content = false;
|
||||
self.render_shape(
|
||||
tree,
|
||||
modifiers,
|
||||
structure,
|
||||
&element_strokes,
|
||||
scale_content,
|
||||
None,
|
||||
@@ -1179,9 +1095,6 @@ impl RenderState {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn render_drop_black_shadow(
|
||||
&mut self,
|
||||
shapes: ShapesPoolRef,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
shape: &Shape,
|
||||
shadow: &Shadow,
|
||||
scale_content: Option<&f32>,
|
||||
@@ -1233,9 +1146,6 @@ impl RenderState {
|
||||
.translate(translation);
|
||||
|
||||
self.render_shape(
|
||||
shapes,
|
||||
modifiers,
|
||||
structure,
|
||||
&plain_shape,
|
||||
scale_content,
|
||||
clip_bounds,
|
||||
@@ -1254,8 +1164,6 @@ impl RenderState {
|
||||
pub fn render_shape_tree_partial_uncached(
|
||||
&mut self,
|
||||
tree: ShapesPoolRef,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
scale_content: &HashMap<Uuid, f32>,
|
||||
timestamp: i32,
|
||||
) -> Result<(bool, bool), String> {
|
||||
@@ -1272,10 +1180,11 @@ impl RenderState {
|
||||
} = node_render_state;
|
||||
|
||||
is_empty = false;
|
||||
let element = tree.get(&node_id).ok_or(
|
||||
"Error: Element with root_id {node_render_state.id} not found in the tree."
|
||||
.to_string(),
|
||||
)?;
|
||||
|
||||
let element = tree.get(&node_id).ok_or(format!(
|
||||
"Error: Element with root_id {} not found in the tree.",
|
||||
node_render_state.id
|
||||
))?;
|
||||
|
||||
// If the shape is not in the tile set, then we update
|
||||
// it.
|
||||
@@ -1284,14 +1193,7 @@ impl RenderState {
|
||||
}
|
||||
|
||||
if visited_children {
|
||||
self.render_shape_exit(
|
||||
tree,
|
||||
modifiers,
|
||||
structure,
|
||||
element,
|
||||
visited_mask,
|
||||
scale_content.get(&element.id),
|
||||
);
|
||||
self.render_shape_exit(element, visited_mask, scale_content.get(&element.id));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1351,9 +1253,6 @@ impl RenderState {
|
||||
|
||||
// First pass: Render shadow in black to establish alpha mask
|
||||
self.render_drop_black_shadow(
|
||||
tree,
|
||||
modifiers,
|
||||
structure,
|
||||
element,
|
||||
shadow,
|
||||
scale_content.get(&element.id),
|
||||
@@ -1369,17 +1268,11 @@ impl RenderState {
|
||||
if shadow_shape.hidden {
|
||||
continue;
|
||||
}
|
||||
let clip_bounds = node_render_state.get_nested_shadow_clip_bounds(
|
||||
element,
|
||||
modifiers.get(&element.id),
|
||||
shadow,
|
||||
);
|
||||
let clip_bounds = node_render_state
|
||||
.get_nested_shadow_clip_bounds(element, shadow);
|
||||
|
||||
if !matches!(shadow_shape.shape_type, Type::Text(_)) {
|
||||
self.render_drop_black_shadow(
|
||||
tree,
|
||||
modifiers,
|
||||
structure,
|
||||
shadow_shape,
|
||||
shadow,
|
||||
scale_content.get(&element.id),
|
||||
@@ -1415,9 +1308,6 @@ impl RenderState {
|
||||
new_shadow_paint.set_blend_mode(skia::BlendMode::SrcOver);
|
||||
|
||||
self.render_shape(
|
||||
tree,
|
||||
modifiers,
|
||||
structure,
|
||||
shadow_shape,
|
||||
scale_content.get(&element.id),
|
||||
clip_bounds,
|
||||
@@ -1456,9 +1346,6 @@ impl RenderState {
|
||||
.clear(skia::Color::TRANSPARENT);
|
||||
|
||||
self.render_shape(
|
||||
tree,
|
||||
modifiers,
|
||||
structure,
|
||||
element,
|
||||
scale_content.get(&element.id),
|
||||
clip_bounds,
|
||||
@@ -1497,14 +1384,10 @@ impl RenderState {
|
||||
});
|
||||
|
||||
if element.is_recursive() {
|
||||
let children_clip_bounds = node_render_state.get_children_clip_bounds(
|
||||
element,
|
||||
modifiers.get(&element.id),
|
||||
None,
|
||||
);
|
||||
let children_clip_bounds =
|
||||
node_render_state.get_children_clip_bounds(element, None);
|
||||
|
||||
let mut children_ids =
|
||||
element.modified_children_ids(structure.get(&element.id), false);
|
||||
let mut children_ids = element.children_ids(false);
|
||||
|
||||
// Z-index ordering on Layouts
|
||||
if element.has_layout() {
|
||||
@@ -1538,8 +1421,6 @@ impl RenderState {
|
||||
pub fn render_shape_tree_partial(
|
||||
&mut self,
|
||||
tree: ShapesPoolRef,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
scale_content: &HashMap<Uuid, f32>,
|
||||
timestamp: i32,
|
||||
) -> Result<(), String> {
|
||||
@@ -1566,13 +1447,8 @@ impl RenderState {
|
||||
}
|
||||
} else {
|
||||
performance::begin_measure!("render_shape_tree::uncached");
|
||||
let (is_empty, early_return) = self.render_shape_tree_partial_uncached(
|
||||
tree,
|
||||
modifiers,
|
||||
structure,
|
||||
scale_content,
|
||||
timestamp,
|
||||
)?;
|
||||
let (is_empty, early_return) =
|
||||
self.render_shape_tree_partial_uncached(tree, scale_content, timestamp)?;
|
||||
if early_return {
|
||||
return Ok(());
|
||||
}
|
||||
@@ -1606,7 +1482,7 @@ impl RenderState {
|
||||
let Some(root) = tree.get(&Uuid::nil()) else {
|
||||
return Err(String::from("Root shape not found"));
|
||||
};
|
||||
let root_ids = root.modified_children_ids(structure.get(&root.id), false);
|
||||
let root_ids = root.children_ids(false);
|
||||
|
||||
// If we finish processing every node rendering is complete
|
||||
// let's check if there are more pending nodes
|
||||
@@ -1649,7 +1525,7 @@ impl RenderState {
|
||||
debug::render(self);
|
||||
}
|
||||
|
||||
ui::render(self, tree, modifiers, structure);
|
||||
ui::render(self, tree);
|
||||
debug::render_wasm_label(self);
|
||||
|
||||
Ok(())
|
||||
@@ -1678,6 +1554,7 @@ impl RenderState {
|
||||
|
||||
// Then, add the shape to the new tiles
|
||||
for tile in new_tiles {
|
||||
self.remove_cached_tile_shape(tile, shape.id);
|
||||
self.tiles.add_shape_at(tile, shape.id);
|
||||
}
|
||||
}
|
||||
@@ -1689,27 +1566,18 @@ impl RenderState {
|
||||
self.tiles.remove_shape_at(tile, id);
|
||||
}
|
||||
|
||||
pub fn rebuild_tiles_shallow(
|
||||
&mut self,
|
||||
tree: ShapesPoolRef,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
) {
|
||||
pub fn rebuild_tiles_shallow(&mut self, tree: ShapesPoolRef) {
|
||||
performance::begin_measure!("rebuild_tiles_shallow");
|
||||
self.tiles.invalidate();
|
||||
self.surfaces.remove_cached_tiles(self.background_color);
|
||||
let mut nodes = vec![Uuid::nil()];
|
||||
while let Some(shape_id) = nodes.pop() {
|
||||
if let Some(shape) = tree.get(&shape_id) {
|
||||
let mut shape: Cow<Shape> = Cow::Borrowed(shape);
|
||||
if shape_id != Uuid::nil() {
|
||||
if let Some(modifier) = modifiers.get(&shape_id) {
|
||||
shape.to_mut().apply_transform(modifier);
|
||||
}
|
||||
self.update_tile_for(&shape, tree);
|
||||
} else {
|
||||
// We only need to rebuild tiles from the first level.
|
||||
let children = shape.modified_children_ids(structure.get(&shape.id), false);
|
||||
let children = shape.children_ids(false);
|
||||
for child_id in children.iter() {
|
||||
nodes.push(*child_id);
|
||||
}
|
||||
@@ -1719,27 +1587,18 @@ impl RenderState {
|
||||
performance::end_measure!("rebuild_tiles_shallow");
|
||||
}
|
||||
|
||||
pub fn rebuild_tiles(
|
||||
&mut self,
|
||||
tree: ShapesPoolRef,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
) {
|
||||
pub fn rebuild_tiles(&mut self, tree: ShapesPoolRef) {
|
||||
performance::begin_measure!("rebuild_tiles");
|
||||
self.tiles.invalidate();
|
||||
self.surfaces.remove_cached_tiles(self.background_color);
|
||||
let mut nodes = vec![Uuid::nil()];
|
||||
while let Some(shape_id) = nodes.pop() {
|
||||
if let Some(shape) = tree.get(&shape_id) {
|
||||
let mut shape: Cow<Shape> = Cow::Borrowed(shape);
|
||||
if shape_id != Uuid::nil() {
|
||||
if let Some(modifier) = modifiers.get(&shape_id) {
|
||||
shape.to_mut().apply_transform(modifier);
|
||||
}
|
||||
self.update_tile_for(&shape, tree);
|
||||
}
|
||||
|
||||
let children = shape.modified_children_ids(structure.get(&shape.id), false);
|
||||
let children = shape.children_ids(false);
|
||||
for child_id in children.iter() {
|
||||
nodes.push(*child_id);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,12 @@
|
||||
use skia_safe::{self as skia};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::math::{Matrix, Rect};
|
||||
use crate::math::Rect;
|
||||
use crate::shapes::modifiers::grid_layout::grid_cell_data;
|
||||
use crate::shapes::{Shape, StructureEntry};
|
||||
use crate::shapes::Shape;
|
||||
use crate::state::ShapesPoolRef;
|
||||
use crate::uuid::Uuid;
|
||||
|
||||
pub fn render_overlay(
|
||||
zoom: f32,
|
||||
canvas: &skia::Canvas,
|
||||
shape: &Shape,
|
||||
shapes: ShapesPoolRef,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
) {
|
||||
let cells = grid_cell_data(shape, shapes, modifiers, structure, true);
|
||||
pub fn render_overlay(zoom: f32, canvas: &skia::Canvas, shape: &Shape, shapes: ShapesPoolRef) {
|
||||
let cells = grid_cell_data(shape, shapes, true);
|
||||
|
||||
let mut paint = skia::Paint::default();
|
||||
paint.set_style(skia::PaintStyle::Stroke);
|
||||
|
||||
@@ -1,18 +1,9 @@
|
||||
use skia_safe::{self as skia, Color4f};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use super::{RenderState, ShapesPoolRef, SurfaceId};
|
||||
use crate::math::Matrix;
|
||||
use crate::render::grid_layout;
|
||||
use crate::shapes::StructureEntry;
|
||||
use crate::uuid::Uuid;
|
||||
|
||||
pub fn render(
|
||||
render_state: &mut RenderState,
|
||||
shapes: ShapesPoolRef,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
) {
|
||||
pub fn render(render_state: &mut RenderState, shapes: ShapesPoolRef) {
|
||||
let canvas = render_state.surfaces.canvas(SurfaceId::UI);
|
||||
|
||||
canvas.clear(Color4f::new(0.0, 0.0, 0.0, 0.0));
|
||||
@@ -29,7 +20,7 @@ pub fn render(
|
||||
|
||||
if let Some(id) = render_state.show_grid {
|
||||
if let Some(shape) = shapes.get(&id) {
|
||||
grid_layout::render_overlay(zoom, canvas, shape, shapes, modifiers, structure);
|
||||
grid_layout::render_overlay(zoom, canvas, shape, shapes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ pub use svgraw::*;
|
||||
pub use text::*;
|
||||
pub use transform::*;
|
||||
|
||||
use crate::math::bools as math_bools;
|
||||
use crate::math::{self, Bounds, Matrix, Point};
|
||||
use indexmap::IndexSet;
|
||||
|
||||
@@ -309,6 +310,10 @@ impl Shape {
|
||||
matches!(self.shape_type, Type::Frame(_))
|
||||
}
|
||||
|
||||
pub fn is_bool(&self) -> bool {
|
||||
matches!(self.shape_type, Type::Bool(_))
|
||||
}
|
||||
|
||||
pub fn is_group_like(&self) -> bool {
|
||||
matches!(self.shape_type, Type::Group(_)) || matches!(self.shape_type, Type::Bool(_))
|
||||
}
|
||||
@@ -901,6 +906,7 @@ impl Shape {
|
||||
self.children.first()
|
||||
}
|
||||
|
||||
// TODO: Review this to use children_ids_iter instead
|
||||
pub fn children_ids(&self, include_hidden: bool) -> IndexSet<Uuid> {
|
||||
if include_hidden {
|
||||
return self.children.clone().into_iter().rev().collect();
|
||||
@@ -1164,7 +1170,7 @@ impl Shape {
|
||||
for st in structure {
|
||||
match st.entry_type {
|
||||
StructureEntryType::AddChild => {
|
||||
result.insert(result.len() - st.index as usize, st.id);
|
||||
result.insert(st.index as usize, st.id);
|
||||
}
|
||||
StructureEntryType::RemoveChild => {
|
||||
to_remove.insert(&st.id);
|
||||
@@ -1182,6 +1188,7 @@ impl Shape {
|
||||
|
||||
pub fn transformed(
|
||||
&self,
|
||||
shapes_pool: ShapesPoolRef,
|
||||
transform: Option<&Matrix>,
|
||||
structure: Option<&Vec<StructureEntry>>,
|
||||
) -> Self {
|
||||
@@ -1192,6 +1199,9 @@ impl Shape {
|
||||
if let Some(structure) = structure {
|
||||
shape.to_mut().apply_structure(structure);
|
||||
}
|
||||
if self.is_bool() {
|
||||
math_bools::update_bool_to_path(shape.to_mut(), shapes_pool)
|
||||
}
|
||||
shape.into_owned()
|
||||
}
|
||||
|
||||
@@ -1247,73 +1257,6 @@ impl Shape {
|
||||
.count()
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the list of children taking into account the structure modifiers
|
||||
*/
|
||||
pub fn modified_children_ids(
|
||||
&self,
|
||||
structure: Option<&Vec<StructureEntry>>,
|
||||
include_hidden: bool,
|
||||
) -> IndexSet<Uuid> {
|
||||
if let Some(structure) = structure {
|
||||
let mut result: Vec<Uuid> =
|
||||
Vec::from_iter(self.children_ids(include_hidden).iter().copied());
|
||||
let mut to_remove = HashSet::<&Uuid>::new();
|
||||
|
||||
for st in structure {
|
||||
match st.entry_type {
|
||||
StructureEntryType::AddChild => {
|
||||
result.insert(result.len() - st.index as usize, st.id);
|
||||
}
|
||||
StructureEntryType::RemoveChild => {
|
||||
to_remove.insert(&st.id);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
let ret: IndexSet<Uuid> = result
|
||||
.iter()
|
||||
.filter(|id| !to_remove.contains(id))
|
||||
.copied()
|
||||
.collect();
|
||||
|
||||
ret
|
||||
} else {
|
||||
self.children_ids(include_hidden)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modified_children_ids_iter<'a>(
|
||||
&'a self,
|
||||
structure: Option<&'a Vec<StructureEntry>>,
|
||||
include_hidden: bool,
|
||||
) -> Box<dyn Iterator<Item = Cow<'a, Uuid>> + 'a> {
|
||||
if let Some(structure) = structure {
|
||||
let mut result: Vec<Cow<'a, Uuid>> = self
|
||||
.children_ids_iter(include_hidden)
|
||||
.map(Cow::Borrowed)
|
||||
.collect();
|
||||
let mut to_remove = HashSet::<Cow<'a, Uuid>>::new();
|
||||
|
||||
for st in structure {
|
||||
match st.entry_type {
|
||||
StructureEntryType::AddChild => {
|
||||
result.insert(result.len() - st.index as usize, Cow::Owned(st.id));
|
||||
}
|
||||
StructureEntryType::RemoveChild => {
|
||||
to_remove.insert(Cow::Owned(st.id));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
Box::new(result.into_iter().filter(move |id| !to_remove.contains(id)))
|
||||
} else {
|
||||
Box::new(self.children_ids_iter(include_hidden).map(Cow::Borrowed))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn drop_shadow_paints(&self) -> Vec<skia_safe::Paint> {
|
||||
let drop_shadows: Vec<&Shadow> = self.drop_shadows_visible().collect();
|
||||
|
||||
|
||||
@@ -10,8 +10,7 @@ use crate::math::{self as math, bools, identitish, Bounds, Matrix, Point};
|
||||
use common::GetBounds;
|
||||
|
||||
use crate::shapes::{
|
||||
ConstraintH, ConstraintV, Frame, Group, GrowType, Layout, Modifier, Shape, StructureEntry,
|
||||
TransformEntry, Type,
|
||||
ConstraintH, ConstraintV, Frame, Group, GrowType, Layout, Modifier, Shape, TransformEntry, Type,
|
||||
};
|
||||
use crate::state::{ShapesPoolRef, State};
|
||||
use crate::uuid::Uuid;
|
||||
@@ -24,10 +23,9 @@ fn propagate_children(
|
||||
parent_bounds_after: &Bounds,
|
||||
transform: Matrix,
|
||||
bounds: &HashMap<Uuid, Bounds>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
scale_content: &HashMap<Uuid, f32>,
|
||||
) -> VecDeque<Modifier> {
|
||||
let children_ids = shape.modified_children_ids(structure.get(&shape.id), true);
|
||||
let children_ids = shape.children_ids(true);
|
||||
|
||||
if children_ids.is_empty() || identitish(&transform) {
|
||||
return VecDeque::new();
|
||||
@@ -92,12 +90,11 @@ fn calculate_group_bounds(
|
||||
shape: &Shape,
|
||||
shapes: ShapesPoolRef,
|
||||
bounds: &HashMap<Uuid, Bounds>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
) -> Option<Bounds> {
|
||||
let shape_bounds = bounds.find(shape);
|
||||
let mut result = Vec::<Point>::new();
|
||||
|
||||
for child_id in shape.modified_children_ids_iter(structure.get(&shape.id), true) {
|
||||
for child_id in shape.children_ids_iter(true) {
|
||||
let Some(child) = shapes.get(&child_id) else {
|
||||
continue;
|
||||
};
|
||||
@@ -112,23 +109,15 @@ fn calculate_bool_bounds(
|
||||
shape: &Shape,
|
||||
shapes: ShapesPoolRef,
|
||||
bounds: &HashMap<Uuid, Bounds>,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
) -> Option<Bounds> {
|
||||
let shape_bounds = bounds.find(shape);
|
||||
let children_ids = shape.modified_children_ids(structure.get(&shape.id), true);
|
||||
let children_ids = shape.children_ids(true);
|
||||
|
||||
let Type::Bool(bool_data) = &shape.shape_type else {
|
||||
return Some(shape_bounds);
|
||||
};
|
||||
|
||||
let path = bools::bool_from_shapes(
|
||||
bool_data.bool_type,
|
||||
&children_ids,
|
||||
shapes,
|
||||
modifiers,
|
||||
structure,
|
||||
);
|
||||
let path = bools::bool_from_shapes(bool_data.bool_type, &children_ids, shapes);
|
||||
|
||||
Some(path.bounds())
|
||||
}
|
||||
@@ -235,7 +224,6 @@ fn propagate_transform(
|
||||
&shape_bounds_after,
|
||||
transform,
|
||||
bounds,
|
||||
&state.structure,
|
||||
&state.scale_content,
|
||||
);
|
||||
entries.append(&mut children);
|
||||
@@ -265,7 +253,6 @@ fn propagate_reflow(
|
||||
bounds: &mut HashMap<Uuid, Bounds>,
|
||||
layout_reflows: &mut Vec<Uuid>,
|
||||
reflown: &mut HashSet<Uuid>,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
) {
|
||||
let Some(shape) = state.shapes.get(id) else {
|
||||
return;
|
||||
@@ -303,7 +290,7 @@ fn propagate_reflow(
|
||||
}
|
||||
}
|
||||
Type::Group(Group { masked: true }) => {
|
||||
let children_ids = shape.modified_children_ids(state.structure.get(&shape.id), true);
|
||||
let children_ids = shape.children_ids(true);
|
||||
if let Some(child) = shapes.get(&children_ids[0]) {
|
||||
let child_bounds = bounds.find(child);
|
||||
bounds.insert(shape.id, child_bounds);
|
||||
@@ -312,18 +299,14 @@ fn propagate_reflow(
|
||||
reflown.insert(*id);
|
||||
}
|
||||
Type::Group(_) => {
|
||||
if let Some(shape_bounds) =
|
||||
calculate_group_bounds(shape, shapes, bounds, &state.structure)
|
||||
{
|
||||
if let Some(shape_bounds) = calculate_group_bounds(shape, shapes, bounds) {
|
||||
bounds.insert(shape.id, shape_bounds);
|
||||
reflow_parent = true;
|
||||
}
|
||||
reflown.insert(*id);
|
||||
}
|
||||
Type::Bool(_) => {
|
||||
if let Some(shape_bounds) =
|
||||
calculate_bool_bounds(shape, shapes, bounds, modifiers, &state.structure)
|
||||
{
|
||||
if let Some(shape_bounds) = calculate_bool_bounds(shape, shapes, bounds) {
|
||||
bounds.insert(shape.id, shape_bounds);
|
||||
reflow_parent = true;
|
||||
}
|
||||
@@ -365,24 +348,12 @@ fn reflow_shape(
|
||||
};
|
||||
|
||||
if let Some(Layout::FlexLayout(layout_data, flex_data)) = &frame_data.layout {
|
||||
let mut children = flex_layout::reflow_flex_layout(
|
||||
shape,
|
||||
layout_data,
|
||||
flex_data,
|
||||
shapes,
|
||||
bounds,
|
||||
&state.structure,
|
||||
);
|
||||
let mut children =
|
||||
flex_layout::reflow_flex_layout(shape, layout_data, flex_data, shapes, bounds);
|
||||
entries.append(&mut children);
|
||||
} else if let Some(Layout::GridLayout(layout_data, grid_data)) = &frame_data.layout {
|
||||
let mut children = grid_layout::reflow_grid_layout(
|
||||
shape,
|
||||
layout_data,
|
||||
grid_data,
|
||||
shapes,
|
||||
bounds,
|
||||
&state.structure,
|
||||
);
|
||||
let mut children =
|
||||
grid_layout::reflow_grid_layout(shape, layout_data, grid_data, shapes, bounds);
|
||||
entries.append(&mut children);
|
||||
}
|
||||
reflown.insert(*id);
|
||||
@@ -398,12 +369,6 @@ pub fn propagate_modifiers(
|
||||
.map(|entry| Modifier::Transform(entry.clone()))
|
||||
.collect();
|
||||
|
||||
for id in state.structure.keys() {
|
||||
if id != &Uuid::nil() {
|
||||
entries.push_back(Modifier::Reflow(*id));
|
||||
}
|
||||
}
|
||||
|
||||
let mut modifiers = HashMap::<Uuid, Matrix>::new();
|
||||
let mut bounds = HashMap::<Uuid, Bounds>::new();
|
||||
let mut reflown = HashSet::<Uuid>::new();
|
||||
@@ -432,7 +397,6 @@ pub fn propagate_modifiers(
|
||||
&mut bounds,
|
||||
&mut layout_reflows,
|
||||
&mut reflown,
|
||||
&modifiers,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
use crate::math::{self as math, Bounds, Matrix, Point, Vector, VectorExt};
|
||||
use crate::shapes::{
|
||||
AlignContent, AlignItems, AlignSelf, FlexData, JustifyContent, LayoutData, LayoutItem,
|
||||
Modifier, Shape, StructureEntry,
|
||||
Modifier, Shape,
|
||||
};
|
||||
use crate::state::ShapesPoolRef;
|
||||
use crate::uuid::Uuid;
|
||||
@@ -181,11 +181,10 @@ fn initialize_tracks(
|
||||
flex_data: &FlexData,
|
||||
shapes: ShapesPoolRef,
|
||||
bounds: &HashMap<Uuid, Bounds>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
) -> Vec<TrackData> {
|
||||
let mut tracks = Vec::<TrackData>::new();
|
||||
let mut current_track = TrackData::default();
|
||||
let mut children = shape.modified_children_ids(structure.get(&shape.id), true);
|
||||
let mut children = shape.children_ids(true);
|
||||
let mut first = true;
|
||||
|
||||
if flex_data.is_reverse() {
|
||||
@@ -435,7 +434,6 @@ fn calculate_track_data(
|
||||
layout_bounds: &Bounds,
|
||||
shapes: ShapesPoolRef,
|
||||
bounds: &HashMap<Uuid, Bounds>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
) -> Vec<TrackData> {
|
||||
let layout_axis = LayoutAxis::new(shape, layout_bounds, layout_data, flex_data);
|
||||
let mut tracks = initialize_tracks(
|
||||
@@ -445,7 +443,6 @@ fn calculate_track_data(
|
||||
flex_data,
|
||||
shapes,
|
||||
bounds,
|
||||
structure,
|
||||
);
|
||||
|
||||
distribute_fill_main_space(&layout_axis, &mut tracks);
|
||||
@@ -576,20 +573,11 @@ pub fn reflow_flex_layout(
|
||||
flex_data: &FlexData,
|
||||
shapes: ShapesPoolRef,
|
||||
bounds: &mut HashMap<Uuid, Bounds>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
) -> VecDeque<Modifier> {
|
||||
let mut result = VecDeque::new();
|
||||
let layout_bounds = &bounds.find(shape);
|
||||
let layout_axis = LayoutAxis::new(shape, layout_bounds, layout_data, flex_data);
|
||||
let tracks = calculate_track_data(
|
||||
shape,
|
||||
layout_data,
|
||||
flex_data,
|
||||
layout_bounds,
|
||||
shapes,
|
||||
bounds,
|
||||
structure,
|
||||
);
|
||||
let tracks = calculate_track_data(shape, layout_data, flex_data, layout_bounds, shapes, bounds);
|
||||
|
||||
for track in tracks.iter() {
|
||||
let total_shapes_size = track.shapes.iter().map(|s| s.main_size).sum::<f32>();
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::math::{self as math, intersect_rays, Bounds, Matrix, Point, Ray, Vect
|
||||
use crate::shapes::{
|
||||
AlignContent, AlignItems, AlignSelf, Frame, GridCell, GridData, GridTrack, GridTrackType,
|
||||
JustifyContent, JustifyItems, JustifySelf, Layout, LayoutData, LayoutItem, Modifier, Shape,
|
||||
StructureEntry, Type,
|
||||
Type,
|
||||
};
|
||||
use crate::state::ShapesPoolRef;
|
||||
use crate::uuid::Uuid;
|
||||
@@ -603,8 +603,6 @@ pub fn create_cell_data<'a>(
|
||||
pub fn grid_cell_data<'a>(
|
||||
shape: &Shape,
|
||||
shapes: ShapesPoolRef<'a>,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
allow_empty: bool,
|
||||
) -> Vec<CellData<'a>> {
|
||||
let Type::Frame(Frame {
|
||||
@@ -616,26 +614,8 @@ pub fn grid_cell_data<'a>(
|
||||
};
|
||||
|
||||
let bounds = &mut HashMap::<Uuid, Bounds>::new();
|
||||
|
||||
let shape = &mut shape.clone();
|
||||
if let Some(modifiers) = modifiers.get(&shape.id) {
|
||||
shape.apply_transform(modifiers);
|
||||
}
|
||||
|
||||
let layout_bounds = shape.bounds();
|
||||
let children = shape.modified_children_ids(structure.get(&shape.id), false);
|
||||
|
||||
for child_id in children.iter() {
|
||||
let Some(child) = shapes.get(child_id) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if let Some(modifier) = modifiers.get(child_id) {
|
||||
let mut b = bounds.find(child);
|
||||
b.transform_mut(modifier);
|
||||
bounds.insert(*child_id, b);
|
||||
}
|
||||
}
|
||||
let children = shape.children_ids(false);
|
||||
|
||||
let column_tracks = calculate_tracks(
|
||||
true,
|
||||
@@ -725,11 +705,10 @@ pub fn reflow_grid_layout(
|
||||
grid_data: &GridData,
|
||||
shapes: ShapesPoolRef,
|
||||
bounds: &mut HashMap<Uuid, Bounds>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
) -> VecDeque<Modifier> {
|
||||
let mut result = VecDeque::new();
|
||||
let layout_bounds = bounds.find(shape);
|
||||
let children = shape.modified_children_ids(structure.get(&shape.id), true);
|
||||
let children = shape.children_ids(true);
|
||||
|
||||
let column_tracks = calculate_tracks(
|
||||
true,
|
||||
|
||||
@@ -1,22 +1,13 @@
|
||||
use skia_safe::Matrix;
|
||||
|
||||
use super::{Corners, Path, Segment, Shape, StructureEntry, Type};
|
||||
use super::{Corners, Path, Segment, Shape, Type};
|
||||
use crate::math;
|
||||
|
||||
use crate::shapes::text_paths::TextPaths;
|
||||
use crate::state::ShapesPoolRef;
|
||||
use crate::uuid::Uuid;
|
||||
use std::collections::HashMap;
|
||||
|
||||
const BEZIER_CIRCLE_C: f32 = 0.551_915_05;
|
||||
|
||||
pub trait ToPath {
|
||||
fn to_path(
|
||||
&self,
|
||||
shapes: ShapesPoolRef,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
) -> Path;
|
||||
fn to_path(&self, shapes: ShapesPoolRef) -> Path;
|
||||
}
|
||||
|
||||
enum CornerType {
|
||||
@@ -180,33 +171,28 @@ fn transform_segments(segments: Vec<Segment>, shape: &Shape) -> Vec<Segment> {
|
||||
}
|
||||
|
||||
impl ToPath for Shape {
|
||||
fn to_path(
|
||||
&self,
|
||||
shapes: ShapesPoolRef,
|
||||
modifiers: &HashMap<Uuid, Matrix>,
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
) -> Path {
|
||||
fn to_path(&self, shapes: ShapesPoolRef) -> Path {
|
||||
match &self.shape_type {
|
||||
Type::Frame(ref frame) => {
|
||||
let children = self.modified_children_ids(structure.get(&self.id), true);
|
||||
let children = self.children_ids(true);
|
||||
let mut result = Path::new(rect_segments(&self, frame.corners));
|
||||
for id in children {
|
||||
let Some(shape) = shapes.get(&id) else {
|
||||
continue;
|
||||
};
|
||||
result = join_paths(result, shape.to_path(shapes, modifiers, structure));
|
||||
result = join_paths(result, shape.to_path(shapes));
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
Type::Group(_) => {
|
||||
let children = self.modified_children_ids(structure.get(&self.id), true);
|
||||
let children = self.children_ids(true);
|
||||
let mut result = Path::default();
|
||||
for id in children {
|
||||
let Some(shape) = shapes.get(&id) else {
|
||||
continue;
|
||||
};
|
||||
result = join_paths(result, shape.to_path(shapes, modifiers, structure));
|
||||
result = join_paths(result, shape.to_path(shapes));
|
||||
}
|
||||
// Force closure of the group path
|
||||
let mut segments = result.segments().clone();
|
||||
|
||||
@@ -8,7 +8,6 @@ pub use text_editor::*;
|
||||
|
||||
use crate::render::RenderState;
|
||||
use crate::shapes::Shape;
|
||||
use crate::shapes::StructureEntry;
|
||||
use crate::tiles;
|
||||
use crate::uuid::Uuid;
|
||||
|
||||
@@ -24,9 +23,7 @@ pub(crate) struct State<'a> {
|
||||
pub text_editor_state: TextEditorState,
|
||||
pub current_id: Option<Uuid>,
|
||||
pub shapes: ShapesPool<'a>,
|
||||
pub modifiers: HashMap<Uuid, skia::Matrix>,
|
||||
pub scale_content: HashMap<Uuid, f32>,
|
||||
pub structure: HashMap<Uuid, Vec<StructureEntry>>,
|
||||
}
|
||||
|
||||
impl<'a> State<'a> {
|
||||
@@ -36,9 +33,7 @@ impl<'a> State<'a> {
|
||||
text_editor_state: TextEditorState::new(),
|
||||
current_id: None,
|
||||
shapes: ShapesPool::new(),
|
||||
modifiers: HashMap::new(),
|
||||
scale_content: HashMap::new(),
|
||||
structure: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,29 +60,18 @@ impl<'a> State<'a> {
|
||||
}
|
||||
|
||||
pub fn render_from_cache(&mut self) {
|
||||
self.render_state
|
||||
.render_from_cache(&self.shapes, &self.modifiers, &self.structure);
|
||||
self.render_state.render_from_cache(&self.shapes);
|
||||
}
|
||||
|
||||
pub fn start_render_loop(&mut self, timestamp: i32) -> Result<(), String> {
|
||||
self.render_state.start_render_loop(
|
||||
&self.shapes,
|
||||
&self.modifiers,
|
||||
&self.structure,
|
||||
&self.scale_content,
|
||||
timestamp,
|
||||
)?;
|
||||
self.render_state
|
||||
.start_render_loop(&self.shapes, &self.scale_content, timestamp)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn process_animation_frame(&mut self, timestamp: i32) -> Result<(), String> {
|
||||
self.render_state.process_animation_frame(
|
||||
&self.shapes,
|
||||
&self.modifiers,
|
||||
&self.structure,
|
||||
&self.scale_content,
|
||||
timestamp,
|
||||
)?;
|
||||
self.render_state
|
||||
.process_animation_frame(&self.shapes, &self.scale_content, timestamp)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -147,6 +131,8 @@ impl<'a> State<'a> {
|
||||
panic!("Invalid current shape")
|
||||
};
|
||||
shape.set_parent(id);
|
||||
|
||||
// TODO this clone doesn't seem necessary
|
||||
shape.clone()
|
||||
};
|
||||
|
||||
@@ -166,6 +152,7 @@ impl<'a> State<'a> {
|
||||
let Some(shape) = self.current_shape() else {
|
||||
panic!("Invalid current shape")
|
||||
};
|
||||
// TODO: Remove this clone
|
||||
if !shape.id.is_nil() {
|
||||
self.render_state
|
||||
.update_tile_for(&shape.clone(), &self.shapes);
|
||||
@@ -173,13 +160,11 @@ impl<'a> State<'a> {
|
||||
}
|
||||
|
||||
pub fn rebuild_tiles_shallow(&mut self) {
|
||||
self.render_state
|
||||
.rebuild_tiles_shallow(&self.shapes, &self.modifiers, &self.structure);
|
||||
self.render_state.rebuild_tiles_shallow(&self.shapes);
|
||||
}
|
||||
|
||||
pub fn rebuild_tiles(&mut self) {
|
||||
self.render_state
|
||||
.rebuild_tiles(&self.shapes, &self.modifiers, &self.structure);
|
||||
self.render_state.rebuild_tiles(&self.shapes);
|
||||
}
|
||||
|
||||
pub fn rebuild_modifier_tiles(&mut self, ids: Vec<Uuid>) {
|
||||
@@ -204,7 +189,7 @@ impl<'a> State<'a> {
|
||||
let bounds = shape.bounds();
|
||||
let position = Point::new(pos_x, pos_y);
|
||||
|
||||
let cells = grid_cell_data(shape, &self.shapes, &self.modifiers, &self.structure, true);
|
||||
let cells = grid_cell_data(shape, &self.shapes, true);
|
||||
|
||||
for cell in cells {
|
||||
let points = &[
|
||||
|
||||
@@ -2,6 +2,7 @@ use std::collections::HashMap;
|
||||
use std::iter;
|
||||
|
||||
use crate::performance;
|
||||
use crate::shapes;
|
||||
use crate::shapes::Shape;
|
||||
use crate::uuid::Uuid;
|
||||
|
||||
@@ -208,11 +209,15 @@ impl<'a> ShapesPoolImpl<'a> {
|
||||
// Extend the lifetime of id to 'a - safe because it's the same Uuid stored in shapes[idx].id
|
||||
let id_ref: &'a Uuid = &*(id as *const Uuid);
|
||||
|
||||
if (*modifiers_ptr).contains_key(&id_ref) || (*structure_ptr).contains_key(&id_ref) {
|
||||
if self.to_update_bool(&*shape_ptr)
|
||||
|| (*modifiers_ptr).contains_key(&id_ref)
|
||||
|| (*structure_ptr).contains_key(&id_ref)
|
||||
{
|
||||
if let Some(cell) = (*cache_ptr).get(&id_ref) {
|
||||
Some(cell.get_or_init(|| {
|
||||
let shape = &*shape_ptr;
|
||||
shape.transformed(
|
||||
&self,
|
||||
(*modifiers_ptr).get(&id_ref),
|
||||
(*structure_ptr).get(&id_ref),
|
||||
)
|
||||
@@ -246,14 +251,25 @@ impl<'a> ShapesPoolImpl<'a> {
|
||||
|
||||
// Convert HashMap<Uuid, V> to HashMap<&'a Uuid, V> using references from shapes and
|
||||
// Initialize the cache cells because later we don't want to have the mutable pointer
|
||||
|
||||
let mut ids = Vec::<Uuid>::new();
|
||||
|
||||
let mut modifiers_with_refs = HashMap::with_capacity(modifiers.len());
|
||||
for (uuid, matrix) in modifiers {
|
||||
if let Some(uuid_ref) = self.get_uuid_ref(&uuid) {
|
||||
self.modified_shape_cache.insert(uuid_ref, OnceCell::new());
|
||||
// self.modified_shape_cache.insert(uuid_ref, OnceCell::new());
|
||||
modifiers_with_refs.insert(uuid_ref, matrix);
|
||||
ids.push(*uuid_ref);
|
||||
}
|
||||
}
|
||||
self.modifiers = modifiers_with_refs;
|
||||
|
||||
let all_ids = shapes::all_with_ancestors(&ids, &self, true);
|
||||
for uuid in all_ids {
|
||||
if let Some(uuid_ref) = self.get_uuid_ref(&uuid) {
|
||||
self.modified_shape_cache.insert(uuid_ref, OnceCell::new());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@@ -261,13 +277,22 @@ impl<'a> ShapesPoolImpl<'a> {
|
||||
// Convert HashMap<Uuid, V> to HashMap<&'a Uuid, V> using references from shapes and
|
||||
// Initialize the cache cells because later we don't want to have the mutable pointer
|
||||
let mut structure_with_refs = HashMap::with_capacity(structure.len());
|
||||
let mut ids = Vec::<Uuid>::new();
|
||||
|
||||
for (uuid, entries) in structure {
|
||||
if let Some(uuid_ref) = self.get_uuid_ref(&uuid) {
|
||||
self.modified_shape_cache.insert(uuid_ref, OnceCell::new());
|
||||
structure_with_refs.insert(uuid_ref, entries);
|
||||
ids.push(*uuid_ref);
|
||||
}
|
||||
}
|
||||
self.structure = structure_with_refs;
|
||||
|
||||
let all_ids = shapes::all_with_ancestors(&ids, &self, true);
|
||||
for uuid in all_ids {
|
||||
if let Some(uuid_ref) = self.get_uuid_ref(&uuid) {
|
||||
self.modified_shape_cache.insert(uuid_ref, OnceCell::new());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@@ -290,4 +315,33 @@ impl<'a> ShapesPoolImpl<'a> {
|
||||
// and won't be reallocated.
|
||||
unsafe { Some(&*(&self.shapes[idx].id as *const Uuid)) }
|
||||
}
|
||||
|
||||
fn to_update_bool(&self, shape: &Shape) -> bool {
|
||||
// TODO: Check if any of the children is in the modifiers with a
|
||||
// different matrix than the current one.
|
||||
shape.is_bool()
|
||||
}
|
||||
}
|
||||
|
||||
// fn is_modified_child(
|
||||
// shape: &Shape,
|
||||
// shapes: ShapesPoolRef,
|
||||
// modifiers: &HashMap<Uuid, Matrix>,
|
||||
// ) -> bool {
|
||||
// if modifiers.is_empty() {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// let ids = shape.all_children(shapes, true, false);
|
||||
// let default = &Matrix::default();
|
||||
// let parent_modifier = modifiers.get(&shape.id).unwrap_or(default);
|
||||
//
|
||||
// // Returns true if the transform of any child is different to the parent's
|
||||
// ids.iter().any(|id| {
|
||||
// !math::is_close_matrix(
|
||||
// parent_modifier,
|
||||
// modifiers.get(id).unwrap_or(&Matrix::default()),
|
||||
// )
|
||||
// })
|
||||
// }
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ pub extern "C" fn set_shape_path_content() {
|
||||
pub extern "C" fn current_to_path() -> *mut u8 {
|
||||
let mut result = Vec::<RawSegmentData>::default();
|
||||
with_current_shape!(state, |shape: &Shape| {
|
||||
let path = shape.to_path(&state.shapes, &state.modifiers, &state.structure);
|
||||
let path = shape.to_path(&state.shapes);
|
||||
result = path
|
||||
.segments()
|
||||
.iter()
|
||||
|
||||
@@ -57,13 +57,7 @@ pub extern "C" fn calculate_bool(raw_bool_type: u8) -> *mut u8 {
|
||||
let bool_type = RawBoolType::from(raw_bool_type).into();
|
||||
let result;
|
||||
with_state!(state, {
|
||||
let path = math::bools::bool_from_shapes(
|
||||
bool_type,
|
||||
&entries,
|
||||
&state.shapes,
|
||||
&state.modifiers,
|
||||
&state.structure,
|
||||
);
|
||||
let path = math::bools::bool_from_shapes(bool_type, &entries, &state.shapes);
|
||||
result = path
|
||||
.segments()
|
||||
.iter()
|
||||
|
||||
Reference in New Issue
Block a user