diff --git a/crates/gpui/src/platform/test/platform.rs b/crates/gpui/src/platform/test/platform.rs index 15b909199f..39f7f235d2 100644 --- a/crates/gpui/src/platform/test/platform.rs +++ b/crates/gpui/src/platform/test/platform.rs @@ -15,11 +15,6 @@ use std::{ rc::{Rc, Weak}, sync::Arc, }; -#[cfg(target_os = "windows")] -use windows::Win32::{ - Graphics::Imaging::{CLSID_WICImagingFactory, IWICImagingFactory}, - System::Com::{CLSCTX_INPROC_SERVER, CoCreateInstance}, -}; /// TestPlatform implements the Platform trait for use in tests. pub(crate) struct TestPlatform { @@ -36,8 +31,6 @@ pub(crate) struct TestPlatform { screen_capture_sources: RefCell>, pub opened_url: RefCell>, pub text_system: Arc, - #[cfg(target_os = "windows")] - bitmap_factory: std::mem::ManuallyDrop, weak: Weak, } @@ -92,16 +85,6 @@ pub(crate) struct TestPrompts { impl TestPlatform { pub fn new(executor: BackgroundExecutor, foreground_executor: ForegroundExecutor) -> Rc { - #[cfg(target_os = "windows")] - let bitmap_factory = unsafe { - windows::Win32::System::Ole::OleInitialize(None) - .expect("unable to initialize Windows OLE"); - std::mem::ManuallyDrop::new( - CoCreateInstance(&CLSID_WICImagingFactory, None, CLSCTX_INPROC_SERVER) - .expect("Error creating bitmap factory."), - ) - }; - let text_system = Arc::new(NoopTextSystem); Rc::new_cyclic(|weak| TestPlatform { @@ -117,8 +100,6 @@ impl TestPlatform { current_primary_item: Mutex::new(None), weak: weak.clone(), opened_url: Default::default(), - #[cfg(target_os = "windows")] - bitmap_factory, text_system, }) } @@ -440,16 +421,6 @@ impl TestScreenCaptureSource { } } -#[cfg(target_os = "windows")] -impl Drop for TestPlatform { - fn drop(&mut self) { - unsafe { - std::mem::ManuallyDrop::drop(&mut self.bitmap_factory); - windows::Win32::System::Ole::OleUninitialize(); - } - } -} - struct TestKeyboardLayout; impl PlatformKeyboardLayout for TestKeyboardLayout { diff --git a/crates/gpui/src/platform/windows/direct_write.rs b/crates/gpui/src/platform/windows/direct_write.rs index a86a1fab62..c10a284492 100644 --- a/crates/gpui/src/platform/windows/direct_write.rs +++ b/crates/gpui/src/platform/windows/direct_write.rs @@ -15,7 +15,6 @@ use windows::{ DirectWrite::*, Dxgi::Common::*, Gdi::{IsRectEmpty, LOGFONTW}, - Imaging::*, }, System::SystemServices::LOCALE_NAME_MAX_LENGTH, UI::WindowsAndMessaging::*, @@ -40,7 +39,6 @@ pub(crate) struct DirectWriteTextSystem(RwLock); struct DirectWriteComponent { locale: String, factory: IDWriteFactory5, - bitmap_factory: AgileReference, in_memory_loader: IDWriteInMemoryFontFileLoader, builder: IDWriteFontSetBuilder1, text_renderer: Arc, @@ -76,11 +74,10 @@ struct FontIdentifier { } impl DirectWriteComponent { - pub fn new(bitmap_factory: &IWICImagingFactory, gpu_context: &DirectXDevices) -> Result { + pub fn new(gpu_context: &DirectXDevices) -> Result { // todo: ideally this would not be a large unsafe block but smaller isolated ones for easier auditing unsafe { let factory: IDWriteFactory5 = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED)?; - let bitmap_factory = AgileReference::new(bitmap_factory)?; // The `IDWriteInMemoryFontFileLoader` here is supported starting from // Windows 10 Creators Update, which consequently requires the entire // `DirectWriteTextSystem` to run on `win10 1703`+. @@ -117,7 +114,6 @@ impl DirectWriteComponent { Ok(DirectWriteComponent { locale, factory, - bitmap_factory, in_memory_loader, builder, text_renderer, @@ -212,11 +208,8 @@ impl GPUState { } impl DirectWriteTextSystem { - pub(crate) fn new( - gpu_context: &DirectXDevices, - bitmap_factory: &IWICImagingFactory, - ) -> Result { - let components = DirectWriteComponent::new(bitmap_factory, gpu_context)?; + pub(crate) fn new(gpu_context: &DirectXDevices) -> Result { + let components = DirectWriteComponent::new(gpu_context)?; let system_font_collection = unsafe { let mut result = std::mem::zeroed(); components @@ -782,8 +775,8 @@ impl DirectWriteState { rendering_mode, DWRITE_MEASURING_MODE_NATURAL, grid_fit_mode, - // We're using cleartype not grayscale for monochrome is because it provides better quality - DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE, + // Use grayscale antialiasing for consistent quality across all color combinations + DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE, baseline_origin_x, baseline_origin_y, ) @@ -794,8 +787,8 @@ impl DirectWriteState { fn raster_bounds(&self, params: &RenderGlyphParams) -> Result> { let glyph_analysis = self.create_glyph_run_analysis(params)?; - let bounds = unsafe { glyph_analysis.GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1)? }; - // Some glyphs cannot be drawn with ClearType, such as bitmap fonts. In that case + let bounds = unsafe { glyph_analysis.GetAlphaTextureBounds(DWRITE_TEXTURE_ALIASED_1x1)? }; + // Some glyphs cannot be drawn with antialiasing, such as bitmap fonts. In that case // GetAlphaTextureBounds() supposedly returns an empty RECT, but I haven't tested that yet. if !unsafe { IsRectEmpty(&bounds) }.as_bool() { Ok(Bounds { @@ -871,49 +864,25 @@ impl DirectWriteState { params: &RenderGlyphParams, glyph_bounds: Bounds, ) -> Result> { - let mut bitmap_data = - vec![0u8; glyph_bounds.size.width.0 as usize * glyph_bounds.size.height.0 as usize * 3]; + // Use single-channel grayscale data directly from DirectWrite + let mut grayscale_data = + vec![0u8; glyph_bounds.size.width.0 as usize * glyph_bounds.size.height.0 as usize]; let glyph_analysis = self.create_glyph_run_analysis(params)?; unsafe { glyph_analysis.CreateAlphaTexture( - // We're using cleartype not grayscale for monochrome is because it provides better quality - DWRITE_TEXTURE_CLEARTYPE_3x1, + DWRITE_TEXTURE_ALIASED_1x1, &RECT { left: glyph_bounds.origin.x.0, top: glyph_bounds.origin.y.0, right: glyph_bounds.size.width.0 + glyph_bounds.origin.x.0, bottom: glyph_bounds.size.height.0 + glyph_bounds.origin.y.0, }, - &mut bitmap_data, + &mut grayscale_data, )?; } - let bitmap_factory = self.components.bitmap_factory.resolve()?; - let bitmap = unsafe { - bitmap_factory.CreateBitmapFromMemory( - glyph_bounds.size.width.0 as u32, - glyph_bounds.size.height.0 as u32, - &GUID_WICPixelFormat24bppRGB, - glyph_bounds.size.width.0 as u32 * 3, - &bitmap_data, - ) - }?; - - let grayscale_bitmap = - unsafe { WICConvertBitmapSource(&GUID_WICPixelFormat8bppGray, &bitmap) }?; - - let mut bitmap_data = - vec![0u8; glyph_bounds.size.width.0 as usize * glyph_bounds.size.height.0 as usize]; - unsafe { - grayscale_bitmap.CopyPixels( - std::ptr::null() as _, - glyph_bounds.size.width.0 as u32, - &mut bitmap_data, - ) - }?; - - Ok(bitmap_data) + Ok(grayscale_data) } fn rasterize_color( @@ -981,25 +950,24 @@ impl DirectWriteState { DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC, DWRITE_MEASURING_MODE_NATURAL, DWRITE_GRID_FIT_MODE_DEFAULT, - DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE, + DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE, baseline_origin_x, baseline_origin_y, ) }?; let color_bounds = - unsafe { color_analysis.GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1) }?; + unsafe { color_analysis.GetAlphaTextureBounds(DWRITE_TEXTURE_ALIASED_1x1) }?; 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]; + let mut alpha_data = vec![0u8; (color_size.width * color_size.height) as usize]; unsafe { color_analysis.CreateAlphaTexture( - DWRITE_TEXTURE_CLEARTYPE_3x1, + DWRITE_TEXTURE_ALIASED_1x1, &color_bounds, &mut alpha_data, ) @@ -1016,8 +984,8 @@ impl DirectWriteState { }; 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]) + .iter() + .flat_map(|&alpha| [255, 255, 255, alpha]) .collect::>(); glyph_layers.push(GlyphLayerTexture::new( &self.components.gpu_state, diff --git a/crates/gpui/src/platform/windows/platform.rs b/crates/gpui/src/platform/windows/platform.rs index 5ac2be2f23..41400635a1 100644 --- a/crates/gpui/src/platform/windows/platform.rs +++ b/crates/gpui/src/platform/windows/platform.rs @@ -1,7 +1,6 @@ use std::{ cell::RefCell, ffi::OsStr, - mem::ManuallyDrop, path::{Path, PathBuf}, rc::Rc, sync::Arc, @@ -18,10 +17,7 @@ use windows::{ UI::ViewManagement::UISettings, Win32::{ Foundation::*, - Graphics::{ - Gdi::*, - Imaging::{CLSID_WICImagingFactory, IWICImagingFactory}, - }, + Graphics::Gdi::*, Security::Credentials::*, System::{Com::*, LibraryLoader::*, Ole::*, SystemInformation::*, Threading::*}, UI::{Input::KeyboardAndMouse::*, Shell::*, WindowsAndMessaging::*}, @@ -41,7 +37,6 @@ pub(crate) struct WindowsPlatform { foreground_executor: ForegroundExecutor, text_system: Arc, windows_version: WindowsVersion, - bitmap_factory: ManuallyDrop, drop_target_helper: IDropTargetHelper, validation_number: usize, main_thread_id_win32: u32, @@ -101,12 +96,8 @@ impl WindowsPlatform { let foreground_executor = ForegroundExecutor::new(dispatcher); let directx_devices = DirectXDevices::new(disable_direct_composition) .context("Unable to init directx devices.")?; - let bitmap_factory = ManuallyDrop::new(unsafe { - CoCreateInstance(&CLSID_WICImagingFactory, None, CLSCTX_INPROC_SERVER) - .context("Error creating bitmap factory.")? - }); let text_system = Arc::new( - DirectWriteTextSystem::new(&directx_devices, &bitmap_factory) + DirectWriteTextSystem::new(&directx_devices) .context("Error creating DirectWriteTextSystem")?, ); let drop_target_helper: IDropTargetHelper = unsafe { @@ -128,7 +119,6 @@ impl WindowsPlatform { text_system, disable_direct_composition, windows_version, - bitmap_factory, drop_target_helper, validation_number, main_thread_id_win32, @@ -716,7 +706,6 @@ impl Platform for WindowsPlatform { impl Drop for WindowsPlatform { fn drop(&mut self) { unsafe { - ManuallyDrop::drop(&mut self.bitmap_factory); OleUninitialize(); } } diff --git a/crates/gpui/src/platform/windows/shaders.hlsl b/crates/gpui/src/platform/windows/shaders.hlsl index 6fabe859e3..f69122124c 100644 --- a/crates/gpui/src/platform/windows/shaders.hlsl +++ b/crates/gpui/src/platform/windows/shaders.hlsl @@ -1098,6 +1098,18 @@ MonochromeSpriteVertexOutput monochrome_sprite_vertex(uint vertex_id: SV_VertexI float4 monochrome_sprite_fragment(MonochromeSpriteFragmentInput input): SV_Target { float sample = t_sprite.Sample(s_sprite, input.tile_position).r; + + float textLuminance = dot(input.color.rgb, float3(0.2126, 0.7152, 0.0722)); + bool isLightText = textLuminance > 0.5; + + if (isLightText) { + // Stronger gamma correction - try values from 0.4 to 0.6 + sample = pow(sample, 0.45); + + // More aggressive bias to strengthen thin features + sample = saturate(sample * 1.2 - 0.1); + } + return float4(input.color.rgb, input.color.a * sample); }