Shape plan caching (#2876)

This commit is contained in:
Laurenz 2023-12-18 15:35:21 +01:00 committed by GitHub
parent 84597b46a4
commit a821b48cf4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -2,10 +2,11 @@ use std::borrow::Cow;
use std::fmt::{self, Debug, Formatter}; use std::fmt::{self, Debug, Formatter};
use std::ops::Range; use std::ops::Range;
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc;
use az::SaturatingAs; use az::SaturatingAs;
use ecow::EcoString; use ecow::EcoString;
use rustybuzz::{Tag, UnicodeBuffer}; use rustybuzz::{ShapePlan, Tag, UnicodeBuffer};
use unicode_script::{Script, UnicodeScript}; use unicode_script::{Script, UnicodeScript};
use super::SpanMapper; use super::SpanMapper;
@ -690,9 +691,21 @@ fn shape_segment<'a>(
Dir::RTL => rustybuzz::Direction::RightToLeft, Dir::RTL => rustybuzz::Direction::RightToLeft,
_ => unimplemented!("vertical text layout"), _ => unimplemented!("vertical text layout"),
}); });
buffer.guess_segment_properties();
// Prepare the shape plan. This plan depends on direction, script, language,
// and features, but is independent from the text and can thus be
// memoized.
let plan = create_shape_plan(
&font,
buffer.direction(),
buffer.script(),
buffer.language().as_ref(),
&ctx.features,
);
// Shape! // Shape!
let buffer = rustybuzz::shape(font.rusty(), &ctx.features, buffer); let buffer = rustybuzz::shape_with_plan(font.rusty(), &plan, buffer);
let infos = buffer.glyph_infos(); let infos = buffer.glyph_infos();
let pos = buffer.glyph_positions(); let pos = buffer.glyph_positions();
let ltr = ctx.dir.is_positive(); let ltr = ctx.dir.is_positive();
@ -783,6 +796,24 @@ fn shape_segment<'a>(
ctx.used.pop(); ctx.used.pop();
} }
/// Create a shape plan.
#[comemo::memoize]
fn create_shape_plan(
font: &Font,
direction: rustybuzz::Direction,
script: rustybuzz::Script,
language: Option<&rustybuzz::Language>,
features: &[rustybuzz::Feature],
) -> Arc<ShapePlan> {
Arc::new(rustybuzz::ShapePlan::new(
font.rusty(),
direction,
Some(script),
language,
features,
))
}
/// Shape the text with tofus from the given font. /// Shape the text with tofus from the given font.
fn shape_tofus(ctx: &mut ShapingContext, base: usize, text: &str, font: Font) { fn shape_tofus(ctx: &mut ShapingContext, base: usize, text: &str, font: Font) {
let x_advance = font.advance(0).unwrap_or_default(); let x_advance = font.advance(0).unwrap_or_default();