mirror of
https://github.com/penpot/penpot.git
synced 2026-10-29 05:50:35 +00:00
🐛 Paint layout children in canvas z-order in vector exports (#12171)
This commit is contained in:
parent
30127e57a0
commit
b3a62eeb4b
@ -349,6 +349,13 @@ fn sort_z_index(tree: ShapesPoolRef, element: &Shape, children_ids: Vec<Uuid>) -
|
||||
}
|
||||
}
|
||||
|
||||
/// Children bottom to top, in the same order the GPU renderer paints them.
|
||||
pub(crate) fn children_paint_order(tree: ShapesPoolRef, element: &Shape) -> Vec<Uuid> {
|
||||
let mut ids = sort_z_index(tree, element, element.children_ids(false));
|
||||
ids.reverse();
|
||||
ids
|
||||
}
|
||||
|
||||
/// Whether this `render_shape_exit` pass closes the shape's focus scope. A
|
||||
/// masked group keeps it open across the mask pass.
|
||||
fn exit_closes_focus_scope(element: &Shape, visited_mask: bool) -> bool {
|
||||
|
||||
@ -9,7 +9,7 @@ use super::document::{
|
||||
};
|
||||
use super::images::{emit_fills, emit_strokes};
|
||||
use super::render_tree;
|
||||
use crate::render::RenderResources;
|
||||
use crate::render::{children_paint_order, RenderResources};
|
||||
|
||||
pub(super) fn render_frame(
|
||||
builder: &mut SvgLayerCanvas,
|
||||
@ -104,7 +104,7 @@ fn render_frame_body(
|
||||
)?;
|
||||
}
|
||||
|
||||
let children: Vec<_> = element.children_ids_iter_forward(false).copied().collect();
|
||||
let children = children_paint_order(tree, element);
|
||||
for child_id in &children {
|
||||
render_tree(builder, shared, child_id, tree, scale)?;
|
||||
}
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
use super::fixtures::*;
|
||||
|
||||
use crate::shapes::{
|
||||
radius_to_sigma, BlendMode, Blur, BlurType, Fill, ImageFill, ImageFillTransform, Shadow,
|
||||
ShadowStyle, SolidColor, StrokeCap, StrokeKind,
|
||||
radius_to_sigma, AlignContent, AlignItems, BlendMode, Blur, BlurType, Fill, FlexDirection,
|
||||
ImageFill, ImageFillTransform, JustifyContent, JustifyItems, Shadow, ShadowStyle, SolidColor,
|
||||
StrokeCap, StrokeKind, WrapType,
|
||||
};
|
||||
use crate::state::ShapesPool;
|
||||
use crate::uuid::Uuid;
|
||||
@ -222,6 +223,63 @@ fn exports_frame_background_blur_before_children() {
|
||||
insta::assert_snapshot!(svg);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exports_flex_children_with_first_child_on_top() {
|
||||
let mut pool = ShapesPool::new();
|
||||
let frame_id = uid(1);
|
||||
let first = uid(2);
|
||||
let second = uid(3);
|
||||
add_frame(
|
||||
&mut pool,
|
||||
frame_id,
|
||||
Uuid::nil(),
|
||||
(0.0, 0.0, 200.0, 120.0),
|
||||
skia::Color::from_rgb(255, 255, 255),
|
||||
false,
|
||||
);
|
||||
pool.get_mut(&frame_id).unwrap().set_flex_layout_data(
|
||||
FlexDirection::Row,
|
||||
0.0,
|
||||
0.0,
|
||||
AlignItems::Start,
|
||||
AlignContent::Start,
|
||||
JustifyItems::Start,
|
||||
JustifyContent::Start,
|
||||
WrapType::NoWrap,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
);
|
||||
add_solid_rect(
|
||||
&mut pool,
|
||||
first,
|
||||
frame_id,
|
||||
(20.0, 20.0, 80.0, 80.0),
|
||||
skia::Color::from_rgb(255, 0, 0),
|
||||
);
|
||||
add_solid_rect(
|
||||
&mut pool,
|
||||
second,
|
||||
frame_id,
|
||||
(40.0, 40.0, 100.0, 100.0),
|
||||
skia::Color::from_rgb(0, 0, 255),
|
||||
);
|
||||
{
|
||||
let frame = pool.get_mut(&frame_id).unwrap();
|
||||
frame.add_child(first);
|
||||
frame.add_child(second);
|
||||
}
|
||||
|
||||
let svg = render(&pool, frame_id);
|
||||
let first_pos = svg.find("fill=\"red\"").expect("first child");
|
||||
let second_pos = svg.find("fill=\"blue\"").expect("second child");
|
||||
assert!(
|
||||
second_pos < first_pos,
|
||||
"flex paints its first child on top: {svg}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exports_group_background_blur_selrect_clip() {
|
||||
let mut pool = ShapesPool::new();
|
||||
|
||||
@ -8,6 +8,7 @@ use crate::shapes::{
|
||||
use crate::state::ShapesPoolRef;
|
||||
use crate::uuid::Uuid;
|
||||
|
||||
use super::children_paint_order;
|
||||
use super::shape_renderer::ShapeRenderer;
|
||||
use super::text;
|
||||
use super::RenderResources;
|
||||
@ -934,7 +935,7 @@ fn render_frame(
|
||||
}
|
||||
|
||||
// Children (absolute coords, no frame transform).
|
||||
let children: Vec<Uuid> = element.children_ids_iter_forward(false).copied().collect();
|
||||
let children = children_paint_order(tree, element);
|
||||
let child_opts = opts.for_children_of(element);
|
||||
for child_id in &children {
|
||||
render_tree_inner(shared, canvas, child_id, tree, scale, &child_opts)?;
|
||||
@ -988,7 +989,7 @@ fn render_container_drop_shadows(
|
||||
renderer.draw_fills(element, &element.fills)?;
|
||||
}
|
||||
|
||||
let children: Vec<Uuid> = element.children_ids_iter_forward(false).copied().collect();
|
||||
let children = children_paint_order(tree, element);
|
||||
let child_opts = opts.for_children_of(element);
|
||||
for child_id in &children {
|
||||
render_tree_inner(shared, canvas, child_id, tree, scale, &child_opts)?;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user