windows: Introduce Direct Write (#10119)

This PR brings `Direct Write` to Zed. Now, Zed first trys to query
dwrite interface, if not supported, which means runing on Windows below
win10 1703), will choose `cosmic` as a fallback text system.

This direct write text system supports:
- Full font features support
- Emoji support
- Default system fonts as fallback

### Font features


https://github.com/zed-industries/zed/assets/14981363/198eff88-47df-4bc8-a257-e3acf81fd61d

### Emoji

![Screenshot 2024-04-03
211354](https://github.com/zed-industries/zed/assets/14981363/a5bc5845-42e8-4af1-af7e-abba598c1e72)

**Note: input emoji through IME or IMM not working yet, copy paste emoji
works fine (will be fixed by #10125 )**

### Font fallback

I use `Zed mono` which dose not support chinese chars to test font
fallback



https://github.com/zed-industries/zed/assets/14981363/c97d0847-0ac5-47e6-aa00-f3ce6d1e50a5



Release Notes:

- N/A
This commit is contained in:
张小白 2024-04-19 02:58:46 +08:00 committed by GitHub
parent 1127b1a0de
commit 11a3d2b04b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 1329 additions and 8 deletions

View file

@ -26,6 +26,29 @@ macro_rules! create_definitions {
}
}
)*
/// Get the tag name list of the font OpenType features
/// only enabled or disabled features are returned
#[cfg(target_os = "windows")]
pub fn tag_value_list(&self) -> Vec<(String, bool)> {
let mut result = Vec::new();
$(
{
let value = if (self.enabled & (1 << $idx)) != 0 {
Some(true)
} else if (self.disabled & (1 << $idx)) != 0 {
Some(false)
} else {
None
};
if let Some(enable) = value {
let tag_name = stringify!($name).to_owned();
result.push((tag_name, enable));
}
}
)*
result
}
}
impl std::fmt::Debug for FontFeatures {
@ -94,9 +117,11 @@ macro_rules! create_definitions {
let mut map = serializer.serialize_map(None)?;
$(
let feature = stringify!($name);
if let Some(value) = self.$name() {
map.serialize_entry(feature, &value)?;
{
let feature = stringify!($name);
if let Some(value) = self.$name() {
map.serialize_entry(feature, &value)?;
}
}
)*
@ -161,5 +186,5 @@ create_definitions!(
(swsh, 30),
(titl, 31),
(tnum, 32),
(zero, 33)
(zero, 33),
);