mirror of
https://github.com/penpot/penpot.git
synced 2026-08-05 04:18:41 +00:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
adcc2ebd1a
@ -2392,7 +2392,52 @@ impl RenderState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn render_shape_enter(&mut self, element: &Shape, mask: bool, target_surface: SurfaceId) {
|
fn clip_target_surface_to_stack(
|
||||||
|
&mut self,
|
||||||
|
clips: &ClipStack,
|
||||||
|
target_surface: SurfaceId,
|
||||||
|
scale: f32,
|
||||||
|
antialias: bool,
|
||||||
|
) {
|
||||||
|
let translation = self
|
||||||
|
.surfaces
|
||||||
|
.get_render_context_translation(self.render_area, scale);
|
||||||
|
|
||||||
|
for (bounds, corners, transform) in clips.iter() {
|
||||||
|
let mut total_matrix = Matrix::new_identity();
|
||||||
|
if target_surface == SurfaceId::Export {
|
||||||
|
let Some((export_rect, export_scale)) = self.export_context else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
total_matrix.pre_scale((export_scale, export_scale), None);
|
||||||
|
total_matrix.pre_translate((-export_rect.x(), -export_rect.y()));
|
||||||
|
} else {
|
||||||
|
total_matrix.pre_scale((scale, scale), None);
|
||||||
|
total_matrix.pre_translate((translation.0, translation.1));
|
||||||
|
}
|
||||||
|
total_matrix.pre_concat(transform);
|
||||||
|
|
||||||
|
let canvas = self.surfaces.canvas(target_surface);
|
||||||
|
canvas.concat(&total_matrix);
|
||||||
|
if let Some(corners) = corners {
|
||||||
|
let rrect = RRect::new_rect_radii(*bounds, corners);
|
||||||
|
canvas.clip_rrect(rrect, skia::ClipOp::Intersect, antialias);
|
||||||
|
} else {
|
||||||
|
canvas.clip_rect(*bounds, skia::ClipOp::Intersect, antialias);
|
||||||
|
}
|
||||||
|
self.surfaces
|
||||||
|
.canvas(target_surface)
|
||||||
|
.concat(&total_matrix.invert().unwrap_or_default());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_shape_enter(
|
||||||
|
&mut self,
|
||||||
|
element: &Shape,
|
||||||
|
mask: bool,
|
||||||
|
clip_bounds: Option<&ClipStack>,
|
||||||
|
target_surface: SurfaceId,
|
||||||
|
) {
|
||||||
// Masked groups needs two rendering passes, the first one rendering
|
// Masked groups needs two rendering passes, the first one rendering
|
||||||
// the content and the second one rendering the mask so we need to do
|
// the content and the second one rendering the mask so we need to do
|
||||||
// an extra save_layer to keep all the masked group separate from
|
// an extra save_layer to keep all the masked group separate from
|
||||||
@ -2404,7 +2449,33 @@ impl RenderState {
|
|||||||
self.nested_shadows.push(shadows.to_vec());
|
self.nested_shadows.push(shadows.to_vec());
|
||||||
|
|
||||||
if group.masked {
|
if group.masked {
|
||||||
let paint = skia::Paint::default();
|
// A masked group's blur is applied as a single layer blur over
|
||||||
|
// the whole masked result.
|
||||||
|
let mask_group_blur = element.masked_group_layer_blur().is_some();
|
||||||
|
if mask_group_blur {
|
||||||
|
self.surfaces.canvas(target_surface).save();
|
||||||
|
if let Some(clips) = clip_bounds {
|
||||||
|
let scale = self.get_scale();
|
||||||
|
let antialias = !self.options.is_fast_mode()
|
||||||
|
&& element
|
||||||
|
.should_use_antialias(scale, self.options.antialias_threshold);
|
||||||
|
self.clip_target_surface_to_stack(clips, target_surface, scale, antialias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut paint = skia::Paint::default();
|
||||||
|
if !self.options.is_fast_mode() {
|
||||||
|
if let Some(blur) = element.masked_group_layer_blur() {
|
||||||
|
let scale = self.get_scale();
|
||||||
|
let sigma = radius_to_sigma(blur.value * scale);
|
||||||
|
if let Some(filter) =
|
||||||
|
skia::image_filters::blur((sigma, sigma), None, None, None)
|
||||||
|
{
|
||||||
|
paint.set_image_filter(filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let layer_rec = skia::canvas::SaveLayerRec::default().paint(&paint);
|
let layer_rec = skia::canvas::SaveLayerRec::default().paint(&paint);
|
||||||
self.surfaces.canvas(target_surface).save_layer(&layer_rec);
|
self.surfaces.canvas(target_surface).save_layer(&layer_rec);
|
||||||
}
|
}
|
||||||
@ -2558,6 +2629,10 @@ impl RenderState {
|
|||||||
self.surfaces.canvas(target_surface).restore();
|
self.surfaces.canvas(target_surface).restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if visited_mask && element.masked_group_layer_blur().is_some() {
|
||||||
|
self.surfaces.canvas(target_surface).restore();
|
||||||
|
}
|
||||||
|
|
||||||
self.focus_mode.exit(&element.id);
|
self.focus_mode.exit(&element.id);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -2857,7 +2932,6 @@ impl RenderState {
|
|||||||
extrect: &mut Option<Rect>,
|
extrect: &mut Option<Rect>,
|
||||||
clip_bounds: Option<ClipStack>,
|
clip_bounds: Option<ClipStack>,
|
||||||
scale: f32,
|
scale: f32,
|
||||||
translation: (f32, f32),
|
|
||||||
node_render_state: &NodeRenderState,
|
node_render_state: &NodeRenderState,
|
||||||
target_surface: SurfaceId,
|
target_surface: SurfaceId,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
@ -2963,60 +3037,7 @@ impl RenderState {
|
|||||||
let antialias = !self.options.is_fast_mode()
|
let antialias = !self.options.is_fast_mode()
|
||||||
&& element.should_use_antialias(scale, self.options.antialias_threshold);
|
&& element.should_use_antialias(scale, self.options.antialias_threshold);
|
||||||
self.surfaces.canvas(target_surface).save();
|
self.surfaces.canvas(target_surface).save();
|
||||||
for (bounds, corners, transform) in clips.iter() {
|
self.clip_target_surface_to_stack(clips, target_surface, scale, antialias);
|
||||||
if target_surface == SurfaceId::Export {
|
|
||||||
let Some((export_rect, export_scale)) = self.export_context else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut total_matrix = Matrix::new_identity();
|
|
||||||
|
|
||||||
total_matrix.pre_scale((export_scale, export_scale), None);
|
|
||||||
total_matrix.pre_translate((-export_rect.x(), -export_rect.y()));
|
|
||||||
|
|
||||||
total_matrix.pre_concat(transform);
|
|
||||||
|
|
||||||
let canvas = self.surfaces.canvas(target_surface);
|
|
||||||
canvas.concat(&total_matrix);
|
|
||||||
|
|
||||||
let bounds = *bounds;
|
|
||||||
if let Some(corners) = corners {
|
|
||||||
let rrect = RRect::new_rect_radii(bounds, corners);
|
|
||||||
canvas.clip_rrect(rrect, skia::ClipOp::Intersect, antialias);
|
|
||||||
} else {
|
|
||||||
canvas.clip_rect(bounds, skia::ClipOp::Intersect, antialias);
|
|
||||||
}
|
|
||||||
self.surfaces
|
|
||||||
.canvas(target_surface)
|
|
||||||
.concat(&total_matrix.invert().unwrap_or_default());
|
|
||||||
} else {
|
|
||||||
let mut total_matrix = Matrix::new_identity();
|
|
||||||
total_matrix.pre_scale((scale, scale), None);
|
|
||||||
total_matrix.pre_translate((translation.0, translation.1));
|
|
||||||
total_matrix.pre_concat(transform);
|
|
||||||
|
|
||||||
self.surfaces.canvas(target_surface).concat(&total_matrix);
|
|
||||||
|
|
||||||
if let Some(corners) = corners {
|
|
||||||
let rrect = RRect::new_rect_radii(*bounds, corners);
|
|
||||||
self.surfaces.canvas(target_surface).clip_rrect(
|
|
||||||
rrect,
|
|
||||||
skia::ClipOp::Intersect,
|
|
||||||
antialias,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
self.surfaces.canvas(target_surface).clip_rect(
|
|
||||||
*bounds,
|
|
||||||
skia::ClipOp::Intersect,
|
|
||||||
antialias,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.surfaces
|
|
||||||
.canvas(target_surface)
|
|
||||||
.concat(&total_matrix.invert().unwrap_or_default());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.surfaces
|
self.surfaces
|
||||||
.draw_into(SurfaceId::DropShadows, target_surface, None);
|
.draw_into(SurfaceId::DropShadows, target_surface, None);
|
||||||
self.surfaces.canvas(target_surface).restore();
|
self.surfaces.canvas(target_surface).restore();
|
||||||
@ -3242,17 +3263,12 @@ impl RenderState {
|
|||||||
&& element.drop_shadows_visible().next().is_some();
|
&& element.drop_shadows_visible().next().is_some();
|
||||||
|
|
||||||
if shadow_before_layer {
|
if shadow_before_layer {
|
||||||
let translation = self
|
|
||||||
.surfaces
|
|
||||||
.get_render_context_translation(self.render_area, scale);
|
|
||||||
|
|
||||||
self.render_element_drop_shadows_and_composite(
|
self.render_element_drop_shadows_and_composite(
|
||||||
element,
|
element,
|
||||||
tree,
|
tree,
|
||||||
&mut extrect,
|
&mut extrect,
|
||||||
clip_bounds.clone(),
|
clip_bounds.clone(),
|
||||||
scale,
|
scale,
|
||||||
translation,
|
|
||||||
&node_render_state,
|
&node_render_state,
|
||||||
target_surface,
|
target_surface,
|
||||||
)?;
|
)?;
|
||||||
@ -3264,14 +3280,10 @@ impl RenderState {
|
|||||||
self.render_background_blur(element, target_surface);
|
self.render_background_blur(element, target_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.render_shape_enter(element, mask, target_surface);
|
self.render_shape_enter(element, mask, clip_bounds.as_ref(), target_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !node_render_state.is_root() && self.focus_mode.is_active() {
|
if !node_render_state.is_root() && self.focus_mode.is_active() {
|
||||||
let translation = self
|
|
||||||
.surfaces
|
|
||||||
.get_render_context_translation(self.render_area, scale);
|
|
||||||
|
|
||||||
// Skip expensive drop shadow rendering in fast mode (during pan/zoom).
|
// Skip expensive drop shadow rendering in fast mode (during pan/zoom).
|
||||||
let skip_shadows = self.options.is_fast_mode();
|
let skip_shadows = self.options.is_fast_mode();
|
||||||
|
|
||||||
@ -3289,7 +3301,6 @@ impl RenderState {
|
|||||||
&mut extrect,
|
&mut extrect,
|
||||||
clip_bounds.clone(),
|
clip_bounds.clone(),
|
||||||
scale,
|
scale,
|
||||||
translation,
|
|
||||||
&node_render_state,
|
&node_render_state,
|
||||||
target_surface,
|
target_surface,
|
||||||
)?;
|
)?;
|
||||||
@ -3343,6 +3354,9 @@ impl RenderState {
|
|||||||
Type::Frame(_) if Self::frame_clip_layer_blur(element).is_some() => {
|
Type::Frame(_) if Self::frame_clip_layer_blur(element).is_some() => {
|
||||||
self.nested_blurs.push(None);
|
self.nested_blurs.push(None);
|
||||||
}
|
}
|
||||||
|
Type::Group(_) if element.masked_group_layer_blur().is_some() => {
|
||||||
|
self.nested_blurs.push(None);
|
||||||
|
}
|
||||||
Type::Frame(_) | Type::Group(_) => {
|
Type::Frame(_) | Type::Group(_) => {
|
||||||
self.nested_blurs.push(element.blur);
|
self.nested_blurs.push(element.blur);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1711,6 +1711,16 @@ impl Shape {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn masked_group_layer_blur(&self) -> Option<Blur> {
|
||||||
|
use crate::shapes::BlurType;
|
||||||
|
match self.shape_type {
|
||||||
|
Type::Group(Group { masked: true }) => self.blur.filter(|blur| {
|
||||||
|
!blur.hidden && blur.blur_type == BlurType::LayerBlur && blur.value > 0.0
|
||||||
|
}),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks if this shape has visual effects that might extend its bounds beyond selrect
|
/// Checks if this shape has visual effects that might extend its bounds beyond selrect
|
||||||
/// Shapes with these effects require expensive extrect calculation for accurate visibility checks
|
/// Shapes with these effects require expensive extrect calculation for accurate visibility checks
|
||||||
pub fn has_effects_that_extend_bounds(&self) -> bool {
|
pub fn has_effects_that_extend_bounds(&self) -> bool {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user