fonts: Make fast shaping determination platform-independent (#33540)

This makes the determination of whether or not to use fast shaping
platform independent. Previously it was less stringent for Windows,
leading to using it in cases where a font had a GSUB or GPOS table --
which broke proper shaping.

In addition, the test is made platform independent and expanded to be
more complete.

Finally, comments are added indicating that "fast shaping" will be
removed.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Martin Robinson 2024-09-25 12:00:36 +02:00 committed by GitHub
parent 6f797709cf
commit 64f32f7ab3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 129 additions and 116 deletions

View file

@ -0,0 +1,109 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
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 fonts::platform::font::PlatformFont;
use fonts::{
Font, FontData, FontDescriptor, FontIdentifier, FontTemplate, PlatformFontMethods,
ShapingFlags, ShapingOptions,
};
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;
fn make_font(path: PathBuf) -> Font {
let identifier = FontIdentifier::Web(ServoUrl::from_file_path(path.clone()).unwrap());
let file = File::open(path).unwrap();
let data = Arc::new(FontData::from_bytes(
file.bytes().map(Result::unwrap).collect(),
));
let platform_font =
PlatformFont::new_from_data(identifier.clone(), data.as_arc().clone(), 0, None).unwrap();
let template = FontTemplate {
identifier,
descriptor: platform_font.descriptor(),
stylesheet: None,
};
let descriptor = FontDescriptor {
weight: FontWeight::normal(),
stretch: FontStretch::hundred(),
style: FontStyle::normal(),
variant: FontVariantCaps::Normal,
pt_size: Au::from_px(24),
};
Font::new(
Arc::new(atomic_refcell::AtomicRefCell::new(template)),
descriptor,
data,
None,
)
.unwrap()
}
#[test]
fn test_font_can_do_fast_shaping() {
let dejavu_sans = make_font(
[
env!("CARGO_MANIFEST_DIR"),
"tests",
"support",
"dejavu-fonts-ttf-2.37",
"ttf",
"DejaVuSans.ttf",
]
.iter()
.collect(),
);
let dejavu_sans_fast_shapeable = make_font(
[
env!("CARGO_MANIFEST_DIR"),
"tests",
"support",
"dejavu-fonts-ttf-2.37",
"ttf",
"DejaVuSansNoGSUBNoGPOS.ttf",
]
.iter()
.collect(),
);
// Fast shaping requires a font with a kern table and no GPOS or GSUB tables.
let shaping_options = ShapingOptions {
letter_spacing: None,
word_spacing: Au::zero(),
script: Script::Latin,
flags: ShapingFlags::empty(),
};
assert!(!dejavu_sans.can_do_fast_shaping("WAVE", &shaping_options));
assert!(dejavu_sans_fast_shapeable.can_do_fast_shaping("WAVE", &shaping_options));
// Non-Latin script should never have fast shaping.
let shaping_options = ShapingOptions {
letter_spacing: None,
word_spacing: Au::zero(),
script: Script::Cherokee,
flags: ShapingFlags::empty(),
};
assert!(!dejavu_sans.can_do_fast_shaping("WAVE", &shaping_options));
assert!(!dejavu_sans_fast_shapeable.can_do_fast_shaping("WAVE", &shaping_options));
// Right-to-left text should never use fast shaping.
let shaping_options = ShapingOptions {
letter_spacing: None,
word_spacing: Au::zero(),
script: Script::Latin,
flags: ShapingFlags::RTL_FLAG,
};
assert!(!dejavu_sans.can_do_fast_shaping("WAVE", &shaping_options));
assert!(!dejavu_sans_fast_shapeable.can_do_fast_shaping("WAVE", &shaping_options));
}