mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-17 15:28:04 +08:00
Fix color and gradient list paints not rendering as stacks (#4439)
Stack every item of a color or gradient paint instead of painting only the first
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
use crate::renderer::{ClearGuardPlacement, ItemRef, RenderParams, format_transform_matrix, gradient_placement, gradient_settings_from_item, spread_adjusted_samples, transform_is_invertible};
|
||||
use crate::renderer::{
|
||||
ClearGuardPlacement, ItemRef, RenderParams, composite_paint_colors, faded_paint_color, format_transform_matrix, gradient_placement, gradient_settings_from_item, spread_adjusted_samples,
|
||||
transform_is_invertible,
|
||||
};
|
||||
use crate::{Render, RenderSvgSegmentList, SvgRender};
|
||||
use core_types::color::SRGBA8;
|
||||
use core_types::list::List;
|
||||
@@ -50,19 +53,13 @@ pub trait RenderExt {
|
||||
) -> Self::Output;
|
||||
}
|
||||
|
||||
/// The paint attribute for a solid color, or the SVG `none` keyword when the color is absent.
|
||||
/// `for_mask` keeps the fill opacity at full, as [`ItemRef::paint_opacity`] explains.
|
||||
fn render_color_paint(item: Option<ItemRef<'_, Color>>, target: PaintTarget, for_mask: bool) -> String {
|
||||
let unpainted = || format!(r#" {}="none""#, target.paint_attr());
|
||||
/// The paint attribute for an already-faded solid color, or the SVG `none` keyword when the color is absent.
|
||||
fn render_color_paint(color: Option<Color>, target: PaintTarget) -> String {
|
||||
let Some(color) = color else { return format!(r#" {}="none""#, target.paint_attr()) };
|
||||
|
||||
let Some(item) = item else { return unpainted() };
|
||||
let Some(color) = item.element() else { return unpainted() };
|
||||
|
||||
let alpha = color.a() * item.paint_opacity(for_mask);
|
||||
|
||||
let mut result = format!(r##" {}="#{}""##, target.paint_attr(), SRGBA8::from(*color).to_rgb_hex());
|
||||
if alpha < 1. {
|
||||
let _ = write!(result, r#" {}="{}""#, target.opacity_attr(), (alpha * 1000.).round() / 1000.);
|
||||
let mut result = format!(r##" {}="#{}""##, target.paint_attr(), SRGBA8::from(color).to_rgb_hex());
|
||||
if color.a() < 1. {
|
||||
let _ = write!(result, r#" {}="{}""#, target.opacity_attr(), (color.a() * 1000.).round() / 1000.);
|
||||
}
|
||||
|
||||
result
|
||||
@@ -81,7 +78,7 @@ impl RenderExt for List<Color> {
|
||||
render_params: &RenderParams,
|
||||
target: PaintTarget,
|
||||
) -> Self::Output {
|
||||
render_color_paint((!self.is_empty()).then_some(ItemRef::ListItem(self, 0)), target, render_params.for_mask)
|
||||
render_color_paint(composite_paint_colors(self, render_params.for_mask), target)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,12 +272,13 @@ impl RenderExt for List<Graphic> {
|
||||
let paint_attr = target.paint_attr();
|
||||
|
||||
match fill_graphic {
|
||||
Some(Graphic::Color(item)) => render_color_paint(Some(ItemRef::Item(item)), target, render_params.for_mask),
|
||||
Some(Graphic::Color(item)) => render_color_paint(faded_paint_color(ItemRef::Item(item), render_params.for_mask), target),
|
||||
Some(Graphic::ColorList(color_list)) => color_list.render(svg_defs, item_transform, element_transform, stroke_transform, bounds, render_params, target),
|
||||
Some(Graphic::Gradient(item)) => render_gradient_paint(Some(ItemRef::Item(item)), svg_defs, item_transform, element_transform, render_params.for_mask)
|
||||
.map(|gradient_id| format!(r##" {paint_attr}="url(#{gradient_id})""##))
|
||||
.unwrap_or_else(|| format!(r#" {paint_attr}="none""#)),
|
||||
Some(Graphic::GradientList(gradient_list)) => gradient_list
|
||||
// One gradient resolves to a paint server; stacking several needs them composited, which only the pattern below can do
|
||||
Some(Graphic::GradientList(gradient_list)) if gradient_list.len() <= 1 => gradient_list
|
||||
.render(svg_defs, item_transform, element_transform, stroke_transform, bounds, render_params, target)
|
||||
.map(|gradient_id| format!(r##" {paint_attr}="url(#{gradient_id})""##))
|
||||
.unwrap_or_else(|| format!(r#" {paint_attr}="none""#)),
|
||||
@@ -294,6 +292,7 @@ impl RenderExt for List<Graphic> {
|
||||
| Some(Graphic::RasterCPUList(_))
|
||||
| Some(Graphic::RasterGPUList(_))
|
||||
| Some(Graphic::GraphicList(_))
|
||||
| Some(Graphic::GradientList(_))
|
||||
| Some(Graphic::TextList(_)) => {
|
||||
let bounds = if target == PaintTarget::Stroke {
|
||||
// To prevent a wraparound artefact occurring when the tile boundary and the stroke region are perfectly aligned, the local coordinate is expanded slightly.
|
||||
|
||||
Reference in New Issue
Block a user