mirror of
https://github.com/typst/typst
synced 2025-08-24 03:34:14 +08:00
Compute width of shaped text on-demand (#6806)
This commit is contained in:
parent
aef36f3962
commit
f9caddc6d3
@ -82,7 +82,7 @@ impl<'a> Item<'a> {
|
||||
/// The natural layouted width of the item.
|
||||
pub fn natural_width(&self) -> Abs {
|
||||
match self {
|
||||
Self::Text(shaped) => shaped.width,
|
||||
Self::Text(shaped) => shaped.width(),
|
||||
Self::Absolute(v, _) => *v,
|
||||
Self::Frame(frame) => frame.width(),
|
||||
Self::Fractional(_, _) | Self::Tag(_) => Abs::zero(),
|
||||
|
@ -364,7 +364,6 @@ fn adjust_cj_at_line_start(p: &Preparation, items: &mut Items) {
|
||||
let glyph = shaped.glyphs.to_mut().first_mut().unwrap();
|
||||
let shrink = glyph.shrinkability().0;
|
||||
glyph.shrink_left(shrink);
|
||||
shaped.width -= shrink.at(glyph.size);
|
||||
} else if p.config.cjk_latin_spacing
|
||||
&& glyph.is_cj_script()
|
||||
&& glyph.x_offset > Em::zero()
|
||||
@ -376,7 +375,6 @@ fn adjust_cj_at_line_start(p: &Preparation, items: &mut Items) {
|
||||
glyph.x_advance -= shrink;
|
||||
glyph.x_offset = Em::zero();
|
||||
glyph.adjustability.shrinkability.0 = Em::zero();
|
||||
shaped.width -= shrink.at(glyph.size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -394,7 +392,6 @@ fn adjust_cj_at_line_end(p: &Preparation, items: &mut Items) {
|
||||
let shrink = glyph.shrinkability().1;
|
||||
let punct = shaped.glyphs.to_mut().last_mut().unwrap();
|
||||
punct.shrink_right(shrink);
|
||||
shaped.width -= shrink.at(punct.size);
|
||||
} else if p.config.cjk_latin_spacing
|
||||
&& glyph.is_cj_script()
|
||||
&& (glyph.x_advance - glyph.x_offset) > Em::one()
|
||||
@ -405,7 +402,6 @@ fn adjust_cj_at_line_end(p: &Preparation, items: &mut Items) {
|
||||
let glyph = shaped.glyphs.to_mut().last_mut().unwrap();
|
||||
glyph.x_advance -= shrink;
|
||||
glyph.adjustability.shrinkability.1 = Em::zero();
|
||||
shaped.width -= shrink.at(glyph.size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,6 @@ fn add_cjk_latin_spacing(items: &mut [(Range, Item)]) {
|
||||
// The spacing is default to 1/4 em, and can be shrunk to 1/8 em.
|
||||
glyph.x_advance += Em::new(0.25);
|
||||
glyph.adjustability.shrinkability.1 += Em::new(0.125);
|
||||
text.width += Em::new(0.25).at(glyph.size);
|
||||
}
|
||||
|
||||
// Case 2: Latin followed by a CJ character
|
||||
@ -160,7 +159,6 @@ fn add_cjk_latin_spacing(items: &mut [(Range, Item)]) {
|
||||
glyph.x_advance += Em::new(0.25);
|
||||
glyph.x_offset += Em::new(0.25);
|
||||
glyph.adjustability.shrinkability.0 += Em::new(0.125);
|
||||
text.width += Em::new(0.25).at(glyph.size);
|
||||
}
|
||||
|
||||
prev = Some(glyph);
|
||||
|
@ -47,8 +47,6 @@ pub struct ShapedText<'a> {
|
||||
pub styles: StyleChain<'a>,
|
||||
/// The font variant.
|
||||
pub variant: FontVariant,
|
||||
/// The width of the text's bounding box.
|
||||
pub width: Abs,
|
||||
/// The shaped glyphs.
|
||||
pub glyphs: Cow<'a, [ShapedGlyph]>,
|
||||
}
|
||||
@ -214,7 +212,7 @@ impl<'a> ShapedText<'a> {
|
||||
extra_justification: Abs,
|
||||
) -> Frame {
|
||||
let (top, bottom) = self.measure(engine);
|
||||
let size = Size::new(self.width, top + bottom);
|
||||
let size = Size::new(self.width(), top + bottom);
|
||||
|
||||
let mut offset = Abs::zero();
|
||||
let mut frame = Frame::soft(size);
|
||||
@ -332,6 +330,12 @@ impl<'a> ShapedText<'a> {
|
||||
frame
|
||||
}
|
||||
|
||||
/// Computes the width of a run of glyphs relative to the font size,
|
||||
/// accounting for their individual scaling factors and other font metrics.
|
||||
pub fn width(&self) -> Abs {
|
||||
self.glyphs.iter().map(|g| g.x_advance.at(g.size)).sum()
|
||||
}
|
||||
|
||||
/// Measure the top and bottom extent of this text.
|
||||
pub fn measure(&self, engine: &Engine) -> (Abs, Abs) {
|
||||
let mut top = Abs::zero();
|
||||
@ -419,7 +423,6 @@ impl<'a> ShapedText<'a> {
|
||||
region: self.region,
|
||||
styles: self.styles,
|
||||
variant: self.variant,
|
||||
width: glyphs_width(glyphs),
|
||||
glyphs: Cow::Borrowed(glyphs),
|
||||
}
|
||||
} else {
|
||||
@ -437,12 +440,7 @@ impl<'a> ShapedText<'a> {
|
||||
|
||||
/// Derive an empty text run with the same properties as this one.
|
||||
pub fn empty(&self) -> Self {
|
||||
Self {
|
||||
text: "",
|
||||
width: Abs::zero(),
|
||||
glyphs: Cow::Borrowed(&[]),
|
||||
..*self
|
||||
}
|
||||
Self { text: "", glyphs: Cow::Borrowed(&[]), ..*self }
|
||||
}
|
||||
|
||||
/// Creates shaped text containing a hyphen.
|
||||
@ -485,7 +483,6 @@ impl<'a> ShapedText<'a> {
|
||||
region: base.region,
|
||||
styles: base.styles,
|
||||
variant: base.variant,
|
||||
width: x_advance.at(size),
|
||||
glyphs: Cow::Owned(vec![ShapedGlyph {
|
||||
font,
|
||||
glyph_id: glyph_id.0,
|
||||
@ -694,17 +691,10 @@ fn shape<'a>(
|
||||
region,
|
||||
styles,
|
||||
variant: ctx.variant,
|
||||
width: glyphs_width(&ctx.glyphs),
|
||||
glyphs: Cow::Owned(ctx.glyphs),
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the width of a run of glyphs relative to the font size, accounting
|
||||
/// for their individual scaling factors and other font metrics.
|
||||
fn glyphs_width(glyphs: &[ShapedGlyph]) -> Abs {
|
||||
glyphs.iter().map(|g| g.x_advance.at(g.size)).sum()
|
||||
}
|
||||
|
||||
/// Holds shaping results and metadata common to all shaped segments.
|
||||
struct ShapingContext<'a, 'v> {
|
||||
engine: &'a Engine<'v>,
|
||||
|
Loading…
x
Reference in New Issue
Block a user