mirror of
https://github.com/penpot/penpot.git
synced 2025-06-03 22:21:38 +02:00
Merge pull request #6126 from penpot/elenatorro-10516-fix-stroke-shadows
🐛 Fix stroke shadows
This commit is contained in:
commit
bd5e47f5fc
6 changed files with 122 additions and 201 deletions
|
@ -210,43 +210,35 @@ impl RenderState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_drawing_to_render_canvas(&mut self, shape: Option<&Shape>) {
|
pub fn apply_drawing_to_render_canvas(&mut self, shape: Option<&Shape>) {
|
||||||
self.surfaces
|
|
||||||
.flush_and_submit(&mut self.gpu_state, SurfaceId::Fills);
|
|
||||||
|
|
||||||
self.surfaces
|
self.surfaces
|
||||||
.flush_and_submit(&mut self.gpu_state, SurfaceId::DropShadows);
|
.flush_and_submit(&mut self.gpu_state, SurfaceId::DropShadows);
|
||||||
|
|
||||||
self.surfaces
|
|
||||||
.flush_and_submit(&mut self.gpu_state, SurfaceId::InnerShadows);
|
|
||||||
|
|
||||||
self.surfaces.draw_into(
|
self.surfaces.draw_into(
|
||||||
SurfaceId::DropShadows,
|
SurfaceId::DropShadows,
|
||||||
SurfaceId::Current,
|
SurfaceId::Current,
|
||||||
Some(&skia::Paint::default()),
|
Some(&skia::Paint::default()),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
self.surfaces
|
||||||
|
.flush_and_submit(&mut self.gpu_state, SurfaceId::Fills);
|
||||||
|
|
||||||
self.surfaces.draw_into(
|
self.surfaces.draw_into(
|
||||||
SurfaceId::Fills,
|
SurfaceId::Fills,
|
||||||
SurfaceId::Current,
|
SurfaceId::Current,
|
||||||
Some(&skia::Paint::default()),
|
Some(&skia::Paint::default()),
|
||||||
);
|
);
|
||||||
|
|
||||||
self.surfaces.draw_into(
|
|
||||||
SurfaceId::InnerShadows,
|
|
||||||
SurfaceId::Current,
|
|
||||||
Some(&skia::Paint::default()),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut render_overlay_below_strokes = false;
|
let mut render_overlay_below_strokes = false;
|
||||||
if let Some(shape) = shape {
|
if let Some(shape) = shape {
|
||||||
render_overlay_below_strokes = shape.fills().len() > 0;
|
render_overlay_below_strokes = shape.has_fills();
|
||||||
}
|
}
|
||||||
|
|
||||||
if render_overlay_below_strokes {
|
if render_overlay_below_strokes {
|
||||||
self.surfaces
|
self.surfaces
|
||||||
.flush_and_submit(&mut self.gpu_state, SurfaceId::Overlay);
|
.flush_and_submit(&mut self.gpu_state, SurfaceId::InnerShadows);
|
||||||
|
|
||||||
self.surfaces.draw_into(
|
self.surfaces.draw_into(
|
||||||
SurfaceId::Overlay,
|
SurfaceId::InnerShadows,
|
||||||
SurfaceId::Current,
|
SurfaceId::Current,
|
||||||
Some(&skia::Paint::default()),
|
Some(&skia::Paint::default()),
|
||||||
);
|
);
|
||||||
|
@ -254,6 +246,7 @@ impl RenderState {
|
||||||
|
|
||||||
self.surfaces
|
self.surfaces
|
||||||
.flush_and_submit(&mut self.gpu_state, SurfaceId::Strokes);
|
.flush_and_submit(&mut self.gpu_state, SurfaceId::Strokes);
|
||||||
|
|
||||||
self.surfaces.draw_into(
|
self.surfaces.draw_into(
|
||||||
SurfaceId::Strokes,
|
SurfaceId::Strokes,
|
||||||
SurfaceId::Current,
|
SurfaceId::Current,
|
||||||
|
@ -262,25 +255,22 @@ impl RenderState {
|
||||||
|
|
||||||
if !render_overlay_below_strokes {
|
if !render_overlay_below_strokes {
|
||||||
self.surfaces
|
self.surfaces
|
||||||
.flush_and_submit(&mut self.gpu_state, SurfaceId::Overlay);
|
.flush_and_submit(&mut self.gpu_state, SurfaceId::InnerShadows);
|
||||||
|
|
||||||
self.surfaces.draw_into(
|
self.surfaces.draw_into(
|
||||||
SurfaceId::Overlay,
|
SurfaceId::InnerShadows,
|
||||||
SurfaceId::Current,
|
SurfaceId::Current,
|
||||||
Some(&skia::Paint::default()),
|
Some(&skia::Paint::default()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.surfaces
|
|
||||||
.draw_into(SurfaceId::Overlay, SurfaceId::Current, None);
|
|
||||||
self.surfaces
|
self.surfaces
|
||||||
.flush_and_submit(&mut self.gpu_state, SurfaceId::Current);
|
.flush_and_submit(&mut self.gpu_state, SurfaceId::Current);
|
||||||
|
|
||||||
self.surfaces.apply_mut(
|
self.surfaces.apply_mut(
|
||||||
&[
|
&[
|
||||||
SurfaceId::Shadow,
|
|
||||||
SurfaceId::InnerShadows,
|
|
||||||
SurfaceId::DropShadows,
|
SurfaceId::DropShadows,
|
||||||
SurfaceId::Overlay,
|
SurfaceId::InnerShadows,
|
||||||
SurfaceId::Fills,
|
SurfaceId::Fills,
|
||||||
SurfaceId::Strokes,
|
SurfaceId::Strokes,
|
||||||
],
|
],
|
||||||
|
@ -403,11 +393,13 @@ impl RenderState {
|
||||||
}
|
}
|
||||||
|
|
||||||
for stroke in shape.strokes().rev() {
|
for stroke in shape.strokes().rev() {
|
||||||
strokes::render(self, &shape, stroke, antialias);
|
shadows::render_stroke_drop_shadows(self, &shape, stroke, antialias);
|
||||||
|
strokes::render(self, &shape, stroke, None, None, antialias);
|
||||||
|
shadows::render_stroke_inner_shadows(self, &shape, stroke, antialias);
|
||||||
}
|
}
|
||||||
|
|
||||||
shadows::render_inner_shadows(self, &shape, antialias);
|
shadows::render_fill_inner_shadows(self, &shape, antialias);
|
||||||
shadows::render_drop_shadows(self, &shape, antialias);
|
shadows::render_fill_drop_shadows(self, &shape, antialias);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,14 @@
|
||||||
use super::{RenderState, SurfaceId};
|
use super::{RenderState, SurfaceId};
|
||||||
use crate::shapes::{Shadow, Shape, Type};
|
use crate::render::strokes;
|
||||||
use skia_safe::{self as skia, Paint};
|
use crate::shapes::{Shadow, Shape, Stroke, Type};
|
||||||
|
use skia_safe::Paint;
|
||||||
|
|
||||||
// Drop Shadows
|
// Fill Shadows
|
||||||
pub fn render_drop_shadows(render_state: &mut RenderState, shape: &Shape, antialias: bool) {
|
pub fn render_fill_drop_shadows(render_state: &mut RenderState, shape: &Shape, antialias: bool) {
|
||||||
if shape.has_fills() {
|
if shape.has_fills() {
|
||||||
for shadow in shape.drop_shadows().rev().filter(|s| !s.hidden()) {
|
for shadow in shape.drop_shadows().rev().filter(|s| !s.hidden()) {
|
||||||
render_fill_drop_shadow(render_state, &shape, &shadow, antialias);
|
render_fill_drop_shadow(render_state, &shape, &shadow, antialias);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
let scale = render_state.get_scale();
|
|
||||||
for shadow in shape.drop_shadows().rev().filter(|s| !s.hidden()) {
|
|
||||||
render_stroke_drop_shadow(render_state, &shadow, scale, antialias);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,42 +22,11 @@ fn render_fill_drop_shadow(
|
||||||
render_shadow_paint(render_state, shape, paint, SurfaceId::DropShadows);
|
render_shadow_paint(render_state, shape, paint, SurfaceId::DropShadows);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Stroke shadows
|
pub fn render_fill_inner_shadows(render_state: &mut RenderState, shape: &Shape, antialias: bool) {
|
||||||
fn render_stroke_drop_shadow(
|
|
||||||
render_state: &mut RenderState,
|
|
||||||
shadow: &Shadow,
|
|
||||||
scale: f32,
|
|
||||||
antialias: bool,
|
|
||||||
) {
|
|
||||||
let shadow_paint = &shadow.to_paint(scale, antialias);
|
|
||||||
|
|
||||||
render_state
|
|
||||||
.surfaces
|
|
||||||
.draw_into(SurfaceId::Strokes, SurfaceId::Shadow, Some(shadow_paint));
|
|
||||||
|
|
||||||
render_state.surfaces.draw_into(
|
|
||||||
SurfaceId::Shadow,
|
|
||||||
SurfaceId::Current,
|
|
||||||
Some(&skia::Paint::default()),
|
|
||||||
);
|
|
||||||
|
|
||||||
render_state
|
|
||||||
.surfaces
|
|
||||||
.canvas(SurfaceId::Shadow)
|
|
||||||
.clear(skia::Color::TRANSPARENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inner Shadows
|
|
||||||
pub fn render_inner_shadows(render_state: &mut RenderState, shape: &Shape, antialias: bool) {
|
|
||||||
if shape.has_fills() {
|
if shape.has_fills() {
|
||||||
for shadow in shape.inner_shadows().rev().filter(|s| !s.hidden()) {
|
for shadow in shape.inner_shadows().rev().filter(|s| !s.hidden()) {
|
||||||
render_fill_inner_shadow(render_state, &shape, &shadow, antialias);
|
render_fill_inner_shadow(render_state, &shape, &shadow, antialias);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
let scale = render_state.get_scale();
|
|
||||||
for shadow in shape.inner_shadows().rev().filter(|s| !s.hidden()) {
|
|
||||||
render_stroke_inner_shadow(render_state, &shadow, scale, antialias);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,29 +40,46 @@ fn render_fill_inner_shadow(
|
||||||
render_shadow_paint(render_state, shape, paint, SurfaceId::InnerShadows);
|
render_shadow_paint(render_state, shape, paint, SurfaceId::InnerShadows);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Stroke shadows
|
pub fn render_stroke_drop_shadows(
|
||||||
fn render_stroke_inner_shadow(
|
|
||||||
render_state: &mut RenderState,
|
render_state: &mut RenderState,
|
||||||
shadow: &Shadow,
|
shape: &Shape,
|
||||||
scale: f32,
|
stroke: &Stroke,
|
||||||
antialias: bool,
|
antialias: bool,
|
||||||
) {
|
) {
|
||||||
let shadow_paint = &shadow.to_paint(scale, antialias);
|
if !shape.has_fills() {
|
||||||
|
for shadow in shape.drop_shadows().rev().filter(|s| !s.hidden()) {
|
||||||
|
let filter = shadow.get_drop_shadow_filter();
|
||||||
|
strokes::render(
|
||||||
|
render_state,
|
||||||
|
&shape,
|
||||||
|
stroke,
|
||||||
|
Some(SurfaceId::Strokes), // FIXME
|
||||||
|
filter.as_ref(),
|
||||||
|
antialias,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render_state
|
pub fn render_stroke_inner_shadows(
|
||||||
.surfaces
|
render_state: &mut RenderState,
|
||||||
.draw_into(SurfaceId::Strokes, SurfaceId::Shadow, Some(shadow_paint));
|
shape: &Shape,
|
||||||
|
stroke: &Stroke,
|
||||||
render_state.surfaces.draw_into(
|
antialias: bool,
|
||||||
SurfaceId::Shadow,
|
) {
|
||||||
SurfaceId::Overlay,
|
if !shape.has_fills() {
|
||||||
Some(&skia::Paint::default()),
|
for shadow in shape.inner_shadows().rev().filter(|s| !s.hidden()) {
|
||||||
);
|
let filter = shadow.get_inner_shadow_filter();
|
||||||
|
strokes::render(
|
||||||
render_state
|
render_state,
|
||||||
.surfaces
|
&shape,
|
||||||
.canvas(SurfaceId::Shadow)
|
stroke,
|
||||||
.clear(skia::Color::TRANSPARENT);
|
Some(SurfaceId::Strokes), // FIXME
|
||||||
|
filter.as_ref(),
|
||||||
|
antialias,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_shadow_paint(
|
fn render_shadow_paint(
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||||
use crate::math::{Matrix, Point, Rect};
|
use crate::math::{Matrix, Point, Rect};
|
||||||
|
|
||||||
use crate::shapes::{Corners, Fill, ImageFill, Path, Shape, Stroke, StrokeCap, StrokeKind, Type};
|
use crate::shapes::{Corners, Fill, ImageFill, Path, Shape, Stroke, StrokeCap, StrokeKind, Type};
|
||||||
use skia_safe::{self as skia, RRect};
|
use skia_safe::{self as skia, ImageFilter, RRect};
|
||||||
|
|
||||||
use super::{RenderState, SurfaceId};
|
use super::{RenderState, SurfaceId};
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ fn draw_stroke_on_rect(
|
||||||
corners: &Option<Corners>,
|
corners: &Option<Corners>,
|
||||||
svg_attrs: &HashMap<String, String>,
|
svg_attrs: &HashMap<String, String>,
|
||||||
scale: f32,
|
scale: f32,
|
||||||
|
shadow: Option<&ImageFilter>,
|
||||||
antialias: bool,
|
antialias: bool,
|
||||||
) {
|
) {
|
||||||
// Draw the different kind of strokes for a rect is straightforward, we just need apply a stroke to:
|
// Draw the different kind of strokes for a rect is straightforward, we just need apply a stroke to:
|
||||||
|
@ -22,7 +23,11 @@ fn draw_stroke_on_rect(
|
||||||
// - A bigger rect if it's an outer stroke
|
// - A bigger rect if it's an outer stroke
|
||||||
// - A smaller rect if it's an outer stroke
|
// - A smaller rect if it's an outer stroke
|
||||||
let stroke_rect = stroke.outer_rect(rect);
|
let stroke_rect = stroke.outer_rect(rect);
|
||||||
let paint = stroke.to_paint(selrect, svg_attrs, scale, antialias);
|
let mut paint = stroke.to_paint(selrect, svg_attrs, scale, antialias);
|
||||||
|
|
||||||
|
if let Some(filter) = shadow {
|
||||||
|
paint.set_image_filter(filter.clone());
|
||||||
|
}
|
||||||
|
|
||||||
match corners {
|
match corners {
|
||||||
Some(radii) => {
|
Some(radii) => {
|
||||||
|
@ -43,6 +48,7 @@ fn draw_stroke_on_circle(
|
||||||
selrect: &Rect,
|
selrect: &Rect,
|
||||||
svg_attrs: &HashMap<String, String>,
|
svg_attrs: &HashMap<String, String>,
|
||||||
scale: f32,
|
scale: f32,
|
||||||
|
shadow: Option<&ImageFilter>,
|
||||||
antialias: bool,
|
antialias: bool,
|
||||||
) {
|
) {
|
||||||
// Draw the different kind of strokes for an oval is straightforward, we just need apply a stroke to:
|
// Draw the different kind of strokes for an oval is straightforward, we just need apply a stroke to:
|
||||||
|
@ -50,13 +56,16 @@ fn draw_stroke_on_circle(
|
||||||
// - A bigger oval if it's an outer stroke
|
// - A bigger oval if it's an outer stroke
|
||||||
// - A smaller oval if it's an outer stroke
|
// - A smaller oval if it's an outer stroke
|
||||||
let stroke_rect = stroke.outer_rect(rect);
|
let stroke_rect = stroke.outer_rect(rect);
|
||||||
canvas.draw_oval(
|
let mut paint = stroke.to_paint(selrect, svg_attrs, scale, antialias);
|
||||||
&stroke_rect,
|
|
||||||
&stroke.to_paint(selrect, svg_attrs, scale, antialias),
|
if let Some(filter) = shadow {
|
||||||
);
|
paint.set_image_filter(filter.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.draw_oval(&stroke_rect, &paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_stroke_on_path(
|
pub fn draw_stroke_on_path(
|
||||||
canvas: &skia::Canvas,
|
canvas: &skia::Canvas,
|
||||||
stroke: &Stroke,
|
stroke: &Stroke,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
|
@ -64,13 +73,19 @@ fn draw_stroke_on_path(
|
||||||
path_transform: Option<&Matrix>,
|
path_transform: Option<&Matrix>,
|
||||||
svg_attrs: &HashMap<String, String>,
|
svg_attrs: &HashMap<String, String>,
|
||||||
scale: f32,
|
scale: f32,
|
||||||
|
shadow: Option<&ImageFilter>,
|
||||||
antialias: bool,
|
antialias: bool,
|
||||||
) {
|
) {
|
||||||
let mut skia_path = path.to_skia_path();
|
let mut skia_path = path.to_skia_path();
|
||||||
skia_path.transform(path_transform.unwrap());
|
skia_path.transform(path_transform.unwrap());
|
||||||
|
|
||||||
let is_open = path.is_open();
|
let is_open = path.is_open();
|
||||||
let paint_stroke = stroke.to_stroked_paint(is_open, selrect, svg_attrs, scale, antialias);
|
let mut paint: skia_safe::Handle<_> =
|
||||||
|
stroke.to_stroked_paint(path.is_open(), selrect, svg_attrs, scale, antialias);
|
||||||
|
|
||||||
|
if let Some(filter) = shadow {
|
||||||
|
paint.set_image_filter(filter.clone());
|
||||||
|
}
|
||||||
|
|
||||||
// Draw the different kind of strokes for a path requires different strategies:
|
// Draw the different kind of strokes for a path requires different strategies:
|
||||||
match stroke.render_kind(is_open) {
|
match stroke.render_kind(is_open) {
|
||||||
|
@ -78,22 +93,21 @@ fn draw_stroke_on_path(
|
||||||
StrokeKind::InnerStroke => {
|
StrokeKind::InnerStroke => {
|
||||||
canvas.save(); // As we are using clear for surfaces we use save and restore here to still be able to clean the full surface
|
canvas.save(); // As we are using clear for surfaces we use save and restore here to still be able to clean the full surface
|
||||||
canvas.clip_path(&skia_path, skia::ClipOp::Intersect, antialias);
|
canvas.clip_path(&skia_path, skia::ClipOp::Intersect, antialias);
|
||||||
canvas.draw_path(&skia_path, &paint_stroke);
|
canvas.draw_path(&skia_path, &paint);
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
}
|
}
|
||||||
// For center stroke we don't need to do anything extra
|
// For center stroke we don't need to do anything extra
|
||||||
StrokeKind::CenterStroke => {
|
StrokeKind::CenterStroke => {
|
||||||
canvas.draw_path(&skia_path, &paint_stroke);
|
canvas.draw_path(&skia_path, &paint);
|
||||||
}
|
}
|
||||||
// For outer stroke we draw a center stroke (with double width) and use another path with blend mode clear to remove the inner stroke added
|
// For outer stroke we draw a center stroke (with double width) and use another path with blend mode clear to remove the inner stroke added
|
||||||
StrokeKind::OuterStroke => {
|
StrokeKind::OuterStroke => {
|
||||||
let mut paint = skia::Paint::default();
|
let mut outer_paint = skia::Paint::default();
|
||||||
paint.set_blend_mode(skia::BlendMode::SrcOver);
|
outer_paint.set_blend_mode(skia::BlendMode::SrcOver);
|
||||||
paint.set_anti_alias(antialias);
|
outer_paint.set_anti_alias(antialias);
|
||||||
let layer_rec = skia::canvas::SaveLayerRec::default().paint(&paint);
|
let layer_rec = skia::canvas::SaveLayerRec::default().paint(&outer_paint);
|
||||||
canvas.save_layer(&layer_rec);
|
canvas.save_layer(&layer_rec);
|
||||||
|
canvas.draw_path(&skia_path, &paint);
|
||||||
canvas.draw_path(&skia_path, &paint_stroke);
|
|
||||||
|
|
||||||
let mut clear_paint = skia::Paint::default();
|
let mut clear_paint = skia::Paint::default();
|
||||||
clear_paint.set_blend_mode(skia::BlendMode::Clear);
|
clear_paint.set_blend_mode(skia::BlendMode::Clear);
|
||||||
|
@ -344,7 +358,7 @@ fn draw_image_stroke_in_container(
|
||||||
|
|
||||||
let size = image_fill.size();
|
let size = image_fill.size();
|
||||||
let scale = render_state.get_scale();
|
let scale = render_state.get_scale();
|
||||||
let canvas = render_state.surfaces.canvas(SurfaceId::Fills);
|
let canvas = render_state.surfaces.canvas(SurfaceId::Strokes);
|
||||||
let container = &shape.selrect;
|
let container = &shape.selrect;
|
||||||
let path_transform = shape.to_path_transform();
|
let path_transform = shape.to_path_transform();
|
||||||
let svg_attrs = &shape.svg_attrs;
|
let svg_attrs = &shape.svg_attrs;
|
||||||
|
@ -370,6 +384,7 @@ fn draw_image_stroke_in_container(
|
||||||
&shape_type.corners(),
|
&shape_type.corners(),
|
||||||
svg_attrs,
|
svg_attrs,
|
||||||
scale,
|
scale,
|
||||||
|
None,
|
||||||
antialias,
|
antialias,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -380,6 +395,7 @@ fn draw_image_stroke_in_container(
|
||||||
&outer_rect,
|
&outer_rect,
|
||||||
svg_attrs,
|
svg_attrs,
|
||||||
scale,
|
scale,
|
||||||
|
None,
|
||||||
antialias,
|
antialias,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
@ -456,15 +472,26 @@ fn draw_image_stroke_in_container(
|
||||||
/**
|
/**
|
||||||
* This SHOULD be the only public function in this module.
|
* This SHOULD be the only public function in this module.
|
||||||
*/
|
*/
|
||||||
pub fn render(render_state: &mut RenderState, shape: &Shape, stroke: &Stroke, antialias: bool) {
|
pub fn render(
|
||||||
|
render_state: &mut RenderState,
|
||||||
|
shape: &Shape,
|
||||||
|
stroke: &Stroke,
|
||||||
|
surface_id: Option<SurfaceId>,
|
||||||
|
shadow: Option<&ImageFilter>,
|
||||||
|
antialias: bool,
|
||||||
|
) {
|
||||||
let scale = render_state.get_scale();
|
let scale = render_state.get_scale();
|
||||||
let canvas = render_state.surfaces.canvas(SurfaceId::Strokes);
|
let canvas = render_state
|
||||||
|
.surfaces
|
||||||
|
.canvas(surface_id.unwrap_or(SurfaceId::Strokes));
|
||||||
let selrect = shape.selrect;
|
let selrect = shape.selrect;
|
||||||
let path_transform = shape.to_path_transform();
|
let path_transform = shape.to_path_transform();
|
||||||
let svg_attrs = &shape.svg_attrs;
|
let svg_attrs = &shape.svg_attrs;
|
||||||
|
|
||||||
if let Fill::Image(image_fill) = &stroke.fill {
|
if !shadow.is_some() && matches!(stroke.fill, Fill::Image(_)) {
|
||||||
draw_image_stroke_in_container(render_state, shape, stroke, image_fill, antialias);
|
if let Fill::Image(image_fill) = &stroke.fill {
|
||||||
|
draw_image_stroke_in_container(render_state, shape, stroke, image_fill, antialias);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
match &shape.shape_type {
|
match &shape.shape_type {
|
||||||
shape_type @ (Type::Rect(_) | Type::Frame(_)) => {
|
shape_type @ (Type::Rect(_) | Type::Frame(_)) => {
|
||||||
|
@ -476,11 +503,12 @@ pub fn render(render_state: &mut RenderState, shape: &Shape, stroke: &Stroke, an
|
||||||
&shape_type.corners(),
|
&shape_type.corners(),
|
||||||
svg_attrs,
|
svg_attrs,
|
||||||
scale,
|
scale,
|
||||||
|
shadow,
|
||||||
antialias,
|
antialias,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Type::Circle => draw_stroke_on_circle(
|
Type::Circle => draw_stroke_on_circle(
|
||||||
canvas, stroke, &selrect, &selrect, svg_attrs, scale, antialias,
|
canvas, stroke, &selrect, &selrect, svg_attrs, scale, shadow, antialias,
|
||||||
),
|
),
|
||||||
shape_type @ (Type::Path(_) | Type::Bool(_)) => {
|
shape_type @ (Type::Path(_) | Type::Bool(_)) => {
|
||||||
if let Some(path) = shape_type.path() {
|
if let Some(path) = shape_type.path() {
|
||||||
|
@ -492,6 +520,7 @@ pub fn render(render_state: &mut RenderState, shape: &Shape, stroke: &Stroke, an
|
||||||
path_transform.as_ref(),
|
path_transform.as_ref(),
|
||||||
svg_attrs,
|
svg_attrs,
|
||||||
scale,
|
scale,
|
||||||
|
shadow,
|
||||||
antialias,
|
antialias,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,8 @@ pub enum SurfaceId {
|
||||||
Current,
|
Current,
|
||||||
Fills,
|
Fills,
|
||||||
Strokes,
|
Strokes,
|
||||||
Shadow,
|
|
||||||
DropShadows,
|
DropShadows,
|
||||||
InnerShadows,
|
InnerShadows,
|
||||||
Overlay,
|
|
||||||
Debug,
|
Debug,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,12 +28,9 @@ pub struct Surfaces {
|
||||||
// keeps the current shape's strokes
|
// keeps the current shape's strokes
|
||||||
shape_strokes: skia::Surface,
|
shape_strokes: skia::Surface,
|
||||||
// used for rendering shadows
|
// used for rendering shadows
|
||||||
shadow: skia::Surface,
|
|
||||||
// used for new shadow rendering
|
|
||||||
drop_shadows: skia::Surface,
|
drop_shadows: skia::Surface,
|
||||||
|
// used fo rendering over shadows.
|
||||||
inner_shadows: skia::Surface,
|
inner_shadows: skia::Surface,
|
||||||
// for drawing the things that are over shadows.
|
|
||||||
overlay: skia::Surface,
|
|
||||||
// for drawing debug info.
|
// for drawing debug info.
|
||||||
debug: skia::Surface,
|
debug: skia::Surface,
|
||||||
// for drawing tiles.
|
// for drawing tiles.
|
||||||
|
@ -63,10 +58,8 @@ impl Surfaces {
|
||||||
|
|
||||||
let mut target = gpu_state.create_target_surface(width, height);
|
let mut target = gpu_state.create_target_surface(width, height);
|
||||||
let current = target.new_surface_with_dimensions(extra_tile_dims).unwrap();
|
let current = target.new_surface_with_dimensions(extra_tile_dims).unwrap();
|
||||||
let shadow = target.new_surface_with_dimensions(extra_tile_dims).unwrap();
|
|
||||||
let drop_shadows = target.new_surface_with_dimensions(extra_tile_dims).unwrap();
|
let drop_shadows = target.new_surface_with_dimensions(extra_tile_dims).unwrap();
|
||||||
let inner_shadows = target.new_surface_with_dimensions(extra_tile_dims).unwrap();
|
let inner_shadows = target.new_surface_with_dimensions(extra_tile_dims).unwrap();
|
||||||
let overlay = target.new_surface_with_dimensions(extra_tile_dims).unwrap();
|
|
||||||
let shape_fills = target.new_surface_with_dimensions(extra_tile_dims).unwrap();
|
let shape_fills = target.new_surface_with_dimensions(extra_tile_dims).unwrap();
|
||||||
let shape_strokes = target.new_surface_with_dimensions(extra_tile_dims).unwrap();
|
let shape_strokes = target.new_surface_with_dimensions(extra_tile_dims).unwrap();
|
||||||
let debug = target.new_surface_with_dimensions((width, height)).unwrap();
|
let debug = target.new_surface_with_dimensions((width, height)).unwrap();
|
||||||
|
@ -79,10 +72,8 @@ impl Surfaces {
|
||||||
Surfaces {
|
Surfaces {
|
||||||
target,
|
target,
|
||||||
current,
|
current,
|
||||||
shadow,
|
|
||||||
drop_shadows,
|
drop_shadows,
|
||||||
inner_shadows,
|
inner_shadows,
|
||||||
overlay,
|
|
||||||
shape_fills,
|
shape_fills,
|
||||||
shape_strokes,
|
shape_strokes,
|
||||||
debug,
|
debug,
|
||||||
|
@ -176,10 +167,8 @@ impl Surfaces {
|
||||||
match id {
|
match id {
|
||||||
SurfaceId::Target => &mut self.target,
|
SurfaceId::Target => &mut self.target,
|
||||||
SurfaceId::Current => &mut self.current,
|
SurfaceId::Current => &mut self.current,
|
||||||
SurfaceId::Shadow => &mut self.shadow,
|
|
||||||
SurfaceId::DropShadows => &mut self.drop_shadows,
|
SurfaceId::DropShadows => &mut self.drop_shadows,
|
||||||
SurfaceId::InnerShadows => &mut self.inner_shadows,
|
SurfaceId::InnerShadows => &mut self.inner_shadows,
|
||||||
SurfaceId::Overlay => &mut self.overlay,
|
|
||||||
SurfaceId::Fills => &mut self.shape_fills,
|
SurfaceId::Fills => &mut self.shape_fills,
|
||||||
SurfaceId::Strokes => &mut self.shape_strokes,
|
SurfaceId::Strokes => &mut self.shape_strokes,
|
||||||
SurfaceId::Debug => &mut self.debug,
|
SurfaceId::Debug => &mut self.debug,
|
||||||
|
@ -225,8 +214,6 @@ impl Surfaces {
|
||||||
SurfaceId::Current,
|
SurfaceId::Current,
|
||||||
SurfaceId::DropShadows,
|
SurfaceId::DropShadows,
|
||||||
SurfaceId::InnerShadows,
|
SurfaceId::InnerShadows,
|
||||||
SurfaceId::Shadow,
|
|
||||||
SurfaceId::Overlay,
|
|
||||||
],
|
],
|
||||||
|s| {
|
|s| {
|
||||||
s.canvas().clear(color).reset_matrix();
|
s.canvas().clear(color).reset_matrix();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use skia_safe::{self as skia, image_filters, ImageFilter};
|
use skia_safe::{self as skia, image_filters, ImageFilter, Paint};
|
||||||
|
|
||||||
use super::Color;
|
use super::Color;
|
||||||
|
|
||||||
|
@ -62,75 +62,8 @@ impl Shadow {
|
||||||
self.hidden
|
self.hidden
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_paint(&self, scale: f32, antialias: bool) -> skia::Paint {
|
pub fn get_drop_shadow_paint(&self, antialias: bool) -> Paint {
|
||||||
let mut paint = skia::Paint::default();
|
let mut paint = Paint::default();
|
||||||
|
|
||||||
let image_filter = match self.style {
|
|
||||||
ShadowStyle::Drop => self.drop_shadow_filters(scale),
|
|
||||||
ShadowStyle::Inner => self.inner_shadow_filters(scale),
|
|
||||||
};
|
|
||||||
|
|
||||||
paint.set_image_filter(image_filter);
|
|
||||||
paint.set_anti_alias(antialias);
|
|
||||||
|
|
||||||
paint
|
|
||||||
}
|
|
||||||
|
|
||||||
// To be removed: Old methods for Drop Shadows and Inner Shadows (now used opnly for stroke shadows)
|
|
||||||
|
|
||||||
fn drop_shadow_filters(&self, scale: f32) -> Option<ImageFilter> {
|
|
||||||
let mut filter = image_filters::drop_shadow_only(
|
|
||||||
(self.offset.0 * scale, self.offset.1 * scale),
|
|
||||||
(self.blur * scale, self.blur * scale),
|
|
||||||
self.color,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
|
|
||||||
if self.spread > 0. {
|
|
||||||
filter =
|
|
||||||
image_filters::dilate((self.spread * scale, self.spread * scale), filter, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
filter
|
|
||||||
}
|
|
||||||
|
|
||||||
fn inner_shadow_filters(&self, scale: f32) -> Option<ImageFilter> {
|
|
||||||
let sigma = self.blur * 0.5;
|
|
||||||
let mut filter = skia::image_filters::drop_shadow_only(
|
|
||||||
(self.offset.0 * scale, self.offset.1 * scale), // DPR?
|
|
||||||
(sigma * scale, sigma * scale),
|
|
||||||
skia::Color::BLACK,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
|
|
||||||
filter = skia::image_filters::color_filter(
|
|
||||||
skia::color_filters::blend(self.color, skia::BlendMode::SrcOut).unwrap(),
|
|
||||||
filter,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
|
|
||||||
if self.spread > 0. {
|
|
||||||
filter = skia::image_filters::dilate(
|
|
||||||
(self.spread * scale, self.spread * scale),
|
|
||||||
filter,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
filter = skia::image_filters::blend(skia::BlendMode::SrcIn, None, filter, None);
|
|
||||||
|
|
||||||
filter
|
|
||||||
}
|
|
||||||
|
|
||||||
// New methods for Drop Shadows
|
|
||||||
|
|
||||||
pub fn get_drop_shadow_paint(&self, antialias: bool) -> skia::Paint {
|
|
||||||
let mut paint = skia::Paint::default();
|
|
||||||
|
|
||||||
let image_filter = self.get_drop_shadow_filter();
|
let image_filter = self.get_drop_shadow_filter();
|
||||||
|
|
||||||
paint.set_image_filter(image_filter);
|
paint.set_image_filter(image_filter);
|
||||||
|
@ -139,7 +72,7 @@ impl Shadow {
|
||||||
paint
|
paint
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_drop_shadow_filter(&self) -> Option<ImageFilter> {
|
pub fn get_drop_shadow_filter(&self) -> Option<ImageFilter> {
|
||||||
let mut filter = image_filters::drop_shadow_only(
|
let mut filter = image_filters::drop_shadow_only(
|
||||||
(self.offset.0, self.offset.1),
|
(self.offset.0, self.offset.1),
|
||||||
(self.blur, self.blur),
|
(self.blur, self.blur),
|
||||||
|
@ -156,10 +89,8 @@ impl Shadow {
|
||||||
filter
|
filter
|
||||||
}
|
}
|
||||||
|
|
||||||
// New methods for Inner Shadows
|
pub fn get_inner_shadow_paint(&self, antialias: bool) -> Paint {
|
||||||
|
let mut paint = Paint::default();
|
||||||
pub fn get_inner_shadow_paint(&self, antialias: bool) -> skia::Paint {
|
|
||||||
let mut paint = skia::Paint::default();
|
|
||||||
|
|
||||||
let image_filter = self.get_inner_shadow_filter();
|
let image_filter = self.get_inner_shadow_filter();
|
||||||
|
|
||||||
|
@ -169,12 +100,12 @@ impl Shadow {
|
||||||
paint
|
paint
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_inner_shadow_filter(&self) -> Option<ImageFilter> {
|
pub fn get_inner_shadow_filter(&self) -> Option<ImageFilter> {
|
||||||
let sigma = self.blur * 0.5;
|
let sigma = self.blur * 0.5;
|
||||||
let mut filter = skia::image_filters::drop_shadow_only(
|
let mut filter = skia::image_filters::drop_shadow_only(
|
||||||
(self.offset.0, self.offset.1), // DPR?
|
(self.offset.0, self.offset.1), // DPR?
|
||||||
(sigma, sigma),
|
(sigma, sigma),
|
||||||
skia::Color::BLACK,
|
skia::Color::WHITE,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -232,13 +232,13 @@ impl Stroke {
|
||||||
match self.render_kind(is_open) {
|
match self.render_kind(is_open) {
|
||||||
StrokeKind::InnerStroke => {
|
StrokeKind::InnerStroke => {
|
||||||
paint.set_stroke_width(2. * paint.stroke_width());
|
paint.set_stroke_width(2. * paint.stroke_width());
|
||||||
paint
|
|
||||||
}
|
}
|
||||||
StrokeKind::CenterStroke => paint,
|
StrokeKind::CenterStroke => {}
|
||||||
StrokeKind::OuterStroke => {
|
StrokeKind::OuterStroke => {
|
||||||
paint.set_stroke_width(2. * paint.stroke_width());
|
paint.set_stroke_width(2. * paint.stroke_width());
|
||||||
paint
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
paint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue