From ab2b9cc73329bb3dfff1e5b707fe49d336cf4ef5 Mon Sep 17 00:00:00 2001 From: David Wendt Date: Mon, 1 Jun 2020 21:49:26 -0400 Subject: [PATCH] Change all of the `BoxBounds` in the layout machinery to not use `Default`. The `Default` bounds are NOT safe to union against if they were uninitialized. Doing so will force any resulting layout box to enclose `(0,0)`, which can throw off certain layout calculations. Instead, we use `None` to signal an uninitialized box. --- core/src/html/layout.rs | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/core/src/html/layout.rs b/core/src/html/layout.rs index 08d96ef6b..e40c9a227 100644 --- a/core/src/html/layout.rs +++ b/core/src/html/layout.rs @@ -36,7 +36,11 @@ pub struct LayoutContext<'a, 'gc> { /// The exterior bounds of all laid-out text, including left and right /// margins. - exterior_bounds: BoxBounds, + /// + /// None indicates that no bounds have yet to be calculated. If the layout + /// ends without a line having been generated, the default bounding box + /// should be used. + exterior_bounds: Option>, /// Whether or not we are laying out the first line of a paragraph. is_first_line: bool, @@ -60,7 +64,7 @@ impl<'a, 'gc> LayoutContext<'a, 'gc> { max_font_size: Default::default(), first_box: None, last_box: None, - exterior_bounds: Default::default(), + exterior_bounds: None, is_first_line: true, current_line: None, current_line_span: Default::default(), @@ -78,8 +82,8 @@ impl<'a, 'gc> LayoutContext<'a, 'gc> { /// Apply all indents and alignment to the current line, if necessary. fn fixup_line(&mut self, mc: MutationContext<'gc, '_>) { - let mut line_bounds = BoxBounds::default(); let mut line = self.current_line; + let mut line_bounds = None; while let Some(linebox) = line { let read = linebox.read(); line = read.next_sibling(); @@ -92,11 +96,15 @@ impl<'a, 'gc> LayoutContext<'a, 'gc> { .with_size(Size::from(font.measure(self.text[start..end].trim(), size))) }; line_bounds += trimmed_bounds; + if let Some(mut line_bounds) = line_bounds { + line_bounds += write.bounds; } else { - line_bounds += read.bounds(); + line_bounds = Some(write.bounds); } } + let mut line_bounds = line_bounds.unwrap_or_else(Default::default); + let left_adjustment = Self::left_alignment_offset(&self.current_line_span, self.is_first_line); let right_adjustment = Twips::from_pixels(self.current_line_span.right_margin); @@ -145,7 +153,12 @@ impl<'a, 'gc> LayoutContext<'a, 'gc> { line_bounds += Size::from((left_adjustment + right_adjustment, font_leading_adjustment)); self.current_line = None; - self.exterior_bounds += line_bounds; + + if let Some(eb) = &mut self.exterior_bounds { + *eb += line_bounds; + } else { + self.exterior_bounds = Some(line_bounds); + } } /// Adjust the text layout cursor down to the next line. @@ -254,7 +267,10 @@ impl<'a, 'gc> LayoutContext<'a, 'gc> { ) -> (Option>>, BoxBounds) { self.fixup_line(mc); - (self.first_box, self.exterior_bounds) + ( + self.first_box, + self.exterior_bounds.unwrap_or_else(Default::default), + ) } }