mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
fonts: Enable fast text shaping on Windows (#33123)
* Use patched dwrote Signed-off-by: crbrz <cristianb@gmail.com> * Enable fast text shaping Signed-off-by: crbrz <cristianb@gmail.com> * Add fast text shape test Signed-off-by: crbrz <cristianb@gmail.com> * Update dwrote to 0.11.1 Signed-off-by: crbrz <cristianb@gmail.com> --------- Signed-off-by: crbrz <cristianb@gmail.com>
This commit is contained in:
parent
6f333a8e29
commit
4ae2610c24
4 changed files with 103 additions and 15 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -1516,9 +1516,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dwrote"
|
name = "dwrote"
|
||||||
version = "0.11.0"
|
version = "0.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b"
|
checksum = "2da3498378ed373237bdef1eddcc64e7be2d3ba4841f4c22a998e81cadeea83c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
|
|
|
@ -9,7 +9,7 @@ publish.workspace = true
|
||||||
[lib]
|
[lib]
|
||||||
name = "fonts"
|
name = "fonts"
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
test = false
|
test = true
|
||||||
doctest = false
|
doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -75,5 +75,5 @@ harfbuzz-sys = { version = "0.6.1", features = ["bundled"] }
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
harfbuzz-sys = { version = "0.6", features = ["bundled"] }
|
harfbuzz-sys = { version = "0.6", features = ["bundled"] }
|
||||||
dwrote = "0.11"
|
dwrote = "0.11.1"
|
||||||
truetype = { version = "0.47.3", features = ["ignore-invalid-language-ids"] }
|
truetype = { version = "0.47.3", features = ["ignore-invalid-language-ids"] }
|
||||||
|
|
|
@ -325,7 +325,6 @@ struct ShapeCacheEntry {
|
||||||
|
|
||||||
impl Font {
|
impl Font {
|
||||||
pub fn shape_text(&self, text: &str, options: &ShapingOptions) -> Arc<GlyphStore> {
|
pub fn shape_text(&self, text: &str, options: &ShapingOptions) -> Arc<GlyphStore> {
|
||||||
let this = self as *const Font;
|
|
||||||
let lookup_key = ShapeCacheEntry {
|
let lookup_key = ShapeCacheEntry {
|
||||||
text: text.to_owned(),
|
text: text.to_owned(),
|
||||||
options: *options,
|
options: *options,
|
||||||
|
@ -353,9 +352,7 @@ impl Font {
|
||||||
self.shape_text_fast(text, options, &mut glyphs);
|
self.shape_text_fast(text, options, &mut glyphs);
|
||||||
} else {
|
} else {
|
||||||
debug!("shape_text: Using Harfbuzz.");
|
debug!("shape_text: Using Harfbuzz.");
|
||||||
self.shaper
|
self.shape_text_harfbuzz(text, options, &mut glyphs);
|
||||||
.get_or_init(|| Shaper::new(this))
|
|
||||||
.shape_text(text, options, &mut glyphs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let shaped_text = Arc::new(glyphs);
|
let shaped_text = Arc::new(glyphs);
|
||||||
|
@ -371,6 +368,13 @@ impl Font {
|
||||||
shaped_text
|
shaped_text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn shape_text_harfbuzz(&self, text: &str, options: &ShapingOptions, glyphs: &mut GlyphStore) {
|
||||||
|
let this = self as *const Font;
|
||||||
|
self.shaper
|
||||||
|
.get_or_init(|| Shaper::new(this))
|
||||||
|
.shape_text(text, options, glyphs);
|
||||||
|
}
|
||||||
|
|
||||||
fn can_do_fast_shaping(&self, text: &str, options: &ShapingOptions) -> bool {
|
fn can_do_fast_shaping(&self, text: &str, options: &ShapingOptions) -> bool {
|
||||||
options.script == Script::Latin &&
|
options.script == Script::Latin &&
|
||||||
!options.flags.contains(ShapingFlags::RTL_FLAG) &&
|
!options.flags.contains(ShapingFlags::RTL_FLAG) &&
|
||||||
|
@ -869,3 +873,87 @@ pub(crate) fn map_platform_values_to_style_values(mapping: &[(f64, f64)], value:
|
||||||
|
|
||||||
mapping[mapping.len() - 1].1
|
mapping[mapping.len() - 1].1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
#[test]
|
||||||
|
fn test_shape_text_fast() {
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Read;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use app_units::Au;
|
||||||
|
use euclid::num::Zero;
|
||||||
|
use servo_url::ServoUrl;
|
||||||
|
use style::properties::longhands::font_variant_caps::computed_value::T as FontVariantCaps;
|
||||||
|
use style::values::computed::{FontStretch, FontStyle, FontWeight};
|
||||||
|
use unicode_script::Script;
|
||||||
|
|
||||||
|
use crate::platform::font::PlatformFont;
|
||||||
|
use crate::{
|
||||||
|
Font, FontDescriptor, FontIdentifier, FontTemplate, GlyphStore, PlatformFontMethods,
|
||||||
|
ShapingFlags, ShapingOptions,
|
||||||
|
};
|
||||||
|
|
||||||
|
let path: PathBuf = [
|
||||||
|
env!("CARGO_MANIFEST_DIR"),
|
||||||
|
"tests",
|
||||||
|
"support",
|
||||||
|
"dejavu-fonts-ttf-2.37",
|
||||||
|
"ttf",
|
||||||
|
"DejaVuSans.ttf",
|
||||||
|
]
|
||||||
|
.iter()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let identifier = FontIdentifier::Web(ServoUrl::from_file_path(path.clone()).unwrap());
|
||||||
|
let file = File::open(path).unwrap();
|
||||||
|
let data: Arc<Vec<u8>> = Arc::new(file.bytes().map(|b| b.unwrap()).collect());
|
||||||
|
let platform_font =
|
||||||
|
PlatformFont::new_from_data(identifier.clone(), data.clone(), 0, None).unwrap();
|
||||||
|
|
||||||
|
let template = FontTemplate {
|
||||||
|
identifier,
|
||||||
|
descriptor: platform_font.descriptor(),
|
||||||
|
data: Some(data),
|
||||||
|
stylesheet: None,
|
||||||
|
};
|
||||||
|
let descriptor = FontDescriptor {
|
||||||
|
weight: FontWeight::normal(),
|
||||||
|
stretch: FontStretch::hundred(),
|
||||||
|
style: FontStyle::normal(),
|
||||||
|
variant: FontVariantCaps::Normal,
|
||||||
|
pt_size: Au::from_px(24),
|
||||||
|
};
|
||||||
|
let font = Font::new(
|
||||||
|
Arc::new(atomic_refcell::AtomicRefCell::new(template)),
|
||||||
|
descriptor,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let shaping_options = ShapingOptions {
|
||||||
|
letter_spacing: None,
|
||||||
|
word_spacing: Au::zero(),
|
||||||
|
script: Script::Latin,
|
||||||
|
flags: ShapingFlags::empty(),
|
||||||
|
};
|
||||||
|
let text = "WAVE";
|
||||||
|
|
||||||
|
assert!(font.can_do_fast_shaping(text, &shaping_options));
|
||||||
|
|
||||||
|
let mut expected_glyphs = GlyphStore::new(text.len(), false, false, false);
|
||||||
|
font.shape_text_harfbuzz(text, &shaping_options, &mut expected_glyphs);
|
||||||
|
|
||||||
|
let mut glyphs = GlyphStore::new(text.len(), false, false, false);
|
||||||
|
font.shape_text_fast(text, &shaping_options, &mut glyphs);
|
||||||
|
|
||||||
|
assert_eq!(glyphs.len(), expected_glyphs.len());
|
||||||
|
assert_eq!(
|
||||||
|
glyphs.total_advance().to_nearest_px(),
|
||||||
|
expected_glyphs.total_advance().to_nearest_px()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -213,15 +213,15 @@ impl PlatformFontMethods for PlatformFont {
|
||||||
|
|
||||||
/// Can this font do basic horizontal LTR shaping without Harfbuzz?
|
/// Can this font do basic horizontal LTR shaping without Harfbuzz?
|
||||||
fn can_do_fast_shaping(&self) -> bool {
|
fn can_do_fast_shaping(&self) -> bool {
|
||||||
// TODO copy CachedKernTable from the MacOS X implementation to
|
self.face.has_kerning_pairs()
|
||||||
// somehwere global and use it here. We could also implement the
|
|
||||||
// IDirectWriteFontFace1 interface and use the glyph kerning pair
|
|
||||||
// methods there.
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn glyph_h_kerning(&self, _: GlyphId, _: GlyphId) -> FractionalPixel {
|
fn glyph_h_kerning(&self, first_glyph: GlyphId, second_glyph: GlyphId) -> FractionalPixel {
|
||||||
0.0
|
let adjustment = self
|
||||||
|
.face
|
||||||
|
.get_glyph_pair_kerning_adjustment(first_glyph as u16, second_glyph as u16);
|
||||||
|
|
||||||
|
(adjustment as f32 * self.scaled_du_to_px) as FractionalPixel
|
||||||
}
|
}
|
||||||
|
|
||||||
fn metrics(&self) -> FontMetrics {
|
fn metrics(&self) -> FontMetrics {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue