🎉 Add text shadows (#6335)

This commit is contained in:
Elena Torró 2025-04-24 12:19:41 +02:00 committed by GitHub
parent 14e8026e30
commit c2ae58bf08
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 93 additions and 7 deletions

View file

@ -371,7 +371,12 @@ impl RenderState {
self.surfaces.apply_mut(&[SurfaceId::Fills], |s| { self.surfaces.apply_mut(&[SurfaceId::Fills], |s| {
s.canvas().concat(&matrix); s.canvas().concat(&matrix);
}); });
text::render(self, &shape, text_content);
let paragraphs = text_content.to_skia_paragraphs(&self.fonts.font_collection());
shadows::render_text_drop_shadows(self, &shape, &paragraphs, antialias);
text::render(self, &shape, &paragraphs, None, None);
shadows::render_text_inner_shadows(self, &shape, &paragraphs, antialias);
} }
_ => { _ => {
self.surfaces.apply_mut( self.surfaces.apply_mut(

View file

@ -1,7 +1,8 @@
use super::{RenderState, SurfaceId}; use super::{RenderState, SurfaceId};
use crate::render::strokes; use crate::render::strokes;
use crate::render::text::{self};
use crate::shapes::{Shadow, Shape, Stroke, Type}; use crate::shapes::{Shadow, Shape, Stroke, Type};
use skia_safe::Paint; use skia_safe::{textlayout::Paragraph, Paint};
// Fill Shadows // Fill Shadows
pub fn render_fill_drop_shadows(render_state: &mut RenderState, shape: &Shape, antialias: bool) { pub fn render_fill_drop_shadows(render_state: &mut RenderState, shape: &Shape, antialias: bool) {
@ -82,6 +83,64 @@ pub fn render_stroke_inner_shadows(
} }
} }
pub fn render_text_drop_shadows(
render_state: &mut RenderState,
shape: &Shape,
paragraphs: &[Paragraph],
antialias: bool,
) {
for shadow in shape.drop_shadows().rev().filter(|s| !s.hidden()) {
render_text_drop_shadow(render_state, &shape, &shadow, &paragraphs, antialias);
}
}
pub fn render_text_drop_shadow(
render_state: &mut RenderState,
shape: &Shape,
shadow: &Shadow,
paragraphs: &[Paragraph],
antialias: bool,
) {
let paint = &shadow.get_drop_shadow_paint(antialias);
text::render(
render_state,
shape,
&paragraphs,
Some(SurfaceId::DropShadows),
Some(paint),
);
}
pub fn render_text_inner_shadows(
render_state: &mut RenderState,
shape: &Shape,
paragraphs: &[Paragraph],
antialias: bool,
) {
for shadow in shape.inner_shadows().rev().filter(|s| !s.hidden()) {
render_text_inner_shadow(render_state, &shape, &shadow, &paragraphs, antialias);
}
}
pub fn render_text_inner_shadow(
render_state: &mut RenderState,
shape: &Shape,
shadow: &Shadow,
paragraphs: &[Paragraph],
antialias: bool,
) {
let paint = &shadow.get_inner_shadow_paint(antialias);
text::render(
render_state,
shape,
&paragraphs,
Some(SurfaceId::InnerShadows),
Some(paint),
);
}
fn render_shadow_paint( fn render_shadow_paint(
render_state: &mut RenderState, render_state: &mut RenderState,
shape: &Shape, shape: &Shape,

View file

@ -1,13 +1,25 @@
use super::{RenderState, Shape, SurfaceId}; use super::{RenderState, Shape, SurfaceId};
use crate::shapes::TextContent; use skia_safe::{self as skia, canvas::SaveLayerRec, paint, textlayout::Paragraph};
pub fn render(render_state: &mut RenderState, shape: &Shape, text: &TextContent) { pub fn render(
render_state: &mut RenderState,
shape: &Shape,
paragraphs: &[Paragraph],
surface_id: Option<SurfaceId>,
paint: Option<&paint::Paint>,
) {
let mut offset_y = 0.0; let mut offset_y = 0.0;
for mut skia_paragraph in text.to_paragraphs(&render_state.fonts().font_collection()) { let default_paint = skia::Paint::default();
skia_paragraph.layout(shape.width()); let mask = SaveLayerRec::default().paint(&paint.unwrap_or(&default_paint));
let canvas = render_state
.surfaces
.canvas(surface_id.unwrap_or(SurfaceId::Fills));
canvas.save_layer(&mask);
for skia_paragraph in paragraphs {
let xy = (shape.selrect().x(), shape.selrect.y() + offset_y); let xy = (shape.selrect().x(), shape.selrect.y() + offset_y);
skia_paragraph.paint(render_state.surfaces.canvas(SurfaceId::Fills), xy); skia_paragraph.paint(canvas, xy);
offset_y += skia_paragraph.height(); offset_y += skia_paragraph.height();
} }
canvas.restore();
} }

View file

@ -549,6 +549,7 @@ impl Shape {
self.hidden self.hidden
} }
#[allow(dead_code)]
pub fn width(&self) -> f32 { pub fn width(&self) -> f32 {
self.selrect.width() self.selrect.width()
} }

View file

@ -65,6 +65,15 @@ impl TextContent {
}) })
.collect() .collect()
} }
pub fn to_skia_paragraphs(&self, fonts: &FontCollection) -> Vec<skia::textlayout::Paragraph> {
let mut paragraphs = Vec::new();
for mut skia_paragraph in self.to_paragraphs(fonts) {
skia_paragraph.layout(self.width());
paragraphs.push(skia_paragraph);
}
paragraphs
}
} }
impl Default for TextContent { impl Default for TextContent {