mirror of
https://github.com/servo/servo.git
synced 2025-08-26 07:38:21 +01:00
fonts: Add font variations support for Windows (#38831)
Unlike other platforms where we read the default axis values and combine it with variations from style to make the font face, we set the variations from the style when creating the font face and then read the final variations from the face. It seems that DirectWrite does the normalization of variation values internally. This depends on servo/dwrote-rs#68. Testing: We currently don't have tests for Windows, but variation support is covered by the WPT tests. Fixes: This is part of #38800. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
16ba172ba8
commit
2ac8665e03
3 changed files with 63 additions and 17 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -2174,9 +2174,9 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dwrote"
|
name = "dwrote"
|
||||||
version = "0.11.3"
|
version = "0.11.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bfe1f192fcce01590bd8d839aca53ce0d11d803bf291b2a6c4ad925a8f0024be"
|
checksum = "20c93d234bac0cdd0e2ac08bc8a5133f8df2169e95b262dfcea5e5cb7855672f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -4903,7 +4903,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
|
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"windows-targets 0.48.5",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -10079,7 +10079,7 @@ version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22"
|
checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -73,7 +73,7 @@ fontconfig_sys = { package = "yeslogic-fontconfig-sys", version = "6" }
|
||||||
xml-rs = "0.8"
|
xml-rs = "0.8"
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
dwrote = "0.11.2"
|
dwrote = "0.11.4"
|
||||||
truetype = { version = "0.47.3", features = ["ignore-invalid-language-ids"] }
|
truetype = { version = "0.47.3", features = ["ignore-invalid-language-ids"] }
|
||||||
|
|
||||||
[lints.rust]
|
[lints.rust]
|
||||||
|
|
|
@ -12,7 +12,9 @@ use std::ops::Deref;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use dwrote::{FontCollection, FontFace, FontFile};
|
use dwrote::{
|
||||||
|
DWRITE_FONT_AXIS_VALUE, DWRITE_FONT_SIMULATIONS_NONE, FontCollection, FontFace, FontFile,
|
||||||
|
};
|
||||||
use euclid::default::{Point2D, Rect, Size2D};
|
use euclid::default::{Point2D, Rect, Size2D};
|
||||||
use log::{debug, warn};
|
use log::{debug, warn};
|
||||||
use style::Zero;
|
use style::Zero;
|
||||||
|
@ -67,6 +69,7 @@ pub struct PlatformFont {
|
||||||
em_size: f32,
|
em_size: f32,
|
||||||
du_to_px: f32,
|
du_to_px: f32,
|
||||||
scaled_du_to_px: f32,
|
scaled_du_to_px: f32,
|
||||||
|
variations: Vec<FontVariation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Based on information from the Skia codebase, it seems that DirectWrite APIs from
|
// Based on information from the Skia codebase, it seems that DirectWrite APIs from
|
||||||
|
@ -92,7 +95,11 @@ impl<T> Deref for Nondebug<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PlatformFont {
|
impl PlatformFont {
|
||||||
fn new(font_face: FontFace, pt_size: Option<Au>) -> Result<Self, &'static str> {
|
fn new(
|
||||||
|
font_face: FontFace,
|
||||||
|
pt_size: Option<Au>,
|
||||||
|
variations: Vec<FontVariation>,
|
||||||
|
) -> Result<Self, &'static str> {
|
||||||
let pt_size = pt_size.unwrap_or(au_from_pt(12.));
|
let pt_size = pt_size.unwrap_or(au_from_pt(12.));
|
||||||
let du_per_em = font_face.metrics().metrics0().designUnitsPerEm as f32;
|
let du_per_em = font_face.metrics().metrics0().designUnitsPerEm as f32;
|
||||||
|
|
||||||
|
@ -107,8 +114,51 @@ impl PlatformFont {
|
||||||
em_size,
|
em_size,
|
||||||
du_to_px: design_units_to_pixels,
|
du_to_px: design_units_to_pixels,
|
||||||
scaled_du_to_px: scaled_design_units_to_pixels,
|
scaled_du_to_px: scaled_design_units_to_pixels,
|
||||||
|
variations,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn new_with_variations(
|
||||||
|
font_face: FontFace,
|
||||||
|
pt_size: Option<Au>,
|
||||||
|
variations: &[FontVariation],
|
||||||
|
) -> Result<Self, &'static str> {
|
||||||
|
if variations.is_empty() {
|
||||||
|
return Self::new(font_face, pt_size, vec![]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// On FreeType and CoreText platforms, the platform layer is able to read the minimum, maxmimum,
|
||||||
|
// and default values of each axis. This doesn't seem possible here and it seems that Gecko
|
||||||
|
// also just sets the value of the axis based on the values from the style as well.
|
||||||
|
//
|
||||||
|
// dwrote (and presumably the Windows APIs) accept a reversed version of the table
|
||||||
|
// tag bytes, which means that `u32::swap_bytes` must be called here in order to
|
||||||
|
// use a byte order compatible with the rest of Servo.
|
||||||
|
let variations: Vec<_> = variations
|
||||||
|
.into_iter()
|
||||||
|
.map(|variation| DWRITE_FONT_AXIS_VALUE {
|
||||||
|
axisTag: variation.tag.swap_bytes(),
|
||||||
|
value: variation.value,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let Some(font_face) =
|
||||||
|
font_face.create_font_face_with_variations(DWRITE_FONT_SIMULATIONS_NONE, &variations)
|
||||||
|
else {
|
||||||
|
return Err("Could not adapt FontFace to given variations");
|
||||||
|
};
|
||||||
|
|
||||||
|
let variations = font_face.variations().unwrap_or_default();
|
||||||
|
let variations = variations
|
||||||
|
.iter()
|
||||||
|
.map(|dwrote_variation| FontVariation {
|
||||||
|
tag: dwrote_variation.axisTag.swap_bytes(),
|
||||||
|
value: dwrote_variation.value,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Self::new(font_face, pt_size, variations)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PlatformFontMethods for PlatformFont {
|
impl PlatformFontMethods for PlatformFont {
|
||||||
|
@ -116,22 +166,19 @@ impl PlatformFontMethods for PlatformFont {
|
||||||
_font_identifier: FontIdentifier,
|
_font_identifier: FontIdentifier,
|
||||||
data: &FontData,
|
data: &FontData,
|
||||||
pt_size: Option<Au>,
|
pt_size: Option<Au>,
|
||||||
_variations: &[FontVariation],
|
variations: &[FontVariation],
|
||||||
) -> Result<Self, &'static str> {
|
) -> Result<Self, &'static str> {
|
||||||
let font_face = FontFile::new_from_buffer(Arc::new(data.clone()))
|
let font_face = FontFile::new_from_buffer(Arc::new(data.clone()))
|
||||||
.ok_or("Could not create FontFile")?
|
.ok_or("Could not create FontFile")?
|
||||||
.create_face(
|
.create_face(0 /* face_index */, DWRITE_FONT_SIMULATIONS_NONE)
|
||||||
0, /* face_index */
|
|
||||||
dwrote::DWRITE_FONT_SIMULATIONS_NONE,
|
|
||||||
)
|
|
||||||
.map_err(|_| "Could not create FontFace")?;
|
.map_err(|_| "Could not create FontFace")?;
|
||||||
Self::new(font_face, pt_size)
|
Self::new_with_variations(font_face, pt_size, variations)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_from_local_font_identifier(
|
fn new_from_local_font_identifier(
|
||||||
font_identifier: LocalFontIdentifier,
|
font_identifier: LocalFontIdentifier,
|
||||||
pt_size: Option<Au>,
|
pt_size: Option<Au>,
|
||||||
_variations: &[FontVariation],
|
variations: &[FontVariation],
|
||||||
) -> Result<PlatformFont, &'static str> {
|
) -> Result<PlatformFont, &'static str> {
|
||||||
let font_face = FontCollection::system()
|
let font_face = FontCollection::system()
|
||||||
.font_from_descriptor(&font_identifier.font_descriptor)
|
.font_from_descriptor(&font_identifier.font_descriptor)
|
||||||
|
@ -139,7 +186,7 @@ impl PlatformFontMethods for PlatformFont {
|
||||||
.flatten()
|
.flatten()
|
||||||
.ok_or("Could not create Font from descriptor")?
|
.ok_or("Could not create Font from descriptor")?
|
||||||
.create_font_face();
|
.create_font_face();
|
||||||
Self::new(font_face, pt_size)
|
Self::new_with_variations(font_face, pt_size, variations)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn descriptor(&self) -> FontTemplateDescriptor {
|
fn descriptor(&self) -> FontTemplateDescriptor {
|
||||||
|
@ -324,7 +371,6 @@ impl PlatformFontMethods for PlatformFont {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn variations(&self) -> &[FontVariation] {
|
fn variations(&self) -> &[FontVariation] {
|
||||||
// FIXME: implement this for windows
|
&self.variations
|
||||||
&[]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue