diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs
index 9076d0354e..81b0193b43 100644
--- a/editor/src/messages/portfolio/document/document_message_handler.rs
+++ b/editor/src/messages/portfolio/document/document_message_handler.rs
@@ -35,8 +35,11 @@ use graphene_std::raster::BlendMode;
 use graphene_std::raster_types::Raster;
 use graphene_std::table::Table;
 use graphene_std::vector::PointId;
+use graphene_std::vector::algorithms::intersection::bezpath_and_segment_intersections;
 use graphene_std::vector::click_target::{ClickTarget, ClickTargetType};
+use graphene_std::vector::misc::{dvec2_to_point, pathseg_to_points, point_to_dvec2, rect_from_minmax};
 use graphene_std::vector::style::ViewMode;
+use kurbo::{Affine, BezPath, CubicBez, Line, PathSeg, QuadBez, Rect, Shape};
 use std::path::PathBuf;
 use std::time::Duration;
 
@@ -973,6 +976,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
 
 				let viewport_size = ipp.viewport_bounds.size();
 				let viewport_mid = ipp.viewport_bounds.center();
+				let viewport_mid_rect = Rect::new(viewport_mid.x, viewport_mid.y, viewport_mid.x, viewport_mid.y);
 				let [bounds1, bounds2] = if !self.graph_view_overlay_open {
 					self.metadata().document_bounds_viewport_space().unwrap_or([viewport_mid; 2])
 				} else {
@@ -1627,24 +1631,29 @@ impl DocumentMessageHandler {
 		layer_left >= quad_left && layer_right <= quad_right && layer_top <= quad_top && layer_bottom >= quad_bottom
 	}
 
-	pub fn is_layer_fully_inside_polygon(&self, layer: &LayerNodeIdentifier, ipp: &InputPreprocessorMessageHandler, mut viewport_polygon: Subpath<PointId>) -> bool {
+	pub fn is_layer_fully_inside_polygon(&self, layer: &LayerNodeIdentifier, ipp: &InputPreprocessorMessageHandler, mut viewport_polygon: BezPath) -> bool {
 		let document_to_viewport = self.navigation_handler.calculate_offset_transform(ipp.viewport_bounds.center(), &self.document_ptz);
-		viewport_polygon.apply_transform(document_to_viewport.inverse());
+		viewport_polygon.apply_affine(Affine::new(document_to_viewport.to_cols_array()).inverse());
 
 		let layer_click_targets = self.network_interface.document_metadata().click_targets(*layer);
 		let layer_transform = self.network_interface.document_metadata().transform_to_document(*layer);
 
 		layer_click_targets.is_some_and(|targets| {
 			targets.iter().all(|target| match target.target_type() {
-				ClickTargetType::Subpath(subpath) => {
-					let mut subpath = subpath.clone();
-					subpath.apply_transform(layer_transform);
-					subpath.is_inside_subpath(&viewport_polygon, None, None)
+				ClickTargetType::BezPath(bezpath) => {
+					let mut bezpath = bezpath.clone();
+					bezpath.apply_affine(Affine::new(layer_transform.to_cols_array()));
+
+					// TODO: Refactor this into function bezpath_is_inside_bepath()
+					let inside = |segment: PathSeg| pathseg_to_points(segment).iter().filter_map(|point| *point).all(|point| viewport_polygon.contains(point));
+					let intersects = |segment: PathSeg| !bezpath_and_segment_intersections(&viewport_polygon, segment, None, None).is_empty();
+
+					bezpath.segments().all(|segment| inside(segment)) && !bezpath.segments().all(|target_segment| intersects(target_segment))
 				}
 				ClickTargetType::FreePoint(point) => {
 					let mut point = *point;
 					point.apply_transform(layer_transform);
-					viewport_polygon.contains_point(point.position)
+					viewport_polygon.contains(dvec2_to_point(point.position))
 				}
 			})
 		})
@@ -2949,21 +2958,21 @@ fn quad_to_path_lib_segments(quad: Quad) -> Vec<path_bool_lib::PathSegment> {
 }
 
 fn click_targets_to_path_lib_segments<'a>(click_targets: impl Iterator<Item = &'a ClickTarget>, transform: DAffine2) -> Vec<path_bool_lib::PathSegment> {
-	let segment = |bezier: bezier_rs::Bezier| match bezier.handles {
-		bezier_rs::BezierHandles::Linear => path_bool_lib::PathSegment::Line(bezier.start, bezier.end),
-		bezier_rs::BezierHandles::Quadratic { handle } => path_bool_lib::PathSegment::Quadratic(bezier.start, handle, bezier.end),
-		bezier_rs::BezierHandles::Cubic { handle_start, handle_end } => path_bool_lib::PathSegment::Cubic(bezier.start, handle_start, handle_end, bezier.end),
+	let to_path_bool_segment = |segment: PathSeg| match segment {
+		PathSeg::Line(line) => path_bool_lib::PathSegment::Line(point_to_dvec2(line.p0), point_to_dvec2(line.p1)),
+		PathSeg::Quad(quad) => path_bool_lib::PathSegment::Quadratic(point_to_dvec2(quad.p0), point_to_dvec2(quad.p1), point_to_dvec2(quad.p2)),
+		PathSeg::Cubic(cubic) => path_bool_lib::PathSegment::Cubic(point_to_dvec2(cubic.p0), point_to_dvec2(cubic.p1), point_to_dvec2(cubic.p2), point_to_dvec2(cubic.p3)),
 	};
 	click_targets
 		.filter_map(|target| {
-			if let ClickTargetType::Subpath(subpath) = target.target_type() {
-				Some(subpath.iter())
+			if let ClickTargetType::BezPath(subpath) = target.target_type() {
+				Some(subpath.segments())
 			} else {
 				None
 			}
 		})
 		.flatten()
-		.map(|bezier| segment(bezier.apply_transformation(|x| transform.transform_point2(x))))
+		.map(|kurbo_segment| to_path_bool_segment(Affine::new(transform.to_cols_array()) * kurbo_segment))
 		.collect()
 }
 
@@ -2988,14 +2997,15 @@ impl<'a> ClickXRayIter<'a> {
 	fn check_layer_area_target(&mut self, click_targets: Option<&Vec<ClickTarget>>, clip: bool, layer: LayerNodeIdentifier, path: Vec<path_bool_lib::PathSegment>, transform: DAffine2) -> XRayResult {
 		// Convert back to Bezier-rs types for intersections
 		let segment = |bezier: &path_bool_lib::PathSegment| match *bezier {
-			path_bool_lib::PathSegment::Line(start, end) => bezier_rs::Bezier::from_linear_dvec2(start, end),
-			path_bool_lib::PathSegment::Cubic(start, h1, h2, end) => bezier_rs::Bezier::from_cubic_dvec2(start, h1, h2, end),
-			path_bool_lib::PathSegment::Quadratic(start, h1, end) => bezier_rs::Bezier::from_quadratic_dvec2(start, h1, end),
+			path_bool_lib::PathSegment::Line(start, end) => PathSeg::Line(Line::new(dvec2_to_point(start), dvec2_to_point(end))),
+			path_bool_lib::PathSegment::Cubic(start, h1, h2, end) => PathSeg::Cubic(CubicBez::new(dvec2_to_point(start), dvec2_to_point(h1), dvec2_to_point(h2), dvec2_to_point(end))),
+			path_bool_lib::PathSegment::Quadratic(start, h1, end) => PathSeg::Quad(QuadBez::new(dvec2_to_point(start), dvec2_to_point(h1), dvec2_to_point(end))),
 			path_bool_lib::PathSegment::Arc(_, _, _, _, _, _, _) => unimplemented!(),
 		};
-		let get_clip = || path.iter().map(segment);
+		let clip_bezpath = BezPath::from_path_segments(path.iter().map(segment));
 
-		let intersects = click_targets.is_some_and(|targets| targets.iter().any(|target| target.intersect_path(get_clip, transform)));
+		// TODO: Avoid cloning bezpath.
+		let intersects = click_targets.is_some_and(|targets| targets.iter().any(|target| target.intersect_path(clip_bezpath.clone(), transform)));
 		let clicked = intersects;
 		let mut use_children = !clip || intersects;
 
diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs
index e02856bcac..b84ae735a1 100644
--- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs
+++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs
@@ -24,11 +24,9 @@ use bezier_rs::Subpath;
 use glam::{DAffine2, DVec2, IVec2};
 use graph_craft::document::{DocumentNodeImplementation, NodeId, NodeInput};
 use graph_craft::proto::GraphErrors;
-use graphene_std::math::math_ext::QuadExt;
 use graphene_std::vector::misc::subpath_to_kurbo_bezpath;
 use graphene_std::*;
-use kurbo::{Line, Point};
-use renderer::Quad;
+use kurbo::{DEFAULT_ACCURACY, Line, Point, Rect, Shape};
 use std::cmp::Ordering;
 
 #[derive(Debug, ExtractField)]
@@ -1853,8 +1851,8 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
 							log::error!("Could not get transient metadata for node {node_id}");
 							continue;
 						};
-						let quad = Quad::from_box([box_selection_start, box_selection_end_graph]);
-						if click_targets.node_click_target.intersect_path(|| quad.bezier_lines(), DAffine2::IDENTITY) {
+						let quad = Rect::new(box_selection_start.x, box_selection_start.y, box_selection_end_graph.x, box_selection_end_graph.y).to_path(DEFAULT_ACCURACY);
+						if click_targets.node_click_target.intersect_path(quad, DAffine2::IDENTITY) {
 							nodes.insert(node_id);
 						}
 					}
diff --git a/editor/src/messages/portfolio/document/overlays/utility_functions.rs b/editor/src/messages/portfolio/document/overlays/utility_functions.rs
index db94184211..d860d0bcd1 100644
--- a/editor/src/messages/portfolio/document/overlays/utility_functions.rs
+++ b/editor/src/messages/portfolio/document/overlays/utility_functions.rs
@@ -125,7 +125,7 @@ pub fn path_overlays(document: &DocumentMessageHandler, draw_handles: DrawHandle
 		}
 
 		// Get the selected segments and then add a bold line overlay on them
-		for (segment_id, bezier, _, _) in vector.segment_bezier_iter() {
+		for (segment_id, bezier, _, _) in vector.segment_iter() {
 			let Some(selected_shape_state) = shape_editor.selected_shape_state.get_mut(&layer) else {
 				continue;
 			};
diff --git a/editor/src/messages/portfolio/document/overlays/utility_types.rs b/editor/src/messages/portfolio/document/overlays/utility_types.rs
index 4569cda2d8..b9de992823 100644
--- a/editor/src/messages/portfolio/document/overlays/utility_types.rs
+++ b/editor/src/messages/portfolio/document/overlays/utility_types.rs
@@ -13,6 +13,7 @@ use graphene_std::Color;
 use graphene_std::math::quad::Quad;
 use graphene_std::vector::click_target::ClickTargetType;
 use graphene_std::vector::{PointId, SegmentId, Vector};
+use kurbo::PathSeg;
 use std::collections::HashMap;
 use wasm_bindgen::{JsCast, JsValue};
 use web_sys::{OffscreenCanvas, OffscreenCanvasRenderingContext2d};
@@ -788,7 +789,7 @@ impl OverlayContext {
 	}
 
 	/// Used by the path tool segment mode in order to show the selected segments.
-	pub fn outline_select_bezier(&mut self, bezier: Bezier, transform: DAffine2) {
+	pub fn outline_select_bezier(&mut self, bezier: PathSeg, transform: DAffine2) {
 		self.start_dpi_aware_transform();
 
 		self.render_context.begin_path();
@@ -885,13 +886,13 @@ impl OverlayContext {
 
 	/// Used by the Select tool to outline a path or a free point when selected or hovered.
 	pub fn outline(&mut self, target_types: impl Iterator<Item = impl Borrow<ClickTargetType>>, transform: DAffine2, color: Option<&str>) {
-		let mut subpaths: Vec<bezier_rs::Subpath<PointId>> = vec![];
+		let mut subpaths: Vec<Bezpath> = vec![];
 
 		target_types.for_each(|target_type| match target_type.borrow() {
 			ClickTargetType::FreePoint(point) => {
 				self.manipulator_anchor(transform.transform_point2(point.position), false, None);
 			}
-			ClickTargetType::Subpath(subpath) => subpaths.push(subpath.clone()),
+			ClickTargetType::BezPath(subpath) => subpaths.push(subpath.clone()),
 		});
 
 		if !subpaths.is_empty() {
diff --git a/editor/src/messages/portfolio/document/overlays/utility_types_vello.rs b/editor/src/messages/portfolio/document/overlays/utility_types_vello.rs
index 2d1d5d0b6e..7a26e4588d 100644
--- a/editor/src/messages/portfolio/document/overlays/utility_types_vello.rs
+++ b/editor/src/messages/portfolio/document/overlays/utility_types_vello.rs
@@ -4,14 +4,15 @@ use crate::consts::{
 	PIVOT_CROSSHAIR_LENGTH, PIVOT_CROSSHAIR_THICKNESS, PIVOT_DIAMETER,
 };
 use crate::messages::prelude::Message;
-use bezier_rs::{Bezier, Subpath};
 use core::borrow::Borrow;
 use core::f64::consts::{FRAC_PI_2, PI, TAU};
 use glam::{DAffine2, DVec2};
 use graphene_std::Color;
 use graphene_std::math::quad::Quad;
 use graphene_std::vector::click_target::ClickTargetType;
+use graphene_std::vector::misc::{is_bezpath_closed, point_to_dvec2};
 use graphene_std::vector::{PointId, SegmentId, Vector};
+use kurbo::{Affine, ParamCurve, PathSeg};
 use std::collections::HashMap;
 use std::sync::{Arc, Mutex, MutexGuard};
 use vello::Scene;
@@ -343,17 +344,17 @@ impl OverlayContext {
 	}
 
 	/// Used by the Pen tool in order to show how the bezier curve would look like.
-	pub fn outline_bezier(&mut self, bezier: Bezier, transform: DAffine2) {
-		self.internal().outline_bezier(bezier, transform);
+	pub fn outline_bezier(&mut self, segment: PathSeg, transform: DAffine2) {
+		self.internal().outline_bezier(segment, transform);
 	}
 
 	/// Used by the path tool segment mode in order to show the selected segments.
-	pub fn outline_select_bezier(&mut self, bezier: Bezier, transform: DAffine2) {
-		self.internal().outline_select_bezier(bezier, transform);
+	pub fn outline_select_bezier(&mut self, segment: PathSeg, transform: DAffine2) {
+		self.internal().outline_select_bezier(segment, transform);
 	}
 
-	pub fn outline_overlay_bezier(&mut self, bezier: Bezier, transform: DAffine2) {
-		self.internal().outline_overlay_bezier(bezier, transform);
+	pub fn outline_overlay_bezier(&mut self, segment: PathSeg, transform: DAffine2) {
+		self.internal().outline_overlay_bezier(segment, transform);
 	}
 
 	/// Used by the Select tool to outline a path or a free point when selected or hovered.
@@ -363,14 +364,14 @@ impl OverlayContext {
 
 	/// Fills the area inside the path. Assumes `color` is in gamma space.
 	/// Used by the Pen tool to show the path being closed.
-	pub fn fill_path(&mut self, subpaths: impl Iterator<Item = impl Borrow<Subpath<PointId>>>, transform: DAffine2, color: &str) {
-		self.internal().fill_path(subpaths, transform, color);
+	pub fn fill_path(&mut self, bezpaths: impl Iterator<Item = impl Borrow<BezPath>>, transform: DAffine2, color: &str) {
+		self.internal().fill_path(bezpaths, transform, color);
 	}
 
 	/// Fills the area inside the path with a pattern. Assumes `color` is in gamma space.
 	/// Used by the fill tool to show the area to be filled.
-	pub fn fill_path_pattern(&mut self, subpaths: impl Iterator<Item = impl Borrow<Subpath<PointId>>>, transform: DAffine2, color: &Color) {
-		self.internal().fill_path_pattern(subpaths, transform, color);
+	pub fn fill_path_pattern(&mut self, bezpaths: impl Iterator<Item = impl Borrow<BezPath>>, transform: DAffine2, color: &Color) {
+		self.internal().fill_path_pattern(bezpaths, transform, color);
 	}
 
 	pub fn get_width(&self, text: &str) -> f64 {
@@ -839,18 +840,18 @@ impl OverlayContextInternal {
 		let mut path = BezPath::new();
 
 		let mut last_point = None;
-		for (_, bezier, start_id, end_id) in vector.segment_bezier_iter() {
+		for (_, segment, start_id, end_id) in vector.segment_iter() {
 			let move_to = last_point != Some(start_id);
 			last_point = Some(end_id);
 
-			self.bezier_to_path(bezier, transform, move_to, &mut path);
+			self.bezier_to_path(segment, transform, move_to, &mut path);
 		}
 
 		self.scene.stroke(&kurbo::Stroke::new(1.0), vello_transform, Self::parse_color(COLOR_OVERLAY_BLUE), None, &path);
 	}
 
 	/// Used by the Pen tool in order to show how the bezier curve would look like.
-	fn outline_bezier(&mut self, bezier: Bezier, transform: DAffine2) {
+	fn outline_bezier(&mut self, bezier: PathSeg, transform: DAffine2) {
 		let vello_transform = self.get_transform();
 		let mut path = BezPath::new();
 		self.bezier_to_path(bezier, transform, true, &mut path);
@@ -859,7 +860,7 @@ impl OverlayContextInternal {
 	}
 
 	/// Used by the path tool segment mode in order to show the selected segments.
-	fn outline_select_bezier(&mut self, bezier: Bezier, transform: DAffine2) {
+	fn outline_select_bezier(&mut self, bezier: PathSeg, transform: DAffine2) {
 		let vello_transform = self.get_transform();
 		let mut path = BezPath::new();
 		self.bezier_to_path(bezier, transform, true, &mut path);
@@ -867,7 +868,7 @@ impl OverlayContextInternal {
 		self.scene.stroke(&kurbo::Stroke::new(4.0), vello_transform, Self::parse_color(COLOR_OVERLAY_BLUE), None, &path);
 	}
 
-	fn outline_overlay_bezier(&mut self, bezier: Bezier, transform: DAffine2) {
+	fn outline_overlay_bezier(&mut self, bezier: PathSeg, transform: DAffine2) {
 		let vello_transform = self.get_transform();
 		let mut path = BezPath::new();
 		self.bezier_to_path(bezier, transform, true, &mut path);
@@ -875,55 +876,46 @@ impl OverlayContextInternal {
 		self.scene.stroke(&kurbo::Stroke::new(4.0), vello_transform, Self::parse_color(COLOR_OVERLAY_BLUE_50), None, &path);
 	}
 
-	fn bezier_to_path(&self, bezier: Bezier, transform: DAffine2, move_to: bool, path: &mut BezPath) {
-		let Bezier { start, end, handles } = bezier.apply_transformation(|point| transform.transform_point2(point));
+	fn bezier_to_path(&self, bezier: PathSeg, transform: DAffine2, move_to: bool, path: &mut BezPath) {
+		let segment = Affine::new(transform.to_cols_array()) * bezier;
 		if move_to {
-			path.move_to(kurbo::Point::new(start.x, start.y));
-		}
-
-		match handles {
-			bezier_rs::BezierHandles::Linear => path.line_to(kurbo::Point::new(end.x, end.y)),
-			bezier_rs::BezierHandles::Quadratic { handle } => path.quad_to(kurbo::Point::new(handle.x, handle.y), kurbo::Point::new(end.x, end.y)),
-			bezier_rs::BezierHandles::Cubic { handle_start, handle_end } => path.curve_to(
-				kurbo::Point::new(handle_start.x, handle_start.y),
-				kurbo::Point::new(handle_end.x, handle_end.y),
-				kurbo::Point::new(end.x, end.y),
-			),
+			path.move_to(segment.start());
 		}
+		path.push(segment.as_path_el());
 	}
 
-	fn push_path(&mut self, subpaths: impl Iterator<Item = impl Borrow<Subpath<PointId>>>, transform: DAffine2) -> BezPath {
+	fn push_path(&mut self, bezpaths: impl Iterator<Item = impl Borrow<BezPath>>, transform: DAffine2) -> BezPath {
 		let mut path = BezPath::new();
 
-		for subpath in subpaths {
-			let subpath = subpath.borrow();
-			let mut curves = subpath.iter().peekable();
+		for bezpath in bezpaths {
+			let bezpath = bezpath.borrow();
+			let mut segments = bezpath.segments().peekable();
 
-			let Some(first) = curves.peek() else {
+			let Some(first) = segments.peek() else {
 				continue;
 			};
 
-			let start_point = transform.transform_point2(first.start());
+			let start_point = transform.transform_point2(point_to_dvec2(first.start()));
 			path.move_to(kurbo::Point::new(start_point.x, start_point.y));
 
-			for curve in curves {
-				match curve.handles {
-					bezier_rs::BezierHandles::Linear => {
-						let a = transform.transform_point2(curve.end());
+			for segment in segments {
+				match segment {
+					PathSeg::Line(line) => {
+						let a = transform.transform_point2(point_to_dvec2(line.p1));
 						let a = a.round() - DVec2::splat(0.5);
 						path.line_to(kurbo::Point::new(a.x, a.y));
 					}
-					bezier_rs::BezierHandles::Quadratic { handle } => {
-						let a = transform.transform_point2(handle);
-						let b = transform.transform_point2(curve.end());
+					PathSeg::Quad(quad_bez) => {
+						let a = transform.transform_point2(point_to_dvec2(quad_bez.p1));
+						let b = transform.transform_point2(point_to_dvec2(quad_bez.p2));
 						let a = a.round() - DVec2::splat(0.5);
 						let b = b.round() - DVec2::splat(0.5);
 						path.quad_to(kurbo::Point::new(a.x, a.y), kurbo::Point::new(b.x, b.y));
 					}
-					bezier_rs::BezierHandles::Cubic { handle_start, handle_end } => {
-						let a = transform.transform_point2(handle_start);
-						let b = transform.transform_point2(handle_end);
-						let c = transform.transform_point2(curve.end());
+					PathSeg::Cubic(cubic_bez) => {
+						let a = transform.transform_point2(point_to_dvec2(cubic_bez.p1));
+						let b = transform.transform_point2(point_to_dvec2(cubic_bez.p2));
+						let c = transform.transform_point2(point_to_dvec2(cubic_bez.p3));
 						let a = a.round() - DVec2::splat(0.5);
 						let b = b.round() - DVec2::splat(0.5);
 						let c = c.round() - DVec2::splat(0.5);
@@ -932,7 +924,7 @@ impl OverlayContextInternal {
 				}
 			}
 
-			if subpath.closed() {
+			if is_bezpath_closed(bezpath) {
 				path.close_path();
 			}
 		}
@@ -942,14 +934,14 @@ impl OverlayContextInternal {
 
 	/// Used by the Select tool to outline a path or a free point when selected or hovered.
 	fn outline(&mut self, target_types: impl Iterator<Item = impl Borrow<ClickTargetType>>, transform: DAffine2, color: Option<&str>) {
-		let mut subpaths: Vec<bezier_rs::Subpath<PointId>> = vec![];
+		let mut subpaths: Vec<BezPath> = vec![];
 
 		for target_type in target_types {
 			match target_type.borrow() {
 				ClickTargetType::FreePoint(point) => {
 					self.manipulator_anchor(transform.transform_point2(point.position), false, None);
 				}
-				ClickTargetType::Subpath(subpath) => subpaths.push(subpath.clone()),
+				ClickTargetType::BezPath(subpath) => subpaths.push(subpath.clone()),
 			}
 		}
 
@@ -963,18 +955,18 @@ impl OverlayContextInternal {
 
 	/// Fills the area inside the path. Assumes `color` is in gamma space.
 	/// Used by the Pen tool to show the path being closed.
-	fn fill_path(&mut self, subpaths: impl Iterator<Item = impl Borrow<Subpath<PointId>>>, transform: DAffine2, color: &str) {
-		let path = self.push_path(subpaths, transform);
+	fn fill_path(&mut self, bezpaths: impl Iterator<Item = impl Borrow<BezPath>>, transform: DAffine2, color: &str) {
+		let path = self.push_path(bezpaths, transform);
 
 		self.scene.fill(peniko::Fill::NonZero, self.get_transform(), Self::parse_color(color), None, &path);
 	}
 
 	/// Fills the area inside the path with a pattern. Assumes `color` is in gamma space.
 	/// Used by the fill tool to show the area to be filled.
-	fn fill_path_pattern(&mut self, subpaths: impl Iterator<Item = impl Borrow<Subpath<PointId>>>, transform: DAffine2, color: &Color) {
+	fn fill_path_pattern(&mut self, bezpaths: impl Iterator<Item = impl Borrow<BezPath>>, transform: DAffine2, color: &Color) {
 		// TODO: Implement pattern fill in Vello
 		// For now, just fill with a semi-transparent version of the color
-		let path = self.push_path(subpaths, transform);
+		let path = self.push_path(bezpaths, transform);
 		let semi_transparent_color = color.with_alpha(0.5);
 
 		self.scene.fill(
diff --git a/editor/src/messages/portfolio/document/utility_types/document_metadata.rs b/editor/src/messages/portfolio/document/utility_types/document_metadata.rs
index 34ac029599..04a401fa2b 100644
--- a/editor/src/messages/portfolio/document/utility_types/document_metadata.rs
+++ b/editor/src/messages/portfolio/document/utility_types/document_metadata.rs
@@ -5,10 +5,12 @@ use crate::messages::portfolio::document::utility_types::network_interface::Flow
 use crate::messages::tool::common_functionality::graph_modification_utils;
 use glam::{DAffine2, DVec2};
 use graph_craft::document::NodeId;
-use graphene_std::math::quad::Quad;
+use graphene_std::renderer::Quad;
 use graphene_std::transform::Footprint;
+use graphene_std::vector::Vector;
 use graphene_std::vector::click_target::{ClickTarget, ClickTargetType};
-use graphene_std::vector::{PointId, Vector};
+use graphene_std::vector::misc::{rect_to_minmax, transform_rect};
+use kurbo::{BezPath, Shape};
 use std::collections::{HashMap, HashSet};
 use std::num::NonZeroU64;
 
@@ -154,7 +156,7 @@ impl DocumentMetadata {
 		self.click_targets(layer)?
 			.iter()
 			.filter_map(|click_target| match click_target.target_type() {
-				ClickTargetType::Subpath(subpath) => subpath.bounding_box_with_transform(transform),
+				ClickTargetType::BezPath(bezpath) => Some(rect_to_minmax(transform_rect(bezpath.bounding_box(), transform))),
 				ClickTargetType::FreePoint(_) => click_target.bounding_box_with_transform(transform),
 			})
 			.reduce(Quad::combine_bounds)
@@ -196,11 +198,11 @@ impl DocumentMetadata {
 		self.all_layers().filter_map(|layer| self.bounding_box_viewport(layer)).reduce(Quad::combine_bounds)
 	}
 
-	pub fn layer_outline(&self, layer: LayerNodeIdentifier) -> impl Iterator<Item = &bezier_rs::Subpath<PointId>> {
+	pub fn layer_outline(&self, layer: LayerNodeIdentifier) -> impl Iterator<Item = &BezPath> {
 		static EMPTY: Vec<ClickTarget> = Vec::new();
 		let click_targets = self.click_targets.get(&layer).unwrap_or(&EMPTY);
 		click_targets.iter().filter_map(|target| match target.target_type() {
-			ClickTargetType::Subpath(subpath) => Some(subpath),
+			ClickTargetType::BezPath(subpath) => Some(subpath),
 			_ => None,
 		})
 	}
diff --git a/editor/src/messages/portfolio/document/utility_types/network_interface.rs b/editor/src/messages/portfolio/document/utility_types/network_interface.rs
index 5d46f10401..870dd4929d 100644
--- a/editor/src/messages/portfolio/document/utility_types/network_interface.rs
+++ b/editor/src/messages/portfolio/document/utility_types/network_interface.rs
@@ -18,9 +18,11 @@ use graphene_std::math::quad::Quad;
 use graphene_std::table::Table;
 use graphene_std::transform::Footprint;
 use graphene_std::vector::click_target::{ClickTarget, ClickTargetType};
+use graphene_std::vector::misc::{combine_rect, rect_from_minmax, rect_to_minmax};
 use graphene_std::vector::{PointId, Vector, VectorModificationType};
 use interpreted_executor::dynamic_executor::ResolvedDocumentNodeTypes;
 use interpreted_executor::node_registry::NODE_REGISTRY;
+use kurbo::{DEFAULT_ACCURACY, Ellipse, Rect, Shape};
 use serde_json::{Value, json};
 use std::collections::{HashMap, HashSet, VecDeque};
 use std::hash::{DefaultHasher, Hash, Hasher};
@@ -2095,10 +2097,12 @@ impl NodeNetworkInterface {
 			let bounding_box_top_right = DVec2::new((all_nodes_bounding_box[1].x / 24. + 0.5).floor() * 24., (all_nodes_bounding_box[0].y / 24. + 0.5).floor() * 24.) + offset_from_top_right;
 			let export_top_right: DVec2 = DVec2::new(viewport_top_right.x.max(bounding_box_top_right.x), viewport_top_right.y.min(bounding_box_top_right.y));
 			let add_export_center = export_top_right + DVec2::new(0., network.exports.len() as f64 * 24.);
-			let add_export = ClickTarget::new_with_subpath(
-				Subpath::new_rounded_rect(add_export_center - DVec2::new(12., 12.), add_export_center + DVec2::new(12., 12.), [3.; 4]),
-				0.,
-			);
+
+			let (corner1, corner2, radii) = (add_export_center - DVec2::new(12., 12.), add_export_center + DVec2::new(12., 12.), 3.);
+			let rounded_rect = Rect::new(corner1.x, corner1.y, corner2.x, corner2.y).to_rounded_rect(radii).to_path(DEFAULT_ACCURACY);
+
+			let add_export = ClickTarget::new_with_bezpath(rounded_rect, 0.);
+
 			add_import_export.insert_custom_input_port(0, add_export);
 
 			let viewport_top_left = network_metadata
@@ -2121,10 +2125,11 @@ impl NodeNetworkInterface {
 			let bounding_box_top_left = DVec2::new((all_nodes_bounding_box[0].x / 24. + 0.5).floor() * 24., (all_nodes_bounding_box[0].y / 24. + 0.5).floor() * 24.) + offset_from_top_left;
 			let import_top_left = DVec2::new(viewport_top_left.x.min(bounding_box_top_left.x), viewport_top_left.y.min(bounding_box_top_left.y));
 			let add_import_center = import_top_left + DVec2::new(0., self.number_of_displayed_imports(network_path) as f64 * 24.);
-			let add_import = ClickTarget::new_with_subpath(
-				Subpath::new_rounded_rect(add_import_center - DVec2::new(12., 12.), add_import_center + DVec2::new(12., 12.), [3.; 4]),
-				0.,
-			);
+
+			let (corner1, corner2, radii) = (add_import_center - DVec2::new(12., 12.), add_import_center + DVec2::new(12., 12.), 3.);
+			let rounded_rect = Rect::new(corner1.x, corner1.y, corner2.x, corner2.y).to_rounded_rect(radii).to_path(DEFAULT_ACCURACY);
+
+			let add_import = ClickTarget::new_with_bezpath(rounded_rect, 0.);
 			add_import_export.insert_custom_output_port(0, add_import);
 
 			let Some(import_exports) = self.import_export_ports(network_path) else {
@@ -2140,8 +2145,17 @@ impl NodeNetworkInterface {
 				let reorder_import_center = (import_bounding_box[0] + import_bounding_box[1]) / 2. + DVec2::new(-12., 0.);
 				let remove_import_center = reorder_import_center + DVec2::new(-12., 0.);
 
-				let reorder_import = ClickTarget::new_with_subpath(Subpath::new_rect(reorder_import_center - DVec2::new(3., 4.), reorder_import_center + DVec2::new(3., 4.)), 0.);
-				let remove_import = ClickTarget::new_with_subpath(Subpath::new_rect(remove_import_center - DVec2::new(8., 8.), remove_import_center + DVec2::new(8., 8.)), 0.);
+				let corner1 = reorder_import_center - DVec2::new(3., 4.);
+				let corner2 = reorder_import_center + DVec2::new(3., 4.);
+				let rect = Rect::new(corner1.x, corner1.y, corner2.x, corner2.y).to_path(DEFAULT_ACCURACY);
+
+				let reorder_import = ClickTarget::new_with_bezpath(rect, 0.);
+
+				let corner1 = remove_import_center - DVec2::new(8., 8.);
+				let corner2 = remove_import_center + DVec2::new(8., 8.);
+				let rect = Rect::new(corner1.x, corner1.y, corner2.x, corner2.y).to_path(DEFAULT_ACCURACY);
+
+				let remove_import = ClickTarget::new_with_bezpath(rect, 0.);
 
 				reorder_imports_exports.insert_custom_output_port(*import_index, reorder_import);
 				remove_imports_exports.insert_custom_output_port(*import_index, remove_import);
@@ -2155,8 +2169,17 @@ impl NodeNetworkInterface {
 				let reorder_export_center = (export_bounding_box[0] + export_bounding_box[1]) / 2. + DVec2::new(12., 0.);
 				let remove_export_center = reorder_export_center + DVec2::new(12., 0.);
 
-				let reorder_export = ClickTarget::new_with_subpath(Subpath::new_rect(reorder_export_center - DVec2::new(3., 4.), reorder_export_center + DVec2::new(3., 4.)), 0.);
-				let remove_export = ClickTarget::new_with_subpath(Subpath::new_rect(remove_export_center - DVec2::new(8., 8.), remove_export_center + DVec2::new(8., 8.)), 0.);
+				let corner1 = reorder_export_center - DVec2::new(3., 4.);
+				let corner2 = reorder_export_center + DVec2::new(3., 4.);
+				let reorder_rect = Rect::new(corner1.x, corner1.y, corner2.x, corner2.y).to_path(DEFAULT_ACCURACY);
+
+				let reorder_export = ClickTarget::new_with_bezpath(reorder_rect, 0.);
+
+				let corner1 = remove_export_center - DVec2::new(8., 8.);
+				let corner2 = remove_export_center + DVec2::new(8., 8.);
+				let remove_rect = Rect::new(corner1.x, corner1.y, corner2.x, corner2.y).to_path(DEFAULT_ACCURACY);
+
+				let remove_export = ClickTarget::new_with_bezpath(remove_rect, 0.);
 
 				reorder_imports_exports.insert_custom_input_port(*export_index, reorder_export);
 				remove_imports_exports.insert_custom_input_port(*export_index, remove_export);
@@ -2787,6 +2810,7 @@ impl NodeNetworkInterface {
 		Some(click_target)
 	}
 
+	// REFACTOR
 	pub fn load_node_click_targets(&mut self, node_id: &NodeId, network_path: &[NodeId]) {
 		let Some(node_position) = self.position_from_downstream_node(node_id, network_path) else {
 			log::error!("Could not get node position in load_node_click_targets for node {node_id}");
@@ -2833,8 +2857,16 @@ impl NodeNetworkInterface {
 			let node_click_target_bottom_right = node_click_target_top_left + DVec2::new(width as f64, height as f64);
 
 			let radius = 3.;
-			let subpath = bezier_rs::Subpath::new_rounded_rect(node_click_target_top_left, node_click_target_bottom_right, [radius; 4]);
-			let node_click_target = ClickTarget::new_with_subpath(subpath, 0.);
+			let rounded_rect = Rect::new(
+				node_click_target_top_left.x,
+				node_click_target_top_left.y,
+				node_click_target_bottom_right.x,
+				node_click_target_bottom_right.y,
+			)
+			.to_rounded_rect(radius)
+			.to_path(DEFAULT_ACCURACY);
+
+			let node_click_target = ClickTarget::new_with_bezpath(rounded_rect, 0.);
 
 			DocumentNodeClickTargets {
 				node_click_target,
@@ -2858,13 +2890,21 @@ impl NodeNetworkInterface {
 
 			// Update visibility button click target
 			let visibility_offset = node_top_left + DVec2::new(width as f64, 24.);
-			let subpath = Subpath::new_rounded_rect(DVec2::new(-12., -12.) + visibility_offset, DVec2::new(12., 12.) + visibility_offset, [3.; 4]);
-			let visibility_click_target = ClickTarget::new_with_subpath(subpath, 0.);
+
+			let corner1 = DVec2::new(-12., -12.) + visibility_offset;
+			let corner2 = DVec2::new(12., 12.) + visibility_offset;
+			let rounded_rect = Rect::new(corner1.x, corner1.y, corner2.x, corner2.y).to_rounded_rect(3.).to_path(DEFAULT_ACCURACY);
+
+			let visibility_click_target = ClickTarget::new_with_bezpath(rounded_rect, 0.);
 
 			// Update grip button click target, which is positioned to the left of the left most icon
 			let grip_offset_right_edge = node_top_left + DVec2::new(width as f64 - (GRID_SIZE as f64) / 2., 24.);
-			let subpath = Subpath::new_rounded_rect(DVec2::new(-8., -12.) + grip_offset_right_edge, DVec2::new(0., 12.) + grip_offset_right_edge, [0.; 4]);
-			let grip_click_target = ClickTarget::new_with_subpath(subpath, 0.);
+
+			let corner1 = DVec2::new(-8., -12.) + grip_offset_right_edge;
+			let corner2 = DVec2::new(0., 12.) + grip_offset_right_edge;
+			let rounded_rect = Rect::new(corner1.x, corner1.y, corner2.x, corner2.y).to_rounded_rect(0.).to_path(DEFAULT_ACCURACY);
+
+			let grip_click_target = ClickTarget::new_with_bezpath(rounded_rect, 0.);
 
 			// Create layer click target, which is contains the layer and the chain background
 			let chain_width_grid_spaces = self.chain_width(node_id, network_path);
@@ -2872,8 +2912,12 @@ impl NodeNetworkInterface {
 			let node_bottom_right = node_top_left + DVec2::new(width as f64, height as f64);
 			let chain_top_left = node_top_left - DVec2::new((chain_width_grid_spaces * crate::consts::GRID_SIZE) as f64, 0.);
 			let radius = 10.;
-			let subpath = bezier_rs::Subpath::new_rounded_rect(chain_top_left, node_bottom_right, [radius; 4]);
-			let node_click_target = ClickTarget::new_with_subpath(subpath, 0.);
+
+			let rounded_rect = Rect::new(chain_top_left.x, chain_top_left.y, node_bottom_right.x, node_bottom_right.y)
+				.to_rounded_rect(radius)
+				.to_path(DEFAULT_ACCURACY);
+
+			let node_click_target = ClickTarget::new_with_bezpath(rounded_rect, 0.);
 
 			DocumentNodeClickTargets {
 				node_click_target,
@@ -3059,28 +3103,22 @@ impl NodeNetworkInterface {
 			if let (Some(import_export_click_targets), Some(node_click_targets)) = (self.import_export_ports(network_path).cloned(), self.node_click_targets(&node_id, network_path)) {
 				let mut node_path = String::new();
 
-				if let ClickTargetType::Subpath(subpath) = node_click_targets.node_click_target.target_type() {
-					let _ = subpath.subpath_to_svg(&mut node_path, DAffine2::IDENTITY);
+				if let ClickTargetType::BezPath(subpath) = node_click_targets.node_click_target.target_type() {
+					node_path.push_str(&subpath.to_svg());
 				}
 				all_node_click_targets.push((node_id, node_path));
 				for port in node_click_targets.port_click_targets.click_targets().chain(import_export_click_targets.click_targets()) {
-					if let ClickTargetType::Subpath(subpath) = port.target_type() {
-						let mut port_path = String::new();
-						let _ = subpath.subpath_to_svg(&mut port_path, DAffine2::IDENTITY);
-						port_click_targets.push(port_path);
+					if let ClickTargetType::BezPath(subpath) = port.target_type() {
+						port_click_targets.push(subpath.to_svg());
 					}
 				}
 				if let NodeTypeClickTargets::Layer(layer_metadata) = &node_click_targets.node_type_metadata {
-					if let ClickTargetType::Subpath(subpath) = layer_metadata.visibility_click_target.target_type() {
-						let mut port_path = String::new();
-						let _ = subpath.subpath_to_svg(&mut port_path, DAffine2::IDENTITY);
-						icon_click_targets.push(port_path);
+					if let ClickTargetType::BezPath(subpath) = layer_metadata.visibility_click_target.target_type() {
+						icon_click_targets.push(subpath.to_svg());
 					}
 
-					if let ClickTargetType::Subpath(subpath) = layer_metadata.grip_click_target.target_type() {
-						let mut port_path = String::new();
-						let _ = subpath.subpath_to_svg(&mut port_path, DAffine2::IDENTITY);
-						icon_click_targets.push(port_path);
+					if let ClickTargetType::BezPath(subpath) = layer_metadata.grip_click_target.target_type() {
+						icon_click_targets.push(subpath.to_svg());
 					}
 				}
 			}
@@ -3136,10 +3174,8 @@ impl NodeNetworkInterface {
 				.chain(modify_import_export_click_targets.remove_imports_exports.click_targets())
 				.chain(modify_import_export_click_targets.reorder_imports_exports.click_targets())
 			{
-				if let ClickTargetType::Subpath(subpath) = click_target.target_type() {
-					let mut remove_string = String::new();
-					let _ = subpath.subpath_to_svg(&mut remove_string, DAffine2::IDENTITY);
-					modify_import_export.push(remove_string);
+				if let ClickTargetType::BezPath(bezpath) = click_target.target_type() {
+					modify_import_export.push(bezpath.to_svg());
 				}
 			}
 		}
@@ -6217,8 +6253,10 @@ impl Ports {
 	}
 
 	fn insert_input_port_at_center(&mut self, input_index: usize, center: DVec2) {
-		let subpath = Subpath::new_ellipse(center - DVec2::new(8., 8.), center + DVec2::new(8., 8.));
-		self.insert_custom_input_port(input_index, ClickTarget::new_with_subpath(subpath, 0.));
+		let corner1 = center - DVec2::new(8., 8.);
+		let corner2 = center + DVec2::new(8., 8.);
+		let bezpath = Ellipse::from_rect(Rect::new(corner1.x, corner1.y, corner2.x, corner2.y)).to_path(DEFAULT_ACCURACY);
+		self.insert_custom_input_port(input_index, ClickTarget::new_with_bezpath(bezpath, 0.));
 	}
 
 	fn insert_custom_input_port(&mut self, input_index: usize, click_target: ClickTarget) {
@@ -6226,8 +6264,10 @@ impl Ports {
 	}
 
 	fn insert_output_port_at_center(&mut self, output_index: usize, center: DVec2) {
-		let subpath = Subpath::new_ellipse(center - DVec2::new(8., 8.), center + DVec2::new(8., 8.));
-		self.insert_custom_output_port(output_index, ClickTarget::new_with_subpath(subpath, 0.));
+		let corner1 = center - DVec2::new(8., 8.);
+		let corner2 = center + DVec2::new(8., 8.);
+		let bezpath = Ellipse::from_rect(Rect::new(corner1.x, corner1.y, corner2.x, corner2.y)).to_path(DEFAULT_ACCURACY);
+		self.insert_custom_output_port(output_index, ClickTarget::new_with_bezpath(bezpath, 0.));
 	}
 
 	fn insert_custom_output_port(&mut self, output_index: usize, click_target: ClickTarget) {
diff --git a/editor/src/messages/portfolio/document/utility_types/transformation.rs b/editor/src/messages/portfolio/document/utility_types/transformation.rs
index 36d7d734ad..8052150513 100644
--- a/editor/src/messages/portfolio/document/utility_types/transformation.rs
+++ b/editor/src/messages/portfolio/document/utility_types/transformation.rs
@@ -8,8 +8,9 @@ use crate::messages::tool::common_functionality::shape_editor::ShapeState;
 use crate::messages::tool::utility_types::ToolType;
 use glam::{DAffine2, DMat2, DVec2};
 use graphene_std::renderer::Quad;
-use graphene_std::vector::misc::{HandleId, ManipulatorPointId};
+use graphene_std::vector::misc::{HandleId, ManipulatorPointId, combine_rect, point_to_dvec2, transform_rect};
 use graphene_std::vector::{HandleExt, PointId, VectorModificationType};
+use kurbo::Rect;
 use std::collections::{HashMap, VecDeque};
 use std::f64::consts::PI;
 
diff --git a/editor/src/messages/tool/common_functionality/shape_editor.rs b/editor/src/messages/tool/common_functionality/shape_editor.rs
index 45a1740f91..4da8b1324d 100644
--- a/editor/src/messages/tool/common_functionality/shape_editor.rs
+++ b/editor/src/messages/tool/common_functionality/shape_editor.rs
@@ -13,8 +13,9 @@ use crate::messages::tool::common_functionality::utility_functions::{is_intersec
 use crate::messages::tool::tool_messages::path_tool::{PathOverlayMode, PointSelectState};
 use bezier_rs::{Bezier, BezierHandles, Subpath, TValue};
 use glam::{DAffine2, DVec2};
-use graphene_std::vector::misc::{HandleId, ManipulatorPointId};
+use graphene_std::vector::misc::{HandleId, ManipulatorPointId, handles_to_segment};
 use graphene_std::vector::{HandleExt, PointId, SegmentId, Vector, VectorModificationType};
+use kurbo::PathSeg;
 use std::f64::consts::TAU;
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -209,6 +210,10 @@ impl ClosestSegment {
 		self.bezier
 	}
 
+	pub fn to_pathseg(&self) -> PathSeg {
+		handles_to_segment(self.bezier.start, self.bezier.handles, self.bezier.end)
+	}
+
 	pub fn closest_point_document(&self) -> DVec2 {
 		self.bezier.evaluate(TValue::Parametric(self.t))
 	}
diff --git a/editor/src/messages/tool/common_functionality/shapes/shape_utility.rs b/editor/src/messages/tool/common_functionality/shapes/shape_utility.rs
index aa43e0cb29..d0c7f78e79 100644
--- a/editor/src/messages/tool/common_functionality/shapes/shape_utility.rs
+++ b/editor/src/messages/tool/common_functionality/shapes/shape_utility.rs
@@ -328,7 +328,7 @@ pub fn star_outline(layer: Option<LayerNodeIdentifier>, document: &DocumentMessa
 	let diameter: f64 = radius1 * 2.;
 	let inner_diameter = radius2 * 2.;
 
-	let subpath: Vec<ClickTargetType> = vec![ClickTargetType::Subpath(Subpath::new_star_polygon(DVec2::splat(-diameter), points, diameter, inner_diameter))];
+	let subpath: Vec<ClickTargetType> = vec![ClickTargetType::BezPath(Subpath::new_star_polygon(DVec2::splat(-diameter), points, diameter, inner_diameter))];
 
 	overlay_context.outline(subpath.iter(), viewport, None);
 }
@@ -345,7 +345,7 @@ pub fn polygon_outline(layer: Option<LayerNodeIdentifier>, document: &DocumentMe
 	let points = sides as u64;
 	let radius: f64 = radius * 2.;
 
-	let subpath: Vec<ClickTargetType> = vec![ClickTargetType::Subpath(Subpath::new_regular_polygon(DVec2::splat(-radius), points, radius))];
+	let subpath: Vec<ClickTargetType> = vec![ClickTargetType::BezPath(Subpath::new_regular_polygon(DVec2::splat(-radius), points, radius))];
 
 	overlay_context.outline(subpath.iter(), viewport, None);
 }
@@ -358,7 +358,7 @@ pub fn arc_outline(layer: Option<LayerNodeIdentifier>, document: &DocumentMessag
 		return;
 	};
 
-	let subpath: Vec<ClickTargetType> = vec![ClickTargetType::Subpath(Subpath::new_arc(
+	let subpath: Vec<ClickTargetType> = vec![ClickTargetType::BezPath(Subpath::new_arc(
 		radius,
 		start_angle / 360. * std::f64::consts::TAU,
 		sweep_angle / 360. * std::f64::consts::TAU,
diff --git a/editor/src/messages/tool/common_functionality/snapping/layer_snapper.rs b/editor/src/messages/tool/common_functionality/snapping/layer_snapper.rs
index 3a30671357..e20aa9a0f6 100644
--- a/editor/src/messages/tool/common_functionality/snapping/layer_snapper.rs
+++ b/editor/src/messages/tool/common_functionality/snapping/layer_snapper.rs
@@ -48,6 +48,7 @@ impl LayerSnapper {
 		}
 	}
 
+	///////// Find why
 	pub fn collect_paths(&mut self, snap_data: &mut SnapData, first_point: bool) {
 		if !first_point {
 			return;
@@ -69,9 +70,9 @@ impl LayerSnapper {
 
 			if document.snapping_state.target_enabled(SnapTarget::Path(PathSnapTarget::IntersectionPoint)) || document.snapping_state.target_enabled(SnapTarget::Path(PathSnapTarget::AlongPath)) {
 				for subpath in document.metadata().layer_outline(layer) {
-					for (start_index, curve) in subpath.iter().enumerate() {
-						let document_curve = curve.apply_transformation(|p| transform.transform_point2(p));
-						let start = subpath.manipulator_groups()[start_index].id;
+					for (start_index, curve) in subpath.segments().enumerate() {
+						let document_curve = curve.app(|p| transform.transform_point2(p));
+						let start = 0;
 						if snap_data.ignore_manipulator(layer, start) || snap_data.ignore_manipulator(layer, subpath.manipulator_groups()[(start_index + 1) % subpath.len()].id) {
 							continue;
 						}
diff --git a/editor/src/messages/tool/tool_messages/path_tool.rs b/editor/src/messages/tool/tool_messages/path_tool.rs
index 00c99bd975..0a3f387869 100644
--- a/editor/src/messages/tool/tool_messages/path_tool.rs
+++ b/editor/src/messages/tool/tool_messages/path_tool.rs
@@ -1737,7 +1737,7 @@ impl Fsm for PathToolFsmState {
 							if tool_options.path_editing_mode.segment_editing_mode && !tool_data.segment_editing_modifier {
 								let transform = document.metadata().transform_to_viewport_if_feeds(closest_segment.layer(), &document.network_interface);
 
-								overlay_context.outline_overlay_bezier(closest_segment.bezier(), transform);
+								overlay_context.outline_overlay_bezier(closest_segment.to_pathseg(), transform);
 
 								// Draw the anchors again
 								let display_anchors = overlay_context.visibility_settings.anchors();
@@ -1865,9 +1865,9 @@ impl Fsm for PathToolFsmState {
 
 							let transform = document.metadata().transform_to_viewport_if_feeds(layer, &document.network_interface);
 
-							for (segment, bezier, _, _) in vector.segment_bezier_iter() {
-								if segments.contains(&segment) {
-									overlay_context.outline_overlay_bezier(bezier, transform);
+							for (segment_id, segment, _, _) in vector.segment_iter() {
+								if segments.contains(&segment_id) {
+									overlay_context.outline_overlay_bezier(segment, transform);
 								}
 							}
 						}
diff --git a/editor/src/messages/tool/tool_messages/pen_tool.rs b/editor/src/messages/tool/tool_messages/pen_tool.rs
index ba2d8b98b6..85ba737439 100644
--- a/editor/src/messages/tool/tool_messages/pen_tool.rs
+++ b/editor/src/messages/tool/tool_messages/pen_tool.rs
@@ -14,7 +14,7 @@ use crate::messages::tool::common_functionality::utility_functions::{calculate_s
 use bezier_rs::{Bezier, BezierHandles};
 use graph_craft::document::NodeId;
 use graphene_std::Color;
-use graphene_std::vector::misc::{HandleId, ManipulatorPointId};
+use graphene_std::vector::misc::{HandleId, ManipulatorPointId, bezpath_from_manipulator_groups, handles_to_segment};
 use graphene_std::vector::{NoHashBuilder, PointId, SegmentId, StrokeId, Vector, VectorModificationType};
 
 #[derive(Default, ExtractField)]
@@ -1603,7 +1603,7 @@ impl Fsm for PenToolFsmState {
 					let bezier = Bezier { start, handles, end };
 					if (end - start).length_squared() > f64::EPSILON {
 						// Draw the curve for the currently-being-placed segment
-						overlay_context.outline_bezier(bezier, transform);
+						overlay_context.outline_bezier(handles_to_segment(start, handles, end), transform);
 					}
 				}
 
@@ -1738,6 +1738,7 @@ impl Fsm for PenToolFsmState {
 									});
 									vector.subpath_from_segments_ignore_discontinuities(segments)
 								})
+								.map(|subpath| bezpath_from_manipulator_groups(subpath.manipulator_groups(), subpath.closed))
 								.collect();
 
 							let mut fill_color = graphene_std::Color::from_rgb_str(COLOR_OVERLAY_BLUE.strip_prefix('#').unwrap())
diff --git a/editor/src/messages/tool/tool_messages/select_tool.rs b/editor/src/messages/tool/tool_messages/select_tool.rs
index 31bd2c3a4b..b472a1b721 100644
--- a/editor/src/messages/tool/tool_messages/select_tool.rs
+++ b/editor/src/messages/tool/tool_messages/select_tool.rs
@@ -27,6 +27,7 @@ use graphene_std::path_bool::BooleanOperation;
 use graphene_std::renderer::Quad;
 use graphene_std::renderer::Rect;
 use graphene_std::transform::ReferencePoint;
+use graphene_std::vector::misc::bezpath_from_manipulator_groups;
 use std::fmt;
 
 #[derive(Default, ExtractField)]
@@ -463,6 +464,7 @@ impl SelectToolData {
 			return false;
 		}
 		let polygon = Subpath::from_anchors_linear(self.lasso_polygon.clone(), true);
+		let polygon = bezpath_from_manipulator_groups(polygon.manipulator_groups(), polygon.closed);
 		document.is_layer_fully_inside_polygon(layer, input, polygon)
 	}
 
diff --git a/node-graph/gcore/src/vector/click_target.rs b/node-graph/gcore/src/vector/click_target.rs
index 4ea81c3cd2..9a1e02faa5 100644
--- a/node-graph/gcore/src/vector/click_target.rs
+++ b/node-graph/gcore/src/vector/click_target.rs
@@ -1,8 +1,10 @@
-use crate::math::math_ext::QuadExt;
-use crate::math::quad::Quad;
 use crate::vector::PointId;
-use bezier_rs::Subpath;
+use crate::vector::misc::rect_with_size;
 use glam::{DAffine2, DMat2, DVec2};
+use kurbo::{Affine, BezPath, DEFAULT_ACCURACY, PathSeg, Rect, Shape};
+
+use super::algorithms::intersection::bezpath_and_segment_intersections;
+use super::misc::{bezpath_loose_bounding_box, dvec2_to_point, is_bezpath_closed, pathseg_to_points, point_to_dvec2, rect_to_minmax, transform_rect};
 
 #[derive(Copy, Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
 pub struct FreePoint {
@@ -22,7 +24,7 @@ impl FreePoint {
 
 #[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
 pub enum ClickTargetType {
-	Subpath(Subpath<PointId>),
+	BezPath(BezPath),
 	FreePoint(FreePoint),
 }
 
@@ -31,14 +33,14 @@ pub enum ClickTargetType {
 pub struct ClickTarget {
 	target_type: ClickTargetType,
 	stroke_width: f64,
-	bounding_box: Option<[DVec2; 2]>,
+	bounding_box: Option<Rect>,
 }
 
 impl ClickTarget {
-	pub fn new_with_subpath(subpath: Subpath<PointId>, stroke_width: f64) -> Self {
-		let bounding_box = subpath.loose_bounding_box();
+	pub fn new_with_bezpath(bezpath: BezPath, stroke_width: f64) -> Self {
+		let bounding_box = bezpath_loose_bounding_box(&bezpath);
 		Self {
-			target_type: ClickTargetType::Subpath(subpath),
+			target_type: ClickTargetType::BezPath(bezpath),
 			stroke_width,
 			bounding_box,
 		}
@@ -47,10 +49,8 @@ impl ClickTarget {
 	pub fn new_with_free_point(point: FreePoint) -> Self {
 		const MAX_LENGTH_FOR_NO_WIDTH_OR_HEIGHT: f64 = 1e-4 / 2.;
 		let stroke_width = 10.;
-		let bounding_box = Some([
-			point.position - DVec2::splat(MAX_LENGTH_FOR_NO_WIDTH_OR_HEIGHT),
-			point.position + DVec2::splat(MAX_LENGTH_FOR_NO_WIDTH_OR_HEIGHT),
-		]);
+
+		let bounding_box = Some(rect_with_size(point.position, MAX_LENGTH_FOR_NO_WIDTH_OR_HEIGHT));
 
 		Self {
 			target_type: ClickTargetType::FreePoint(point),
@@ -64,21 +64,26 @@ impl ClickTarget {
 	}
 
 	pub fn bounding_box(&self) -> Option<[DVec2; 2]> {
-		self.bounding_box
+		self.bounding_box.map(|bbox| rect_to_minmax(bbox))
 	}
 
 	pub fn bounding_box_center(&self) -> Option<DVec2> {
-		self.bounding_box.map(|bbox| bbox[0] + (bbox[1] - bbox[0]) / 2.)
+		self.bounding_box.map(|bbox| point_to_dvec2(bbox.center()))
 	}
 
 	pub fn bounding_box_with_transform(&self, transform: DAffine2) -> Option<[DVec2; 2]> {
-		self.bounding_box.map(|[a, b]| [transform.transform_point2(a), transform.transform_point2(b)])
+		self.bounding_box.map(|bbox| {
+			[
+				transform.transform_point2(DVec2::new(bbox.min_x(), bbox.min_y())),
+				transform.transform_point2(DVec2::new(bbox.max_x(), bbox.max_y())),
+			]
+		})
 	}
 
 	pub fn apply_transform(&mut self, affine_transform: DAffine2) {
 		match self.target_type {
-			ClickTargetType::Subpath(ref mut subpath) => {
-				subpath.apply_transform(affine_transform);
+			ClickTargetType::BezPath(ref mut subpath) => {
+				subpath.apply_affine(Affine::new(affine_transform.to_cols_array()));
 			}
 			ClickTargetType::FreePoint(ref mut point) => {
 				point.apply_transform(affine_transform);
@@ -89,17 +94,17 @@ impl ClickTarget {
 
 	fn update_bbox(&mut self) {
 		match self.target_type {
-			ClickTargetType::Subpath(ref subpath) => {
-				self.bounding_box = subpath.bounding_box();
+			ClickTargetType::BezPath(ref subpath) => {
+				self.bounding_box = Some(subpath.bounding_box());
 			}
 			ClickTargetType::FreePoint(ref point) => {
-				self.bounding_box = Some([point.position - DVec2::splat(self.stroke_width / 2.), point.position + DVec2::splat(self.stroke_width / 2.)]);
+				self.bounding_box = Some(rect_with_size(point.position, self.stroke_width));
 			}
 		}
 	}
 
 	/// Does the click target intersect the path
-	pub fn intersect_path<It: Iterator<Item = bezier_rs::Bezier>>(&self, mut bezier_iter: impl FnMut() -> It, layer_transform: DAffine2) -> bool {
+	pub fn intersect_path(&self, mut selection_bezpath: BezPath, layer_transform: DAffine2) -> bool {
 		// Check if the matrix is not invertible
 		let mut layer_transform = layer_transform;
 		if layer_transform.matrix2.determinant().abs() <= f64::EPSILON {
@@ -107,56 +112,39 @@ impl ClickTarget {
 		}
 
 		let inverse = layer_transform.inverse();
-		let mut bezier_iter = || bezier_iter().map(|bezier| bezier.apply_transformation(|point| inverse.transform_point2(point)));
+		selection_bezpath.apply_affine(Affine::new(inverse.to_cols_array()));
 
 		match self.target_type() {
-			ClickTargetType::Subpath(subpath) => {
-				// Check if outlines intersect
-				let outline_intersects = |path_segment: bezier_rs::Bezier| bezier_iter().any(|line| !path_segment.intersections(&line, None, None).is_empty());
-				if subpath.iter().any(outline_intersects) {
-					return true;
-				}
-				// Check if selection is entirely within the shape
-				if subpath.closed() && bezier_iter().next().is_some_and(|bezier| subpath.contains_point(bezier.start)) {
-					return true;
-				}
-
-				// Check if shape is entirely within selection
-				let any_point_from_subpath = subpath.manipulator_groups().first().map(|group| group.anchor);
-				any_point_from_subpath.is_some_and(|shape_point| bezier_iter().map(|bezier| bezier.winding(shape_point)).sum::<i32>() != 0)
+			ClickTargetType::BezPath(click_target_bezpath) => {
+				let inside = |segment: PathSeg| pathseg_to_points(segment).iter().filter_map(|point| *point).all(|point| selection_bezpath.contains(point));
+				let intersects = |segment: PathSeg| !bezpath_and_segment_intersections(&selection_bezpath, segment, None, None).is_empty();
+
+				click_target_bezpath.segments().any(|target_segment| inside(target_segment)) || click_target_bezpath.segments().any(|target_segment| intersects(target_segment))
 			}
-			ClickTargetType::FreePoint(point) => bezier_iter().map(|bezier: bezier_rs::Bezier| bezier.winding(point.position)).sum::<i32>() != 0,
+			ClickTargetType::FreePoint(point) => selection_bezpath.contains(dvec2_to_point(point.position)),
 		}
 	}
 
 	/// Does the click target intersect the point (accounting for stroke size)
 	pub fn intersect_point(&self, point: DVec2, layer_transform: DAffine2) -> bool {
-		let target_bounds = [point - DVec2::splat(self.stroke_width / 2.), point + DVec2::splat(self.stroke_width / 2.)];
-		let intersects = |a: [DVec2; 2], b: [DVec2; 2]| a[0].x <= b[1].x && a[1].x >= b[0].x && a[0].y <= b[1].y && a[1].y >= b[0].y;
+		let target_bounds = rect_with_size(point, self.stroke_width);
 		// This bounding box is not very accurate as it is the axis aligned version of the transformed bounding box. However it is fast.
-		if !self
-			.bounding_box
-			.is_some_and(|loose| (loose[0] - loose[1]).abs().cmpgt(DVec2::splat(1e-4)).any() && intersects((layer_transform * Quad::from_box(loose)).bounding_box(), target_bounds))
-		{
+		if !self.bounding_box.is_some_and(|bbox| (transform_rect(bbox, layer_transform)).overlaps(target_bounds)) {
 			return false;
 		}
 
 		// Allows for selecting lines
 		// TODO: actual intersection of stroke
-		let inflated_quad = Quad::from_box(target_bounds);
-		self.intersect_path(|| inflated_quad.bezier_lines(), layer_transform)
+		self.intersect_path(target_bounds.to_path(DEFAULT_ACCURACY), layer_transform)
 	}
 
 	/// Does the click target intersect the point (not accounting for stroke size)
 	pub fn intersect_point_no_stroke(&self, point: DVec2) -> bool {
 		// Check if the point is within the bounding box
-		if self
-			.bounding_box
-			.is_some_and(|bbox| bbox[0].x <= point.x && point.x <= bbox[1].x && bbox[0].y <= point.y && point.y <= bbox[1].y)
-		{
+		if self.bounding_box.is_some_and(|bbox| bbox.contains(dvec2_to_point(point))) {
 			// Check if the point is within the shape
 			match self.target_type() {
-				ClickTargetType::Subpath(subpath) => subpath.closed() && subpath.contains_point(point),
+				ClickTargetType::BezPath(bezpath) => is_bezpath_closed(bezpath) && bezpath.contains(dvec2_to_point(point)),
 				ClickTargetType::FreePoint(free_point) => free_point.position == point,
 			}
 		} else {
diff --git a/node-graph/gcore/src/vector/misc.rs b/node-graph/gcore/src/vector/misc.rs
index b87e21a947..e20af5dadf 100644
--- a/node-graph/gcore/src/vector/misc.rs
+++ b/node-graph/gcore/src/vector/misc.rs
@@ -3,8 +3,8 @@ use super::algorithms::offset_subpath::MAX_ABSOLUTE_DIFFERENCE;
 use crate::vector::{SegmentId, Vector};
 use bezier_rs::{BezierHandles, ManipulatorGroup, Subpath};
 use dyn_any::DynAny;
-use glam::DVec2;
-use kurbo::{BezPath, CubicBez, Line, ParamCurve, PathSeg, Point, QuadBez};
+use glam::{DAffine2, DVec2};
+use kurbo::{BezPath, CubicBez, Line, ParamCurve, PathEl, PathSeg, Point, QuadBez, Rect};
 use std::ops::Sub;
 
 /// Represents different ways of calculating the centroid.
@@ -204,6 +204,52 @@ pub fn bezpath_to_manipulator_groups(bezpath: &BezPath) -> (Vec<ManipulatorGroup
 	(manipulator_groups, is_closed)
 }
 
+pub fn pathseg_to_points(segment: PathSeg) -> [Option<Point>; 4] {
+	match segment {
+		PathSeg::Line(line) => [Some(line.p0), None, None, Some(line.p1)],
+		PathSeg::Quad(quad_bez) => [Some(quad_bez.p0), None, Some(quad_bez.p1), Some(quad_bez.p2)],
+		PathSeg::Cubic(cubic_bez) => [Some(cubic_bez.p0), Some(cubic_bez.p1), Some(cubic_bez.p2), Some(cubic_bez.p3)],
+	}
+}
+
+pub fn bezpath_loose_bounding_box(bezpath: &BezPath) -> Option<Rect> {
+	let to_rect = |point: Point| Rect::new(point.x, point.y, point.x, point.y);
+	let combine = |r1: Rect, r2: Rect| Rect::new(r1.x0.min(r2.x0), r1.y0.min(r2.y0), r1.x1.max(r2.x1), r1.y1.max(r2.y1));
+
+	bezpath
+		.segments()
+		.flat_map(|segment| pathseg_to_points(segment))
+		.flat_map(|point| point)
+		.map(|point| to_rect(point))
+		.reduce(|bbox1, bbox2| combine(bbox1, bbox2))
+}
+
+pub fn is_bezpath_closed(bezpath: &BezPath) -> bool {
+	bezpath.elements().last().is_some_and(|el| *el == PathEl::ClosePath)
+}
+
+pub fn combine_rect(r1: Rect, r2: Rect) -> Rect {
+	Rect::new(r1.x0.min(r2.x0), r1.y0.min(r2.y0), r1.x1.max(r2.x1), r1.y1.max(r2.y1))
+}
+
+pub fn rect_from_minmax(minmax: [DVec2; 2]) -> Rect {
+	Rect::new(minmax[0].x, minmax[0].y, minmax[1].x, minmax[1].y)
+}
+
+pub fn rect_to_minmax(rect: Rect) -> [DVec2; 2] {
+	[DVec2::new(rect.min_x(), rect.min_y()), DVec2::new(rect.max_x(), rect.max_y())]
+}
+
+pub fn transform_rect(rect: Rect, transform: DAffine2) -> Rect {
+	let min = transform.transform_point2(DVec2::new(rect.x0, rect.y0));
+	let max = transform.transform_point2(DVec2::new(rect.x1, rect.y1));
+	Rect::new(min.x, min.y, max.x, max.y)
+}
+
+pub fn rect_with_size(point: DVec2, size: f64) -> Rect {
+	Rect::new(point.x - size / 2., point.y - size / 2., point.x + size / 2., point.y + size / 2.)
+}
+
 /// Returns true if the [`PathSeg`] is equivalent to a line.
 ///
 /// This is different from simply checking if the segment is [`PathSeg::Line`] or [`PathSeg::Quad`] or [`PathSeg::Cubic`]. Bezier curve can also be a line if the control points are colinear to the start and end points. Therefore if the handles exceed the start and end point, it will still be considered as a line.
diff --git a/node-graph/gcore/src/vector/vector_types.rs b/node-graph/gcore/src/vector/vector_types.rs
index 30bbd33063..75646f3d36 100644
--- a/node-graph/gcore/src/vector/vector_types.rs
+++ b/node-graph/gcore/src/vector/vector_types.rs
@@ -157,7 +157,7 @@ impl Vector {
 
 		for target_type in target_types.into_iter() {
 			match target_type.borrow() {
-				ClickTargetType::Subpath(subpath) => vector.append_subpath(subpath, preserve_id),
+				ClickTargetType::BezPath(bezpath) => vector.append_bezpath(bezpath.clone()),
 				ClickTargetType::FreePoint(point) => vector.append_free_point(point, preserve_id),
 			}
 		}
diff --git a/node-graph/gsvg-renderer/src/renderer.rs b/node-graph/gsvg-renderer/src/renderer.rs
index 8c7d91fb30..e029bac964 100644
--- a/node-graph/gsvg-renderer/src/renderer.rs
+++ b/node-graph/gsvg-renderer/src/renderer.rs
@@ -1,6 +1,5 @@
 use crate::render_ext::RenderExt;
 use crate::to_peniko::BlendModeExt;
-use bezier_rs::Subpath;
 use dyn_any::DynAny;
 use glam::{DAffine2, DVec2};
 use graphene_core::blending::BlendMode;
@@ -15,6 +14,7 @@ use graphene_core::transform::{Footprint, Transform};
 use graphene_core::uuid::{NodeId, generate_uuid};
 use graphene_core::vector::Vector;
 use graphene_core::vector::click_target::{ClickTarget, FreePoint};
+use graphene_core::vector::misc::is_bezpath_closed;
 use graphene_core::vector::style::{Fill, Stroke, StrokeAlign, ViewMode};
 use graphene_core::{Artboard, Graphic};
 use num_traits::Zero;
@@ -23,6 +23,7 @@ use std::fmt::Write;
 use std::hash::{DefaultHasher, Hash, Hasher};
 use std::ops::Deref;
 use std::sync::{Arc, LazyLock};
+use vello::kurbo::{BezPath, DEFAULT_ACCURACY, Rect, Shape};
 #[cfg(feature = "vello")]
 use vello::*;
 
@@ -735,11 +736,11 @@ impl Render for Table<Vector> {
 			if let Some(element_id) = element_id {
 				let stroke_width = vector.style.stroke().as_ref().map_or(0., Stroke::weight);
 				let filled = vector.style.fill() != &Fill::None;
-				let fill = |mut subpath: Subpath<_>| {
-					if filled {
-						subpath.set_closed(true);
+				let fill = |mut bezpath: BezPath| {
+					if filled && !is_bezpath_closed(&bezpath) {
+						bezpath.close_path();
 					}
-					subpath
+					bezpath
 				};
 
 				// For free-floating anchors, we need to add a click target for each
@@ -755,9 +756,9 @@ impl Render for Table<Vector> {
 				});
 
 				let click_targets = vector
-					.stroke_bezier_paths()
+					.stroke_bezpath_iter()
 					.map(fill)
-					.map(|subpath| ClickTarget::new_with_subpath(subpath, stroke_width))
+					.map(|bezpath| ClickTarget::new_with_bezpath(bezpath, stroke_width))
 					.chain(single_anchors_targets.into_iter())
 					.collect::<Vec<ClickTarget>>();
 
@@ -775,14 +776,14 @@ impl Render for Table<Vector> {
 		for row in self.iter() {
 			let stroke_width = row.element.style.stroke().as_ref().map_or(0., Stroke::weight);
 			let filled = row.element.style.fill() != &Fill::None;
-			let fill = |mut subpath: Subpath<_>| {
-				if filled {
-					subpath.set_closed(true);
+			let fill = |mut bezpath: BezPath| {
+				if filled && !is_bezpath_closed(&bezpath) {
+					bezpath.close_path();
 				}
-				subpath
+				bezpath
 			};
-			click_targets.extend(row.element.stroke_bezier_paths().map(fill).map(|subpath| {
-				let mut click_target = ClickTarget::new_with_subpath(subpath, stroke_width);
+			click_targets.extend(row.element.stroke_bezpath_iter().map(fill).map(|subpath| {
+				let mut click_target = ClickTarget::new_with_bezpath(subpath, stroke_width);
 				click_target.apply_transform(*row.transform);
 				click_target
 			}));
@@ -885,8 +886,8 @@ impl Render for Artboard {
 
 	fn collect_metadata(&self, metadata: &mut RenderMetadata, mut footprint: Footprint, element_id: Option<NodeId>) {
 		if let Some(element_id) = element_id {
-			let subpath = Subpath::new_rect(DVec2::ZERO, self.dimensions.as_dvec2());
-			metadata.click_targets.insert(element_id, vec![ClickTarget::new_with_subpath(subpath, 0.)]);
+			let bezpath = Rect::new(0., 0., self.dimensions.x as f64, self.dimensions.y as f64).to_path(DEFAULT_ACCURACY);
+			metadata.click_targets.insert(element_id, vec![ClickTarget::new_with_bezpath(bezpath, 0.)]);
 			metadata.upstream_footprints.insert(element_id, footprint);
 			metadata.local_transforms.insert(element_id, DAffine2::from_translation(self.location.as_dvec2()));
 			if self.clip {
@@ -898,8 +899,8 @@ impl Render for Artboard {
 	}
 
 	fn add_upstream_click_targets(&self, click_targets: &mut Vec<ClickTarget>) {
-		let subpath_rectangle = Subpath::new_rect(DVec2::ZERO, self.dimensions.as_dvec2());
-		click_targets.push(ClickTarget::new_with_subpath(subpath_rectangle, 0.));
+		let bezpath_rectangle = Rect::new(0., 0., self.dimensions.x as f64, self.dimensions.y as f64).to_path(DEFAULT_ACCURACY);
+		click_targets.push(ClickTarget::new_with_bezpath(bezpath_rectangle, 0.));
 	}
 
 	fn contains_artboard(&self) -> bool {
@@ -1063,9 +1064,9 @@ impl Render for Table<Raster<CPU>> {
 
 	fn collect_metadata(&self, metadata: &mut RenderMetadata, footprint: Footprint, element_id: Option<NodeId>) {
 		let Some(element_id) = element_id else { return };
-		let subpath = Subpath::new_rect(DVec2::ZERO, DVec2::ONE);
+		let bezpath = Rect::new(0., 0., 1., 1.).to_path(DEFAULT_ACCURACY);
 
-		metadata.click_targets.insert(element_id, vec![ClickTarget::new_with_subpath(subpath, 0.)]);
+		metadata.click_targets.insert(element_id, vec![ClickTarget::new_with_bezpath(bezpath, 0.)]);
 		metadata.upstream_footprints.insert(element_id, footprint);
 		// TODO: Find a way to handle more than one row of the graphical data table
 		if let Some(image) = self.iter().next() {
@@ -1074,8 +1075,8 @@ impl Render for Table<Raster<CPU>> {
 	}
 
 	fn add_upstream_click_targets(&self, click_targets: &mut Vec<ClickTarget>) {
-		let subpath = Subpath::new_rect(DVec2::ZERO, DVec2::ONE);
-		click_targets.push(ClickTarget::new_with_subpath(subpath, 0.));
+		let bezpath = Rect::new(0., 0., 1., 1.).to_path(DEFAULT_ACCURACY);
+		click_targets.push(ClickTarget::new_with_bezpath(bezpath, 0.));
 	}
 }
 
@@ -1121,9 +1122,9 @@ impl Render for Table<Raster<GPU>> {
 
 	fn collect_metadata(&self, metadata: &mut RenderMetadata, footprint: Footprint, element_id: Option<NodeId>) {
 		let Some(element_id) = element_id else { return };
-		let subpath = Subpath::new_rect(DVec2::ZERO, DVec2::ONE);
+		let bezpath = Rect::new(0., 0., 1., 1.).to_path(DEFAULT_ACCURACY);
 
-		metadata.click_targets.insert(element_id, vec![ClickTarget::new_with_subpath(subpath, 0.)]);
+		metadata.click_targets.insert(element_id, vec![ClickTarget::new_with_bezpath(bezpath, 0.)]);
 		metadata.upstream_footprints.insert(element_id, footprint);
 		// TODO: Find a way to handle more than one row of the graphical data table
 		if let Some(image) = self.iter().next() {
@@ -1132,8 +1133,8 @@ impl Render for Table<Raster<GPU>> {
 	}
 
 	fn add_upstream_click_targets(&self, click_targets: &mut Vec<ClickTarget>) {
-		let subpath = Subpath::new_rect(DVec2::ZERO, DVec2::ONE);
-		click_targets.push(ClickTarget::new_with_subpath(subpath, 0.));
+		let bezpath = Rect::new(0., 0., 1., 1.).to_path(DEFAULT_ACCURACY);
+		click_targets.push(ClickTarget::new_with_bezpath(bezpath, 0.));
 	}
 }
 
