From 9223717234fcdc9d5497ddb1802624fde6ba595d Mon Sep 17 00:00:00 2001 From: fschutt Date: Thu, 3 May 2018 07:54:46 +0200 Subject: [PATCH] Fixed calculation of glyph dimensions on Windows The dimensions in the `DWRITE_GLYPH_METRICS` are a bit special: the `rightSideBearing` is measured from the right edge of the character boundary, not the left edge. So, doing (right - left) would usually return a negative or very small number, which, when casted to a u32 in an unsafe block, would silently overflow to a very large number and make webrender crash. Therefore, in order to calculate the metrics correctly, we have to first calculate the full width of the character, then subtract the right and left edges, same width the height. --- font-renderer/src/directwrite/mod.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/font-renderer/src/directwrite/mod.rs b/font-renderer/src/directwrite/mod.rs index fd16678f..d14616c9 100644 --- a/font-renderer/src/directwrite/mod.rs +++ b/font-renderer/src/directwrite/mod.rs @@ -213,6 +213,9 @@ impl FontContext where FK: Clone + Hash + Eq + Ord { glyph_key: &GlyphKey, _exact: bool) -> Result { + + let mut metrics: DWRITE_GLYPH_METRICS = unsafe { mem::zeroed() }; + unsafe { let font_face = match self.dwrite_font_faces.get(&font_instance.font_key) { None => return Err(()), @@ -220,20 +223,22 @@ impl FontContext where FK: Clone + Hash + Eq + Ord { }; let glyph_index = glyph_key.glyph_index as UINT16; - let mut metrics: DWRITE_GLYPH_METRICS = mem::zeroed(); let result = (**font_face).GetDesignGlyphMetrics(&glyph_index, 1, &mut metrics, FALSE); if !winerror::SUCCEEDED(result) { return Err(()); } - - Ok(GlyphDimensions { - advance: metrics.advanceWidth as f32, - origin: Point2D::new(metrics.leftSideBearing, metrics.bottomSideBearing), - size: Size2D::new((metrics.rightSideBearing - metrics.leftSideBearing) as u32, - (metrics.topSideBearing - metrics.bottomSideBearing) as u32), - }) } + + let character_width = metrics.advanceWidth as i32 - metrics.rightSideBearing - metrics.leftSideBearing; + let character_height = metrics.advanceHeight as i32 - metrics.topSideBearing - metrics.bottomSideBearing; + + Ok(GlyphDimensions { + advance: metrics.advanceWidth as f32, + origin: Point2D::new(metrics.leftSideBearing, metrics.bottomSideBearing), + size: Size2D::new(character_width as u32, + character_height as u32), + }) } /// Returns a list of path commands that represent the given glyph in the given font.