editor: Fix panics that could occur when content mask had negative bounds (#47327)

Anthony Eid and Zed Zippy created

Closes #47157

This panic happened because the editor was using `window.content_mask`
to get the visible bounds, which had a negative value for its height in
some cases.

This happened for three reasons:

1. `Bounds::from_corners` returns a negative size if callers pass in
corners where `bottom_right < top_left`. I originally wanted to add
error checking to this function but didn't, because it might be better
to move the error checking higher up. For now I'm going to push a fix
and figure out a better solution later

2. `Bounds::intersect` could return negative-sized bounds when the two
bounds didn't overlap, instead of returning a zero sized bounds.

3. `Style::paint` sometimes passed invalid corner values to
`Bounds::from_corners` (where the computed bottom-right was above/left
of the top-left).

Release Notes:

- editor: Fix a crash that could happen when editor visible line height
is zero

---------

Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>

Change summary

crates/gpui/src/geometry.rs |  5 ++++-
crates/gpui/src/style.rs    | 16 ++++++++++++----
2 files changed, 16 insertions(+), 5 deletions(-)

Detailed changes

crates/gpui/src/geometry.rs 🔗

@@ -1112,7 +1112,10 @@ impl<T: PartialOrd + Add<T, Output = T> + Sub<Output = T> + Clone + Debug + Defa
     /// ```
     pub fn intersect(&self, other: &Self) -> Self {
         let upper_left = self.origin.max(&other.origin);
-        let bottom_right = self.bottom_right().min(&other.bottom_right());
+        let bottom_right = self
+            .bottom_right()
+            .min(&other.bottom_right())
+            .max(&upper_left);
         Self::from_corners(upper_left, bottom_right)
     }
 

crates/gpui/src/style.rs 🔗

@@ -666,23 +666,31 @@ impl Style {
             let border_widths = self.border_widths.to_pixels(rem_size);
             let max_border_width = border_widths.max();
             let max_corner_radius = corner_radii.max();
+            let zero_size = Size {
+                width: Pixels::ZERO,
+                height: Pixels::ZERO,
+            };
 
-            let top_bounds = Bounds::from_corners(
+            let mut top_bounds = Bounds::from_corners(
                 bounds.origin,
                 bounds.top_right() + point(Pixels::ZERO, max_border_width.max(max_corner_radius)),
             );
-            let bottom_bounds = Bounds::from_corners(
+            top_bounds.size = top_bounds.size.max(&zero_size);
+            let mut bottom_bounds = Bounds::from_corners(
                 bounds.bottom_left() - point(Pixels::ZERO, max_border_width.max(max_corner_radius)),
                 bounds.bottom_right(),
             );
-            let left_bounds = Bounds::from_corners(
+            bottom_bounds.size = bottom_bounds.size.max(&zero_size);
+            let mut left_bounds = Bounds::from_corners(
                 top_bounds.bottom_left(),
                 bottom_bounds.origin + point(max_border_width, Pixels::ZERO),
             );
-            let right_bounds = Bounds::from_corners(
+            left_bounds.size = left_bounds.size.max(&zero_size);
+            let mut right_bounds = Bounds::from_corners(
                 top_bounds.bottom_right() - point(max_border_width, Pixels::ZERO),
                 bottom_bounds.top_right(),
             );
+            right_bounds.size = right_bounds.size.max(&zero_size);
 
             let mut background = self.border_color.unwrap_or_default();
             background.a = 0.;