From 30f6699b56af32f09677c0dc16ab2578d1f04672 Mon Sep 17 00:00:00 2001 From: Junkui Zhang <364772080@qq.com> Date: Thu, 31 Jul 2025 17:27:06 +0800 Subject: [PATCH] checkpoint --- .../gpui/src/platform/windows/direct_write.rs | 184 ++++++------------ 1 file changed, 64 insertions(+), 120 deletions(-) diff --git a/crates/gpui/src/platform/windows/direct_write.rs b/crates/gpui/src/platform/windows/direct_write.rs index 96c4b7771c..4fddd466f1 100644 --- a/crates/gpui/src/platform/windows/direct_write.rs +++ b/crates/gpui/src/platform/windows/direct_write.rs @@ -707,11 +707,18 @@ impl DirectWriteState { } } - fn raster_bounds(&self, params: &RenderGlyphParams) -> Result> { + fn create_glyph_run_analysis( + &self, + params: &RenderGlyphParams, + advance: f32, + offset: DWRITE_GLYPH_OFFSET, + baseline_origin_x: f32, + baseline_origin_y: f32, + ) -> Result { let font = &self.fonts[params.font_id.0]; let glyph_id = [params.glyph_id.0 as u16]; - let advance = [0.0f32]; - let offset = [DWRITE_GLYPH_OFFSET::default()]; + let advance = [advance]; + let offset = [offset]; let glyph_run = DWRITE_GLYPH_RUN { fontFace: unsafe { std::mem::transmute_copy(&font.font_face) }, fontEmSize: params.font_size.0, @@ -722,10 +729,6 @@ impl DirectWriteState { isSideways: BOOL(0), bidiLevel: 0, }; - - let baseline_origin_x = 0.0; - let baseline_origin_y = 0.0; - let transform = DWRITE_MATRIX { m11: params.scale_factor, m12: 0.0, @@ -740,10 +743,10 @@ impl DirectWriteState { unsafe { font.font_face.GetRecommendedRenderingMode( params.font_size.0, - // Is this correct? - 1.0, - 1.0, - Some(&transform), + // The dpi here seems that it has the same effect with `Some(&transform)` + params.scale_factor, + params.scale_factor, + None, false, DWRITE_OUTLINE_THRESHOLD_ANTIALIASED, DWRITE_MEASURING_MODE_NATURAL, @@ -769,12 +772,19 @@ impl DirectWriteState { antialias_mode, baseline_origin_x, baseline_origin_y, - )? - }; + ) + }?; + Ok(glyph_analysis) + } + + fn raster_bounds(&self, params: &RenderGlyphParams) -> Result> { + let glyph_analysis = + self.create_glyph_run_analysis(params, 0.0, DWRITE_GLYPH_OFFSET::default(), 0.0, 0.0)?; if params.is_emoji { let bounds = unsafe { glyph_analysis.GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1)? }; + // If it's empty, retry with grayscale AA. if !unsafe { IsRectEmpty(&bounds) }.as_bool() { return Ok(Bounds { origin: point((bounds.left as i32).into(), (bounds.top as i32).into()), @@ -826,24 +836,6 @@ impl DirectWriteState { anyhow::bail!("glyph bounds are empty"); } - let font_info = &self.fonts[params.font_id.0]; - let glyph_id = [params.glyph_id.0 as u16]; - let advance = [glyph_bounds.size.width.0 as f32]; - let offset = [DWRITE_GLYPH_OFFSET { - advanceOffset: -glyph_bounds.origin.x.0 as f32 / params.scale_factor, - ascenderOffset: glyph_bounds.origin.y.0 as f32 / params.scale_factor, - }]; - let glyph_run = DWRITE_GLYPH_RUN { - fontFace: ManuallyDrop::new(Some(font_info.font_face.cast()?)), - fontEmSize: params.font_size.0, - glyphCount: 1, - glyphIndices: glyph_id.as_ptr(), - glyphAdvances: advance.as_ptr(), - glyphOffsets: offset.as_ptr(), - isSideways: BOOL(0), - bidiLevel: 0, - }; - // Add an extra pixel when the subpixel variant isn't zero to make room for anti-aliasing. let mut bitmap_size = glyph_bounds.size; if params.subpixel_variant.x > 0 { @@ -860,6 +852,31 @@ impl DirectWriteState { let baseline_origin_x = subpixel_shift.x / params.scale_factor; let baseline_origin_y = subpixel_shift.y / params.scale_factor; + let glyph_analysis = self.create_glyph_run_analysis( + params, + glyph_bounds.size.width.0 as f32, + DWRITE_GLYPH_OFFSET::default(), + baseline_origin_x, + baseline_origin_y, + )?; + + let font = &self.fonts[params.font_id.0]; + let glyph_id = [params.glyph_id.0 as u16]; + let advance = [glyph_bounds.size.width.0 as f32]; + let offset = [DWRITE_GLYPH_OFFSET { + advanceOffset: -glyph_bounds.origin.x.0 as f32 / params.scale_factor, + ascenderOffset: glyph_bounds.origin.y.0 as f32 / params.scale_factor, + }]; + let glyph_run = DWRITE_GLYPH_RUN { + fontFace: unsafe { std::mem::transmute_copy(&font.font_face) }, + fontEmSize: params.font_size.0, + glyphCount: 1, + glyphIndices: glyph_id.as_ptr(), + glyphAdvances: advance.as_ptr(), + glyphOffsets: offset.as_ptr(), + isSideways: BOOL(0), + bidiLevel: 0, + }; let transform = DWRITE_MATRIX { m11: params.scale_factor, m12: 0.0, @@ -869,74 +886,26 @@ impl DirectWriteState { dy: 0.0, }; - let rendering_mode = if params.is_emoji { - DWRITE_RENDERING_MODE1_NATURAL - } else { - DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC - }; - - let measuring_mode = DWRITE_MEASURING_MODE_NATURAL; - - let glyph_analysis = unsafe { - self.components.factory.CreateGlyphRunAnalysis( - &glyph_run, - Some(&transform), - rendering_mode, - measuring_mode, - DWRITE_GRID_FIT_MODE_DEFAULT, - DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE, - baseline_origin_x, - baseline_origin_y, - )? - }; - - let texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1; - let texture_bounds = unsafe { glyph_analysis.GetAlphaTextureBounds(texture_type)? }; - let texture_width = (texture_bounds.right - texture_bounds.left) as u32; - let texture_height = (texture_bounds.bottom - texture_bounds.top) as u32; - - if texture_width == 0 || texture_height == 0 { - return Ok(( - bitmap_size, - vec![ - 0u8; - bitmap_size.width.0 as usize - * bitmap_size.height.0 as usize - * if params.is_emoji { 4 } else { 1 } - ], - )); - } - let mut bitmap_data: Vec; if params.is_emoji { if let Ok(color) = self.rasterize_color( &glyph_run, - rendering_mode, - measuring_mode, &transform, point(baseline_origin_x, baseline_origin_y), bitmap_size, ) { bitmap_data = color; } else { - let monochrome = Self::rasterize_monochrome( - &glyph_analysis, - bitmap_size, - size(texture_width, texture_height), - &texture_bounds, - )?; + let monochrome = + Self::rasterize_monochrome(&glyph_analysis, glyph_bounds.origin, bitmap_size)?; bitmap_data = monochrome .into_iter() .flat_map(|pixel| [0, 0, 0, pixel]) .collect::>(); } } else { - bitmap_data = Self::rasterize_monochrome( - &glyph_analysis, - bitmap_size, - size(texture_width, texture_height), - &texture_bounds, - )?; + bitmap_data = + Self::rasterize_monochrome(&glyph_analysis, glyph_bounds.origin, bitmap_size)?; } Ok((bitmap_size, bitmap_data)) @@ -944,56 +913,31 @@ impl DirectWriteState { fn rasterize_monochrome( glyph_analysis: &IDWriteGlyphRunAnalysis, + origin: Point, bitmap_size: Size, - texture_size: Size, - texture_bounds: &RECT, ) -> Result> { let mut bitmap_data = vec![0u8; bitmap_size.width.0 as usize * bitmap_size.height.0 as usize]; - let mut alpha_data = vec![0u8; (texture_size.width * texture_size.height * 3) as usize]; - unsafe { glyph_analysis.CreateAlphaTexture( - DWRITE_TEXTURE_CLEARTYPE_3x1, - texture_bounds, - &mut alpha_data, + DWRITE_TEXTURE_ALIASED_1x1, + &RECT { + left: origin.x.0, + top: origin.y.0, + right: bitmap_size.width.0 + origin.x.0, + bottom: bitmap_size.height.0 + origin.y.0, + }, + &mut bitmap_data, )?; } - // Convert ClearType RGB data to grayscale and place in bitmap - let offset_x = texture_bounds.left.max(0) as usize; - let offset_y = texture_bounds.top.max(0) as usize; - - for y in 0..texture_size.height as usize { - for x in 0..texture_size.width as usize { - let bitmap_x = offset_x + x; - let bitmap_y = offset_y + y; - - if bitmap_x < bitmap_size.width.0 as usize - && bitmap_y < bitmap_size.height.0 as usize - { - let texture_idx = (y * texture_size.width as usize + x) * 3; - let bitmap_idx = bitmap_y * bitmap_size.width.0 as usize + bitmap_x; - - if texture_idx + 2 < alpha_data.len() && bitmap_idx < bitmap_data.len() { - let max_value = alpha_data[texture_idx] - .max(alpha_data[texture_idx + 1]) - .max(alpha_data[texture_idx + 2]); - bitmap_data[bitmap_idx] = max_value; - } - } - } - } - Ok(bitmap_data) } fn rasterize_color( &self, glyph_run: &DWRITE_GLYPH_RUN, - rendering_mode: DWRITE_RENDERING_MODE1, - measuring_mode: DWRITE_MEASURING_MODE, transform: &DWRITE_MATRIX, baseline_origin: Point, bitmap_size: Size, @@ -1005,7 +949,7 @@ impl DirectWriteState { glyph_run, None, DWRITE_GLYPH_IMAGE_FORMATS_COLR, - measuring_mode, + DWRITE_MEASURING_MODE_NATURAL, Some(transform), 0, ) @@ -1021,8 +965,8 @@ impl DirectWriteState { self.components.factory.CreateGlyphRunAnalysis( &color_run.Base.glyphRun as *const _, Some(transform), - rendering_mode, - measuring_mode, + DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC, + DWRITE_MEASURING_MODE_NATURAL, DWRITE_GRID_FIT_MODE_DEFAULT, DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE, baseline_origin.x,