Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pbr = "1.0"
prettytable-rs = "0.10"

[target.'cfg(target_family = "windows")'.dependencies]
dwrote = { version = "^0.11.3", default-features = false }
dwrote = { git = "https://github.com/warpdotdev/dwrote-rs", rev = "a71ce6c0136f7d0954a9a8b181b5b2d8ace5eb9c", default-features = false }

[target.'cfg(target_family = "windows")'.dependencies.winapi]
version = "0.3"
Expand Down
56 changes: 37 additions & 19 deletions src/loaders/directwrite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,9 @@ impl Font {
let Ok(dwrite_font) = family.font(family_font_index) else {
continue;
};
let dwrite_font_face = dwrite_font.create_font_face();
let Ok(dwrite_font_face) = dwrite_font.create_font_face() else {
continue;
};
return Ok(Font {
dwrite_font,
dwrite_font_face,
Expand Down Expand Up @@ -224,7 +226,7 @@ impl Font {
#[inline]
pub fn postscript_name(&self) -> Option<String> {
let dwrite_font = &self.dwrite_font;
dwrite_font.informational_string(DWriteInformationalStringId::PostscriptName)
dwrite_font.informational_string(DWriteInformationalStringId::PostscriptName).ok()?
}

/// Returns the full name of the font (also known as "display name" on macOS).
Expand All @@ -233,13 +235,15 @@ impl Font {
let dwrite_font = &self.dwrite_font;
dwrite_font
.informational_string(DWriteInformationalStringId::FullName)
.unwrap_or_else(|| dwrite_font.family_name())
.ok()
.flatten()
.unwrap_or_else(|| dwrite_font.family_name().unwrap_or_default())
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh I don't love the unwrap_or_default here. This should probably return a Result too but AFAICT getting the full name from an existing Font struct is for displaying the the user and for that purpose an empty string seems fine. That's all we use it for:

https://github.com/warpdotdev/warp-internal/blob/101359bbe9406fee3b095cdcc05bdc8930d11b20/crates/warpui/src/windowing/winit/fonts/windows.rs#L221-L221

}

/// Returns the name of the font family.
#[inline]
pub fn family_name(&self) -> String {
self.dwrite_font.family_name()
self.dwrite_font.family_name().unwrap_or_default()
}

/// Returns true if and only if the font is monospace (fixed-width).
Expand All @@ -265,8 +269,10 @@ impl Font {
/// use cases like "what does character X look like on its own".
pub fn glyph_for_char(&self, character: char) -> Option<u32> {
let chars = [character as u32];
self.dwrite_font_face
.get_glyph_indices(&chars)
let indices = self.dwrite_font_face
.glyph_indices(&chars)
.ok()?;
indices
.into_iter()
.next()
.and_then(|g| {
Expand Down Expand Up @@ -304,15 +310,15 @@ impl Font {
S: OutlineSink,
{
let outline_sink = OutlineCanonicalizer::new();
self.dwrite_font_face.get_glyph_run_outline(
self.dwrite_font_face.glyph_run_outline(
self.metrics().units_per_em as f32,
&[glyph_id as u16],
None,
None,
false,
false,
Box::new(outline_sink.clone()),
);
).map_err(|_| GlyphLoadingError::NoSuchGlyph)?;
outline_sink
.0
.lock()
Expand All @@ -327,7 +333,8 @@ impl Font {
pub fn typographic_bounds(&self, glyph_id: u32) -> Result<RectF, GlyphLoadingError> {
let metrics = self
.dwrite_font_face
.get_design_glyph_metrics(&[glyph_id as u16], false);
.design_glyph_metrics(&[glyph_id as u16], false)
.map_err(|_| GlyphLoadingError::NoSuchGlyph)?;

let metrics = &metrics[0];
let advance_width = metrics.advanceWidth as i32;
Expand All @@ -354,7 +361,8 @@ impl Font {
pub fn advance(&self, glyph_id: u32) -> Result<Vector2F, GlyphLoadingError> {
let metrics = self
.dwrite_font_face
.get_design_glyph_metrics(&[glyph_id as u16], false);
.design_glyph_metrics(&[glyph_id as u16], false)
.map_err(|_| GlyphLoadingError::NoSuchGlyph)?;
let metrics = &metrics[0];
Ok(Vector2F::new(metrics.advanceWidth as f32, 0.0))
}
Expand All @@ -363,7 +371,8 @@ impl Font {
pub fn origin(&self, glyph: u32) -> Result<Vector2F, GlyphLoadingError> {
let metrics = self
.dwrite_font_face
.get_design_glyph_metrics(&[glyph as u16], false);
.design_glyph_metrics(&[glyph as u16], false)
.map_err(|_| GlyphLoadingError::NoSuchGlyph)?;
Ok(Vector2I::new(
metrics[0].leftSideBearing,
metrics[0].verticalOriginY + metrics[0].bottomSideBearing,
Expand Down Expand Up @@ -400,7 +409,9 @@ impl Font {
DWriteFontMetrics::Metrics0(metrics) => {
let bounding_box = match self
.dwrite_font_face
.get_font_table(OPENTYPE_TABLE_TAG_HEAD.swap_bytes())
.font_table(OPENTYPE_TABLE_TAG_HEAD.swap_bytes())
.ok()
.flatten()
{
Some(head) => {
let mut reader = &head[36..];
Expand Down Expand Up @@ -446,10 +457,13 @@ impl Font {
pub fn copy_font_data(&self) -> Option<Arc<Vec<u8>>> {
let mut font_data = self.cached_data.lock().unwrap();
if font_data.is_none() {
let files = self.dwrite_font_face.get_files();
// FIXME(pcwalton): Is this right? When can a font have multiple files?
if let Some(file) = files.get(0) {
*font_data = Some(Arc::new(file.get_font_file_bytes()))
if let Ok(files) = self.dwrite_font_face.files() {
// FIXME(pcwalton): Is this right? When can a font have multiple files?
if let Some(file) = files.get(0) {
if let Ok(bytes) = file.font_file_bytes() {
*font_data = Some(Arc::new(bytes))
}
}
}
}
(*font_data).clone()
Expand Down Expand Up @@ -668,14 +682,16 @@ impl Font {
0,
text_utf16_len,
&collection,
Some(&self.dwrite_font.family_name()),
self.dwrite_font.family_name().ok().as_deref(),
self.dwrite_font.weight(),
self.dwrite_font.style(),
self.dwrite_font.stretch(),
);
let valid_len = convert_len_utf16_to_utf8(text, fallback_result.mapped_length);
let fonts = if let Some(dwrite_font) = fallback_result.mapped_font {
let dwrite_font_face = dwrite_font.create_font_face();
let Ok(dwrite_font_face) = dwrite_font.create_font_face() else {
return FallbackResult { fonts: vec![], valid_len };
};
let font = Font {
dwrite_font,
dwrite_font_face,
Expand All @@ -699,7 +715,9 @@ impl Font {
/// [OpenType specification]: https://docs.microsoft.com/en-us/typography/opentype/spec/
pub fn load_font_table(&self, table_tag: u32) -> Option<Box<[u8]>> {
self.dwrite_font_face
.get_font_table(table_tag.swap_bytes())
.font_table(table_tag.swap_bytes())
.ok()
.flatten()
.map(|v| v.into())
}
}
Expand Down
31 changes: 22 additions & 9 deletions src/sources/directwrite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@

use dwrote::Font as DWriteFont;
use dwrote::FontCollection as DWriteFontCollection;
use dwrote::HRESULT;
use std::any::Any;
use winapi::shared::winerror;

use crate::error::SelectionError;
use crate::family_handle::FamilyHandle;
Expand Down Expand Up @@ -44,7 +46,10 @@ impl DirectWriteSource {
let Ok(dwrite_font) = dwrite_family.font(font_index) else {
continue;
};
handles.push(self.create_handle_from_dwrite_font(dwrite_font))
let Ok(handle) = self.create_handle_from_dwrite_font(dwrite_font) else {
continue;
};
handles.push(handle)
}
}

Expand Down Expand Up @@ -73,7 +78,10 @@ impl DirectWriteSource {
let Ok(dwrite_font) = dwrite_family.font(font_index) else {
continue;
};
family.push(self.create_handle_from_dwrite_font(dwrite_font));
let Ok(handle) = self.create_handle_from_dwrite_font(dwrite_font) else {
continue;
};
family.push(handle);
}
Ok(family)
}
Expand All @@ -100,13 +108,18 @@ impl DirectWriteSource {
<Self as Source>::select_best_match(self, family_names, properties)
}

fn create_handle_from_dwrite_font(&self, dwrite_font: DWriteFont) -> Handle {
let dwrite_font_face = dwrite_font.create_font_face();
let dwrite_font_files = dwrite_font_face.get_files();
Handle::Path {
path: dwrite_font_files[0].get_font_file_path().unwrap(),
font_index: dwrite_font_face.get_index(),
}
fn create_handle_from_dwrite_font(&self, dwrite_font: DWriteFont) -> Result<Handle, HRESULT> {
let font_face = dwrite_font.create_font_face()?;
let path = font_face
.files()?
.into_iter()
.next()
.ok_or(winerror::E_FAIL)?
.font_file_path()?;
Ok(Handle::Path {
path,
font_index: font_face.get_index(),
})
}
}

Expand Down
Loading