mirror of
https://github.com/penpot/penpot.git
synced 2026-03-28 04:01:07 -04:00
🐛 Fix inset child clip for frames with inner stroke
This commit is contained in:
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 31 KiB |
@@ -115,6 +115,7 @@ impl NodeRenderState {
|
||||
&self,
|
||||
element: &Shape,
|
||||
offset: Option<(f32, f32)>,
|
||||
clip_inset: Option<f32>,
|
||||
) -> Option<ClipStack> {
|
||||
if self.id.is_nil() || !element.clip() {
|
||||
return self.clip_bounds.clone();
|
||||
@@ -138,6 +139,10 @@ impl NodeRenderState {
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(clip_inset) = clip_inset.filter(|&e| e > 0.0) {
|
||||
bounds.inset((clip_inset, clip_inset));
|
||||
}
|
||||
|
||||
Self::append_clip(self.clip_bounds.clone(), (bounds, corners, transform))
|
||||
}
|
||||
|
||||
@@ -2436,8 +2441,18 @@ impl RenderState {
|
||||
});
|
||||
|
||||
if element.is_recursive() {
|
||||
let children_clip_bounds =
|
||||
node_render_state.get_children_clip_bounds(element, None);
|
||||
// Shrink the child clip by ~1 device px when the frame has an inner stroke, same
|
||||
// epsilon as `fills::render` inset, so clipped overflow does not sit under the
|
||||
// stroke band drawn later in `render_shape_exit`.
|
||||
let clip_inset_for_children = (matches!(element.shape_type, Type::Frame(_))
|
||||
&& element.clip()
|
||||
&& element.has_inner_stroke())
|
||||
.then_some(1.0 / scale);
|
||||
let children_clip_bounds = node_render_state.get_children_clip_bounds(
|
||||
element,
|
||||
None,
|
||||
clip_inset_for_children,
|
||||
);
|
||||
|
||||
let children_ids: Vec<_> = if can_flatten {
|
||||
// Container was flattened: get simplified children (which skip this level)
|
||||
|
||||
@@ -3,15 +3,7 @@ use skia_safe::{self as skia, Paint, RRect};
|
||||
use super::{filters, RenderState, SurfaceId};
|
||||
use crate::error::Result;
|
||||
use crate::render::get_source_rect;
|
||||
use crate::shapes::{merge_fills, Fill, Frame, ImageFill, Rect, Shape, StrokeKind, Type};
|
||||
|
||||
/// True when the shape has at least one visible inner stroke.
|
||||
fn has_inner_stroke(shape: &Shape) -> bool {
|
||||
let is_open = shape.is_open();
|
||||
shape
|
||||
.visible_strokes()
|
||||
.any(|s| s.render_kind(is_open) == StrokeKind::Inner)
|
||||
}
|
||||
use crate::shapes::{merge_fills, Fill, Frame, ImageFill, Rect, Shape, Type};
|
||||
|
||||
fn draw_image_fill(
|
||||
render_state: &mut RenderState,
|
||||
@@ -113,7 +105,7 @@ pub fn render(
|
||||
}
|
||||
|
||||
let scale = render_state.get_scale().max(1e-6);
|
||||
let inset = if has_inner_stroke(shape) {
|
||||
let inset = if shape.has_inner_stroke() {
|
||||
Some(1.0 / scale)
|
||||
} else {
|
||||
None
|
||||
|
||||
@@ -1605,6 +1605,13 @@ impl Shape {
|
||||
.count()
|
||||
}
|
||||
|
||||
/// True when the shape has at least one visible inner stroke (open paths render strokes as center).
|
||||
pub fn has_inner_stroke(&self) -> bool {
|
||||
let is_open = self.is_open();
|
||||
self.visible_strokes()
|
||||
.any(|s| s.render_kind(is_open) == StrokeKind::Inner)
|
||||
}
|
||||
|
||||
pub fn drop_shadow_paints(&self) -> Vec<skia_safe::Paint> {
|
||||
let drop_shadows: Vec<&Shadow> = self.drop_shadows_visible().collect();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user