diff options
author | Marge Bot <marge-bot@gnome.org> | 2023-04-25 23:30:10 +0000 |
---|---|---|
committer | Marge Bot <marge-bot@gnome.org> | 2023-04-25 23:30:10 +0000 |
commit | 30567b3eac0148e3e95f5dd011ff76bda5000a99 (patch) | |
tree | 7d5c56dc2b20f91ccc77aee4dad07830e7eb429a /rsvg/src/filters/blend.rs | |
parent | d597831ff93b09cc41ce4768a833bc6407c95184 (diff) | |
parent | 7608c94036d7a44296a7e135f42e84aed20afeb7 (diff) | |
download | librsvg-30567b3eac0148e3e95f5dd011ff76bda5000a99.tar.gz |
Merge branch 'wip/sophie-h/workspace' into 'main'
meta: Move lib and bins into separate crates
Closes #950
See merge request GNOME/librsvg!822
Diffstat (limited to 'rsvg/src/filters/blend.rs')
-rw-r--r-- | rsvg/src/filters/blend.rs | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/rsvg/src/filters/blend.rs b/rsvg/src/filters/blend.rs new file mode 100644 index 00000000..30b0bdf7 --- /dev/null +++ b/rsvg/src/filters/blend.rs @@ -0,0 +1,178 @@ +use cssparser::Parser; +use markup5ever::{expanded_name, local_name, namespace_url, ns}; + +use crate::document::AcquiredNodes; +use crate::drawing_ctx::DrawingCtx; +use crate::element::{set_attribute, ElementTrait}; +use crate::error::*; +use crate::node::{CascadedValues, Node}; +use crate::parsers::{Parse, ParseValue}; +use crate::properties::ColorInterpolationFilters; +use crate::rect::IRect; +use crate::session::Session; +use crate::surface_utils::shared_surface::Operator; +use crate::xml::Attributes; + +use super::bounds::BoundsBuilder; +use super::context::{FilterContext, FilterOutput}; +use super::{ + FilterEffect, FilterError, FilterResolveError, Input, Primitive, PrimitiveParams, + ResolvedPrimitive, +}; + +/// Enumeration of the possible blending modes. +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +enum Mode { + Normal, + Multiply, + Screen, + Darken, + Lighten, + Overlay, + ColorDodge, + ColorBurn, + HardLight, + SoftLight, + Difference, + Exclusion, + HslHue, + HslSaturation, + HslColor, + HslLuminosity, +} + +enum_default!(Mode, Mode::Normal); + +/// The `feBlend` filter primitive. +#[derive(Default)] +pub struct FeBlend { + base: Primitive, + params: Blend, +} + +/// Resolved `feBlend` primitive for rendering. +#[derive(Clone, Default)] +pub struct Blend { + in1: Input, + in2: Input, + mode: Mode, + color_interpolation_filters: ColorInterpolationFilters, +} + +impl ElementTrait for FeBlend { + fn set_attributes(&mut self, attrs: &Attributes, session: &Session) { + let (in1, in2) = self.base.parse_two_inputs(attrs, session); + self.params.in1 = in1; + self.params.in2 = in2; + + for (attr, value) in attrs.iter() { + if let expanded_name!("", "mode") = attr.expanded() { + set_attribute(&mut self.params.mode, attr.parse(value), session); + } + } + } +} + +impl Blend { + pub fn render( + &self, + bounds_builder: BoundsBuilder, + ctx: &FilterContext, + acquired_nodes: &mut AcquiredNodes<'_>, + draw_ctx: &mut DrawingCtx, + ) -> Result<FilterOutput, FilterError> { + let input_1 = ctx.get_input( + acquired_nodes, + draw_ctx, + &self.in1, + self.color_interpolation_filters, + )?; + let input_2 = ctx.get_input( + acquired_nodes, + draw_ctx, + &self.in2, + self.color_interpolation_filters, + )?; + let bounds: IRect = bounds_builder + .add_input(&input_1) + .add_input(&input_2) + .compute(ctx) + .clipped + .into(); + + let surface = input_1 + .surface() + .compose(input_2.surface(), bounds, self.mode.into())?; + + Ok(FilterOutput { surface, bounds }) + } +} + +impl FilterEffect for FeBlend { + fn resolve( + &self, + _acquired_nodes: &mut AcquiredNodes<'_>, + node: &Node, + ) -> Result<Vec<ResolvedPrimitive>, FilterResolveError> { + let cascaded = CascadedValues::new_from_node(node); + let values = cascaded.get(); + + let mut params = self.params.clone(); + params.color_interpolation_filters = values.color_interpolation_filters(); + + Ok(vec![ResolvedPrimitive { + primitive: self.base.clone(), + params: PrimitiveParams::Blend(params), + }]) + } +} + +impl Parse for Mode { + fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> { + Ok(parse_identifiers!( + parser, + "normal" => Mode::Normal, + "multiply" => Mode::Multiply, + "screen" => Mode::Screen, + "darken" => Mode::Darken, + "lighten" => Mode::Lighten, + "overlay" => Mode::Overlay, + "color-dodge" => Mode::ColorDodge, + "color-burn" => Mode::ColorBurn, + "hard-light" => Mode::HardLight, + "soft-light" => Mode::SoftLight, + "difference" => Mode::Difference, + "exclusion" => Mode::Exclusion, + "hue" => Mode::HslHue, + "saturation" => Mode::HslSaturation, + "color" => Mode::HslColor, + "luminosity" => Mode::HslLuminosity, + )?) + } +} + +impl From<Mode> for Operator { + #[inline] + fn from(x: Mode) -> Self { + use Mode::*; + + match x { + Normal => Operator::Over, + Multiply => Operator::Multiply, + Screen => Operator::Screen, + Darken => Operator::Darken, + Lighten => Operator::Lighten, + Overlay => Operator::Overlay, + ColorDodge => Operator::ColorDodge, + ColorBurn => Operator::ColorBurn, + HardLight => Operator::HardLight, + SoftLight => Operator::SoftLight, + Difference => Operator::Difference, + Exclusion => Operator::Exclusion, + HslHue => Operator::HslHue, + HslSaturation => Operator::HslSaturation, + HslColor => Operator::HslColor, + HslLuminosity => Operator::HslLuminosity, + } + } +} |