Use Tag type from font-types crate to represent opentype tags (#38870)

The `font-types` crate is the tiny type-only base crate of `fontations`.
This uses a strongly typed representation of open type tags, and allows
us to remove our custom macro for creating them.

---------

Signed-off-by: Nico Burns <nico@nicoburns.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Nico Burns 2025-08-23 21:32:47 +01:00 committed by GitHub
parent 0a8146143a
commit 1fc857865f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 31 additions and 57 deletions

View file

@ -19,6 +19,7 @@ use log::debug;
use malloc_size_of_derive::MallocSizeOf;
use parking_lot::RwLock;
use read_fonts::tables::os2::{Os2, SelectionFlags};
use read_fonts::types::Tag;
use serde::{Deserialize, Serialize};
use smallvec::SmallVec;
use style::computed_values::font_variant_caps;
@ -38,22 +39,14 @@ use crate::{
FontTemplateRefMethods, GlyphData, GlyphId, GlyphStore, LocalFontIdentifier, Shaper,
};
#[macro_export]
macro_rules! ot_tag {
($t1:expr, $t2:expr, $t3:expr, $t4:expr) => {
(($t1 as u32) << 24) | (($t2 as u32) << 16) | (($t3 as u32) << 8) | ($t4 as u32)
};
}
pub type OpenTypeTableTag = u32;
pub const GPOS: OpenTypeTableTag = ot_tag!('G', 'P', 'O', 'S');
pub const GSUB: OpenTypeTableTag = ot_tag!('G', 'S', 'U', 'B');
pub const KERN: OpenTypeTableTag = ot_tag!('k', 'e', 'r', 'n');
pub const SBIX: OpenTypeTableTag = ot_tag!('s', 'b', 'i', 'x');
pub const CBDT: OpenTypeTableTag = ot_tag!('C', 'B', 'D', 'T');
pub const COLR: OpenTypeTableTag = ot_tag!('C', 'O', 'L', 'R');
pub const BASE: OpenTypeTableTag = ot_tag!('B', 'A', 'S', 'E');
pub const LIGA: OpenTypeTableTag = ot_tag!('l', 'i', 'g', 'a');
pub const GPOS: Tag = Tag::new(b"GPOS");
pub const GSUB: Tag = Tag::new(b"GSUB");
pub const KERN: Tag = Tag::new(b"kern");
pub const SBIX: Tag = Tag::new(b"sbix");
pub const CBDT: Tag = Tag::new(b"CBDT");
pub const COLR: Tag = Tag::new(b"COLR");
pub const BASE: Tag = Tag::new(b"BASE");
pub const LIGA: Tag = Tag::new(b"liga");
pub const LAST_RESORT_GLYPH_ADVANCE: FractionalPixel = 10.0;
@ -112,7 +105,7 @@ pub trait PlatformFontMethods: Sized {
fn glyph_h_kerning(&self, glyph0: GlyphId, glyph1: GlyphId) -> FractionalPixel;
fn metrics(&self) -> FontMetrics;
fn table_for_tag(&self, _: FontTableTag) -> Option<FontTable>;
fn table_for_tag(&self, _: Tag) -> Option<FontTable>;
fn typographic_bounds(&self, _: GlyphId) -> Rect<f32>;
/// Get the necessary [`FontInstanceFlags`]` for this font.
@ -148,24 +141,6 @@ pub trait PlatformFontMethods: Sized {
// Used to abstract over the shaper's choice of fixed int representation.
pub type FractionalPixel = f64;
pub type FontTableTag = u32;
trait FontTableTagConversions {
fn tag_to_str(&self) -> String;
}
impl FontTableTagConversions for FontTableTag {
fn tag_to_str(&self) -> String {
let bytes = [
(self >> 24) as u8,
(self >> 16) as u8,
(self >> 8) as u8,
*self as u8,
];
str::from_utf8(&bytes).unwrap().to_owned()
}
}
pub trait FontTableMethods {
fn buffer(&self) -> &[u8];
}
@ -533,7 +508,7 @@ impl Font {
glyphs.finalize_changes();
}
pub fn table_for_tag(&self, tag: FontTableTag) -> Option<FontTable> {
pub fn table_for_tag(&self, tag: Tag) -> Option<FontTable> {
let result = self.handle.table_for_tag(tag);
let status = if result.is_some() {
"Found"
@ -544,7 +519,7 @@ impl Font {
debug!(
"{} font table[{}] in {:?},",
status,
tag.tag_to_str(),
str::from_utf8(tag.as_ref()).unwrap(),
self.identifier()
);
result

View file

@ -24,9 +24,7 @@ use webrender_api::{FontInstanceFlags, FontVariation};
use super::LocalFontIdentifier;
use super::library_handle::FreeTypeLibraryHandle;
use crate::FontData;
use crate::font::{
FontMetrics, FontTableMethods, FontTableTag, FractionalPixel, PlatformFontMethods,
};
use crate::font::{FontMetrics, FontTableMethods, FractionalPixel, PlatformFontMethods};
use crate::font_template::FontTemplateDescriptor;
use crate::glyph::GlyphId;
use crate::platform::freetype::freetype_face::FreeTypeFace;
@ -324,8 +322,7 @@ impl PlatformFontMethods for PlatformFont {
}
}
fn table_for_tag(&self, tag: FontTableTag) -> Option<FontTable> {
let tag = Tag::from_u32(tag);
fn table_for_tag(&self, tag: Tag) -> Option<FontTable> {
let font_ref = self.table_provider_data.font_ref().ok()?;
let _table_data = font_ref.table_data(tag)?;
Some(FontTable {

View file

@ -18,15 +18,15 @@ use core_text::font_descriptor::{
};
use euclid::default::{Point2D, Rect, Size2D};
use log::debug;
use skrifa::Tag;
use style::values::computed::font::{FontStretch, FontStyle, FontWeight};
use webrender_api::{FontInstanceFlags, FontVariation};
use super::core_text_font_cache::CoreTextFontCache;
use super::font_list::LocalFontIdentifier;
use crate::{
CBDT, COLR, FontData, FontIdentifier, FontMetrics, FontTableMethods, FontTableTag,
FontTemplateDescriptor, FractionalPixel, GlyphId, KERN, PlatformFontMethods, SBIX,
map_platform_values_to_style_values,
CBDT, COLR, FontData, FontIdentifier, FontMetrics, FontTableMethods, FontTemplateDescriptor,
FractionalPixel, GlyphId, KERN, PlatformFontMethods, SBIX, map_platform_values_to_style_values,
};
const KERN_PAIR_LEN: usize = 6;
@ -346,8 +346,9 @@ impl PlatformFontMethods for PlatformFont {
metrics
}
fn table_for_tag(&self, tag: FontTableTag) -> Option<FontTable> {
let result: Option<CFData> = self.ctfont.get_font_table(tag);
fn table_for_tag(&self, tag: Tag) -> Option<FontTable> {
let tag_u32 = u32::from_be_bytes(tag.to_be_bytes());
let result: Option<CFData> = self.ctfont.get_font_table(tag_u32);
result.map(FontTable::wrap)
}

View file

@ -26,7 +26,7 @@ use winapi::shared::minwindef::{BOOL, FALSE};
use super::font_list::LocalFontIdentifier;
use crate::{
FontData, FontIdentifier, FontMetrics, FontTableMethods, FontTableTag, FontTemplateDescriptor,
FontData, FontIdentifier, FontMetrics, FontTableMethods, FontTemplateDescriptor,
FractionalPixel, GlyphId, PlatformFontMethods,
};
@ -282,12 +282,12 @@ impl PlatformFontMethods for PlatformFont {
metrics
}
fn table_for_tag(&self, tag: FontTableTag) -> Option<FontTable> {
fn table_for_tag(&self, tag: Tag) -> Option<FontTable> {
// 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.
self.face
.font_table(u32::swap_bytes(tag))
.font_table(u32::from_be_bytes(tag.to_be_bytes()).swap_bytes())
.ok()
.flatten()
.map(|bytes| FontTable { data: bytes })

View file

@ -26,16 +26,17 @@ use harfbuzz_sys::{
hb_variation_t,
};
use num_traits::Zero;
use read_fonts::types::Tag;
use super::{HarfBuzzShapedGlyphData, ShapedGlyphEntry, unicode_script_to_iso15924_tag};
use crate::platform::font::FontTable;
use crate::{
BASE, Font, FontBaseline, FontTableMethods, FontTableTag, GlyphId, GlyphStore, KERN, LIGA,
OpenTypeTableTag, ShapingFlags, ShapingOptions, fixed_to_float, float_to_fixed, ot_tag,
BASE, Font, FontBaseline, FontTableMethods, GlyphId, GlyphStore, KERN, LIGA, ShapingFlags,
ShapingOptions, fixed_to_float, float_to_fixed,
};
const HB_OT_TAG_DEFAULT_SCRIPT: OpenTypeTableTag = ot_tag!('D', 'F', 'L', 'T');
const HB_OT_TAG_DEFAULT_LANGUAGE: OpenTypeTableTag = ot_tag!('d', 'f', 'l', 't');
const HB_OT_TAG_DEFAULT_SCRIPT: hb_tag_t = u32::from_be_bytes(Tag::new(b"DFLT").to_be_bytes());
const HB_OT_TAG_DEFAULT_LANGUAGE: hb_tag_t = u32::from_be_bytes(Tag::new(b"dflt").to_be_bytes());
pub struct ShapedGlyphData {
count: usize,
@ -238,7 +239,7 @@ impl Shaper {
.contains(ShapingFlags::IGNORE_LIGATURES_SHAPING_FLAG)
{
features.push(hb_feature_t {
tag: LIGA,
tag: u32::from_be_bytes(LIGA.to_be_bytes()),
value: 0,
start: 0,
end: hb_buffer_get_length(hb_buffer),
@ -249,7 +250,7 @@ impl Shaper {
.contains(ShapingFlags::DISABLE_KERNING_SHAPING_FLAG)
{
features.push(hb_feature_t {
tag: KERN,
tag: u32::from_be_bytes(KERN.to_be_bytes()),
value: 0,
start: 0,
end: hb_buffer_get_length(hb_buffer),
@ -391,7 +392,7 @@ extern "C" fn font_table_func(
assert!(!font.is_null());
// TODO(Issue #197): reuse font table data, which will change the unsound trickery here.
let Some(font_table) = (unsafe { (*font).table_for_tag(tag as FontTableTag) }) else {
let Some(font_table) = (unsafe { (*font).table_for_tag(Tag::from_u32(tag)) }) else {
return ptr::null_mut();
};