windows: Update windows-rs crate and better error handling in DirectWrite (#12818)

- Update `windows-rs` from `0.56` to `0.57`
- Use the newly introduced `Owned` struct in `0.57` to handle the RAII
stuff of `HANDLE`
- Better error handling in `DirectWrite`

Release Notes:

- N/A
This commit is contained in:
张小白 2024-06-15 01:12:20 +08:00 committed by GitHub
parent 1413b5af93
commit 4cb45e63f4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 116 additions and 167 deletions

34
Cargo.lock generated
View File

@ -4238,7 +4238,7 @@ dependencies = [
"text", "text",
"time", "time",
"util", "util",
"windows 0.56.0", "windows 0.57.0",
] ]
[[package]] [[package]]
@ -4558,7 +4558,7 @@ dependencies = [
"unindent", "unindent",
"url", "url",
"util", "util",
"windows 0.56.0", "windows 0.57.0",
] ]
[[package]] [[package]]
@ -4781,8 +4781,8 @@ dependencies = [
"wayland-cursor", "wayland-cursor",
"wayland-protocols", "wayland-protocols",
"wayland-protocols-plasma", "wayland-protocols-plasma",
"windows 0.56.0", "windows 0.57.0",
"windows-core 0.56.0", "windows-core 0.57.0",
"x11rb", "x11rb",
"xim", "xim",
"xkbcommon", "xkbcommon",
@ -6096,7 +6096,7 @@ dependencies = [
"serde_json", "serde_json",
"smol", "smol",
"util", "util",
"windows 0.56.0", "windows 0.57.0",
] ]
[[package]] [[package]]
@ -6592,7 +6592,7 @@ dependencies = [
"tempfile", "tempfile",
"util", "util",
"walkdir", "walkdir",
"windows 0.56.0", "windows 0.57.0",
] ]
[[package]] [[package]]
@ -10440,7 +10440,7 @@ dependencies = [
"theme", "theme",
"thiserror", "thiserror",
"util", "util",
"windows 0.56.0", "windows 0.57.0",
] ]
[[package]] [[package]]
@ -11368,7 +11368,7 @@ dependencies = [
"story", "story",
"strum", "strum",
"theme", "theme",
"windows 0.56.0", "windows 0.57.0",
] ]
[[package]] [[package]]
@ -12512,11 +12512,11 @@ dependencies = [
[[package]] [[package]]
name = "windows" name = "windows"
version = "0.56.0" version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143"
dependencies = [ dependencies = [
"windows-core 0.56.0", "windows-core 0.57.0",
"windows-targets 0.52.5", "windows-targets 0.52.5",
] ]
@ -12531,9 +12531,9 @@ dependencies = [
[[package]] [[package]]
name = "windows-core" name = "windows-core"
version = "0.56.0" version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
dependencies = [ dependencies = [
"windows-implement", "windows-implement",
"windows-interface", "windows-interface",
@ -12543,9 +12543,9 @@ dependencies = [
[[package]] [[package]]
name = "windows-implement" name = "windows-implement"
version = "0.56.0" version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -12554,9 +12554,9 @@ dependencies = [
[[package]] [[package]]
name = "windows-interface" name = "windows-interface"
version = "0.56.0" version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View File

@ -410,7 +410,7 @@ wit-component = "0.201"
sys-locale = "0.3.1" sys-locale = "0.3.1"
[workspace.dependencies.windows] [workspace.dependencies.windows]
version = "0.56.0" version = "0.57"
features = [ features = [
"implement", "implement",
"Foundation_Numerics", "Foundation_Numerics",

View File

@ -139,7 +139,7 @@ xim = { git = "https://github.com/npmania/xim-rs", rev = "27132caffc5b9bc9c432ca
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
windows.workspace = true windows.workspace = true
windows-core = "0.56" windows-core = "0.57"
[target.'cfg(windows)'.build-dependencies] [target.'cfg(windows)'.build-dependencies]
embed-resource = "2.4" embed-resource = "2.4"

View File

@ -229,7 +229,14 @@ impl PlatformTextSystem for DirectWriteTextSystem {
} }
fn layout_line(&self, text: &str, font_size: Pixels, runs: &[FontRun]) -> LineLayout { fn layout_line(&self, text: &str, font_size: Pixels, runs: &[FontRun]) -> LineLayout {
self.0.write().layout_line(text, font_size, runs) self.0
.write()
.layout_line(text, font_size, runs)
.log_err()
.unwrap_or(LineLayout {
font_size,
..Default::default()
})
} }
} }
@ -296,20 +303,15 @@ impl DirectWriteState {
} else { } else {
&self.custom_font_collection &self.custom_font_collection
}; };
let Some(fontset) = collection.GetFontSet().log_err() else { let fontset = collection.GetFontSet().log_err()?;
return None; let font = fontset
};
let Some(font) = fontset
.GetMatchingFonts( .GetMatchingFonts(
&HSTRING::from(family_name), &HSTRING::from(family_name),
font_weight.into(), font_weight.into(),
DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STRETCH_NORMAL,
font_style.into(), font_style.into(),
) )
.log_err() .log_err()?;
else {
return None;
};
let total_number = font.GetFontCount(); let total_number = font.GetFontCount();
for index in 0..total_number { for index in 0..total_number {
let Some(font_face_ref) = font.GetFontFaceReference(index).log_err() else { let Some(font_face_ref) = font.GetFontFaceReference(index).log_err() else {
@ -343,11 +345,15 @@ impl DirectWriteState {
unsafe fn update_system_font_collection(&mut self) { unsafe fn update_system_font_collection(&mut self) {
let mut collection = std::mem::zeroed(); let mut collection = std::mem::zeroed();
self.components if self
.components
.factory .factory
.GetSystemFontCollection(false, &mut collection, true) .GetSystemFontCollection(false, &mut collection, true)
.unwrap(); .log_err()
self.system_font_collection = collection.unwrap(); .is_some()
{
self.system_font_collection = collection.unwrap();
}
} }
fn select_font(&mut self, target_font: &Font) -> FontId { fn select_font(&mut self, target_font: &Font) -> FontId {
@ -402,12 +408,17 @@ impl DirectWriteState {
}) })
} }
fn layout_line(&mut self, text: &str, font_size: Pixels, font_runs: &[FontRun]) -> LineLayout { fn layout_line(
&mut self,
text: &str,
font_size: Pixels,
font_runs: &[FontRun],
) -> Result<LineLayout> {
if font_runs.is_empty() { if font_runs.is_empty() {
return LineLayout { return Ok(LineLayout {
font_size, font_size,
..Default::default() ..Default::default()
}; });
} }
unsafe { unsafe {
let text_renderer = self.components.text_renderer.clone(); let text_renderer = self.components.text_renderer.clone();
@ -423,25 +434,22 @@ impl DirectWriteState {
} else { } else {
&self.custom_font_collection &self.custom_font_collection
}; };
let format = self let format = self.components.factory.CreateTextFormat(
.components &HSTRING::from(&font_info.font_family),
.factory collection,
.CreateTextFormat( font_info.font_face.GetWeight(),
&HSTRING::from(&font_info.font_family), font_info.font_face.GetStyle(),
collection, DWRITE_FONT_STRETCH_NORMAL,
font_info.font_face.GetWeight(), font_size.0,
font_info.font_face.GetStyle(), &HSTRING::from(&self.components.locale),
DWRITE_FONT_STRETCH_NORMAL, )?;
font_size.0,
&HSTRING::from(&self.components.locale),
)
.unwrap();
let layout = self let layout = self.components.factory.CreateTextLayout(
.components &text_wide,
.factory &format,
.CreateTextLayout(&text_wide, &format, f32::INFINITY, f32::INFINITY) f32::INFINITY,
.unwrap(); f32::INFINITY,
)?;
let current_text = &text[utf8_offset..(utf8_offset + first_run.len)]; let current_text = &text[utf8_offset..(utf8_offset + first_run.len)];
utf8_offset += first_run.len; utf8_offset += first_run.len;
let current_text_utf16_length = current_text.encode_utf16().count() as u32; let current_text_utf16_length = current_text.encode_utf16().count() as u32;
@ -449,9 +457,7 @@ impl DirectWriteState {
startPosition: utf16_offset, startPosition: utf16_offset,
length: current_text_utf16_length, length: current_text_utf16_length,
}; };
layout layout.SetTypography(&font_info.features, text_range)?;
.SetTypography(&font_info.features, text_range)
.unwrap();
utf16_offset += current_text_utf16_length; utf16_offset += current_text_utf16_length;
layout layout
@ -465,9 +471,7 @@ impl DirectWriteState {
first_run = false; first_run = false;
let mut metrics = vec![DWRITE_LINE_METRICS::default(); 4]; let mut metrics = vec![DWRITE_LINE_METRICS::default(); 4];
let mut line_count = 0u32; let mut line_count = 0u32;
text_layout text_layout.GetLineMetrics(Some(&mut metrics), &mut line_count as _)?;
.GetLineMetrics(Some(&mut metrics), &mut line_count as _)
.unwrap();
ascent = px(metrics[0].baseline); ascent = px(metrics[0].baseline);
descent = px(metrics[0].height - metrics[0].baseline); descent = px(metrics[0].height - metrics[0].baseline);
continue; continue;
@ -487,22 +491,13 @@ impl DirectWriteState {
length: current_text_utf16_length, length: current_text_utf16_length,
}; };
utf16_offset += current_text_utf16_length; utf16_offset += current_text_utf16_length;
text_layout.SetFontCollection(collection, text_range)?;
text_layout text_layout
.SetFontCollection(collection, text_range) .SetFontFamilyName(&HSTRING::from(&font_info.font_family), text_range)?;
.unwrap(); text_layout.SetFontSize(font_size.0, text_range)?;
text_layout text_layout.SetFontStyle(font_info.font_face.GetStyle(), text_range)?;
.SetFontFamilyName(&HSTRING::from(&font_info.font_family), text_range) text_layout.SetFontWeight(font_info.font_face.GetWeight(), text_range)?;
.unwrap(); text_layout.SetTypography(&font_info.features, text_range)?;
text_layout.SetFontSize(font_size.0, text_range).unwrap();
text_layout
.SetFontStyle(font_info.font_face.GetStyle(), text_range)
.unwrap();
text_layout
.SetFontWeight(font_info.font_face.GetWeight(), text_range)
.unwrap();
text_layout
.SetTypography(&font_info.features, text_range)
.unwrap();
} }
let mut runs = Vec::new(); let mut runs = Vec::new();
@ -513,24 +508,22 @@ impl DirectWriteState {
utf16_index: 0, utf16_index: 0,
width: 0.0, width: 0.0,
}; };
text_layout text_layout.Draw(
.Draw( Some(&renderer_context as *const _ as _),
Some(&renderer_context as *const _ as _), &text_renderer.0,
&text_renderer.0, 0.0,
0.0, 0.0,
0.0, )?;
)
.unwrap();
let width = px(renderer_context.width); let width = px(renderer_context.width);
LineLayout { Ok(LineLayout {
font_size, font_size,
width, width,
ascent, ascent,
descent, descent,
runs, runs,
len: text.len(), len: text.len(),
} })
} }
} }
@ -979,7 +972,6 @@ impl IDWriteTextRenderer_Impl for TextRenderer {
let Some((font_identifier, font_struct, is_emoji)) = let Some((font_identifier, font_struct, is_emoji)) =
get_font_identifier_and_font_struct(font_face, &self.locale) get_font_identifier_and_font_struct(font_face, &self.locale)
else { else {
log::error!("none postscript name found");
return Ok(()); return Ok(());
}; };
@ -1142,7 +1134,7 @@ fn get_font_names_from_collection(
let Some(localized_family_name) = font_family.GetFamilyNames().log_err() else { let Some(localized_family_name) = font_family.GetFamilyNames().log_err() else {
continue; continue;
}; };
let Some(family_name) = get_name(localized_family_name, locale) else { let Some(family_name) = get_name(localized_family_name, locale).log_err() else {
continue; continue;
}; };
result.push(family_name); result.push(family_name);
@ -1156,15 +1148,9 @@ fn get_font_identifier_and_font_struct(
font_face: &IDWriteFontFace3, font_face: &IDWriteFontFace3,
locale: &str, locale: &str,
) -> Option<(FontIdentifier, Font, bool)> { ) -> Option<(FontIdentifier, Font, bool)> {
let Some(postscript_name) = get_postscript_name(font_face, locale) else { let postscript_name = get_postscript_name(font_face, locale).log_err()?;
return None; let localized_family_name = unsafe { font_face.GetFamilyNames().log_err() }?;
}; let family_name = get_name(localized_family_name, locale).log_err()?;
let Some(localized_family_name) = (unsafe { font_face.GetFamilyNames().log_err() }) else {
return None;
};
let Some(family_name) = get_name(localized_family_name, locale) else {
return None;
};
let weight = unsafe { font_face.GetWeight() }; let weight = unsafe { font_face.GetWeight() };
let style = unsafe { font_face.GetStyle() }; let style = unsafe { font_face.GetStyle() };
let identifier = FontIdentifier { let identifier = FontIdentifier {
@ -1186,28 +1172,28 @@ fn get_font_identifier_and_font_struct(
fn get_font_identifier(font_face: &IDWriteFontFace3, locale: &str) -> Option<FontIdentifier> { fn get_font_identifier(font_face: &IDWriteFontFace3, locale: &str) -> Option<FontIdentifier> {
let weight = unsafe { font_face.GetWeight().0 }; let weight = unsafe { font_face.GetWeight().0 };
let style = unsafe { font_face.GetStyle().0 }; let style = unsafe { font_face.GetStyle().0 };
get_postscript_name(font_face, locale).map(|postscript_name| FontIdentifier { get_postscript_name(font_face, locale)
postscript_name, .log_err()
weight, .map(|postscript_name| FontIdentifier {
style, postscript_name,
}) weight,
style,
})
} }
#[inline] #[inline]
fn get_postscript_name(font_face: &IDWriteFontFace3, locale: &str) -> Option<String> { fn get_postscript_name(font_face: &IDWriteFontFace3, locale: &str) -> Result<String> {
let mut info = None; let mut info = None;
let mut exists = BOOL(0); let mut exists = BOOL(0);
unsafe { unsafe {
font_face font_face.GetInformationalStrings(
.GetInformationalStrings( DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME,
DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME, &mut info,
&mut info, &mut exists,
&mut exists, )?
) };
.log_err();
}
if !exists.as_bool() || info.is_none() { if !exists.as_bool() || info.is_none() {
return None; return Err(anyhow!("No postscript name found for font face"));
} }
get_name(info.unwrap(), locale) get_name(info.unwrap(), locale)
@ -1281,40 +1267,36 @@ fn make_direct_write_tag(tag_name: &str) -> DWRITE_FONT_FEATURE_TAG {
} }
#[inline] #[inline]
fn get_name(string: IDWriteLocalizedStrings, locale: &str) -> Option<String> { fn get_name(string: IDWriteLocalizedStrings, locale: &str) -> Result<String> {
let mut locale_name_index = 0u32; let mut locale_name_index = 0u32;
let mut exists = BOOL(0); let mut exists = BOOL(0);
unsafe { unsafe {
string string.FindLocaleName(
.FindLocaleName( &HSTRING::from(locale),
&HSTRING::from(locale), &mut locale_name_index,
&mut locale_name_index, &mut exists as _,
&mut exists as _, )?
) };
.log_err();
}
if !exists.as_bool() { if !exists.as_bool() {
unsafe { unsafe {
string string.FindLocaleName(
.FindLocaleName( DEFAULT_LOCALE_NAME,
DEFAULT_LOCALE_NAME, &mut locale_name_index as _,
&mut locale_name_index as _, &mut exists as _,
&mut exists as _, )?
) };
.log_err();
}
if !exists.as_bool() { if !exists.as_bool() {
return None; return Err(anyhow!("No localised string for {}", locale));
} }
} }
let name_length = unsafe { string.GetStringLength(locale_name_index).unwrap() } as usize; let name_length = unsafe { string.GetStringLength(locale_name_index) }? as usize;
let mut name_vec = vec![0u16; name_length + 1]; let mut name_vec = vec![0u16; name_length + 1];
unsafe { unsafe {
string.GetString(locale_name_index, &mut name_vec).unwrap(); string.GetString(locale_name_index, &mut name_vec)?;
} }
Some(String::from_utf16_lossy(&name_vec[..name_length])) Ok(String::from_utf16_lossy(&name_vec[..name_length]))
} }
#[inline] #[inline]

View File

@ -162,16 +162,11 @@ impl Platform for WindowsPlatform {
fn run(&self, on_finish_launching: Box<dyn 'static + FnOnce()>) { fn run(&self, on_finish_launching: Box<dyn 'static + FnOnce()>) {
on_finish_launching(); on_finish_launching();
let vsync_event = create_event().unwrap(); let vsync_event = unsafe { Owned::new(CreateEventW(None, false, false, None).unwrap()) };
begin_vsync(vsync_event.to_raw()); begin_vsync(*vsync_event);
'a: loop { 'a: loop {
let wait_result = unsafe { let wait_result = unsafe {
MsgWaitForMultipleObjects( MsgWaitForMultipleObjects(Some(&[*vsync_event]), false, INFINITE, QS_ALLINPUT)
Some(&[vsync_event.to_raw()]),
false,
INFINITE,
QS_ALLINPUT,
)
}; };
match wait_result { match wait_result {

View File

@ -1,7 +1,7 @@
use std::sync::OnceLock; use std::sync::OnceLock;
use ::util::ResultExt; use ::util::ResultExt;
use windows::Win32::{Foundation::*, System::Threading::*, UI::WindowsAndMessaging::*}; use windows::Win32::{Foundation::*, UI::WindowsAndMessaging::*};
use crate::*; use crate::*;
@ -74,34 +74,6 @@ pub(crate) unsafe fn set_window_long(
} }
} }
#[derive(Debug, Clone)]
pub(crate) struct OwnedHandle(HANDLE);
impl OwnedHandle {
pub(crate) fn new(handle: HANDLE) -> Self {
Self(handle)
}
#[inline(always)]
pub(crate) fn to_raw(&self) -> HANDLE {
self.0
}
}
impl Drop for OwnedHandle {
fn drop(&mut self) {
if !self.0.is_invalid() {
unsafe { CloseHandle(self.0) }.log_err();
}
}
}
pub(crate) fn create_event() -> windows::core::Result<OwnedHandle> {
Ok(OwnedHandle::new(unsafe {
CreateEventW(None, false, false, None)?
}))
}
pub(crate) fn windows_credentials_target_name(url: &str) -> String { pub(crate) fn windows_credentials_target_name(url: &str) -> String {
format!("zed:url={}", url) format!("zed:url={}", url)
} }