diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ba5af396..296189883 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/). This changelog also contains important changes in dependencies. ## [Unreleased] +### Removed +- `FillPaint` and `StrokePaint` filter inputs support. + It's a mostly undocumented SVG feature that no one supports and no one uses. + And it was adding a significant complexity to the codebase. +- `usvg::filter::Filter::fill_paint` and `usvg::filter::Filter::stroke_paint`. +- `BackgroundImage`, `BackgroundAlpha`, `FillPaint` and `StrokePaint` from `usvg::filter::Input`. +- `usvg::Group::filter_fill_paint` and `usvg::Group::filter_stroke_paint`. ## [0.34.1] - 2023-05-28 ### Fixed diff --git a/crates/resvg/src/filter/mod.rs b/crates/resvg/src/filter/mod.rs index 3ea08b9a9..855f63cbb 100644 --- a/crates/resvg/src/filter/mod.rs +++ b/crates/resvg/src/filter/mod.rs @@ -458,31 +458,13 @@ impl Image { } } -struct FilterInputs<'a> { - source: &'a mut tiny_skia::Pixmap, - fill_paint: Option<&'a tiny_skia::Pixmap>, - stroke_paint: Option<&'a tiny_skia::Pixmap>, -} - struct FilterResult { name: String, image: Image, } -pub fn apply( - filter: &Filter, - ts: tiny_skia::Transform, - fill_paint: Option<&tiny_skia::Pixmap>, - stroke_paint: Option<&tiny_skia::Pixmap>, - source: &mut tiny_skia::Pixmap, -) { - let inputs = FilterInputs { - source, - fill_paint, - stroke_paint, - }; - - let result = apply_inner(filter, &inputs, ts); +pub fn apply(filter: &Filter, ts: tiny_skia::Transform, source: &mut tiny_skia::Pixmap) { + let result = apply_inner(filter, ts, source); let result = result.and_then(|image| apply_to_canvas(image, source)); // Clear on error. @@ -501,8 +483,8 @@ pub fn apply( fn apply_inner( filter: &Filter, - inputs: &FilterInputs, ts: usvg::Transform, + source: &mut tiny_skia::Pixmap, ) -> Result { let mut results: Vec = Vec::new(); @@ -531,62 +513,62 @@ fn apply_inner( let mut result = match primitive.kind { usvg::filter::Kind::Blend(ref fe) => { - let input1 = get_input(&fe.input1, region, inputs, &results)?; - let input2 = get_input(&fe.input2, region, inputs, &results)?; + let input1 = get_input(&fe.input1, region, source, &results)?; + let input2 = get_input(&fe.input2, region, source, &results)?; apply_blend(fe, cs, region, input1, input2) } usvg::filter::Kind::DropShadow(ref fe) => { - let input = get_input(&fe.input, region, inputs, &results)?; + let input = get_input(&fe.input, region, source, &results)?; apply_drop_shadow(fe, cs, ts, input) } usvg::filter::Kind::Flood(ref fe) => apply_flood(fe, region), usvg::filter::Kind::GaussianBlur(ref fe) => { - let input = get_input(&fe.input, region, inputs, &results)?; + let input = get_input(&fe.input, region, source, &results)?; apply_blur(fe, cs, ts, input) } usvg::filter::Kind::Offset(ref fe) => { - let input = get_input(&fe.input, region, inputs, &results)?; + let input = get_input(&fe.input, region, source, &results)?; apply_offset(fe, ts, input) } usvg::filter::Kind::Composite(ref fe) => { - let input1 = get_input(&fe.input1, region, inputs, &results)?; - let input2 = get_input(&fe.input2, region, inputs, &results)?; + let input1 = get_input(&fe.input1, region, source, &results)?; + let input2 = get_input(&fe.input2, region, source, &results)?; apply_composite(fe, cs, region, input1, input2) } - usvg::filter::Kind::Merge(ref fe) => apply_merge(fe, cs, region, inputs, &results), + usvg::filter::Kind::Merge(ref fe) => apply_merge(fe, cs, region, source, &results), usvg::filter::Kind::Tile(ref fe) => { - let input = get_input(&fe.input, region, inputs, &results)?; + let input = get_input(&fe.input, region, source, &results)?; apply_tile(input, region) } usvg::filter::Kind::Image(ref fe) => apply_image(fe, region, subregion, ts), usvg::filter::Kind::ComponentTransfer(ref fe) => { - let input = get_input(&fe.input, region, inputs, &results)?; + let input = get_input(&fe.input, region, source, &results)?; apply_component_transfer(fe, cs, input) } usvg::filter::Kind::ColorMatrix(ref fe) => { - let input = get_input(&fe.input, region, inputs, &results)?; + let input = get_input(&fe.input, region, source, &results)?; apply_color_matrix(fe, cs, input) } usvg::filter::Kind::ConvolveMatrix(ref fe) => { - let input = get_input(&fe.input, region, inputs, &results)?; + let input = get_input(&fe.input, region, source, &results)?; apply_convolve_matrix(fe, cs, input) } usvg::filter::Kind::Morphology(ref fe) => { - let input = get_input(&fe.input, region, inputs, &results)?; + let input = get_input(&fe.input, region, source, &results)?; apply_morphology(fe, cs, ts, input) } usvg::filter::Kind::DisplacementMap(ref fe) => { - let input1 = get_input(&fe.input1, region, inputs, &results)?; - let input2 = get_input(&fe.input2, region, inputs, &results)?; + let input1 = get_input(&fe.input1, region, source, &results)?; + let input2 = get_input(&fe.input2, region, source, &results)?; apply_displacement_map(fe, region, cs, ts, input1, input2) } usvg::filter::Kind::Turbulence(ref fe) => apply_turbulence(fe, region, cs, ts), usvg::filter::Kind::DiffuseLighting(ref fe) => { - let input = get_input(&fe.input, region, inputs, &results)?; + let input = get_input(&fe.input, region, source, &results)?; apply_diffuse_lighting(fe, region, cs, ts, input) } usvg::filter::Kind::SpecularLighting(ref fe) => { - let input = get_input(&fe.input, region, inputs, &results)?; + let input = get_input(&fe.input, region, source, &results)?; apply_specular_lighting(fe, region, cs, ts, input) } }?; @@ -748,41 +730,12 @@ fn calc_subregion( fn get_input( input: &usvg::filter::Input, region: IntRect, - inputs: &FilterInputs, + source: &tiny_skia::Pixmap, results: &[FilterResult], ) -> Result { - let convert = |in_image: Option<&tiny_skia::Pixmap>, region: IntRect| { - let image = if let Some(image) = in_image { - image.clone() - } else { - tiny_skia::Pixmap::try_create(region.width(), region.height())? - }; - - Ok(Image { - image: Rc::new(image), - region, - color_space: usvg::filter::ColorInterpolation::SRGB, - }) - }; - - let convert_alpha = |mut image: tiny_skia::Pixmap| { - // Set RGB to black. Keep alpha as is. - for p in image.data_mut().as_rgba_mut() { - p.r = 0; - p.g = 0; - p.b = 0; - } - - Ok(Image { - image: Rc::new(image), - region, - color_space: usvg::filter::ColorInterpolation::SRGB, - }) - }; - match input { usvg::filter::Input::SourceGraphic => { - let image = inputs.source.clone(); + let image = source.clone(); Ok(Image { image: Rc::new(image), @@ -791,24 +744,27 @@ fn get_input( }) } usvg::filter::Input::SourceAlpha => { - let image = inputs.source.clone(); - convert_alpha(image) - } - usvg::filter::Input::BackgroundImage => { - get_input(&usvg::filter::Input::SourceGraphic, region, inputs, results) - } - usvg::filter::Input::BackgroundAlpha => { - get_input(&usvg::filter::Input::SourceAlpha, region, inputs, results) + let mut image = source.clone(); + // Set RGB to black. Keep alpha as is. + for p in image.data_mut().as_rgba_mut() { + p.r = 0; + p.g = 0; + p.b = 0; + } + + Ok(Image { + image: Rc::new(image), + region, + color_space: usvg::filter::ColorInterpolation::SRGB, + }) } - usvg::filter::Input::FillPaint => convert(inputs.fill_paint, region), - usvg::filter::Input::StrokePaint => convert(inputs.stroke_paint, region), usvg::filter::Input::Reference(ref name) => { if let Some(v) = results.iter().rev().find(|v| v.name == *name) { Ok(v.image.clone()) } else { // Technically unreachable. log::warn!("Unknown filter primitive reference '{}'.", name); - get_input(&usvg::filter::Input::SourceGraphic, region, inputs, results) + get_input(&usvg::filter::Input::SourceGraphic, region, source, results) } } } @@ -1043,13 +999,13 @@ fn apply_merge( fe: &usvg::filter::Merge, cs: usvg::filter::ColorInterpolation, region: IntRect, - inputs: &FilterInputs, + source: &tiny_skia::Pixmap, results: &[FilterResult], ) -> Result { let mut pixmap = tiny_skia::Pixmap::try_create(region.width(), region.height())?; for input in &fe.inputs { - let input = get_input(input, region, inputs, results)?; + let input = get_input(input, region, source, results)?; let input = input.into_color_space(cs)?; pixmap.draw_pixmap( 0, diff --git a/crates/resvg/src/render.rs b/crates/resvg/src/render.rs index d0d86da4b..b5f4160a2 100644 --- a/crates/resvg/src/render.rs +++ b/crates/resvg/src/render.rs @@ -140,16 +140,8 @@ fn render_group( render_nodes(&group.children, ctx, transform, &mut sub_pixmap.as_mut()); if !group.filters.is_empty() { - let fill_paint = prepare_filter_paint(group.filter_fill.as_ref(), ctx, &sub_pixmap); - let stroke_paint = prepare_filter_paint(group.filter_stroke.as_ref(), ctx, &sub_pixmap); for filter in &group.filters { - crate::filter::apply( - filter, - transform, - fill_paint.as_ref(), - stroke_paint.as_ref(), - &mut sub_pixmap, - ); + crate::filter::apply(filter, transform, &mut sub_pixmap); } } @@ -179,45 +171,6 @@ fn render_group( Some(()) } -/// Renders an image used by `FillPaint`/`StrokePaint` filter input. -/// -/// FillPaint/StrokePaint is mostly an undefined behavior and will produce different results -/// in every application. -/// And since there are no expected behaviour, we will simply fill the filter region. -/// -/// https://github.com/w3c/fxtf-drafts/issues/323 -fn prepare_filter_paint( - paint: Option<&crate::paint_server::Paint>, - ctx: &Context, - pixmap: &tiny_skia::Pixmap, -) -> Option { - use std::rc::Rc; - - let paint = paint?; - let mut sub_pixmap = tiny_skia::Pixmap::new(pixmap.width(), pixmap.height()).unwrap(); - - let rect = tiny_skia::Rect::from_xywh(0.0, 0.0, pixmap.width() as f32, pixmap.height() as f32)?; - let path = tiny_skia::PathBuilder::from_rect(rect); - - let path = crate::path::FillPath { - transform: tiny_skia::Transform::default(), - paint: paint.clone(), // TODO: remove clone - rule: tiny_skia::FillRule::Winding, - anti_alias: true, - path: Rc::new(path), - }; - - crate::path::render_fill_path( - &path, - tiny_skia::BlendMode::SourceOver, - ctx, - tiny_skia::Transform::default(), - &mut sub_pixmap.as_mut(), - ); - - Some(sub_pixmap) -} - pub trait TinySkiaPixmapMutExt { fn create_rect_mask( &self, diff --git a/crates/resvg/src/tree.rs b/crates/resvg/src/tree.rs index cc119dd56..970c83742 100644 --- a/crates/resvg/src/tree.rs +++ b/crates/resvg/src/tree.rs @@ -7,7 +7,6 @@ use usvg::NodeExt; use crate::clip::ClipPath; use crate::image::Image; use crate::mask::Mask; -use crate::paint_server::Paint; use crate::path::{FillPath, StrokePath}; pub struct Group { @@ -16,11 +15,8 @@ pub struct Group { pub blend_mode: tiny_skia::BlendMode, pub clip_path: Option, pub mask: Option, - pub isolate: bool, - pub filters: Vec, - pub filter_fill: Option, - pub filter_stroke: Option, + pub isolate: bool, /// Group's layer bounding box in canvas coordinates. pub bbox: tiny_skia::Rect, @@ -183,24 +179,6 @@ fn convert_group( bboxes.layer = usvg::BBox::from(filter_bbox); } - let mut filter_fill = None; - if let Some(ref paint) = ugroup.filter_fill_paint() { - filter_fill = crate::paint_server::convert( - paint, - usvg::Opacity::ONE, - bboxes.layer.to_non_zero_rect(), - ); - } - - let mut filter_stroke = None; - if let Some(ref paint) = ugroup.filter_stroke_paint() { - filter_stroke = crate::paint_server::convert( - paint, - usvg::Opacity::ONE, - bboxes.layer.to_non_zero_rect(), - ); - } - let group = Group { transform: ugroup.transform, opacity: ugroup.opacity, @@ -209,8 +187,6 @@ fn convert_group( mask: crate::mask::convert(ugroup.mask.clone(), bboxes.object.to_rect()?), isolate: ugroup.isolate, filters, - filter_fill, - filter_stroke, bbox: bboxes.layer.to_rect()?, children: group_children, }; @@ -231,18 +207,6 @@ fn convert_empty_group(ugroup: &usvg::Group, children: &mut Vec) -> Option let (filters, layer_bbox) = crate::filter::convert(&ugroup.filters, None); let layer_bbox = layer_bbox?; - let mut filter_fill = None; - if let Some(ref paint) = ugroup.filter_fill_paint() { - filter_fill = - crate::paint_server::convert(paint, usvg::Opacity::ONE, layer_bbox.to_non_zero_rect()); - } - - let mut filter_stroke = None; - if let Some(ref paint) = ugroup.filter_stroke_paint() { - filter_stroke = - crate::paint_server::convert(paint, usvg::Opacity::ONE, layer_bbox.to_non_zero_rect()); - } - let group = Group { transform: ugroup.transform, opacity: ugroup.opacity, @@ -251,8 +215,6 @@ fn convert_empty_group(ugroup: &usvg::Group, children: &mut Vec) -> Option mask: None, isolate: ugroup.isolate, filters, - filter_fill, - filter_stroke, bbox: layer_bbox, children: Vec::new(), }; diff --git a/crates/resvg/tests/tests/filters/filter/in=BackgroundAlpha.png b/crates/resvg/tests/tests/filters/filter/in=BackgroundAlpha.png index a7f020ef3..93c0ad187 100644 Binary files a/crates/resvg/tests/tests/filters/filter/in=BackgroundAlpha.png and b/crates/resvg/tests/tests/filters/filter/in=BackgroundAlpha.png differ diff --git a/crates/resvg/tests/tests/filters/filter/in=FillPaint-on-g-without-children.png b/crates/resvg/tests/tests/filters/filter/in=FillPaint-on-g-without-children.png index c2312d159..4fa749a9e 100644 Binary files a/crates/resvg/tests/tests/filters/filter/in=FillPaint-on-g-without-children.png and b/crates/resvg/tests/tests/filters/filter/in=FillPaint-on-g-without-children.png differ diff --git a/crates/resvg/tests/tests/filters/filter/in=FillPaint-with-gradient.png b/crates/resvg/tests/tests/filters/filter/in=FillPaint-with-gradient.png index 039e37a00..f64d21926 100644 Binary files a/crates/resvg/tests/tests/filters/filter/in=FillPaint-with-gradient.png and b/crates/resvg/tests/tests/filters/filter/in=FillPaint-with-gradient.png differ diff --git a/crates/resvg/tests/tests/filters/filter/in=FillPaint-with-pattern.png b/crates/resvg/tests/tests/filters/filter/in=FillPaint-with-pattern.png index 24d867b96..fc9707dc3 100644 Binary files a/crates/resvg/tests/tests/filters/filter/in=FillPaint-with-pattern.png and b/crates/resvg/tests/tests/filters/filter/in=FillPaint-with-pattern.png differ diff --git a/crates/resvg/tests/tests/filters/filter/in=FillPaint-with-target-on-g.png b/crates/resvg/tests/tests/filters/filter/in=FillPaint-with-target-on-g.png index 24d867b96..fc9707dc3 100644 Binary files a/crates/resvg/tests/tests/filters/filter/in=FillPaint-with-target-on-g.png and b/crates/resvg/tests/tests/filters/filter/in=FillPaint-with-target-on-g.png differ diff --git a/crates/resvg/tests/tests/filters/filter/in=FillPaint.png b/crates/resvg/tests/tests/filters/filter/in=FillPaint.png index 2a17f1306..ba3abe975 100644 Binary files a/crates/resvg/tests/tests/filters/filter/in=FillPaint.png and b/crates/resvg/tests/tests/filters/filter/in=FillPaint.png differ diff --git a/crates/resvg/tests/tests/filters/filter/in=StrokePaint.png b/crates/resvg/tests/tests/filters/filter/in=StrokePaint.png index 93e33239e..4fb4f8106 100644 Binary files a/crates/resvg/tests/tests/filters/filter/in=StrokePaint.png and b/crates/resvg/tests/tests/filters/filter/in=StrokePaint.png differ diff --git a/crates/usvg-parser/src/filter.rs b/crates/usvg-parser/src/filter.rs index 45fe2c13b..e73637ead 100644 --- a/crates/usvg-parser/src/filter.rs +++ b/crates/usvg-parser/src/filter.rs @@ -13,7 +13,7 @@ use svgtypes::{Length, LengthUnit as Unit}; use usvg_tree::filter::*; use usvg_tree::{ strict_num, ApproxZeroUlps, Color, Group, Node, NodeKind, NonZeroF32, NonZeroRect, Opacity, - Paint, Units, + Units, }; use crate::converter::SvgColorExt; @@ -62,8 +62,6 @@ pub(crate) fn convert( units: Units::ObjectBoundingBox, primitive_units: Units::UserSpaceOnUse, rect, - fill_paint: None, - stroke_paint: None, primitives: vec![Primitive { x: None, y: None, @@ -129,7 +127,7 @@ pub(crate) fn convert( } svgtypes::FilterValue::Url(url) => { if let Some(link) = node.document().element_by_id(url) { - if let Ok(res) = convert_url(node, link, state, cache) { + if let Ok(res) = convert_url(link, state, cache) { if let Some(f) = res { filters.push(f); } @@ -155,7 +153,6 @@ pub(crate) fn convert( } fn convert_url( - group_node: SvgNode, node: SvgNode, state: &converter::State, cache: &mut converter::Cache, @@ -215,16 +212,11 @@ fn convert_url( return Err(()); } - let fill_paint = resolve_filter_fill(group_node, state, &primitives, cache); - let stroke_paint = resolve_filter_stroke(group_node, state, &primitives, cache); - let filter = Rc::new(Filter { id: node.element_id().to_string(), units, primitive_units, rect, - fill_paint, - stroke_paint, primitives, }); @@ -235,42 +227,6 @@ fn convert_url( Ok(Some(filter)) } -fn resolve_filter_fill( - group_node: SvgNode, - state: &converter::State, - primitives: &[Primitive], - cache: &mut converter::Cache, -) -> Option { - let has_fill_paint = primitives - .iter() - .any(|c| c.kind.has_input(&Input::FillPaint)); - - if !has_fill_paint { - return None; - } - - let stroke = crate::style::resolve_fill(group_node, true, state, cache)?; - Some(stroke.paint) -} - -fn resolve_filter_stroke( - group_node: SvgNode, - state: &converter::State, - primitives: &[Primitive], - cache: &mut converter::Cache, -) -> Option { - let has_stroke_paint = primitives - .iter() - .any(|c| c.kind.has_input(&Input::StrokePaint)); - - if !has_stroke_paint { - return None; - } - - let stroke = crate::style::resolve_stroke(group_node, true, state, cache)?; - Some(stroke.paint) -} - fn find_filter_with_primitives<'a>(node: SvgNode<'a, 'a>) -> Option> { for link in node.href_iter() { if link.tag_name() != Some(EId::Filter) { @@ -421,10 +377,10 @@ fn parse_in(s: &str) -> Input { match s { "SourceGraphic" => Input::SourceGraphic, "SourceAlpha" => Input::SourceAlpha, - "BackgroundImage" => Input::BackgroundImage, - "BackgroundAlpha" => Input::BackgroundAlpha, - "FillPaint" => Input::FillPaint, - "StrokePaint" => Input::StrokePaint, + "BackgroundImage" | "BackgroundAlpha" | "FillPaint" | "StrokePaint" => { + log::warn!("{} filter input isn't supported and not planed.", s); + Input::SourceGraphic + } _ => Input::Reference(s.to_string()), } } diff --git a/crates/usvg-tree/src/filter.rs b/crates/usvg-tree/src/filter.rs index fa15effed..40aa139e9 100644 --- a/crates/usvg-tree/src/filter.rs +++ b/crates/usvg-tree/src/filter.rs @@ -7,9 +7,7 @@ use strict_num::PositiveF32; use svgtypes::AspectRatio; -use crate::{ - BlendMode, Color, ImageRendering, Node, NonZeroF32, NonZeroRect, Opacity, Paint, Units, -}; +use crate::{BlendMode, Color, ImageRendering, Node, NonZeroF32, NonZeroRect, Opacity, Units}; /// A filter element. /// @@ -37,16 +35,6 @@ pub struct Filter { /// `x`, `y`, `width` and `height` in the SVG. pub rect: NonZeroRect, - /// Contains a fill color or paint server used by `FilterInput::FillPaint`. - /// - /// Will be set only when filter actually has a `FilterInput::FillPaint`. - pub fill_paint: Option, - - /// Contains a stroke color or paint server used by `FilterInput::StrokePaint`. - /// - /// Will be set only when filter actually has a `FilterInput::StrokePaint`. - pub stroke_paint: Option, - /// A list of filter primitives. pub primitives: Vec, } @@ -134,10 +122,6 @@ impl Kind { pub enum Input { SourceGraphic, SourceAlpha, - BackgroundImage, - BackgroundAlpha, - FillPaint, - StrokePaint, Reference(String), } diff --git a/crates/usvg-tree/src/lib.rs b/crates/usvg-tree/src/lib.rs index 8cf2ccc5c..93dd0013c 100644 --- a/crates/usvg-tree/src/lib.rs +++ b/crates/usvg-tree/src/lib.rs @@ -812,23 +812,6 @@ impl Group { || !self.filters.is_empty() || self.blend_mode != BlendMode::Normal // TODO: probably not needed? } - - /// Contains a fill paint used by `FilterInput::FillPaint`. - pub fn filter_fill_paint(&self) -> Option<&Paint> { - // While we can have multiple filters, only one can have Paint. - self.filters - .iter() - .filter_map(|f| f.fill_paint.as_ref()) - .next() - } - - /// Contains a stroke paint used by `FilterInput::StrokePaint`. - pub fn filter_stroke_paint(&self) -> Option<&Paint> { - self.filters - .iter() - .filter_map(|f| f.stroke_paint.as_ref()) - .next() - } } /// Representation of the [`paint-order`] property. @@ -1082,12 +1065,7 @@ fn loop_over_paint_servers(root: &Node, f: &mut dyn FnMut(&Paint)) { } for node in root.descendants() { - if let NodeKind::Group(ref group) = *node.borrow() { - for filter in &group.filters { - push(filter.fill_paint.as_ref(), f); - push(filter.stroke_paint.as_ref(), f); - } - } else if let NodeKind::Path(ref path) = *node.borrow() { + if let NodeKind::Path(ref path) = *node.borrow() { push(path.fill.as_ref().map(|f| &f.paint), f); push(path.stroke.as_ref().map(|f| &f.paint), f); } else if let NodeKind::Text(ref text) = *node.borrow() { @@ -1171,11 +1149,6 @@ fn node_subroots(node: &Node, f: &mut dyn FnMut(Node)) { match *node.borrow() { NodeKind::Group(ref g) => { - for filter in &g.filters { - push_patt(filter.fill_paint.as_ref()); - push_patt(filter.stroke_paint.as_ref()); - } - if let Some(ref clip) = g.clip_path { f(clip.root.clone()); diff --git a/crates/usvg/docs/spec.adoc b/crates/usvg/docs/spec.adoc index 500b4dd88..f57b7ed68 100644 --- a/crates/usvg/docs/spec.adoc +++ b/crates/usvg/docs/spec.adoc @@ -271,10 +271,6 @@ A group will have at least one of the attributes present. Cannot be set to `none`. * `filter` = < >>+ + Cannot be set to `none`. -* `fill` = `none` | < >> | < >> + - Will be set only when any of the `filter` primitives has a `FillPaint` input. -* `stroke` = `none` | < >> | < >> + - Will be set only when any of the `filter` primitives has a `StrokePaint` input. * `transform` = < >>? * `style` = < >>? + This is the only place where the `style` attribute is used. @@ -727,11 +723,11 @@ Always a valid, local reference. + ** - A filter source. A reference to a _result_ guarantee to be valid. ``` -filter-input ::= SourceGraphic | SourceAlpha | BackgroundImage - | BackgroundAlpha | FillPaint | StrokePaint - | +filter-input ::= SourceGraphic | SourceAlpha | ``` +We do not support `FillPaint`, `StrokePaint`, `BackgroundImage` and `BackgroundAlpha`. + [[viewBox-type]] diff --git a/crates/usvg/src/writer.rs b/crates/usvg/src/writer.rs index 724f11406..cccde57d0 100644 --- a/crates/usvg/src/writer.rs +++ b/crates/usvg/src/writer.rs @@ -628,14 +628,6 @@ fn conv_element(node: &Node, is_clip_path: bool, opt: &XmlOptions, xml: &mut Xml .map(|filter| format!("url(#{}{})", prefix, filter.id)) .collect(); xml.write_svg_attribute(AId::Filter, &ids.join(" ")); - - if let Some(ref fill) = g.filter_fill_paint() { - write_paint(AId::Fill, fill, opt, xml); - } - - if let Some(ref stroke) = g.filter_stroke_paint() { - write_paint(AId::Stroke, stroke, opt, xml); - } } if g.opacity != Opacity::ONE { @@ -678,7 +670,7 @@ fn conv_element(node: &Node, is_clip_path: bool, opt: &XmlOptions, xml: &mut Xml xml.end_element(); } NodeKind::Text(_) => { - log::warn!("text must be converted into paths"); + log::warn!("Text must be converted into paths."); } } } @@ -854,10 +846,6 @@ impl XmlWriterExt for XmlWriter { match input { filter::Input::SourceGraphic => "SourceGraphic", filter::Input::SourceAlpha => "SourceAlpha", - filter::Input::BackgroundImage => "BackgroundImage", - filter::Input::BackgroundAlpha => "BackgroundAlpha", - filter::Input::FillPaint => "FillPaint", - filter::Input::StrokePaint => "StrokePaint", filter::Input::Reference(ref s) => s, }, );