Skip to content

Commit

Permalink
feat: Improve and optimize elements clipping (#353)
Browse files Browse the repository at this point in the history
* feat: WIP Enhanced alignments

* improvements

* tweak

* remove display attribute, remove 'both' direction, fix tests, fix docs, fix examples, fix components

* feat: Updated examples

* tests

* fixed tests

* update table component and example

* clean up

* clean up

* improvements

* improvements

* fixes

* fix tests

* tweak

* tweaks

* unsized alignment test

* document code

* tweak

* rename attributes

* fixes and cleanup

* fixes and improvements

* typo

* feat: Improve and optimize elements clipping

* improvements

* fix
  • Loading branch information
marc2332 authored Oct 26, 2023
1 parent ac1d1e3 commit 26fcb54
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 19 deletions.
24 changes: 16 additions & 8 deletions crates/core/src/viewports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,30 @@ pub fn calculate_viewports(

// Clip any overflow from it's children
if style.overflow == OverflowMode::Clip {
viewports_collection
let viewport = viewports_collection
.entry(*node_id)
.or_insert_with(|| (None, Vec::new()))
.0 = Some(node_areas.area);
.or_insert_with(|| (None, Vec::new()));
viewport.0 = Some(node_areas.visible_area());
}

// Pass viewports to the children
if let Some((_, mut inherited_viewports)) =
viewports_collection.get(node_id).cloned()
{
// Add the itself
inherited_viewports.push(*node_id);
// Only pass the inherited viewports if they are not empty
// or this same element has a clipped overflow
if !inherited_viewports.is_empty() || style.overflow == OverflowMode::Clip {
// Add itself
inherited_viewports.push(*node_id);

for child in node.children() {
viewports_collection
.insert(child.id(), (None, inherited_viewports.clone()));
for child in node.children() {
if let NodeType::Element(..) = *child.node_type() {
viewports_collection
.entry(child.id())
.or_insert_with(|| (None, Vec::new()))
.1 = inherited_viewports.clone();
}
}
}
}
}
Expand Down
34 changes: 23 additions & 11 deletions crates/renderer/src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ use torin::geometry::Area;

use crate::elements::{render_image, render_label, render_paragraph, render_rect, render_svg};

fn clip_viewport(canvas: &Canvas, viewport: &Area) {
canvas.clip_rect(
Rect::new(
viewport.min_x(),
viewport.min_y(),
viewport.max_x(),
viewport.max_y(),
),
ClipOp::Intersect,
true,
);
}

/// Render a node into the Skia canvas
#[allow(clippy::too_many_arguments)]
pub fn render_skia(
Expand Down Expand Up @@ -53,20 +66,19 @@ pub fn render_skia(
let viewports = viewports_collection.get(&dioxus_node.id());

// Clip all elements with their corresponding viewports
if let Some((_, viewports)) = viewports {
if let Some((element_viewport, viewports)) = viewports {
// Only clip the element iself when it's paragraph because
// it will render the inner text spans on it's own, so if these spans overflow the paragraph,
// It is the paragraph job to make sure they are clipped
if tag.as_str() == "paragraph" {
if let Some(element_viewport) = element_viewport {
clip_viewport(canvas, element_viewport);
}
}
for viewport_id in viewports {
let viewport = viewports_collection.get(viewport_id).unwrap().0;
if let Some(viewport) = viewport {
canvas.clip_rect(
Rect::new(
viewport.min_x(),
viewport.min_y(),
viewport.max_x(),
viewport.max_y(),
),
ClipOp::Intersect,
true,
);
clip_viewport(canvas, &viewport);
}
}
}
Expand Down

0 comments on commit 26fcb54

Please sign in to comment.