Vello Classic: Fix flattening tolerance calculation (#1187)

The parentheses were missing, the greater singular value for a matrix

```math
\begin{bmatrix}a & c \\ b & d\end{bmatrix}
```

is $$\frac{1}{2} (\text{hypot}(a+d,b-c) + \text{hypot}(a-d,b+c))$$.


See the discussion in [#office hours > Renderer 2025-09-03 @
💬](https://xi.zulipchat.com/#narrow/channel/359642-office-hours/topic/Renderer.202025-09-03/near/537558900)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e7beeff..01ad6b3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,11 +17,12 @@
 
 ## Added
 
-- `register_texture`, a helper for using `wgpu` textures in a Vello `Renderer` ([#1161][] by [@DJMcNab][]).
+- `register_texture`, a helper for using `wgpu` textures in a Vello `Renderer`. ([#1161][] by [@DJMcNab][])
 
 ## Fixed
 
-- Examples crashing when window is resized to zero. ([#1182][] by [@xStrom][]).
+- Examples crashing when window is resized to zero. ([#1182][] by [@xStrom][])
+- Correct flattening tolerance calculation from 2D affine transforms. ([#1187][] by [@tomcur][])
 
 ## [0.5.1][] - 2025-08-22
 
@@ -315,6 +316,7 @@
 [#1161]: https://github.com/linebender/vello/pull/1161
 [#1169]: https://github.com/linebender/vello/pull/1169
 [#1182]: https://github.com/linebender/vello/pull/1182
+[#1187]: https://github.com/linebender/vello/pull/1187
 
 <!-- Note that this still comparing against 0.5.0, because 0.5.1 is a cherry-picked patch -->
 [Unreleased]: https://github.com/linebender/vello/compare/v0.5.0...HEAD
diff --git a/vello_shaders/shader/flatten.wgsl b/vello_shaders/shader/flatten.wgsl
index cb4fb7c..cebc7f9 100644
--- a/vello_shaders/shader/flatten.wgsl
+++ b/vello_shaders/shader/flatten.wgsl
@@ -359,8 +359,12 @@
 
         transform = local_to_device;
         let mat = transform.mat;
-        scale = 0.5 * length(vec2(mat.x + mat.w, mat.y - mat.z)) +
-                length(vec2(mat.x - mat.w, mat.y + mat.z));
+        // The scale is the semi-major axis of the ellipse given by the unit
+        // circle transformed by `transform`. This is the greater of the two
+        // singular values of the 2x2 `transform` matrix (ignoring
+        // translation).
+        scale = 0.5 * (length(vec2(mat.x + mat.w, mat.y - mat.z)) +
+                length(vec2(mat.x - mat.w, mat.y + mat.z)));
     }
 
     // Drop zero length lines. This is an exact equality test because dropping very short
diff --git a/vello_shaders/src/cpu/flatten.rs b/vello_shaders/src/cpu/flatten.rs
index caea71e..4aa2ff4 100644
--- a/vello_shaders/src/cpu/flatten.rs
+++ b/vello_shaders/src/cpu/flatten.rs
@@ -223,8 +223,9 @@
         )
     } else {
         let t = local_to_device.0;
-        let scale = 0.5 * Vec2::new(t[0] + t[3], t[1] - t[2]).length()
-            + Vec2::new(t[0] - t[3], t[1] + t[2]).length();
+        let scale = 0.5
+            * (Vec2::new(t[0] + t[3], t[1] - t[2]).length()
+                + Vec2::new(t[0] - t[3], t[1] + t[2]).length());
         (
             cubic.p0,
             cubic.p1,