Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions node-graph/libraries/rendering/src/render_ext.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::renderer::{RenderParams, format_transform_matrix};
use core_types::consts::{LAYER_OUTLINE_STROKE_COLOR, LAYER_OUTLINE_STROKE_WEIGHT};
use crate::renderer::{RenderParams, black_or_white_for_best_contrast, format_transform_matrix};
use core_types::consts::LAYER_OUTLINE_STROKE_WEIGHT;
use core_types::uuid::generate_uuid;
use glam::DAffine2;
use graphic_types::vector_types::gradient::{Gradient, GradientType};
Expand Down Expand Up @@ -167,9 +167,12 @@ impl RenderExt for PathStyle {
match render_mode {
RenderMode::Outline => {
let fill_attribute = Fill::None.render(svg_defs, element_transform, stroke_transform, bounds, transformed_bounds, render_params);
let mut outline_stroke = Stroke::new(Some(LAYER_OUTLINE_STROKE_COLOR), LAYER_OUTLINE_STROKE_WEIGHT);

let outline_color = black_or_white_for_best_contrast(render_params.artboard_background);
let mut outline_stroke = Stroke::new(Some(outline_color), LAYER_OUTLINE_STROKE_WEIGHT);
// Outline strokes should be non-scaling by default
outline_stroke.non_scaling = true;

let stroke_attribute = outline_stroke.render(svg_defs, element_transform, stroke_transform, bounds, transformed_bounds, render_params);
format!("{fill_attribute}{stroke_attribute}")
}
Expand Down
41 changes: 32 additions & 9 deletions node-graph/libraries/rendering/src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ pub struct RenderParams {
pub alignment_parent_transform: Option<DAffine2>,
pub aligned_strokes: bool,
pub override_paint_order: bool,
pub artboard_background: Option<Color>,
}

impl Hash for RenderParams {
Expand All @@ -198,6 +199,7 @@ impl Hash for RenderParams {
}
self.aligned_strokes.hash(state);
self.override_paint_order.hash(state);
self.artboard_background.hash(state);
}
}

Expand Down Expand Up @@ -235,6 +237,26 @@ fn max_scale(transform: DAffine2) -> f64 {
(sx + sy).sqrt()
}

pub fn black_or_white_for_best_contrast(background: Option<Color>) -> Color {
let Some(bg) = background else { return core_types::consts::LAYER_OUTLINE_STROKE_COLOR };

let alpha = bg.a();

// Un-premultiply, then convert to gamma sRGB
let srgb = if alpha > f32::EPSILON {
Color::from_rgbaf32_unchecked(bg.r() / alpha, bg.g() / alpha, bg.b() / alpha, alpha).to_gamma_srgb()
} else {
Color::TRANSPARENT
};

// Composite over black in sRGB space, then convert back to linear for luminance
let composited = Color::from_rgbaf32_unchecked(srgb.r() * alpha, srgb.g() * alpha, srgb.b() * alpha, 1.).to_linear_srgb();

let threshold = (1.05 * 0.05f32).sqrt() - 0.05;

if composited.luminance_srgb() > threshold { Color::BLACK } else { Color::WHITE }
}

pub fn to_transform(transform: DAffine2) -> usvg::Transform {
let cols = transform.to_cols_array();
usvg::Transform::from_row(cols[0] as f32, cols[1] as f32, cols[2] as f32, cols[3] as f32, cols[4] as f32, cols[5] as f32)
Expand Down Expand Up @@ -441,7 +463,9 @@ impl Render for Artboard {
},
// Artwork content
|render| {
self.content.render_svg(render, render_params);
let mut render_params = render_params.clone();
render_params.artboard_background = Some(self.background);
self.content.render_svg(render, &render_params);
},
);
}
Expand All @@ -463,7 +487,9 @@ impl Render for Artboard {
}
// Since the content's transform is right multiplied in when rendering the content, we just need to right multiply by the artboard offset here.
let child_transform = transform * DAffine2::from_translation(self.location.as_dvec2());
self.content.render_to_vello(scene, child_transform, context, render_params);
let mut render_params = render_params.clone();
render_params.artboard_background = Some(self.background);
self.content.render_to_vello(scene, child_transform, context, &render_params);
if self.clip {
scene.pop_layer();
}
Expand Down Expand Up @@ -882,7 +908,7 @@ impl Render for Table<Vector> {
}

fn render_to_vello(&self, scene: &mut Scene, parent_transform: DAffine2, _context: &mut RenderContext, render_params: &RenderParams) {
use core_types::consts::{LAYER_OUTLINE_STROKE_COLOR, LAYER_OUTLINE_STROKE_WEIGHT};
use core_types::consts::LAYER_OUTLINE_STROKE_WEIGHT;
use graphic_types::vector_types::vector::style::{GradientType, StrokeCap, StrokeJoin};
use vello::kurbo::{Cap, Join};
use vello::peniko;
Expand Down Expand Up @@ -1066,12 +1092,9 @@ impl Render for Table<Vector> {
dash_pattern: Default::default(),
dash_offset: 0.,
};
let outline_color = peniko::Color::new([
LAYER_OUTLINE_STROKE_COLOR.r(),
LAYER_OUTLINE_STROKE_COLOR.g(),
LAYER_OUTLINE_STROKE_COLOR.b(),
LAYER_OUTLINE_STROKE_COLOR.a(),
]);

let outline_color = black_or_white_for_best_contrast(render_params.artboard_background);
let outline_color = peniko::Color::new([outline_color.r(), outline_color.g(), outline_color.b(), outline_color.a()]);

scene.stroke(&outline_stroke, kurbo::Affine::new(element_transform.to_cols_array()), outline_color, None, &path);
}
Expand Down
Loading