mirror of
https://github.com/storytold/gridcraft.git
synced 2026-11-05 01:58:58 +00:00
#1786: ink is translucent by its width in points, while drawn and once committed
Addresses CodeRabbit review on #3229, "Use the same translucency threshold as committed ink": the preview judged the pen by its width in points, the committed stroke by its width on screen, so at 50% a 12 pt highlighter turned opaque once committed and at 200% a 6 pt pen turned translucent. Both now use chartview::ink_color, which goes by the stroke's width in points, so the two agree and neither changes with the zoom. Test: ink_render::ink_translucency_follows_the_pen_not_the_zoom. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2fe3bfc077
commit
2adfd5571f
4 files changed
+56
-3
No files matched your search
@@ -316,11 +316,12 @@ pub(crate) fn paint_objects(app: &SheetApp, p: &Painter, geo: &Geo, wb: &Workboo
|
||||
p.add(PathShape::convex_polygon(vec![pos2(r.center().x, r.top()), r.right_bottom(), r.left_bottom()], fill, Stroke::new(1.0, line)));
|
||||
}
|
||||
ShapeKind::Ink => {
|
||||
let w = gridcraft_engine::cmd::draw::ink_width(sp) * geo.z;
|
||||
let pt = gridcraft_engine::cmd::draw::ink_width(sp);
|
||||
let w = pt * geo.z;
|
||||
let pts: Vec<Pos2> =
|
||||
gridcraft_engine::cmd::draw::ink_points(sp).iter().map(|q| pos2(r.left() + q[0] * geo.z, r.top() + q[1] * geo.z)).collect();
|
||||
if pts.len() >= 2 {
|
||||
let col = if w > 8.0 { line.gamma_multiply(0.45) } else { line };
|
||||
let col = ink_color(line, pt);
|
||||
p.add(PathShape::line(pts, PathStroke::new(w, col)));
|
||||
}
|
||||
label = false;
|
||||
@@ -556,3 +557,9 @@ pub fn hit(app: &SheetApp, geo: &Geo, sh: &Sheet, p: Pos2) -> Option<(ObjRef, Re
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// The colour ink is painted in: a highlighter (a stroke over 8 pt wide) is translucent, by its
|
||||
/// width in points, so the live pen stroke and the committed ink agree at every zoom.
|
||||
pub(crate) fn ink_color(line: Color32, width_pt: f32) -> Color32 {
|
||||
if width_pt > 8.0 { line.gamma_multiply(0.45) } else { line }
|
||||
}
|
||||
@@ -257,7 +257,7 @@ pub(crate) fn pen_ink(color: &str, width: f32, theme: &gridcraft_engine::model::
|
||||
let line = gridcraft_engine::model::Color::from_hex(color).unwrap_or(pen_blue);
|
||||
let width = if width <= 0.0 { 2.0 } else { width }.clamp(0.5, 40.0).round().max(1.0);
|
||||
let color = line.resolve(theme).map(crate::theme::color32).unwrap_or(Color32::from_rgb(0x1F, 0x5F, 0xC9));
|
||||
(if width > 8.0 { color.gamma_multiply(0.45) } else { color }, width)
|
||||
(crate::chartview::ink_color(color, width), width)
|
||||
}
|
||||
|
||||
fn handle_header_autofit(app: &mut SheetApp, input: &InteractionInput<'_>) -> bool {
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
//! Committed ink is painted as the pen previews it, at any zoom.
|
||||
|
||||
use egui::Shape;
|
||||
use egui::epaint::ColorMode;
|
||||
use gridcraft_engine::Session;
|
||||
use gridcraft_ui_egui::SheetApp;
|
||||
use serde_json::json;
|
||||
|
||||
/// The colour of the ink stroke drawn from (40, 40) to (200, 40) sheet points, `width` points
|
||||
/// wide: the two-point horizontal path whose width is `width` at its own scale (160 pt long).
|
||||
fn painted_ink(h: &egui_kittest::Harness<'static, SheetApp>, width: f32) -> Option<egui::Color32> {
|
||||
h.output().shapes.iter().find_map(|s| match &s.shape {
|
||||
Shape::Path(p) if p.points.len() == 2 && (p.points[0].y - p.points[1].y).abs() < 0.01 => {
|
||||
let z = (p.points[1].x - p.points[0].x).abs() / 160.0;
|
||||
match p.stroke.color {
|
||||
ColorMode::Solid(c) if z > 0.0 && (p.stroke.width - width * z).abs() < 0.01 => Some(c),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ink_translucency_follows_the_pen_not_the_zoom() {
|
||||
// A highlighter (over 8 pt) is translucent and a pen isn't, whatever the zoom: the committed
|
||||
// stroke used its width on screen, so at 50% a 12 pt highlighter turned opaque and at 200% a
|
||||
// 6 pt pen turned translucent, unlike the pen's preview.
|
||||
for (width, zoom, translucent) in [(12.0_f32, 50, true), (6.0, 200, false), (12.0, 100, true), (6.0, 100, false)] {
|
||||
let mut s = Session::new();
|
||||
s.new_workbook();
|
||||
s.execute("view.zoom", json!({"percent": zoom})).unwrap();
|
||||
s.execute("draw.stroke", json!({"points": [[40, 40], [200, 40]], "color": "#FFFF00", "width": width})).unwrap();
|
||||
let mut h = crate::common::builder().with_size(egui::vec2(1200.0, 800.0)).build_ui_state(
|
||||
|ui, app: &mut SheetApp| {
|
||||
app.logic(&ui.ctx().clone());
|
||||
app.ui(ui);
|
||||
},
|
||||
crate::common::app(s),
|
||||
);
|
||||
h.run_steps(4);
|
||||
let c = painted_ink(&h, width).unwrap_or_else(|| panic!("the {width} pt stroke is painted at {zoom}%"));
|
||||
assert_eq!(c.a() < 255, translucent, "{width} pt at {zoom}%: {c:?}");
|
||||
}
|
||||
}
|
||||
@@ -58,6 +58,7 @@ mod hyperlink_ctrl_click;
|
||||
mod hyperlink_dialog;
|
||||
mod in_cell_editor_size;
|
||||
mod in_cell_editor_wrap;
|
||||
mod ink_render;
|
||||
mod insert_copied_cells;
|
||||
mod interaction;
|
||||
mod interface_scale;
|
||||
|
||||
Reference in new issue
Block a user