color rasterization works now

Kate created

Change summary

crates/gpui/src/platform/windows/direct_write.rs | 167 ++++++++++++-----
1 file changed, 114 insertions(+), 53 deletions(-)

Detailed changes

crates/gpui/src/platform/windows/direct_write.rs 🔗

@@ -831,9 +831,10 @@ impl DirectWriteState {
 
         let mut bitmap_data: Vec<u8>;
         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<DevicePixels>,
         texture_size: Size<u32>,
     ) -> Result<Vec<u8>> {
+        // 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::<Vec<_>>();
-                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::<Vec<_>>();
+                    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::<u8>(
+                    (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::<u32>()),
+                    width * std::mem::size_of::<u32>(),
+                )
+            };
+        }
+
         #[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<Bounds<f32>> {