diff --git a/crates/encoding/src/path.rs b/crates/encoding/src/path.rs index d35edc3e1..6118ff414 100644 --- a/crates/encoding/src/path.rs +++ b/crates/encoding/src/path.rs @@ -525,9 +525,11 @@ impl<'a> PathEncoder<'a> { if self.state == PathState::MoveTo { let x0 = self.first_point[0]; let y0 = self.first_point[1]; - // TODO: should this be an exact match? - if (x - x0).abs() < 1e-12 && (y - y0).abs() < 1e-12 { + // Ensure that we don't end up with a zero-length start tangent. + const EPS: f32 = 1e-12; + if (x - x0).abs() < EPS && (y - y0).abs() < EPS { // Drop the segment if its length is zero + // TODO: do this for all not segments, not just start? return; } self.first_start_tangent_end = [x, y]; @@ -552,13 +554,15 @@ impl<'a> PathEncoder<'a> { if self.state == PathState::MoveTo { let x0 = self.first_point[0]; let y0 = self.first_point[1]; - // TODO clean this up - let (x, y) = if (x1 - x0).abs() > 1e-12 || (y1 - y0).abs() > 1e-12 { + // Ensure that we don't end up with a zero-length start tangent. + const EPS: f32 = 1e-12; + let (x, y) = if (x1 - x0).abs() > EPS || (y1 - y0).abs() > EPS { (x1, y1) - } else if (x2 - x0).abs() > 1e-12 || (y2 - y0).abs() > 1e-12 { + } else if (x2 - x0).abs() > EPS || (y2 - y0).abs() > EPS { (x2, y2) } else { // Drop the segment if its length is zero + // TODO: do this for all not segments, not just start? return; }; self.first_start_tangent_end = [x, y]; @@ -583,15 +587,17 @@ impl<'a> PathEncoder<'a> { if self.state == PathState::MoveTo { let x0 = self.first_point[0]; let y0 = self.first_point[1]; - // TODO clean this up - let (x, y) = if (x1 - x0).abs() > 1e-12 || (y1 - y0).abs() > 1e-12 { + // Ensure that we don't end up with a zero-length start tangent. + const EPS: f32 = 1e-12; + let (x, y) = if (x1 - x0).abs() > EPS || (y1 - y0).abs() > EPS { (x1, y1) - } else if (x2 - x0).abs() > 1e-12 || (y2 - y0).abs() > 1e-12 { + } else if (x2 - x0).abs() > EPS || (y2 - y0).abs() > EPS { (x2, y2) - } else if (x3 - x0).abs() > 1e-12 || (y3 - y0).abs() > 1e-12 { + } else if (x3 - x0).abs() > EPS || (y3 - y0).abs() > EPS { (x3, y3) } else { // Drop the segment if its length is zero + // TODO: do this for all not segments, not just start? return; }; self.first_start_tangent_end = [x, y]; diff --git a/shader/flatten.wgsl b/shader/flatten.wgsl index 13f53f18f..43e1afa53 100644 --- a/shader/flatten.wgsl +++ b/shader/flatten.wgsl @@ -328,7 +328,13 @@ fn read_path_segment(tag: PathTagData, transform: Transform, is_stroke: bool) -> } if is_stroke_cap_marker && is_open { - // TODO: document + // The stroke cap marker for an open path is encoded as a quadto where the p1 and p2 store + // the start control point of the subpath and together with p2 forms the start tangent. p0 + // is ignored. + // + // This is encoded this way because encoding this as a lineto would require adding a moveto, + // which would terminate the subpath too early (by setting the SUBPATH_END_BIT on the + // segment preceding the cap marker). This scheme is only used for strokes. p0 = transform_apply(transform, p1); p1 = transform_apply(transform, p2); seg_type = PATH_TAG_LINETO;