mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 14:18:04 +08:00
Bezier-rs: add Tangents/Normals to Point functions (#1547)
* Add tangent/normal to point to bézier-rs * Add license information and general cleanup * Bump version * Add iframe demos --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
committed by
Keavon Chambers
parent
c14c6fbe93
commit
6a10bcc3fc
@@ -39,6 +39,9 @@ class BezierDemo extends HTMLElement implements Demo {
|
||||
|
||||
sliderUnits!: Record<string, string | string[]>;
|
||||
|
||||
// Avoids "recursive use of an object detected which would lead to unsafe aliasing in rust" error when moving mouse fast.
|
||||
locked!: boolean;
|
||||
|
||||
async connectedCallback() {
|
||||
this.title = this.getAttribute("title") || "";
|
||||
this.points = JSON.parse(this.getAttribute("points") || "[]");
|
||||
@@ -85,6 +88,8 @@ class BezierDemo extends HTMLElement implements Demo {
|
||||
}
|
||||
|
||||
onMouseMove(event: MouseEvent) {
|
||||
if (this.locked) return;
|
||||
this.locked = true;
|
||||
const mx = event.offsetX;
|
||||
const my = event.offsetY;
|
||||
const figure = event.currentTarget as HTMLElement;
|
||||
@@ -96,6 +101,7 @@ class BezierDemo extends HTMLElement implements Demo {
|
||||
} else if (this.triggerOnMouseMove) {
|
||||
this.drawDemo(figure, [mx, my]);
|
||||
}
|
||||
this.locked = false;
|
||||
}
|
||||
|
||||
getSliderUnit(sliderValue: number, variable: string): string {
|
||||
|
||||
@@ -126,6 +126,13 @@ const bezierFeatures = {
|
||||
},
|
||||
},
|
||||
},
|
||||
"tangents-to-point": {
|
||||
name: "Tangents To Point",
|
||||
callback: (bezier: WasmBezierInstance, _: Record<string, number>, mouseLocation?: [number, number]): string =>
|
||||
mouseLocation ? bezier.tangents_to_point(mouseLocation[0], mouseLocation[1]) : bezier.to_svg(),
|
||||
triggerOnMouseMove: true,
|
||||
demoOptions: { Linear: { disabled: true } },
|
||||
},
|
||||
normal: {
|
||||
name: "Normal",
|
||||
callback: (bezier: WasmBezierInstance, options: Record<string, number>, _: undefined): string => bezier.normal(options.t, BEZIER_T_VALUE_VARIANTS[options.TVariant]),
|
||||
@@ -135,6 +142,12 @@ const bezierFeatures = {
|
||||
},
|
||||
},
|
||||
},
|
||||
"normals-to-point": {
|
||||
name: "Normals To Point",
|
||||
callback: (bezier: WasmBezierInstance, _: Record<string, number>, mouseLocation?: [number, number]): string =>
|
||||
mouseLocation ? bezier.normals_to_point(mouseLocation[0], mouseLocation[1]) : bezier.to_svg(),
|
||||
triggerOnMouseMove: true,
|
||||
},
|
||||
curvature: {
|
||||
name: "Curvature",
|
||||
callback: (bezier: WasmBezierInstance, options: Record<string, number>, _: undefined): string => bezier.curvature(options.t, BEZIER_T_VALUE_VARIANTS[options.TVariant]),
|
||||
|
||||
@@ -300,6 +300,31 @@ impl WasmBezier {
|
||||
let content = format!("{bezier}{}", draw_line(projected_point.x, projected_point.y, x, y, RED, 1.),);
|
||||
wrap_svg_tag(content)
|
||||
}
|
||||
pub fn tangents_to_point(&self, x: f64, y: f64) -> String {
|
||||
let bezier = self.get_bezier_path();
|
||||
let mut content = String::new();
|
||||
for t in self.0.tangents_to_point(DVec2::new(x, y)) {
|
||||
let point = self.0.evaluate(TValue::Parametric(t));
|
||||
content += &draw_line(x, y, point.x, point.y, RED, 1.);
|
||||
}
|
||||
use std::fmt::Write;
|
||||
write!(content, "{bezier}").unwrap();
|
||||
|
||||
wrap_svg_tag(content)
|
||||
}
|
||||
|
||||
pub fn normals_to_point(&self, x: f64, y: f64) -> String {
|
||||
let bezier = self.get_bezier_path();
|
||||
let mut content = String::new();
|
||||
for t in self.0.normals_to_point(DVec2::new(x, y)) {
|
||||
let point = self.0.evaluate(TValue::Parametric(t));
|
||||
content += &draw_line(x, y, point.x, point.y, RED, 1.);
|
||||
}
|
||||
use std::fmt::Write;
|
||||
write!(content, "{bezier}").unwrap();
|
||||
|
||||
wrap_svg_tag(content)
|
||||
}
|
||||
|
||||
pub fn local_extrema(&self) -> String {
|
||||
let local_extrema: [Vec<f64>; 2] = self.0.local_extrema();
|
||||
|
||||
@@ -4,7 +4,9 @@ mod svg_drawing;
|
||||
mod utils;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
pub static LOGGER: WasmLog = WasmLog;
|
||||
thread_local! { pub static HAS_CRASHED: std::cell::RefCell<bool> = std::cell::RefCell::new(false); }
|
||||
|
||||
/// Initialize the backend
|
||||
#[wasm_bindgen(start)]
|
||||
@@ -12,6 +14,16 @@ pub fn init() {
|
||||
// Set up the logger with a default level of debug
|
||||
log::set_logger(&LOGGER).expect("Failed to set logger");
|
||||
log::set_max_level(log::LevelFilter::Trace);
|
||||
|
||||
fn panic_hook(info: &core::panic::PanicInfo) {
|
||||
// Skip if we have already panicked
|
||||
if HAS_CRASHED.with(|cell| cell.replace(true)) {
|
||||
return;
|
||||
}
|
||||
log::error!("{}", info);
|
||||
}
|
||||
|
||||
std::panic::set_hook(Box::new(panic_hook));
|
||||
}
|
||||
|
||||
/// Logging to the JS console
|
||||
|
||||
Reference in New Issue
Block a user