From ba80e163394ba5e63c3b5673844160d62b70da00 Mon Sep 17 00:00:00 2001 From: Kate Date: Fri, 18 Jul 2025 21:12:19 +0200 Subject: [PATCH] color rasterization works now --- .../gpui/src/platform/windows/direct_write.rs | 167 ++++++++++++------ 1 file changed, 114 insertions(+), 53 deletions(-) diff --git a/crates/gpui/src/platform/windows/direct_write.rs b/crates/gpui/src/platform/windows/direct_write.rs index a15732c7e672bfa53ffd0dec6e76a4eaef7c9bd1..d39b00280acdb954403820afc6daa571022966d6 100644 --- a/crates/gpui/src/platform/windows/direct_write.rs +++ b/crates/gpui/src/platform/windows/direct_write.rs @@ -831,9 +831,10 @@ impl DirectWriteState { let mut bitmap_data: Vec; if params.is_emoji { - bitmap_data = vec![0u8; texture_width as usize * texture_height as usize * 4]; + // bitmap_data = vec![0u8; texture_width as usize * texture_height as usize * 4]; - self.rasterize_color( + println!("trying to rasterize"); + let res = self.rasterize_color( &glyph_run, rendering_mode, measuring_mode, @@ -1090,12 +1091,13 @@ impl DirectWriteState { bitmap_size: Size, texture_size: Size, ) -> Result> { + // todo: support formats other than COLR let color_enumerator = unsafe { self.components.factory.TranslateColorGlyphRun( Vector2::new(baseline_origin.x, baseline_origin.y), glyph_run, None, - DWRITE_GLYPH_IMAGE_FORMATS_COLR | DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8, + DWRITE_GLYPH_IMAGE_FORMATS_COLR, measuring_mode, Some(transform), 0, @@ -1106,57 +1108,60 @@ impl DirectWriteState { loop { let color_run = unsafe { color_enumerator.GetCurrentRun() }?; let color_run = unsafe { &*color_run }; - - let color_analysis = unsafe { - self.components.factory.CreateGlyphRunAnalysis( - &color_run.Base.glyphRun as *const _, - Some(transform), - rendering_mode, - measuring_mode, - DWRITE_GRID_FIT_MODE_DEFAULT, - DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE, - baseline_origin.x, - baseline_origin.y, - ) - }?; - - let color_bounds = - unsafe { color_analysis.GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1) }?; - - let color_size = size( - color_bounds.right - color_bounds.left, - color_bounds.bottom - color_bounds.top, - ); - if color_size.width > 0 && color_size.height > 0 { - let mut alpha_data = vec![0u8; (color_size.width * color_size.height * 3) as usize]; - unsafe { - color_analysis.CreateAlphaTexture( - DWRITE_TEXTURE_CLEARTYPE_3x1, - &color_bounds, - &mut alpha_data, + let image_format = color_run.glyphImageFormat & !DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE; + if image_format == DWRITE_GLYPH_IMAGE_FORMATS_COLR { + let color_analysis = unsafe { + self.components.factory.CreateGlyphRunAnalysis( + &color_run.Base.glyphRun as *const _, + Some(transform), + rendering_mode, + measuring_mode, + DWRITE_GRID_FIT_MODE_DEFAULT, + DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE, + baseline_origin.x, + baseline_origin.y, ) }?; - let run_color = { - let run_color = color_run.Base.runColor; - Rgba { - r: run_color.r, - g: run_color.g, - b: run_color.b, - a: run_color.a, - } - }; - let bounds = bounds(point(color_bounds.left, color_bounds.top), color_size); - let alpha_data = alpha_data - .chunks_exact(3) - .flat_map(|chunk| [chunk[0], chunk[1], chunk[2], 255]) - .collect::>(); - glyph_layers.push(GlyphLayerTexture::new( - &self.gpu_state, - run_color, - bounds, - &alpha_data, - )?); + let color_bounds = + unsafe { color_analysis.GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1) }?; + + let color_size = size( + color_bounds.right - color_bounds.left, + color_bounds.bottom - color_bounds.top, + ); + if color_size.width > 0 && color_size.height > 0 { + let mut alpha_data = + vec![0u8; (color_size.width * color_size.height * 3) as usize]; + unsafe { + color_analysis.CreateAlphaTexture( + DWRITE_TEXTURE_CLEARTYPE_3x1, + &color_bounds, + &mut alpha_data, + ) + }?; + + let run_color = { + let run_color = color_run.Base.runColor; + Rgba { + r: run_color.r, + g: run_color.g, + b: run_color.b, + a: run_color.a, + } + }; + let bounds = bounds(point(color_bounds.left, color_bounds.top), color_size); + let alpha_data = alpha_data + .chunks_exact(3) + .flat_map(|chunk| [chunk[0], chunk[1], chunk[2], 255]) + .collect::>(); + glyph_layers.push(GlyphLayerTexture::new( + &self.gpu_state, + run_color, + bounds, + &alpha_data, + )?); + } } let has_next = unsafe { color_enumerator.MoveNext() } @@ -1218,7 +1223,7 @@ impl DirectWriteState { }, Usage: D3D11_USAGE_DEFAULT, BindFlags: D3D11_BIND_RENDER_TARGET.0 as u32, - CPUAccessFlags: D3D11_CPU_ACCESS_READ.0 as u32, + CPUAccessFlags: 0, MiscFlags: 0, }; unsafe { @@ -1248,6 +1253,31 @@ impl DirectWriteState { [rtv] }; + let staging_texture = { + let mut texture = None; + let desc = D3D11_TEXTURE2D_DESC { + Width: bitmap_size.width.0 as u32, + Height: bitmap_size.height.0 as u32, + MipLevels: 1, + ArraySize: 1, + Format: DXGI_FORMAT_B8G8R8A8_UNORM, + SampleDesc: DXGI_SAMPLE_DESC { + Count: 1, + Quality: 0, + }, + Usage: D3D11_USAGE_STAGING, + BindFlags: 0, + CPUAccessFlags: D3D11_CPU_ACCESS_READ.0 as u32, + MiscFlags: 0, + }; + unsafe { + self.gpu_state + .device + .CreateTexture2D(&desc, None, Some(&mut texture)) + }?; + texture.unwrap() + }; + let blend_state = { let mut blend_state = None; let desc = D3D11_BLEND_DESC { @@ -1373,6 +1403,37 @@ impl DirectWriteState { unsafe { device_context.Draw(4, 0) }; } + unsafe { device_context.CopyResource(&staging_texture, &render_target_texture) }; + + let mapped_data = { + let mut mapped_data = D3D11_MAPPED_SUBRESOURCE::default(); + unsafe { + device_context.Map( + &staging_texture, + 0, + D3D11_MAP_READ, + 0, + Some(&mut mapped_data), + ) + }?; + mapped_data + }; + let mut rasterized = + vec![0u8; (bitmap_size.width.0 as u32 * bitmap_size.height.0 as u32 * 4) as usize]; + + for y in 0..bitmap_size.height.0 as usize { + let width = bitmap_size.width.0 as usize; + unsafe { + std::ptr::copy_nonoverlapping::( + (mapped_data.pData as *const u8).byte_add(mapped_data.RowPitch as usize * y), + rasterized + .as_mut_ptr() + .byte_add(width * y * std::mem::size_of::()), + width * std::mem::size_of::(), + ) + }; + } + #[cfg(feature = "enable-renderdoc")] self.renderdoc .0 @@ -1381,7 +1442,7 @@ impl DirectWriteState { println!("render finished"); - Ok(Vec::new()) + Ok(rasterized) } fn get_typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId) -> Result> {