mirror of
https://github.com/typst/typst
synced 2025-08-23 19:24:14 +08:00
Use all glyph positioning information from the shaper
This commit is contained in:
parent
b7e5886e42
commit
30d1e62eb2
@ -952,7 +952,7 @@ pub fn create_shape_plan(
|
|||||||
|
|
||||||
/// 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.x_advance(0).unwrap_or_default();
|
||||||
let add_glyph = |(cluster, c): (usize, char)| {
|
let add_glyph = |(cluster, c): (usize, char)| {
|
||||||
let start = base + cluster;
|
let start = base + cluster;
|
||||||
let end = start + c.len_utf8();
|
let end = start + c.len_utf8();
|
||||||
@ -1045,7 +1045,7 @@ fn calculate_adjustability(ctx: &mut ShapingContext, lang: Lang, region: Option<
|
|||||||
/// Difference between non-breaking and normal space.
|
/// Difference between non-breaking and normal space.
|
||||||
fn nbsp_delta(font: &Font) -> Option<Em> {
|
fn nbsp_delta(font: &Font) -> Option<Em> {
|
||||||
let nbsp = font.ttf().glyph_index('\u{00A0}')?.0;
|
let nbsp = font.ttf().glyph_index('\u{00A0}')?.0;
|
||||||
Some(font.advance(nbsp)? - font.space_width()?)
|
Some(font.x_advance(nbsp)? - font.space_width()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if all glyphs in `glyphs` have ranges within the range `range`.
|
/// Returns true if all glyphs in `glyphs` have ranges within the range `range`.
|
||||||
|
@ -23,6 +23,7 @@ use crate::modifiers::{FrameModifiers, FrameModify};
|
|||||||
/// Maximum number of times extenders can be repeated.
|
/// Maximum number of times extenders can be repeated.
|
||||||
const MAX_REPEATS: usize = 1024;
|
const MAX_REPEATS: usize = 1024;
|
||||||
|
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum MathFragment {
|
pub enum MathFragment {
|
||||||
Glyph(GlyphFragment),
|
Glyph(GlyphFragment),
|
||||||
@ -199,7 +200,7 @@ impl MathFragment {
|
|||||||
// For glyph assemblies we pick either the start or end glyph
|
// For glyph assemblies we pick either the start or end glyph
|
||||||
// depending on the corner.
|
// depending on the corner.
|
||||||
let is_vertical =
|
let is_vertical =
|
||||||
glyph.item.glyphs.iter().any(|glyph| glyph.y_advance != Em::zero());
|
glyph.item.glyphs.iter().all(|glyph| glyph.y_advance != Em::zero());
|
||||||
let glyph_index = match (is_vertical, corner) {
|
let glyph_index = match (is_vertical, corner) {
|
||||||
(true, Corner::TopLeft | Corner::TopRight) => {
|
(true, Corner::TopLeft | Corner::TopRight) => {
|
||||||
glyph.item.glyphs.len() - 1
|
glyph.item.glyphs.len() - 1
|
||||||
@ -240,7 +241,7 @@ impl From<FrameFragment> for MathFragment {
|
|||||||
pub struct GlyphFragment {
|
pub struct GlyphFragment {
|
||||||
// Text stuff.
|
// Text stuff.
|
||||||
pub item: TextItem,
|
pub item: TextItem,
|
||||||
pub base_id: GlyphId,
|
pub base_glyph: Glyph,
|
||||||
// Math stuff.
|
// Math stuff.
|
||||||
pub size: Size,
|
pub size: Size,
|
||||||
pub baseline: Option<Abs>,
|
pub baseline: Option<Abs>,
|
||||||
@ -318,6 +319,16 @@ impl GlyphFragment {
|
|||||||
.or_else(|| default_math_class(c))
|
.or_else(|| default_math_class(c))
|
||||||
.unwrap_or(MathClass::Normal);
|
.unwrap_or(MathClass::Normal);
|
||||||
|
|
||||||
|
let glyph = Glyph {
|
||||||
|
id: info.glyph_id as u16,
|
||||||
|
x_advance: font.to_em(pos.x_advance),
|
||||||
|
x_offset: font.to_em(pos.x_offset),
|
||||||
|
y_advance: font.to_em(pos.y_advance),
|
||||||
|
y_offset: font.to_em(pos.y_offset),
|
||||||
|
range: 0..text.len().saturating_as(),
|
||||||
|
span: (span, 0),
|
||||||
|
};
|
||||||
|
|
||||||
let item = TextItem {
|
let item = TextItem {
|
||||||
font: font.clone(),
|
font: font.clone(),
|
||||||
size: TextElem::size_in(styles),
|
size: TextElem::size_in(styles),
|
||||||
@ -326,20 +337,12 @@ impl GlyphFragment {
|
|||||||
lang: TextElem::lang_in(styles),
|
lang: TextElem::lang_in(styles),
|
||||||
region: TextElem::region_in(styles),
|
region: TextElem::region_in(styles),
|
||||||
text: text.into(),
|
text: text.into(),
|
||||||
glyphs: vec![Glyph {
|
glyphs: vec![glyph.clone()],
|
||||||
id: info.glyph_id as u16,
|
|
||||||
x_advance: font.to_em(pos.x_advance),
|
|
||||||
x_offset: Em::zero(),
|
|
||||||
y_advance: Em::zero(),
|
|
||||||
y_offset: Em::zero(),
|
|
||||||
range: 0..text.len().saturating_as(),
|
|
||||||
span: (span, 0),
|
|
||||||
}],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut fragment = Self {
|
let mut fragment = Self {
|
||||||
item,
|
item,
|
||||||
base_id: GlyphId(info.glyph_id as u16),
|
base_glyph: glyph,
|
||||||
// Math
|
// Math
|
||||||
math_size: EquationElem::size_in(styles),
|
math_size: EquationElem::size_in(styles),
|
||||||
class,
|
class,
|
||||||
@ -399,11 +402,7 @@ impl GlyphFragment {
|
|||||||
// base_id's. This is used to return a glyph to its unstretched state.
|
// base_id's. This is used to return a glyph to its unstretched state.
|
||||||
pub fn reset_glyph(&mut self) {
|
pub fn reset_glyph(&mut self) {
|
||||||
self.align = Abs::zero();
|
self.align = Abs::zero();
|
||||||
self.item.glyphs = vec![Glyph {
|
self.item.glyphs = vec![self.base_glyph.clone()];
|
||||||
id: self.base_id.0,
|
|
||||||
x_advance: self.item.font.advance(self.base_id.0).unwrap_or_default(),
|
|
||||||
..self.item.glyphs[0].clone()
|
|
||||||
}];
|
|
||||||
self.update_glyph();
|
self.update_glyph();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,7 +478,11 @@ impl GlyphFragment {
|
|||||||
if target <= best_advance || construction.assembly.is_none() {
|
if target <= best_advance || construction.assembly.is_none() {
|
||||||
self.item.glyphs[0].id = best_id.0;
|
self.item.glyphs[0].id = best_id.0;
|
||||||
self.item.glyphs[0].x_advance =
|
self.item.glyphs[0].x_advance =
|
||||||
self.item.font.advance(best_id.0).unwrap_or_default();
|
self.item.font.x_advance(best_id.0).unwrap_or_default();
|
||||||
|
self.item.glyphs[0].x_offset = Em::zero();
|
||||||
|
self.item.glyphs[0].y_advance =
|
||||||
|
self.item.font.y_advance(best_id.0).unwrap_or_default();
|
||||||
|
self.item.glyphs[0].y_offset = Em::zero();
|
||||||
self.update_glyph();
|
self.update_glyph();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -649,7 +652,8 @@ fn axis_height(font: &Font) -> Option<Em> {
|
|||||||
Some(font.to_em(font.ttf().tables().math?.constants?.axis_height().value))
|
Some(font.to_em(font.ttf().tables().math?.constants?.axis_height().value))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stretch_axes(font: &Font, id: GlyphId) -> Axes<bool> {
|
pub fn stretch_axes(font: &Font, id: u16) -> Axes<bool> {
|
||||||
|
let id = GlyphId(id);
|
||||||
let horizontal = font
|
let horizontal = font
|
||||||
.ttf()
|
.ttf()
|
||||||
.tables()
|
.tables()
|
||||||
@ -783,7 +787,7 @@ fn assemble(
|
|||||||
base.size.y = full;
|
base.size.y = full;
|
||||||
base.size.x = glyphs
|
base.size.x = glyphs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|glyph| base.item.font.advance(glyph.id).unwrap_or_default())
|
.map(|glyph| base.item.font.x_advance(glyph.id).unwrap_or_default())
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.at(base.item.size);
|
.at(base.item.size);
|
||||||
|
@ -34,7 +34,7 @@ pub fn stretch_fragment(
|
|||||||
|
|
||||||
// Return if we attempt to stretch along an axis which isn't stretchable,
|
// Return if we attempt to stretch along an axis which isn't stretchable,
|
||||||
// so that the original fragment isn't modified.
|
// so that the original fragment isn't modified.
|
||||||
let axes = stretch_axes(&glyph.item.font, glyph.base_id);
|
let axes = stretch_axes(&glyph.item.font, glyph.base_glyph.id);
|
||||||
let stretch_axis = if let Some(axis) = axis {
|
let stretch_axis = if let Some(axis) = axis {
|
||||||
if !axes.get(axis) {
|
if !axes.get(axis) {
|
||||||
return;
|
return;
|
||||||
|
@ -106,16 +106,24 @@ impl Font {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Look up the horizontal advance width of a glyph.
|
/// Look up the horizontal advance width of a glyph.
|
||||||
pub fn advance(&self, glyph: u16) -> Option<Em> {
|
pub fn x_advance(&self, glyph: u16) -> Option<Em> {
|
||||||
self.0
|
self.0
|
||||||
.ttf
|
.ttf
|
||||||
.glyph_hor_advance(GlyphId(glyph))
|
.glyph_hor_advance(GlyphId(glyph))
|
||||||
.map(|units| self.to_em(units))
|
.map(|units| self.to_em(units))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Look up the vertical advance width of a glyph.
|
||||||
|
pub fn y_advance(&self, glyph: u16) -> Option<Em> {
|
||||||
|
self.0
|
||||||
|
.ttf
|
||||||
|
.glyph_ver_advance(GlyphId(glyph))
|
||||||
|
.map(|units| self.to_em(units))
|
||||||
|
}
|
||||||
|
|
||||||
/// Look up the width of a space.
|
/// Look up the width of a space.
|
||||||
pub fn space_width(&self) -> Option<Em> {
|
pub fn space_width(&self) -> Option<Em> {
|
||||||
self.0.ttf.glyph_index(' ').and_then(|id| self.advance(id.0))
|
self.0.ttf.glyph_index(' ').and_then(|id| self.x_advance(id.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lookup a name by id.
|
/// Lookup a name by id.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user