mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-04 02:38:11 +08:00
Make the Outline render mode draw with consistent stroke thickness at any viewport zoom (#3848)
* Remove dead code for now-retired SVG implementation * Implement viewport zoom compensation for thickness
This commit is contained in:
@@ -432,10 +432,6 @@ impl TableRowLayout for Vector {
|
|||||||
TextLabel::new("Stroke Transform").narrow(true).widget_instance(),
|
TextLabel::new("Stroke Transform").narrow(true).widget_instance(),
|
||||||
TextLabel::new(format_transform_matrix(&stroke.transform)).narrow(true).widget_instance(),
|
TextLabel::new(format_transform_matrix(&stroke.transform)).narrow(true).widget_instance(),
|
||||||
]);
|
]);
|
||||||
table_rows.push(vec![
|
|
||||||
TextLabel::new("Stroke Non-Scaling").narrow(true).widget_instance(),
|
|
||||||
TextLabel::new((if stroke.non_scaling { "Yes" } else { "No" }).to_string()).narrow(true).widget_instance(),
|
|
||||||
]);
|
|
||||||
table_rows.push(vec![
|
table_rows.push(vec![
|
||||||
TextLabel::new("Stroke Paint Order").narrow(true).widget_instance(),
|
TextLabel::new("Stroke Paint Order").narrow(true).widget_instance(),
|
||||||
TextLabel::new(stroke.paint_order.to_string()).narrow(true).widget_instance(),
|
TextLabel::new(stroke.paint_order.to_string()).narrow(true).widget_instance(),
|
||||||
|
|||||||
-1
@@ -515,7 +515,6 @@ fn apply_usvg_stroke(stroke: &usvg::Stroke, modify_inputs: &mut ModifyInputsCont
|
|||||||
align: StrokeAlign::Center,
|
align: StrokeAlign::Center,
|
||||||
paint_order: PaintOrder::StrokeAbove,
|
paint_order: PaintOrder::StrokeAbove,
|
||||||
transform,
|
transform,
|
||||||
non_scaling: false,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,10 +148,6 @@ impl RenderExt for Stroke {
|
|||||||
if let Some(stroke_join_miter_limit) = stroke_join_miter_limit {
|
if let Some(stroke_join_miter_limit) = stroke_join_miter_limit {
|
||||||
let _ = write!(&mut attributes, r#" stroke-miterlimit="{stroke_join_miter_limit}""#);
|
let _ = write!(&mut attributes, r#" stroke-miterlimit="{stroke_join_miter_limit}""#);
|
||||||
}
|
}
|
||||||
// Add vector-effect attribute to make strokes non-scaling
|
|
||||||
if self.non_scaling {
|
|
||||||
let _ = write!(&mut attributes, r#" vector-effect="non-scaling-stroke""#);
|
|
||||||
}
|
|
||||||
if paint_order.is_some() {
|
if paint_order.is_some() {
|
||||||
let _ = write!(&mut attributes, r#" style="paint-order: stroke;" "#);
|
let _ = write!(&mut attributes, r#" style="paint-order: stroke;" "#);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,6 +180,8 @@ pub struct RenderParams {
|
|||||||
pub aligned_strokes: bool,
|
pub aligned_strokes: bool,
|
||||||
pub override_paint_order: bool,
|
pub override_paint_order: bool,
|
||||||
pub artboard_background: Option<Color>,
|
pub artboard_background: Option<Color>,
|
||||||
|
/// Viewport zoom level (document-space scale). Used to compute constant viewport-pixel stroke widths in Outline mode.
|
||||||
|
pub viewport_zoom: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hash for RenderParams {
|
impl Hash for RenderParams {
|
||||||
@@ -197,6 +199,7 @@ impl Hash for RenderParams {
|
|||||||
self.aligned_strokes.hash(state);
|
self.aligned_strokes.hash(state);
|
||||||
self.override_paint_order.hash(state);
|
self.override_paint_order.hash(state);
|
||||||
self.artboard_background.hash(state);
|
self.artboard_background.hash(state);
|
||||||
|
self.viewport_zoom.to_bits().hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1109,7 +1112,7 @@ impl Render for Table<Vector> {
|
|||||||
match render_params.render_mode {
|
match render_params.render_mode {
|
||||||
RenderMode::Outline => {
|
RenderMode::Outline => {
|
||||||
let outline_stroke = kurbo::Stroke {
|
let outline_stroke = kurbo::Stroke {
|
||||||
width: LAYER_OUTLINE_STROKE_WEIGHT,
|
width: LAYER_OUTLINE_STROKE_WEIGHT / if render_params.viewport_zoom > 0. { render_params.viewport_zoom } else { 1. },
|
||||||
miter_limit: 4.,
|
miter_limit: 4.,
|
||||||
join: Join::Miter,
|
join: Join::Miter,
|
||||||
start_cap: Cap::Butt,
|
start_cap: Cap::Butt,
|
||||||
|
|||||||
@@ -309,8 +309,6 @@ pub struct Stroke {
|
|||||||
#[serde(default = "daffine2_identity")]
|
#[serde(default = "daffine2_identity")]
|
||||||
pub transform: DAffine2,
|
pub transform: DAffine2,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub non_scaling: bool,
|
|
||||||
#[serde(default)]
|
|
||||||
pub paint_order: PaintOrder,
|
pub paint_order: PaintOrder,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,7 +326,6 @@ impl std::hash::Hash for Stroke {
|
|||||||
self.join_miter_limit.to_bits().hash(state);
|
self.join_miter_limit.to_bits().hash(state);
|
||||||
self.align.hash(state);
|
self.align.hash(state);
|
||||||
self.transform.to_cols_array().iter().for_each(|x| x.to_bits().hash(state));
|
self.transform.to_cols_array().iter().for_each(|x| x.to_bits().hash(state));
|
||||||
self.non_scaling.hash(state);
|
|
||||||
self.paint_order.hash(state);
|
self.paint_order.hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -345,7 +342,6 @@ impl Stroke {
|
|||||||
join_miter_limit: 4.,
|
join_miter_limit: 4.,
|
||||||
align: StrokeAlign::Center,
|
align: StrokeAlign::Center,
|
||||||
transform: DAffine2::IDENTITY,
|
transform: DAffine2::IDENTITY,
|
||||||
non_scaling: false,
|
|
||||||
paint_order: PaintOrder::StrokeAbove,
|
paint_order: PaintOrder::StrokeAbove,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -364,7 +360,6 @@ impl Stroke {
|
|||||||
time * self.transform.matrix2 + (1. - time) * other.transform.matrix2,
|
time * self.transform.matrix2 + (1. - time) * other.transform.matrix2,
|
||||||
self.transform.translation * time + other.transform.translation * (1. - time),
|
self.transform.translation * time + other.transform.translation * (1. - time),
|
||||||
),
|
),
|
||||||
non_scaling: if time < 0.5 { self.non_scaling } else { other.non_scaling },
|
|
||||||
paint_order: if time < 0.5 { self.paint_order } else { other.paint_order },
|
paint_order: if time < 0.5 { self.paint_order } else { other.paint_order },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -462,11 +457,6 @@ impl Stroke {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_non_scaling(mut self, non_scaling: bool) -> Self {
|
|
||||||
self.non_scaling = non_scaling;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn has_renderable_stroke(&self) -> bool {
|
pub fn has_renderable_stroke(&self) -> bool {
|
||||||
self.weight > 0. && self.color.is_some_and(|color| color.a() != 0.)
|
self.weight > 0. && self.color.is_some_and(|color| color.a() != 0.)
|
||||||
}
|
}
|
||||||
@@ -485,7 +475,6 @@ impl Default for Stroke {
|
|||||||
join_miter_limit: 4.,
|
join_miter_limit: 4.,
|
||||||
align: StrokeAlign::Center,
|
align: StrokeAlign::Center,
|
||||||
transform: DAffine2::IDENTITY,
|
transform: DAffine2::IDENTITY,
|
||||||
non_scaling: false,
|
|
||||||
paint_order: PaintOrder::default(),
|
paint_order: PaintOrder::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
use core_types::table::Table;
|
use core_types::table::Table;
|
||||||
use core_types::transform::Footprint;
|
use core_types::transform::{Footprint, Transform};
|
||||||
use core_types::{CloneVarArgs, ExtractAll, ExtractVarArgs};
|
use core_types::{CloneVarArgs, ExtractAll, ExtractVarArgs};
|
||||||
use core_types::{Color, Context, Ctx, ExtractFootprint, OwnedContextImpl, WasmNotSend};
|
use core_types::{Color, Context, Ctx, ExtractFootprint, OwnedContextImpl, WasmNotSend};
|
||||||
use graph_craft::document::value::RenderOutput;
|
use graph_craft::document::value::RenderOutput;
|
||||||
pub use graph_craft::document::value::RenderOutputType;
|
pub use graph_craft::document::value::RenderOutputType;
|
||||||
pub use graph_craft::wasm_application_io::*;
|
pub use graph_craft::wasm_application_io::*;
|
||||||
use graphene_application_io::{ApplicationIo, ExportFormat, ImageTexture, RenderConfig};
|
use graphene_application_io::{ApplicationIo, ExportFormat, ImageTexture, RenderConfig};
|
||||||
use graphic_types::Artboard;
|
|
||||||
use graphic_types::Graphic;
|
|
||||||
use graphic_types::Vector;
|
|
||||||
use graphic_types::raster_types::Image;
|
use graphic_types::raster_types::Image;
|
||||||
use graphic_types::raster_types::{CPU, Raster};
|
use graphic_types::raster_types::{CPU, Raster};
|
||||||
|
use graphic_types::{Artboard, Graphic, Vector};
|
||||||
use rendering::{Render, RenderOutputType as RenderOutputTypeRequest, RenderParams, RenderSvgSegmentList, SvgRender, format_transform_matrix};
|
use rendering::{Render, RenderOutputType as RenderOutputTypeRequest, RenderParams, RenderSvgSegmentList, SvgRender, format_transform_matrix};
|
||||||
use rendering::{RenderMetadata, SvgSegment};
|
use rendering::{RenderMetadata, SvgSegment};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@@ -110,6 +108,7 @@ async fn create_context<'a: 'n>(
|
|||||||
render_output_type,
|
render_output_type,
|
||||||
footprint: Footprint::default(),
|
footprint: Footprint::default(),
|
||||||
scale: render_config.scale,
|
scale: render_config.scale,
|
||||||
|
viewport_zoom: footprint.decompose_scale().x,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -211,7 +211,6 @@ where
|
|||||||
join_miter_limit: miter_limit,
|
join_miter_limit: miter_limit,
|
||||||
align,
|
align,
|
||||||
transform: DAffine2::IDENTITY,
|
transform: DAffine2::IDENTITY,
|
||||||
non_scaling: false,
|
|
||||||
paint_order,
|
paint_order,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user