0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-21 06:02:32 -05:00

♻️ Refactor blend mode and fills into their own submodules

This commit is contained in:
Belén Albeza 2024-11-29 11:46:45 +01:00
parent 2d4281bdf2
commit 00ab9ad3f0
5 changed files with 116 additions and 109 deletions

View file

@ -154,7 +154,7 @@ pub extern "C" fn add_shape_solid_fill(raw_color: u32) {
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
if let Some(shape) = state.current_shape() {
let color = skia::Color::new(raw_color);
shape.add_fill(shapes::Fill::from(color));
shape.add_fill(shapes::Fill::Solid(color));
}
}

View file

@ -1,4 +1,3 @@
use skia_safe as skia;
pub type Rect = skia::Rect;
pub type Matrix = skia::Matrix;

View file

@ -2,12 +2,17 @@ use crate::math;
use skia_safe as skia;
use uuid::Uuid;
mod blend;
mod fills;
pub use blend::*;
pub use fills::*;
#[derive(Debug, Clone, Copy)]
pub enum Kind {
Rect,
}
type Color = skia::Color;
pub type Color = skia::Color;
#[derive(Debug, Clone, Copy)]
pub struct Matrix {
@ -32,110 +37,6 @@ impl Matrix {
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Gradient {
colors: Vec<Color>,
offsets: Vec<f32>,
opacity: f32,
start: (f32, f32),
end: (f32, f32),
}
impl Gradient {
fn to_shader(&self, rect: &math::Rect) -> skia::Shader {
let start = (
rect.left + self.start.0 * rect.width(),
rect.top + self.start.1 * rect.height(),
);
let end = (
rect.left + self.end.0 * rect.width(),
rect.top + self.end.1 * rect.height(),
);
let shader = skia::shader::Shader::linear_gradient(
(start, end),
self.colors.as_slice(),
self.offsets.as_slice(),
skia::TileMode::Clamp,
None,
None,
)
.unwrap();
shader
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Fill {
Solid(Color),
LinearGradient(Gradient),
}
impl From<Color> for Fill {
fn from(value: Color) -> Self {
Self::Solid(value)
}
}
impl Fill {
pub fn new_linear_gradient(start: (f32, f32), end: (f32, f32), opacity: f32) -> Self {
Self::LinearGradient(Gradient {
start,
end,
opacity,
colors: vec![],
offsets: vec![],
})
}
pub fn to_paint(&self, rect: &math::Rect) -> skia::Paint {
match self {
Self::Solid(color) => {
let mut p = skia::Paint::default();
p.set_color(*color);
p.set_style(skia::PaintStyle::Fill);
p.set_anti_alias(true);
p.set_blend_mode(skia::BlendMode::SrcOver);
p
}
Self::LinearGradient(gradient) => {
let mut p = skia::Paint::default();
p.set_shader(gradient.to_shader(&rect));
p.set_alpha((gradient.opacity * 255.) as u8);
p.set_style(skia::PaintStyle::Fill);
p.set_blend_mode(skia::BlendMode::SrcOver);
p
}
}
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct BlendMode(skia::BlendMode);
impl Default for BlendMode {
fn default() -> Self {
BlendMode(skia::BlendMode::SrcOver)
}
}
impl From<i32> for BlendMode {
fn from(value: i32) -> Self {
if value <= skia::BlendMode::Luminosity as i32 {
unsafe { Self(std::mem::transmute(value)) }
} else {
Self::default()
}
}
}
impl Into<skia::BlendMode> for BlendMode {
fn into(self) -> skia::BlendMode {
match self {
Self(skia_blend) => skia_blend,
}
}
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct Shape {
@ -196,8 +97,7 @@ impl Shape {
_ => Err("Active fill is not a gradient"),
}?;
gradient.colors.push(color);
gradient.offsets.push(offset);
gradient.add_stop(color, offset);
Ok(())
}

View file

@ -0,0 +1,28 @@
use skia_safe as skia;
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct BlendMode(skia::BlendMode);
impl Default for BlendMode {
fn default() -> Self {
BlendMode(skia::BlendMode::SrcOver)
}
}
impl From<i32> for BlendMode {
fn from(value: i32) -> Self {
if value <= skia::BlendMode::Luminosity as i32 {
unsafe { Self(std::mem::transmute(value)) }
} else {
Self::default()
}
}
}
impl Into<skia::BlendMode> for BlendMode {
fn into(self) -> skia::BlendMode {
match self {
Self(skia_blend) => skia_blend,
}
}
}

View file

@ -0,0 +1,80 @@
use skia_safe as skia;
use super::Color;
use crate::math;
#[derive(Debug, Clone, PartialEq)]
pub struct Gradient {
colors: Vec<Color>,
offsets: Vec<f32>,
opacity: f32,
start: (f32, f32),
end: (f32, f32),
}
impl Gradient {
pub fn add_stop(&mut self, color: Color, offset: f32) {
self.colors.push(color);
self.offsets.push(offset);
}
fn to_shader(&self, rect: &math::Rect) -> skia::Shader {
let start = (
rect.left + self.start.0 * rect.width(),
rect.top + self.start.1 * rect.height(),
);
let end = (
rect.left + self.end.0 * rect.width(),
rect.top + self.end.1 * rect.height(),
);
let shader = skia::shader::Shader::linear_gradient(
(start, end),
self.colors.as_slice(),
self.offsets.as_slice(),
skia::TileMode::Clamp,
None,
None,
)
.unwrap();
shader
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Fill {
Solid(Color),
LinearGradient(Gradient),
}
impl Fill {
pub fn new_linear_gradient(start: (f32, f32), end: (f32, f32), opacity: f32) -> Self {
Self::LinearGradient(Gradient {
start,
end,
opacity,
colors: vec![],
offsets: vec![],
})
}
pub fn to_paint(&self, rect: &math::Rect) -> skia::Paint {
match self {
Self::Solid(color) => {
let mut p = skia::Paint::default();
p.set_color(*color);
p.set_style(skia::PaintStyle::Fill);
p.set_anti_alias(true);
p.set_blend_mode(skia::BlendMode::SrcOver);
p
}
Self::LinearGradient(gradient) => {
let mut p = skia::Paint::default();
p.set_shader(gradient.to_shader(&rect));
p.set_alpha((gradient.opacity * 255.) as u8);
p.set_style(skia::PaintStyle::Fill);
p.set_blend_mode(skia::BlendMode::SrcOver);
p
}
}
}
}