Misc optimization/cleanup of use of Cosmic Text on Linux (#30658)
* Use cosmic_text `metadata` attr to write down the `FontId` from the input run to avoid searching the list of fonts when laying out every glyph. * Instead of checking on every glyph if `postscript_name` is an emoji font, just store `is_known_emoji_font`. * Clarify why `font_id_for_cosmic_id` is used, and when its use is valid. Release Notes: - N/A
This commit is contained in:
parent
48b376fdc9
commit
71ea7aee3b
1 changed files with 35 additions and 27 deletions
|
@ -47,7 +47,7 @@ struct CosmicTextSystemState {
|
||||||
struct LoadedFont {
|
struct LoadedFont {
|
||||||
font: Arc<CosmicTextFont>,
|
font: Arc<CosmicTextFont>,
|
||||||
features: CosmicFontFeatures,
|
features: CosmicFontFeatures,
|
||||||
postscript_name: String,
|
is_known_emoji_font: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CosmicTextSystem {
|
impl CosmicTextSystem {
|
||||||
|
@ -219,7 +219,6 @@ impl CosmicTextSystemState {
|
||||||
name
|
name
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut font_ids = SmallVec::new();
|
|
||||||
let families = self
|
let families = self
|
||||||
.font_system
|
.font_system
|
||||||
.db()
|
.db()
|
||||||
|
@ -228,6 +227,7 @@ impl CosmicTextSystemState {
|
||||||
.map(|face| (face.id, face.post_script_name.clone()))
|
.map(|face| (face.id, face.post_script_name.clone()))
|
||||||
.collect::<SmallVec<[_; 4]>>();
|
.collect::<SmallVec<[_; 4]>>();
|
||||||
|
|
||||||
|
let mut loaded_font_ids = SmallVec::new();
|
||||||
for (font_id, postscript_name) in families {
|
for (font_id, postscript_name) in families {
|
||||||
let font = self
|
let font = self
|
||||||
.font_system
|
.font_system
|
||||||
|
@ -248,15 +248,15 @@ impl CosmicTextSystemState {
|
||||||
};
|
};
|
||||||
|
|
||||||
let font_id = FontId(self.loaded_fonts.len());
|
let font_id = FontId(self.loaded_fonts.len());
|
||||||
font_ids.push(font_id);
|
loaded_font_ids.push(font_id);
|
||||||
self.loaded_fonts.push(LoadedFont {
|
self.loaded_fonts.push(LoadedFont {
|
||||||
font,
|
font,
|
||||||
features: features.try_into()?,
|
features: features.try_into()?,
|
||||||
postscript_name,
|
is_known_emoji_font: check_is_known_emoji_font(&postscript_name),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(font_ids)
|
Ok(loaded_font_ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Size<f32>> {
|
fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Size<f32>> {
|
||||||
|
@ -276,11 +276,6 @@ impl CosmicTextSystemState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_emoji(&self, font_id: FontId) -> bool {
|
|
||||||
// TODO: Include other common emoji fonts
|
|
||||||
self.loaded_font(font_id).postscript_name == "NotoColorEmoji"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn raster_bounds(&mut self, params: &RenderGlyphParams) -> Result<Bounds<DevicePixels>> {
|
fn raster_bounds(&mut self, params: &RenderGlyphParams) -> Result<Bounds<DevicePixels>> {
|
||||||
let font = &self.loaded_fonts[params.font_id.0].font;
|
let font = &self.loaded_fonts[params.font_id.0].font;
|
||||||
let subpixel_shift = params
|
let subpixel_shift = params
|
||||||
|
@ -348,6 +343,14 @@ impl CosmicTextSystemState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This is used when cosmic_text has chosen a fallback font instead of using the requested
|
||||||
|
/// font, typically to handle some unicode characters. When this happens, `loaded_fonts` may not
|
||||||
|
/// yet have an entry for this fallback font, and so one is added.
|
||||||
|
///
|
||||||
|
/// Note that callers shouldn't use this `FontId` somewhere that will retrieve the corresponding
|
||||||
|
/// `LoadedFont.features`, as it will have an arbitrarily chosen or empty value. The only
|
||||||
|
/// current use of this field is for the *input* of `layout_line`, and so it's fine to use
|
||||||
|
/// `font_id_for_cosmic_id` when computing the *output* of `layout_line`.
|
||||||
fn font_id_for_cosmic_id(&mut self, id: cosmic_text::fontdb::ID) -> FontId {
|
fn font_id_for_cosmic_id(&mut self, id: cosmic_text::fontdb::ID) -> FontId {
|
||||||
if let Some(ix) = self
|
if let Some(ix) = self
|
||||||
.loaded_fonts
|
.loaded_fonts
|
||||||
|
@ -356,20 +359,14 @@ impl CosmicTextSystemState {
|
||||||
{
|
{
|
||||||
FontId(ix)
|
FontId(ix)
|
||||||
} else {
|
} else {
|
||||||
// This matches the behavior of the mac text system
|
|
||||||
let font = self.font_system.get_font(id).unwrap();
|
let font = self.font_system.get_font(id).unwrap();
|
||||||
let face = self
|
let face = self.font_system.db().face(id).unwrap();
|
||||||
.font_system
|
|
||||||
.db()
|
|
||||||
.faces()
|
|
||||||
.find(|info| info.id == id)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let font_id = FontId(self.loaded_fonts.len());
|
let font_id = FontId(self.loaded_fonts.len());
|
||||||
self.loaded_fonts.push(LoadedFont {
|
self.loaded_fonts.push(LoadedFont {
|
||||||
font: font,
|
font,
|
||||||
features: CosmicFontFeatures::new(),
|
features: CosmicFontFeatures::new(),
|
||||||
postscript_name: face.post_script_name.clone(),
|
is_known_emoji_font: check_is_known_emoji_font(&face.post_script_name),
|
||||||
});
|
});
|
||||||
|
|
||||||
font_id
|
font_id
|
||||||
|
@ -387,6 +384,7 @@ impl CosmicTextSystemState {
|
||||||
attrs_list.add_span(
|
attrs_list.add_span(
|
||||||
offs..(offs + run.len),
|
offs..(offs + run.len),
|
||||||
&Attrs::new()
|
&Attrs::new()
|
||||||
|
.metadata(run.font_id.0)
|
||||||
.family(Family::Name(&font.families.first().unwrap().0))
|
.family(Family::Name(&font.families.first().unwrap().0))
|
||||||
.stretch(font.stretch)
|
.stretch(font.stretch)
|
||||||
.style(font.style)
|
.style(font.style)
|
||||||
|
@ -395,31 +393,35 @@ impl CosmicTextSystemState {
|
||||||
);
|
);
|
||||||
offs += run.len;
|
offs += run.len;
|
||||||
}
|
}
|
||||||
let mut line = ShapeLine::new(
|
|
||||||
|
let line = ShapeLine::new(
|
||||||
&mut self.font_system,
|
&mut self.font_system,
|
||||||
text,
|
text,
|
||||||
&attrs_list,
|
&attrs_list,
|
||||||
cosmic_text::Shaping::Advanced,
|
cosmic_text::Shaping::Advanced,
|
||||||
4,
|
4,
|
||||||
);
|
);
|
||||||
let mut layout = Vec::with_capacity(1);
|
let mut layout_lines = Vec::with_capacity(1);
|
||||||
line.layout_to_buffer(
|
line.layout_to_buffer(
|
||||||
&mut self.scratch,
|
&mut self.scratch,
|
||||||
font_size.0,
|
font_size.0,
|
||||||
None, // We do our own wrapping
|
None, // We do our own wrapping
|
||||||
cosmic_text::Wrap::None,
|
cosmic_text::Wrap::None,
|
||||||
None,
|
None,
|
||||||
&mut layout,
|
&mut layout_lines,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
let layout = layout_lines.first().unwrap();
|
||||||
|
|
||||||
let mut runs = Vec::new();
|
let mut runs = Vec::new();
|
||||||
let layout = layout.first().unwrap();
|
|
||||||
for glyph in &layout.glyphs {
|
for glyph in &layout.glyphs {
|
||||||
let font_id = glyph.font_id;
|
let mut font_id = FontId(glyph.metadata);
|
||||||
let font_id = self.font_id_for_cosmic_id(font_id);
|
let mut loaded_font = self.loaded_font(font_id);
|
||||||
let is_emoji = self.is_emoji(font_id);
|
if loaded_font.font.id() != glyph.font_id {
|
||||||
let mut glyphs = SmallVec::new();
|
font_id = self.font_id_for_cosmic_id(glyph.font_id);
|
||||||
|
loaded_font = self.loaded_font(font_id);
|
||||||
|
}
|
||||||
|
let is_emoji = loaded_font.is_known_emoji_font;
|
||||||
|
|
||||||
// HACK: Prevent crash caused by variation selectors.
|
// HACK: Prevent crash caused by variation selectors.
|
||||||
if glyph.glyph_id == 3 && is_emoji {
|
if glyph.glyph_id == 3 && is_emoji {
|
||||||
|
@ -427,6 +429,7 @@ impl CosmicTextSystemState {
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo(linux) this is definitely wrong, each glyph in glyphs from cosmic-text is a cluster with one glyph, ShapedRun takes a run of glyphs with the same font and direction
|
// todo(linux) this is definitely wrong, each glyph in glyphs from cosmic-text is a cluster with one glyph, ShapedRun takes a run of glyphs with the same font and direction
|
||||||
|
let mut glyphs = SmallVec::new();
|
||||||
glyphs.push(ShapedGlyph {
|
glyphs.push(ShapedGlyph {
|
||||||
id: GlyphId(glyph.glyph_id as u32),
|
id: GlyphId(glyph.glyph_id as u32),
|
||||||
position: point(glyph.x.into(), glyph.y.into()),
|
position: point(glyph.x.into(), glyph.y.into()),
|
||||||
|
@ -565,3 +568,8 @@ fn face_info_into_properties(
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_is_known_emoji_font(postscript_name: &str) -> bool {
|
||||||
|
// TODO: Include other common emoji fonts
|
||||||
|
postscript_name == "NotoColorEmoji"
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue