@@ -16,9 +16,11 @@ use windows::{
Direct2D::{Common::*, *},
DirectWrite::*,
Dxgi::Common::*,
+ Gdi::LOGFONTW,
Imaging::{D2D::IWICImagingFactory2, *},
},
System::{Com::*, SystemServices::LOCALE_NAME_MAX_LENGTH},
+ UI::WindowsAndMessaging::*,
},
};
@@ -51,6 +53,7 @@ unsafe impl Send for DirectWriteComponent {}
struct DirectWriteState {
components: DirectWriteComponent,
+ system_ui_font_name: SharedString,
system_font_collection: IDWriteFontCollection1,
custom_font_collection: IDWriteFontCollection1,
fonts: Vec<FontInfo>,
@@ -106,9 +109,11 @@ impl DirectWriteTextSystem {
.factory
.CreateFontCollectionFromFontSet(&custom_font_set)?
};
+ let system_ui_font_name = get_system_ui_font_name();
Ok(Self(RwLock::new(DirectWriteState {
components,
+ system_ui_font_name,
system_font_collection,
custom_font_collection,
fonts: Vec::new(),
@@ -309,53 +314,55 @@ impl DirectWriteState {
}
fn select_font(&mut self, target_font: &Font) -> FontId {
- let family_name = if target_font.family == ".SystemUIFont" {
- // https://learn.microsoft.com/en-us/windows/win32/uxguide/vis-fonts
- // Segoe UI is the Windows font intended for user interface text strings.
- "Segoe UI"
- } else {
- target_font.family.as_ref()
- };
unsafe {
- // try to find target font in custom font collection first
- self.get_font_id_from_font_collection(
- family_name,
- target_font.weight,
- target_font.style,
- &target_font.features,
- false,
- )
- .or_else(|| {
- self.get_font_id_from_font_collection(
- family_name,
+ if target_font.family == ".SystemUIFont" {
+ let family = self.system_ui_font_name.clone();
+ self.find_font_id(
+ family.as_ref(),
target_font.weight,
target_font.style,
&target_font.features,
- true,
)
- })
- .or_else(|| {
- self.update_system_font_collection();
- self.get_font_id_from_font_collection(
- family_name,
+ .unwrap()
+ } else {
+ self.find_font_id(
+ target_font.family.as_ref(),
target_font.weight,
target_font.style,
&target_font.features,
- true,
)
+ .unwrap_or_else(|| {
+ let family = self.system_ui_font_name.clone();
+ log::error!("{} not found, use {} instead.", target_font.family, family);
+ self.get_font_id_from_font_collection(
+ family.as_ref(),
+ target_font.weight,
+ target_font.style,
+ &target_font.features,
+ true,
+ )
+ .unwrap()
+ })
+ }
+ }
+ }
+
+ unsafe fn find_font_id(
+ &mut self,
+ family_name: &str,
+ weight: FontWeight,
+ style: FontStyle,
+ features: &FontFeatures,
+ ) -> Option<FontId> {
+ // try to find target font in custom font collection first
+ self.get_font_id_from_font_collection(family_name, weight, style, features, false)
+ .or_else(|| {
+ self.get_font_id_from_font_collection(family_name, weight, style, features, true)
})
.or_else(|| {
- log::error!("{} not found, use Arial instead.", family_name);
- self.get_font_id_from_font_collection(
- "Arial",
- target_font.weight,
- target_font.style,
- &target_font.features,
- false,
- )
+ self.update_system_font_collection();
+ self.get_font_id_from_font_collection(family_name, weight, style, features, true)
})
- .unwrap()
- }
}
fn layout_line(&mut self, text: &str, font_size: Pixels, font_runs: &[FontRun]) -> LineLayout {
@@ -1271,6 +1278,29 @@ fn translate_color(color: &DWRITE_COLOR_F) -> D2D1_COLOR_F {
}
}
+fn get_system_ui_font_name() -> SharedString {
+ unsafe {
+ let mut info: LOGFONTW = std::mem::zeroed();
+ let font_family = if SystemParametersInfoW(
+ SPI_GETICONTITLELOGFONT,
+ std::mem::size_of::<LOGFONTW>() as u32,
+ Some(&mut info as *mut _ as _),
+ SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS(0),
+ )
+ .log_err()
+ .is_none()
+ {
+ // https://learn.microsoft.com/en-us/windows/win32/uxguide/vis-fonts
+ // Segoe UI is the Windows font intended for user interface text strings.
+ "Segoe UI".into()
+ } else {
+ String::from_utf16_lossy(&info.lfFaceName).into()
+ };
+ log::info!("Use {} as UI font.", font_family);
+ font_family
+ }
+}
+
const DEFAULT_LOCALE_NAME: PCWSTR = windows::core::w!("en-US");
const BRUSH_COLOR: D2D1_COLOR_F = D2D1_COLOR_F {
r: 1.0,