mirror of
https://github.com/servo/servo
synced 2026-04-25 17:15:48 +02:00
fonts: Refactor the font fallback code a little bit and remove RwLock around FontGroup (#41449)
This change reworks the logic for finding font fallbacks to make it simpler. I was involved with writing the code for `FontGroupFamily` and `FontGroupFamilyMember` and I still struggle a bit with understanding it, so I've chosen to do this. In addition, the change is in preparation for more flexible font fallback (#41426). The main changes here are: 1. Move the logic for creating a new descriptor with variations into the Font constructor. 2. Add some more general methods to `FontGroupFamily` such as a template iterator. 3. Use `OnceLock` to avoid a convoluted code structure because of mutability and also having boolean "loaded" members. This is what `OnceLock` and `OnceCell` are for! 4. Rename `FontGroupFamilyMember` to `FontGroupFamilyTemplate` to stress that it is one template of a particular `FontGroupFamily`. Testing: This should not change behavior so is covered by existing WPT tests. --------- Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
@@ -602,7 +602,7 @@ impl FontGroup {
|
||||
.font_family
|
||||
.families
|
||||
.iter()
|
||||
.map(FontGroupFamily::new)
|
||||
.map(FontGroupFamily::local_or_web)
|
||||
.collect();
|
||||
|
||||
FontGroup {
|
||||
@@ -616,7 +616,7 @@ impl FontGroup {
|
||||
/// (which will cause a "glyph not found" character to be rendered). If no font at all can be
|
||||
/// found, returns None.
|
||||
pub fn find_by_codepoint(
|
||||
&mut self,
|
||||
&self,
|
||||
font_context: &FontContext,
|
||||
codepoint: char,
|
||||
next_codepoint: Option<char>,
|
||||
@@ -661,8 +661,8 @@ impl FontGroup {
|
||||
|
||||
if let Some(font) = self.find(
|
||||
font_context,
|
||||
char_in_template,
|
||||
font_has_glyph_and_presentation,
|
||||
&char_in_template,
|
||||
&font_has_glyph_and_presentation,
|
||||
) {
|
||||
return font_or_synthesized_small_caps(font);
|
||||
}
|
||||
@@ -678,8 +678,8 @@ impl FontGroup {
|
||||
if let Some(font) = self.find_fallback(
|
||||
font_context,
|
||||
options.clone(),
|
||||
char_in_template,
|
||||
font_has_glyph_and_presentation,
|
||||
&char_in_template,
|
||||
&font_has_glyph_and_presentation,
|
||||
) {
|
||||
return font_or_synthesized_small_caps(font);
|
||||
}
|
||||
@@ -688,7 +688,7 @@ impl FontGroup {
|
||||
}
|
||||
|
||||
/// Find the first available font in the group, or the first available fallback font.
|
||||
pub fn first(&mut self, font_context: &FontContext) -> Option<FontRef> {
|
||||
pub fn first(&self, font_context: &FontContext) -> Option<FontRef> {
|
||||
// From https://drafts.csswg.org/css-fonts/#first-available-font:
|
||||
// > The first available font, used for example in the definition of font-relative lengths
|
||||
// > such as ex or in the definition of the line-height property, is defined to be the first
|
||||
@@ -698,13 +698,13 @@ impl FontGroup {
|
||||
// > Note: it does not matter whether that font actually has a glyph for the space character.
|
||||
let space_in_template = |template: FontTemplateRef| template.char_in_unicode_range(' ');
|
||||
let font_predicate = |_: &FontRef| true;
|
||||
self.find(font_context, space_in_template, font_predicate)
|
||||
self.find(font_context, &space_in_template, &font_predicate)
|
||||
.or_else(|| {
|
||||
self.find_fallback(
|
||||
font_context,
|
||||
FallbackFontSelectionOptions::default(),
|
||||
space_in_template,
|
||||
font_predicate,
|
||||
&space_in_template,
|
||||
&font_predicate,
|
||||
)
|
||||
})
|
||||
}
|
||||
@@ -712,42 +712,36 @@ impl FontGroup {
|
||||
/// Attempts to find a font which matches the given `template_predicate` and `font_predicate`.
|
||||
/// This method mutates because we may need to load new font data in the process of finding
|
||||
/// a suitable font.
|
||||
fn find<TemplatePredicate, FontPredicate>(
|
||||
&mut self,
|
||||
fn find(
|
||||
&self,
|
||||
font_context: &FontContext,
|
||||
template_predicate: TemplatePredicate,
|
||||
font_predicate: FontPredicate,
|
||||
) -> Option<FontRef>
|
||||
where
|
||||
TemplatePredicate: Fn(FontTemplateRef) -> bool,
|
||||
FontPredicate: Fn(&FontRef) -> bool,
|
||||
{
|
||||
let font_descriptor = self.descriptor.clone();
|
||||
self.families.iter_mut().find_map(|font_group_family| {
|
||||
font_group_family.find(
|
||||
&font_descriptor,
|
||||
font_context,
|
||||
&template_predicate,
|
||||
&font_predicate,
|
||||
)
|
||||
})
|
||||
template_predicate: &impl Fn(FontTemplateRef) -> bool,
|
||||
font_predicate: &impl Fn(&FontRef) -> bool,
|
||||
) -> Option<FontRef> {
|
||||
self.families
|
||||
.iter()
|
||||
.flat_map(|family| family.templates(font_context, &self.descriptor))
|
||||
.find_map(|template| {
|
||||
template.font_if_matches(
|
||||
font_context,
|
||||
&self.descriptor,
|
||||
template_predicate,
|
||||
font_predicate,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// Attempts to find a suitable fallback font which matches the given `template_predicate` and
|
||||
/// `font_predicate`. The default family (i.e. "serif") will be tried first, followed by
|
||||
/// platform-specific family names. If a `codepoint` is provided, then its Unicode block may be
|
||||
/// used to refine the list of family names which will be tried.
|
||||
fn find_fallback<TemplatePredicate, FontPredicate>(
|
||||
&mut self,
|
||||
fn find_fallback(
|
||||
&self,
|
||||
font_context: &FontContext,
|
||||
options: FallbackFontSelectionOptions,
|
||||
template_predicate: TemplatePredicate,
|
||||
font_predicate: FontPredicate,
|
||||
) -> Option<FontRef>
|
||||
where
|
||||
TemplatePredicate: Fn(FontTemplateRef) -> bool,
|
||||
FontPredicate: Fn(&FontRef) -> bool,
|
||||
{
|
||||
template_predicate: &impl Fn(FontTemplateRef) -> bool,
|
||||
font_predicate: &impl Fn(&FontRef) -> bool,
|
||||
) -> Option<FontRef> {
|
||||
iter::once(FontFamilyDescriptor::default())
|
||||
.chain(
|
||||
fallback_font_families(options)
|
||||
@@ -761,32 +755,67 @@ impl FontGroup {
|
||||
}),
|
||||
)
|
||||
.find_map(|family_descriptor| {
|
||||
FontGroupFamily {
|
||||
family_descriptor,
|
||||
members: None,
|
||||
}
|
||||
.find(
|
||||
&self.descriptor,
|
||||
font_context,
|
||||
&template_predicate,
|
||||
&font_predicate,
|
||||
)
|
||||
FontGroupFamily::from(family_descriptor)
|
||||
.templates(font_context, &self.descriptor)
|
||||
.find_map(|template| {
|
||||
template.font_if_matches(
|
||||
font_context,
|
||||
&self.descriptor,
|
||||
template_predicate,
|
||||
font_predicate,
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// A [`FontGroupFamily`] can have multiple members if it is a "composite face", meaning
|
||||
/// that it is defined by multiple `@font-face` declarations which vary only by their
|
||||
/// `unicode-range` descriptors. In this case, font selection will select a single member
|
||||
/// that contains the necessary unicode character. Unicode ranges are specified by the
|
||||
/// [`FontGroupFamilyMember::template`] member.
|
||||
/// A [`FontGroupFamily`] can have multiple associated `FontTemplate`s if it is a
|
||||
/// "composite face", meaning that it is defined by multiple `@font-face`
|
||||
/// declarations which vary only by their `unicode-range` descriptors. In this case,
|
||||
/// font selection will select a single member that contains the necessary unicode
|
||||
/// character. Unicode ranges are specified by the [`FontGroupFamilyTemplate::template`]
|
||||
/// member.
|
||||
#[derive(MallocSizeOf)]
|
||||
struct FontGroupFamilyMember {
|
||||
struct FontGroupFamilyTemplate {
|
||||
#[ignore_malloc_size_of = "This measured in the FontContext template cache."]
|
||||
template: FontTemplateRef,
|
||||
#[ignore_malloc_size_of = "This measured in the FontContext font cache."]
|
||||
font: Option<FontRef>,
|
||||
loaded: bool,
|
||||
font: OnceLock<Option<FontRef>>,
|
||||
}
|
||||
|
||||
impl From<FontTemplateRef> for FontGroupFamilyTemplate {
|
||||
fn from(template: FontTemplateRef) -> Self {
|
||||
Self {
|
||||
template,
|
||||
font: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FontGroupFamilyTemplate {
|
||||
fn font(
|
||||
&self,
|
||||
font_context: &FontContext,
|
||||
font_descriptor: &FontDescriptor,
|
||||
) -> Option<FontRef> {
|
||||
self.font
|
||||
.get_or_init(|| font_context.font(self.template.clone(), font_descriptor))
|
||||
.clone()
|
||||
}
|
||||
|
||||
fn font_if_matches(
|
||||
&self,
|
||||
font_context: &FontContext,
|
||||
font_descriptor: &FontDescriptor,
|
||||
template_predicate: &impl Fn(FontTemplateRef) -> bool,
|
||||
font_predicate: &impl Fn(&FontRef) -> bool,
|
||||
) -> Option<FontRef> {
|
||||
if !template_predicate(self.template.clone()) {
|
||||
return None;
|
||||
}
|
||||
self.font(font_context, font_descriptor)
|
||||
.filter(font_predicate)
|
||||
}
|
||||
}
|
||||
|
||||
/// A `FontGroupFamily` is a single font family in a `FontGroup`. It corresponds to one of the
|
||||
@@ -796,75 +825,37 @@ struct FontGroupFamilyMember {
|
||||
#[derive(MallocSizeOf)]
|
||||
struct FontGroupFamily {
|
||||
family_descriptor: FontFamilyDescriptor,
|
||||
members: Option<Vec<FontGroupFamilyMember>>,
|
||||
members: OnceLock<Vec<FontGroupFamilyTemplate>>,
|
||||
}
|
||||
|
||||
impl From<FontFamilyDescriptor> for FontGroupFamily {
|
||||
fn from(family_descriptor: FontFamilyDescriptor) -> Self {
|
||||
Self {
|
||||
family_descriptor,
|
||||
members: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FontGroupFamily {
|
||||
fn new(family: &SingleFontFamily) -> FontGroupFamily {
|
||||
FontGroupFamily {
|
||||
family_descriptor: FontFamilyDescriptor::new(family.clone(), FontSearchScope::Any),
|
||||
members: None,
|
||||
}
|
||||
fn local_or_web(family: &SingleFontFamily) -> FontGroupFamily {
|
||||
FontFamilyDescriptor::new(family.clone(), FontSearchScope::Any).into()
|
||||
}
|
||||
|
||||
fn find<TemplatePredicate, FontPredicate>(
|
||||
&mut self,
|
||||
font_descriptor: &FontDescriptor,
|
||||
fn templates(
|
||||
&self,
|
||||
font_context: &FontContext,
|
||||
template_predicate: &TemplatePredicate,
|
||||
font_predicate: &FontPredicate,
|
||||
) -> Option<FontRef>
|
||||
where
|
||||
TemplatePredicate: Fn(FontTemplateRef) -> bool,
|
||||
FontPredicate: Fn(&FontRef) -> bool,
|
||||
{
|
||||
self.members(font_descriptor, font_context)
|
||||
.find_map(|member| {
|
||||
if !template_predicate(member.template.clone()) {
|
||||
return None;
|
||||
}
|
||||
|
||||
if !member.loaded {
|
||||
if servo_config::pref!(layout_variable_fonts_enabled) {
|
||||
let variation_settings =
|
||||
member.template.borrow().compute_variations(font_descriptor);
|
||||
let descriptor_with_variations =
|
||||
font_descriptor.with_variation_settings(variation_settings);
|
||||
member.font =
|
||||
font_context.font(member.template.clone(), &descriptor_with_variations);
|
||||
} else {
|
||||
member.font = font_context.font(member.template.clone(), font_descriptor)
|
||||
}
|
||||
|
||||
member.loaded = true;
|
||||
}
|
||||
if matches!(&member.font, Some(font) if font_predicate(font)) {
|
||||
return member.font.clone();
|
||||
}
|
||||
|
||||
None
|
||||
font_descriptor: &FontDescriptor,
|
||||
) -> impl Iterator<Item = &FontGroupFamilyTemplate> {
|
||||
self.members
|
||||
.get_or_init(|| {
|
||||
font_context
|
||||
.matching_templates(font_descriptor, &self.family_descriptor)
|
||||
.into_iter()
|
||||
.map(Into::into)
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
|
||||
fn members(
|
||||
&mut self,
|
||||
font_descriptor: &FontDescriptor,
|
||||
font_context: &FontContext,
|
||||
) -> impl Iterator<Item = &mut FontGroupFamilyMember> {
|
||||
let family_descriptor = &self.family_descriptor;
|
||||
let members = self.members.get_or_insert_with(|| {
|
||||
font_context
|
||||
.matching_templates(font_descriptor, family_descriptor)
|
||||
.into_iter()
|
||||
.map(|template| FontGroupFamilyMember {
|
||||
template,
|
||||
loaded: false,
|
||||
font: None,
|
||||
})
|
||||
.collect()
|
||||
});
|
||||
|
||||
members.iter_mut()
|
||||
.iter()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::default::Default;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
@@ -60,15 +59,7 @@ pub(crate) struct FontParameters {
|
||||
pub(crate) flags: FontInstanceFlags,
|
||||
}
|
||||
|
||||
#[derive(MallocSizeOf)]
|
||||
struct FontGroupRef(#[conditional_malloc_size_of] Arc<RwLock<FontGroup>>);
|
||||
|
||||
impl Deref for FontGroupRef {
|
||||
type Target = Arc<RwLock<FontGroup>>;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
pub type FontGroupRef = Arc<FontGroup>;
|
||||
|
||||
/// The FontContext represents the per-thread/thread state necessary for
|
||||
/// working with fonts. It is the public API used by the layout and
|
||||
@@ -91,6 +82,7 @@ pub struct FontContext {
|
||||
/// A caching map between the specification of a font in CSS style and
|
||||
/// resolved [`FontGroup`] which contains information about all fonts that
|
||||
/// can be selected with that style.
|
||||
#[conditional_malloc_size_of]
|
||||
resolved_font_groups: RwLock<HashMap<FontGroupCacheKey, FontGroupRef>>,
|
||||
|
||||
web_fonts: CrossThreadFontStore,
|
||||
@@ -175,7 +167,7 @@ impl FontContext {
|
||||
/// Returns a `FontGroup` representing fonts which can be used for layout, given the `style`.
|
||||
/// Font groups are cached, so subsequent calls with the same `style` will return a reference
|
||||
/// to an existing `FontGroup`.
|
||||
pub fn font_group(&self, style: ServoArc<FontStyleStruct>) -> Arc<RwLock<FontGroup>> {
|
||||
pub fn font_group(&self, style: ServoArc<FontStyleStruct>) -> FontGroupRef {
|
||||
let font_size = style.font_size.computed_size().into();
|
||||
self.font_group_with_size(style, font_size)
|
||||
}
|
||||
@@ -186,19 +178,19 @@ impl FontContext {
|
||||
&self,
|
||||
style: ServoArc<FontStyleStruct>,
|
||||
size: Au,
|
||||
) -> Arc<RwLock<FontGroup>> {
|
||||
) -> Arc<FontGroup> {
|
||||
let cache_key = FontGroupCacheKey { size, style };
|
||||
if let Some(font_group) = self.resolved_font_groups.read().get(&cache_key) {
|
||||
return font_group.0.clone();
|
||||
return font_group.clone();
|
||||
}
|
||||
|
||||
let mut descriptor = FontDescriptor::from(&*cache_key.style);
|
||||
descriptor.pt_size = size;
|
||||
|
||||
let font_group = Arc::new(RwLock::new(FontGroup::new(&cache_key.style, descriptor)));
|
||||
let font_group = Arc::new(FontGroup::new(&cache_key.style, descriptor));
|
||||
self.resolved_font_groups
|
||||
.write()
|
||||
.insert(cache_key, FontGroupRef(font_group.clone()));
|
||||
.insert(cache_key, font_group.clone());
|
||||
font_group
|
||||
}
|
||||
|
||||
@@ -209,6 +201,13 @@ impl FontContext {
|
||||
font_template: FontTemplateRef,
|
||||
font_descriptor: &FontDescriptor,
|
||||
) -> Option<FontRef> {
|
||||
let font_descriptor = if servo_config::pref!(layout_variable_fonts_enabled) {
|
||||
let variation_settings = font_template.borrow().compute_variations(font_descriptor);
|
||||
&font_descriptor.with_variation_settings(variation_settings)
|
||||
} else {
|
||||
font_descriptor
|
||||
};
|
||||
|
||||
self.get_font_maybe_synthesizing_small_caps(
|
||||
font_template,
|
||||
font_descriptor,
|
||||
|
||||
@@ -238,28 +238,16 @@ mod font_context {
|
||||
|
||||
assert!(
|
||||
std::ptr::eq(
|
||||
&*context
|
||||
.context
|
||||
.font_group(ServoArc::new(style1.clone()))
|
||||
.read(),
|
||||
&*context
|
||||
.context
|
||||
.font_group(ServoArc::new(style1.clone()))
|
||||
.read()
|
||||
&*context.context.font_group(ServoArc::new(style1.clone())),
|
||||
&*context.context.font_group(ServoArc::new(style1.clone())),
|
||||
),
|
||||
"the same font group should be returned for two styles with the same hash"
|
||||
);
|
||||
|
||||
assert!(
|
||||
!std::ptr::eq(
|
||||
&*context
|
||||
.context
|
||||
.font_group(ServoArc::new(style1.clone()))
|
||||
.read(),
|
||||
&*context
|
||||
.context
|
||||
.font_group(ServoArc::new(style2.clone()))
|
||||
.read()
|
||||
&*context.context.font_group(ServoArc::new(style1.clone())),
|
||||
&*context.context.font_group(ServoArc::new(style2.clone())),
|
||||
),
|
||||
"different font groups should be returned for two styles with different hashes"
|
||||
)
|
||||
@@ -275,7 +263,6 @@ mod font_context {
|
||||
let group = context.context.font_group(ServoArc::new(style));
|
||||
|
||||
let font = group
|
||||
.write()
|
||||
.find_by_codepoint(&mut context.context, 'a', None, None, None)
|
||||
.unwrap();
|
||||
assert_eq!(&font_face_name(&font.identifier()), "csstest-ascii");
|
||||
@@ -289,7 +276,6 @@ mod font_context {
|
||||
);
|
||||
|
||||
let font = group
|
||||
.write()
|
||||
.find_by_codepoint(&mut context.context, 'a', None, None, None)
|
||||
.unwrap();
|
||||
assert_eq!(&font_face_name(&font.identifier()), "csstest-ascii");
|
||||
@@ -303,7 +289,6 @@ mod font_context {
|
||||
);
|
||||
|
||||
let font = group
|
||||
.write()
|
||||
.find_by_codepoint(&mut context.context, 'á', None, None, None)
|
||||
.unwrap();
|
||||
assert_eq!(&font_face_name(&font.identifier()), "csstest-basic-regular");
|
||||
@@ -327,7 +312,6 @@ mod font_context {
|
||||
let group = context.context.font_group(ServoArc::new(style));
|
||||
|
||||
let font = group
|
||||
.write()
|
||||
.find_by_codepoint(&mut context.context, 'a', None, None, None)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
@@ -337,7 +321,6 @@ mod font_context {
|
||||
);
|
||||
|
||||
let font = group
|
||||
.write()
|
||||
.find_by_codepoint(&mut context.context, 'á', None, None, None)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
|
||||
@@ -480,7 +480,7 @@ impl TextRun {
|
||||
|
||||
let lang = parent_style.get_font()._x_lang.clone();
|
||||
|
||||
let Some(font) = font_group.write().find_by_codepoint(
|
||||
let Some(font) = font_group.find_by_codepoint(
|
||||
&layout_context.font_context,
|
||||
character,
|
||||
next_character,
|
||||
@@ -516,12 +516,9 @@ impl TextRun {
|
||||
// Either we have a current segment or we only had control character and whitespace. In both
|
||||
// of those cases, just use the first font.
|
||||
if current.is_none() {
|
||||
current = font_group
|
||||
.write()
|
||||
.first(&layout_context.font_context)
|
||||
.map(|font| {
|
||||
TextRunSegment::new(font, Script::Common, Level::ltr(), self.text_range.start)
|
||||
})
|
||||
current = font_group.first(&layout_context.font_context).map(|font| {
|
||||
TextRunSegment::new(font, Script::Common, Level::ltr(), self.text_range.start)
|
||||
})
|
||||
}
|
||||
|
||||
// Extend the last segment to the end of the string and add it to the results.
|
||||
@@ -583,7 +580,6 @@ pub(super) fn get_font_for_first_font_for_style(
|
||||
) -> Option<FontRef> {
|
||||
let font = font_context
|
||||
.font_group(style.clone_font())
|
||||
.write()
|
||||
.first(font_context);
|
||||
if font.is_none() {
|
||||
warn!("Could not find font for style: {:?}", style.clone_font());
|
||||
|
||||
@@ -1534,7 +1534,6 @@ impl FontMetricsProvider for LayoutFontMetricsProvider {
|
||||
.font_group_with_size(ServoArc::new(font.clone()), base_size.into());
|
||||
|
||||
let Some(first_font_metrics) = font_group
|
||||
.write()
|
||||
.first(font_context)
|
||||
.map(|font| font.metrics.clone())
|
||||
else {
|
||||
@@ -1551,7 +1550,6 @@ impl FontMetricsProvider for LayoutFontMetricsProvider {
|
||||
.zero_horizontal_advance
|
||||
.or_else(|| {
|
||||
font_group
|
||||
.write()
|
||||
.find_by_codepoint(font_context, '0', None, None, None)?
|
||||
.metrics
|
||||
.zero_horizontal_advance
|
||||
@@ -1562,7 +1560,6 @@ impl FontMetricsProvider for LayoutFontMetricsProvider {
|
||||
.ic_horizontal_advance
|
||||
.or_else(|| {
|
||||
font_group
|
||||
.write()
|
||||
.find_by_codepoint(font_context, '\u{6C34}', None, None, None)?
|
||||
.metrics
|
||||
.ic_horizontal_advance
|
||||
|
||||
@@ -51,7 +51,7 @@ use std::collections::BinaryHeap;
|
||||
use std::hash::{BuildHasher, Hash};
|
||||
use std::ops::Range;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, OnceLock};
|
||||
|
||||
use resvg::usvg::fontdb::Source;
|
||||
use style::properties::ComputedValues;
|
||||
@@ -580,6 +580,22 @@ impl<T: MallocConditionalSizeOf> MallocConditionalSizeOf for OnceCell<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf> MallocSizeOf for OnceLock<T> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.get()
|
||||
.map(|interior| interior.size_of(ops))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocConditionalSizeOf> MallocConditionalSizeOf for OnceLock<T> {
|
||||
fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.get()
|
||||
.map(|interior| interior.conditional_size_of(ops))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
// See https://github.com/rust-lang/rust/issues/68318:
|
||||
// We don't want MallocSizeOf to be defined for Rc and Arc. If negative trait bounds are
|
||||
// ever allowed, this code should be uncommented. Instead, there is a compile-fail test for
|
||||
@@ -697,6 +713,12 @@ impl<T: MallocSizeOf> MallocSizeOf for parking_lot::RwLock<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocConditionalSizeOf> MallocConditionalSizeOf for parking_lot::RwLock<T> {
|
||||
fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
(*self.read()).conditional_size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, Unit> MallocSizeOf for euclid::Length<T, Unit> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.0.size_of(ops)
|
||||
|
||||
@@ -1495,11 +1495,10 @@ impl CanvasState {
|
||||
|
||||
let font_style = self.font_style();
|
||||
let font_group = font_context.font_group(font_style.clone());
|
||||
let mut font_group = font_group.write();
|
||||
let font = font_group.first(font_context).expect("couldn't find font");
|
||||
let ascent = font.metrics.ascent.to_f64_px();
|
||||
let descent = font.metrics.descent.to_f64_px();
|
||||
let runs = self.build_unshaped_text_runs(font_context, &text, &mut font_group);
|
||||
let runs = self.build_unshaped_text_runs(font_context, &text, &font_group);
|
||||
|
||||
let mut total_advance = 0.0;
|
||||
let shaped_runs: Vec<_> = runs
|
||||
@@ -2273,13 +2272,12 @@ impl CanvasState {
|
||||
// > attribute.
|
||||
let font_style = self.font_style();
|
||||
let font_group = font_context.font_group_with_size(font_style, Au::from_f64_px(size));
|
||||
let mut font_group = font_group.write();
|
||||
let Some(first_font) = font_group.first(font_context) else {
|
||||
warn!("Could not render canvas text, because there was no first font.");
|
||||
return None;
|
||||
};
|
||||
|
||||
let runs = self.build_unshaped_text_runs(font_context, &text, &mut font_group);
|
||||
let runs = self.build_unshaped_text_runs(font_context, &text, &font_group);
|
||||
|
||||
// TODO: This doesn't do any kind of line layout at all. In particular, there needs
|
||||
// to be some alignment along a baseline and also support for bidi text.
|
||||
@@ -2340,7 +2338,7 @@ impl CanvasState {
|
||||
&self,
|
||||
font_context: &FontContext,
|
||||
text: &'text str,
|
||||
font_group: &mut FontGroup,
|
||||
font_group: &FontGroup,
|
||||
) -> Vec<UnshapedTextRun<'text>> {
|
||||
let mut runs = Vec::new();
|
||||
let mut current_text_run = UnshapedTextRun::default();
|
||||
|
||||
Reference in New Issue
Block a user