mirror of
https://github.com/typst/typst
synced 2025-05-16 10:05:28 +08:00
Add microtype options for par
This commit is contained in:
parent
422eb36f16
commit
07ba1c1636
@ -488,7 +488,16 @@ pub fn commit(
|
|||||||
let stretchability = line.stretchability();
|
let stretchability = line.stretchability();
|
||||||
if remaining < Abs::zero() && shrinkability > Abs::zero() {
|
if remaining < Abs::zero() && shrinkability > Abs::zero() {
|
||||||
// Attempt to reduce the length of the line, using shrinkability.
|
// Attempt to reduce the length of the line, using shrinkability.
|
||||||
justification_ratio = (remaining / shrinkability).max(-1.0);
|
let microjustifiables = line.microjustifiables();
|
||||||
|
|
||||||
|
extra_microjustification = (remaining / microjustifiables as f64)
|
||||||
|
.max(p.config.microtype.max_retract.abs);
|
||||||
|
|
||||||
|
justification_ratio = ((remaining
|
||||||
|
- extra_microjustification * microjustifiables as f64)
|
||||||
|
/ shrinkability)
|
||||||
|
.max(-1.0);
|
||||||
|
|
||||||
remaining = (remaining + shrinkability).min(Abs::zero());
|
remaining = (remaining + shrinkability).min(Abs::zero());
|
||||||
} else if line.justify && fr.is_zero() {
|
} else if line.justify && fr.is_zero() {
|
||||||
// Attempt to increase the length of the line, using stretchability.
|
// Attempt to increase the length of the line, using stretchability.
|
||||||
@ -502,8 +511,8 @@ pub fn commit(
|
|||||||
|
|
||||||
if justifiables > 0 && remaining > Abs::zero() {
|
if justifiables > 0 && remaining > Abs::zero() {
|
||||||
// Underfull line, distribute the extra space.
|
// Underfull line, distribute the extra space.
|
||||||
extra_microjustification =
|
extra_microjustification = (remaining / microjustifiables as f64)
|
||||||
(remaining / microjustifiables as f64).min(p.config.microjustification);
|
.min(p.config.microtype.max_expand.abs);
|
||||||
|
|
||||||
extra_justification = (remaining
|
extra_justification = (remaining
|
||||||
- extra_microjustification * microjustifiables as f64)
|
- extra_microjustification * microjustifiables as f64)
|
||||||
|
@ -17,8 +17,8 @@ use typst_library::foundations::{Packed, Resolve, Smart, StyleChain};
|
|||||||
use typst_library::introspection::{Introspector, Locator, LocatorLink, SplitLocator};
|
use typst_library::introspection::{Introspector, Locator, LocatorLink, SplitLocator};
|
||||||
use typst_library::layout::{Abs, AlignElem, Dir, FixedAlignment, Fragment, Size};
|
use typst_library::layout::{Abs, AlignElem, Dir, FixedAlignment, Fragment, Size};
|
||||||
use typst_library::model::{
|
use typst_library::model::{
|
||||||
EnumElem, FirstLineIndent, Linebreaks, ListElem, ParElem, ParLine, ParLineMarker,
|
EnumElem, FirstLineIndent, Linebreaks, ListElem, Microtype, ParElem, ParLine,
|
||||||
TermsElem,
|
ParLineMarker, TermsElem,
|
||||||
};
|
};
|
||||||
use typst_library::routines::{Arenas, Pair, RealizationKind, Routines};
|
use typst_library::routines::{Arenas, Pair, RealizationKind, Routines};
|
||||||
use typst_library::text::{Costs, Lang, TextElem};
|
use typst_library::text::{Costs, Lang, TextElem};
|
||||||
@ -183,13 +183,13 @@ fn configuration(
|
|||||||
situation: Option<ParSituation>,
|
situation: Option<ParSituation>,
|
||||||
) -> Config {
|
) -> Config {
|
||||||
let justify = base.justify;
|
let justify = base.justify;
|
||||||
let microjustification = ParElem::microjustification_in(shared);
|
let microtype = ParElem::microtype_in(shared);
|
||||||
let font_size = TextElem::size_in(shared);
|
let font_size = TextElem::size_in(shared);
|
||||||
let dir = TextElem::dir_in(shared);
|
let dir = TextElem::dir_in(shared);
|
||||||
|
|
||||||
Config {
|
Config {
|
||||||
justify,
|
justify,
|
||||||
microjustification,
|
microtype,
|
||||||
linebreaks: base.linebreaks.unwrap_or_else(|| {
|
linebreaks: base.linebreaks.unwrap_or_else(|| {
|
||||||
if justify {
|
if justify {
|
||||||
Linebreaks::Optimized
|
Linebreaks::Optimized
|
||||||
@ -269,10 +269,8 @@ struct ConfigBase {
|
|||||||
struct Config {
|
struct Config {
|
||||||
/// Whether to justify text.
|
/// Whether to justify text.
|
||||||
justify: bool,
|
justify: bool,
|
||||||
|
|
||||||
/// The maximum allowed kerning adjustment for microjustification.
|
/// The maximum allowed kerning adjustment for microjustification.
|
||||||
microjustification: Abs,
|
microtype: Microtype,
|
||||||
|
|
||||||
/// How to determine line breaks.
|
/// How to determine line breaks.
|
||||||
linebreaks: Linebreaks,
|
linebreaks: Linebreaks,
|
||||||
/// The indent the first line of a paragraph should have.
|
/// The indent the first line of a paragraph should have.
|
||||||
|
@ -10,6 +10,7 @@ use ttf_parser::Tag;
|
|||||||
use typst_library::engine::Engine;
|
use typst_library::engine::Engine;
|
||||||
use typst_library::foundations::{Smart, StyleChain};
|
use typst_library::foundations::{Smart, StyleChain};
|
||||||
use typst_library::layout::{Abs, Dir, Em, Frame, FrameItem, Point, Size};
|
use typst_library::layout::{Abs, Dir, Em, Frame, FrameItem, Point, Size};
|
||||||
|
use typst_library::model::{Microtype, ParElem};
|
||||||
use typst_library::text::{
|
use typst_library::text::{
|
||||||
families, features, is_default_ignorable, variant, Font, FontFamily, FontVariant,
|
families, features, is_default_ignorable, variant, Font, FontFamily, FontVariant,
|
||||||
Glyph, Lang, Region, TextEdgeBounds, TextElem, TextItem,
|
Glyph, Lang, Region, TextEdgeBounds, TextElem, TextItem,
|
||||||
@ -152,7 +153,7 @@ impl ShapedGlyph {
|
|||||||
|| self.c.is_ascii_digit()
|
|| self.c.is_ascii_digit()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn base_adjustability(&self, style: CjkPunctStyle) -> Adjustability {
|
pub fn base_adjustability(&self, style: CjkPunctStyle, microtype: Microtype) -> Adjustability {
|
||||||
let width = self.x_advance;
|
let width = self.x_advance;
|
||||||
if self.is_space() {
|
if self.is_space() {
|
||||||
Adjustability {
|
Adjustability {
|
||||||
@ -176,7 +177,10 @@ impl ShapedGlyph {
|
|||||||
shrinkability: (width / 4.0, width / 4.0),
|
shrinkability: (width / 4.0, width / 4.0),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Adjustability::default()
|
Adjustability {
|
||||||
|
stretchability: (Em::zero(), microtype.max_expand.em),
|
||||||
|
shrinkability: (Em::zero(), microtype.max_retract.em),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -900,7 +904,7 @@ fn shape_segment<'a>(
|
|||||||
x_advance,
|
x_advance,
|
||||||
Adjustability::default().stretchability,
|
Adjustability::default().stretchability,
|
||||||
),
|
),
|
||||||
is_microjustifiable: true,
|
is_microjustifiable: false,
|
||||||
script,
|
script,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -1034,9 +1038,10 @@ fn track_and_space(ctx: &mut ShapingContext) {
|
|||||||
/// and CJK punctuation adjustments according to Chinese Layout Requirements.
|
/// and CJK punctuation adjustments according to Chinese Layout Requirements.
|
||||||
fn calculate_adjustability(ctx: &mut ShapingContext, lang: Lang, region: Option<Region>) {
|
fn calculate_adjustability(ctx: &mut ShapingContext, lang: Lang, region: Option<Region>) {
|
||||||
let style = cjk_punct_style(lang, region);
|
let style = cjk_punct_style(lang, region);
|
||||||
|
let microtype = ParElem::microtype_in(ctx.styles);
|
||||||
|
|
||||||
for glyph in &mut ctx.glyphs {
|
for glyph in &mut ctx.glyphs {
|
||||||
glyph.adjustability = glyph.base_adjustability(style);
|
glyph.adjustability = glyph.base_adjustability(style, microtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut glyphs = ctx.glyphs.iter_mut().peekable();
|
let mut glyphs = ctx.glyphs.iter_mut().peekable();
|
||||||
|
@ -138,16 +138,8 @@ pub struct ParElem {
|
|||||||
#[default(false)]
|
#[default(false)]
|
||||||
pub justify: bool,
|
pub justify: bool,
|
||||||
|
|
||||||
/// The maximum amount of kerning that is allowed to be used to further
|
/// Microtypographical settings that are used during justification.
|
||||||
/// justify an existing line. When this value is nonzero, additional
|
pub microtype: Microtype,
|
||||||
/// justification will be applied to individual glyphs.
|
|
||||||
///
|
|
||||||
/// Note that microjustifications are applied only after a line of text has
|
|
||||||
/// been constructed. This means that the layout will *not* be affected by
|
|
||||||
/// microjustifications, but the internal kerning of a line will be.
|
|
||||||
#[resolve]
|
|
||||||
#[default(Em::new(0.0).into())]
|
|
||||||
pub microjustification: Length,
|
|
||||||
|
|
||||||
/// How to determine line breaks.
|
/// How to determine line breaks.
|
||||||
///
|
///
|
||||||
@ -238,6 +230,36 @@ impl ParElem {
|
|||||||
type ParLine;
|
type ParLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Configuration for microtypographical settings to be used during
|
||||||
|
/// justification.
|
||||||
|
#[derive(Debug, Default, Copy, Clone, PartialEq, Hash)]
|
||||||
|
pub struct Microtype {
|
||||||
|
/// How much a glyph is allowed to translate into its neighbor.
|
||||||
|
pub max_retract: Length,
|
||||||
|
/// How much a glyph is allowed to translate away from its neighbor.
|
||||||
|
pub max_expand: Length,
|
||||||
|
}
|
||||||
|
|
||||||
|
cast! {
|
||||||
|
Microtype,
|
||||||
|
self => Value::Dict(self.into()),
|
||||||
|
mut dict: Dict => {
|
||||||
|
let max_retract = dict.take("max_retract")?.cast()?;
|
||||||
|
let max_expand = dict.take("max_expand")?.cast()?;
|
||||||
|
dict.finish(&["max_retract", "max_expand"])?;
|
||||||
|
Self { max_retract, max_expand }
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Microtype> for Dict {
|
||||||
|
fn from(microtype: Microtype) -> Self {
|
||||||
|
dict! {
|
||||||
|
"max_retract" => microtype.max_retract,
|
||||||
|
"max_expand" => microtype.max_expand,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// How to determine line breaks in a paragraph.
|
/// How to determine line breaks in a paragraph.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Cast)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Cast)]
|
||||||
pub enum Linebreaks {
|
pub enum Linebreaks {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user