summaryrefslogtreecommitdiff
path: root/src/library/text
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-09-20 13:05:55 +0200
committerLaurenz <laurmaedje@gmail.com>2022-09-20 16:37:15 +0200
commit757a701c1aa2a6fb80033c7e75666661818da6f9 (patch)
tree0415fec94d3856f4ebc97a1744cf2ba75fe8e7aa /src/library/text
parente29f55bb294cc298daad97accf6d8a76976b409c (diff)
A New World
Diffstat (limited to 'src/library/text')
-rw-r--r--src/library/text/deco.rs4
-rw-r--r--src/library/text/link.rs6
-rw-r--r--src/library/text/mod.rs16
-rw-r--r--src/library/text/par.rs66
-rw-r--r--src/library/text/raw.rs6
-rw-r--r--src/library/text/repeat.rs6
-rw-r--r--src/library/text/shaping.rs32
-rw-r--r--src/library/text/shift.rs14
8 files changed, 72 insertions, 78 deletions
diff --git a/src/library/text/deco.rs b/src/library/text/deco.rs
index 8295f1a2..c58148b4 100644
--- a/src/library/text/deco.rs
+++ b/src/library/text/deco.rs
@@ -34,7 +34,7 @@ impl<const L: DecoLine> DecoNode<L> {
/// with the glyphs. Does not apply to strikethrough.
pub const EVADE: bool = true;
- fn construct(_: &mut Machine, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
Ok(Content::show(Self(args.expect("body")?)))
}
}
@@ -48,7 +48,7 @@ impl<const L: DecoLine> Show for DecoNode<L> {
dict! { "body" => Value::Content(self.0.clone()) }
}
- fn realize(&self, _: &mut Context, styles: StyleChain) -> TypResult<Content> {
+ fn realize(&self, _: &dyn World, styles: StyleChain) -> TypResult<Content> {
Ok(self.0.clone().styled(TextNode::DECO, Decoration {
line: L,
stroke: styles.get(Self::STROKE).unwrap_or_default(),
diff --git a/src/library/text/link.rs b/src/library/text/link.rs
index c4898eb0..7d5c3109 100644
--- a/src/library/text/link.rs
+++ b/src/library/text/link.rs
@@ -18,7 +18,7 @@ impl LinkNode {
/// Whether to underline the link.
pub const UNDERLINE: Smart<bool> = Smart::Auto;
- fn construct(_: &mut Machine, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
Ok(Content::show({
let dest = args.expect::<Destination>("destination")?;
let body = match dest {
@@ -64,7 +64,7 @@ impl Show for LinkNode {
}
}
- fn realize(&self, _: &mut Context, _: StyleChain) -> TypResult<Content> {
+ fn realize(&self, _: &dyn World, _: StyleChain) -> TypResult<Content> {
Ok(self.body.clone().unwrap_or_else(|| match &self.dest {
Destination::Url(url) => {
let mut text = url.as_str();
@@ -80,7 +80,7 @@ impl Show for LinkNode {
fn finalize(
&self,
- _: &mut Context,
+ _: &dyn World,
styles: StyleChain,
mut realized: Content,
) -> TypResult<Content> {
diff --git a/src/library/text/mod.rs b/src/library/text/mod.rs
index 35780186..be586874 100644
--- a/src/library/text/mod.rs
+++ b/src/library/text/mod.rs
@@ -128,7 +128,7 @@ impl TextNode {
#[property(skip, fold)]
pub const DECO: Decoration = vec![];
- fn construct(_: &mut Machine, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
// The text constructor is special: It doesn't create a text node.
// Instead, it leaves the passed argument structurally unchanged, but
// styles all text in it.
@@ -422,12 +422,12 @@ impl Fold for Vec<(Tag, u32)> {
}
/// Convert a string or content to lowercase.
-pub fn lower(_: &mut Machine, args: &mut Args) -> TypResult<Value> {
+pub fn lower(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
case(Case::Lower, args)
}
/// Convert a string or content to uppercase.
-pub fn upper(_: &mut Machine, args: &mut Args) -> TypResult<Value> {
+pub fn upper(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
case(Case::Upper, args)
}
@@ -461,7 +461,7 @@ impl Case {
}
/// Display text in small capitals.
-pub fn smallcaps(_: &mut Machine, args: &mut Args) -> TypResult<Value> {
+pub fn smallcaps(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
let body: Content = args.expect("content")?;
Ok(Value::Content(body.styled(TextNode::SMALLCAPS, true)))
}
@@ -493,7 +493,7 @@ pub struct StrongNode(pub Content);
#[node(showable)]
impl StrongNode {
- fn construct(_: &mut Machine, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
Ok(Content::show(Self(args.expect("body")?)))
}
}
@@ -507,7 +507,7 @@ impl Show for StrongNode {
dict! { "body" => Value::Content(self.0.clone()) }
}
- fn realize(&self, _: &mut Context, _: StyleChain) -> TypResult<Content> {
+ fn realize(&self, _: &dyn World, _: StyleChain) -> TypResult<Content> {
Ok(self.0.clone().styled(TextNode::BOLD, Toggle))
}
}
@@ -518,7 +518,7 @@ pub struct EmphNode(pub Content);
#[node(showable)]
impl EmphNode {
- fn construct(_: &mut Machine, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
Ok(Content::show(Self(args.expect("body")?)))
}
}
@@ -532,7 +532,7 @@ impl Show for EmphNode {
dict! { "body" => Value::Content(self.0.clone()) }
}
- fn realize(&self, _: &mut Context, _: StyleChain) -> TypResult<Content> {
+ fn realize(&self, _: &dyn World, _: StyleChain) -> TypResult<Content> {
Ok(self.0.clone().styled(TextNode::ITALIC, Toggle))
}
}
diff --git a/src/library/text/par.rs b/src/library/text/par.rs
index 8309bcc8..e8282ef1 100644
--- a/src/library/text/par.rs
+++ b/src/library/text/par.rs
@@ -49,7 +49,7 @@ impl ParNode {
#[property(resolve)]
pub const LINEBREAKS: Smart<Linebreaks> = Smart::Auto;
- fn construct(_: &mut Machine, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
// The paragraph constructor is special: It doesn't create a paragraph
// node. Instead, it just ensures that the passed content lives is in a
// separate paragraph and styles it.
@@ -64,7 +64,7 @@ impl ParNode {
impl Layout for ParNode {
fn layout(
&self,
- ctx: &mut Context,
+ world: &dyn World,
regions: &Regions,
styles: StyleChain,
) -> TypResult<Vec<Frame>> {
@@ -74,13 +74,13 @@ impl Layout for ParNode {
// Perform BiDi analysis and then prepare paragraph layout by building a
// representation on which we can do line breaking without layouting
// each and every line from scratch.
- let p = prepare(ctx, self, &text, segments, regions, styles)?;
+ let p = prepare(world, self, &text, segments, regions, styles)?;
// Break the paragraph into lines.
- let lines = linebreak(&p, ctx.loader.as_ref(), regions.first.x);
+ let lines = linebreak(&p, world, regions.first.x);
// Stack the lines into one frame per region.
- stack(&p, ctx, &lines, regions)
+ stack(&p, world, &lines, regions)
}
}
@@ -170,7 +170,7 @@ pub struct ParbreakNode;
#[node]
impl ParbreakNode {
- fn construct(_: &mut Machine, _: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, _: &mut Args) -> TypResult<Content> {
Ok(Content::Parbreak)
}
}
@@ -180,7 +180,7 @@ pub struct LinebreakNode;
#[node]
impl LinebreakNode {
- fn construct(_: &mut Machine, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
let justified = args.named("justified")?.unwrap_or(false);
Ok(Content::Linebreak { justified })
}
@@ -496,7 +496,7 @@ fn collect<'a>(
/// Prepare paragraph layout by shaping the whole paragraph and layouting all
/// contained inline-level nodes.
fn prepare<'a>(
- ctx: &mut Context,
+ world: &dyn World,
par: &'a ParNode,
text: &'a str,
segments: Vec<(Segment<'a>, StyleChain<'a>)>,
@@ -517,13 +517,7 @@ fn prepare<'a>(
let end = cursor + segment.len();
match segment {
Segment::Text(_) => {
- shape_range(
- &mut items,
- ctx.loader.as_ref(),
- &bidi,
- cursor .. end,
- styles,
- );
+ shape_range(&mut items, world, &bidi, cursor .. end, styles);
}
Segment::Spacing(spacing) => match spacing {
Spacing::Relative(v) => {
@@ -540,7 +534,7 @@ fn prepare<'a>(
} else {
let size = Size::new(regions.first.x, regions.base.y);
let pod = Regions::one(size, regions.base, Spec::splat(false));
- let mut frame = node.layout(ctx, &pod, styles)?.remove(0);
+ let mut frame = node.layout(world, &pod, styles)?.remove(0);
frame.translate(Point::with_y(styles.get(TextNode::BASELINE)));
frame.apply_role(Role::GenericInline);
items.push(Item::Frame(frame));
@@ -567,14 +561,14 @@ fn prepare<'a>(
/// items for them.
fn shape_range<'a>(
items: &mut Vec<Item<'a>>,
- loader: &dyn Loader,
+ world: &dyn World,
bidi: &BidiInfo<'a>,
range: Range,
styles: StyleChain<'a>,
) {
let mut process = |text, level: Level| {
let dir = if level.is_ltr() { Dir::LTR } else { Dir::RTL };
- let shaped = shape(loader, text, styles, dir);
+ let shaped = shape(world, text, styles, dir);
items.push(Item::Text(shaped));
};
@@ -633,12 +627,12 @@ fn shared_get<'a, K: Key<'a>>(
/// Find suitable linebreaks.
fn linebreak<'a>(
p: &'a Preparation<'a>,
- loader: &dyn Loader,
+ world: &dyn World,
width: Length,
) -> Vec<Line<'a>> {
match p.styles.get(ParNode::LINEBREAKS) {
- Linebreaks::Simple => linebreak_simple(p, loader, width),
- Linebreaks::Optimized => linebreak_optimized(p, loader, width),
+ Linebreaks::Simple => linebreak_simple(p, world, width),
+ Linebreaks::Optimized => linebreak_optimized(p, world, width),
}
}
@@ -647,7 +641,7 @@ fn linebreak<'a>(
/// very unbalanced line, but is fast and simple.
fn linebreak_simple<'a>(
p: &'a Preparation<'a>,
- loader: &dyn Loader,
+ world: &dyn World,
width: Length,
) -> Vec<Line<'a>> {
let mut lines = vec![];
@@ -656,7 +650,7 @@ fn linebreak_simple<'a>(
for (end, mandatory, hyphen) in breakpoints(p) {
// Compute the line and its size.
- let mut attempt = line(p, loader, start .. end, mandatory, hyphen);
+ let mut attempt = line(p, world, start .. end, mandatory, hyphen);
// If the line doesn't fit anymore, we push the last fitting attempt
// into the stack and rebuild the line from the attempt's end. The
@@ -665,7 +659,7 @@ fn linebreak_simple<'a>(
if let Some((last_attempt, last_end)) = last.take() {
lines.push(last_attempt);
start = last_end;
- attempt = line(p, loader, start .. end, mandatory, hyphen);
+ attempt = line(p, world, start .. end, mandatory, hyphen);
}
}
@@ -707,7 +701,7 @@ fn linebreak_simple<'a>(
/// text.
fn linebreak_optimized<'a>(
p: &'a Preparation<'a>,
- loader: &dyn Loader,
+ world: &dyn World,
width: Length,
) -> Vec<Line<'a>> {
/// The cost of a line or paragraph layout.
@@ -732,7 +726,7 @@ fn linebreak_optimized<'a>(
let mut table = vec![Entry {
pred: 0,
total: 0.0,
- line: line(p, loader, 0 .. 0, false, false),
+ line: line(p, world, 0 .. 0, false, false),
}];
let em = p.styles.get(TextNode::SIZE);
@@ -746,7 +740,7 @@ fn linebreak_optimized<'a>(
for (i, pred) in table.iter_mut().enumerate().skip(active) {
// Layout the line.
let start = pred.line.end;
- let attempt = line(p, loader, start .. end, mandatory, hyphen);
+ let attempt = line(p, world, start .. end, mandatory, hyphen);
// Determine how much the line's spaces would need to be stretched
// to make it the desired width.
@@ -920,7 +914,7 @@ impl Breakpoints<'_> {
/// Create a line which spans the given range.
fn line<'a>(
p: &'a Preparation,
- loader: &dyn Loader,
+ world: &dyn World,
mut range: Range,
mandatory: bool,
hyphen: bool,
@@ -975,9 +969,9 @@ fn line<'a>(
if hyphen || start + shaped.text.len() > range.end {
if hyphen || start < range.end || before.is_empty() {
let shifted = start - base .. range.end - base;
- let mut reshaped = shaped.reshape(loader, shifted);
+ let mut reshaped = shaped.reshape(world, shifted);
if hyphen || shy {
- reshaped.push_hyphen(loader);
+ reshaped.push_hyphen(world);
}
width += reshaped.width;
last = Some(Item::Text(reshaped));
@@ -998,7 +992,7 @@ fn line<'a>(
if range.start + shaped.text.len() > end {
if range.start < end {
let shifted = range.start - base .. end - base;
- let reshaped = shaped.reshape(loader, shifted);
+ let reshaped = shaped.reshape(world, shifted);
width += reshaped.width;
first = Some(Item::Text(reshaped));
}
@@ -1028,7 +1022,7 @@ fn line<'a>(
/// Combine layouted lines into one frame per region.
fn stack(
p: &Preparation,
- ctx: &mut Context,
+ world: &dyn World,
lines: &[Line],
regions: &Regions,
) -> TypResult<Vec<Frame>> {
@@ -1048,7 +1042,7 @@ fn stack(
// Stack the lines into one frame per region.
for line in lines {
- let frame = commit(p, ctx, line, &regions, width)?;
+ let frame = commit(p, world, line, &regions, width)?;
let height = frame.size().y;
while !regions.first.y.fits(height) && !regions.in_last() {
@@ -1078,7 +1072,7 @@ fn stack(
/// Commit to a line and build its frame.
fn commit(
p: &Preparation,
- ctx: &mut Context,
+ world: &dyn World,
line: &Line,
regions: &Regions,
width: Length,
@@ -1149,7 +1143,7 @@ fn commit(
offset += v.share(fr, remaining);
}
Item::Text(shaped) => {
- let frame = shaped.build(ctx.loader.as_ref(), justification);
+ let frame = shaped.build(world, justification);
push(&mut offset, frame);
}
Item::Frame(frame) => {
@@ -1160,7 +1154,7 @@ fn commit(
let fill = Fraction::one().share(fr, remaining);
let size = Size::new(fill, regions.base.y);
let pod = Regions::one(size, regions.base, Spec::new(false, false));
- let frame = node.layout(ctx, &pod, *styles)?.remove(0);
+ let frame = node.layout(world, &pod, *styles)?.remove(0);
let width = frame.width();
let count = (fill / width).floor();
let remaining = fill % width;
diff --git a/src/library/text/raw.rs b/src/library/text/raw.rs
index a2a57fa1..c729fa40 100644
--- a/src/library/text/raw.rs
+++ b/src/library/text/raw.rs
@@ -35,7 +35,7 @@ impl RawNode {
#[property(resolve, shorthand(around))]
pub const BELOW: Option<BlockSpacing> = Some(Ratio::one().into());
- fn construct(_: &mut Machine, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
Ok(Content::show(Self {
text: args.expect("text")?,
block: args.named("block")?.unwrap_or(false),
@@ -59,7 +59,7 @@ impl Show for RawNode {
}
}
- fn realize(&self, _: &mut Context, styles: StyleChain) -> TypResult<Content> {
+ fn realize(&self, _: &dyn World, styles: StyleChain) -> TypResult<Content> {
let lang = styles.get(Self::LANG).as_ref().map(|s| s.to_lowercase());
let foreground = THEME
.settings
@@ -111,7 +111,7 @@ impl Show for RawNode {
fn finalize(
&self,
- _: &mut Context,
+ _: &dyn World,
styles: StyleChain,
mut realized: Content,
) -> TypResult<Content> {
diff --git a/src/library/text/repeat.rs b/src/library/text/repeat.rs
index aca281fc..c2a0de70 100644
--- a/src/library/text/repeat.rs
+++ b/src/library/text/repeat.rs
@@ -6,7 +6,7 @@ pub struct RepeatNode(pub LayoutNode);
#[node]
impl RepeatNode {
- fn construct(_: &mut Machine, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
Ok(Content::inline(Self(args.expect("body")?)))
}
}
@@ -14,11 +14,11 @@ impl RepeatNode {
impl Layout for RepeatNode {
fn layout(
&self,
- ctx: &mut Context,
+ world: &dyn World,
regions: &Regions,
styles: StyleChain,
) -> TypResult<Vec<Frame>> {
// The actual repeating happens directly in the paragraph.
- self.0.layout(ctx, regions, styles)
+ self.0.layout(world, regions, styles)
}
}
diff --git a/src/library/text/shaping.rs b/src/library/text/shaping.rs
index 3d905c99..6e505702 100644
--- a/src/library/text/shaping.rs
+++ b/src/library/text/shaping.rs
@@ -80,8 +80,8 @@ impl<'a> ShapedText<'a> {
///
/// The `justification` defines how much extra advance width each
/// [justifiable glyph](ShapedGlyph::is_justifiable) will get.
- pub fn build(&self, loader: &dyn Loader, justification: Length) -> Frame {
- let (top, bottom) = self.measure(loader);
+ pub fn build(&self, world: &dyn World, justification: Length) -> Frame {
+ let (top, bottom) = self.measure(world);
let size = Size::new(self.width, top + bottom);
let mut offset = Length::zero();
@@ -144,7 +144,7 @@ impl<'a> ShapedText<'a> {
}
/// Measure the top and bottom extent of this text.
- fn measure(&self, loader: &dyn Loader) -> (Length, Length) {
+ fn measure(&self, world: &dyn World) -> (Length, Length) {
let mut top = Length::zero();
let mut bottom = Length::zero();
@@ -162,10 +162,10 @@ impl<'a> ShapedText<'a> {
// When there are no glyphs, we just use the vertical metrics of the
// first available font.
for family in families(self.styles) {
- if let Some(font) = loader
+ if let Some(font) = world
.book()
.select(family, self.variant)
- .and_then(|id| loader.font(id).ok())
+ .and_then(|id| world.font(id).ok())
{
expand(&font);
break;
@@ -199,7 +199,7 @@ impl<'a> ShapedText<'a> {
/// shaping process if possible.
pub fn reshape(
&'a self,
- loader: &dyn Loader,
+ world: &dyn World,
text_range: Range<usize>,
) -> ShapedText<'a> {
if let Some(glyphs) = self.slice_safe_to_break(text_range.clone()) {
@@ -213,17 +213,17 @@ impl<'a> ShapedText<'a> {
glyphs: Cow::Borrowed(glyphs),
}
} else {
- shape(loader, &self.text[text_range], self.styles, self.dir)
+ shape(world, &self.text[text_range], self.styles, self.dir)
}
}
/// Push a hyphen to end of the text.
- pub fn push_hyphen(&mut self, loader: &dyn Loader) {
+ pub fn push_hyphen(&mut self, world: &dyn World) {
families(self.styles).find_map(|family| {
- let font = loader
+ let font = world
.book()
.select(family, self.variant)
- .and_then(|id| loader.font(id).ok())?;
+ .and_then(|id| world.font(id).ok())?;
let ttf = font.ttf();
let glyph_id = ttf.glyph_index('-')?;
let x_advance = font.to_em(ttf.glyph_hor_advance(glyph_id)?);
@@ -306,7 +306,7 @@ impl Debug for ShapedText<'_> {
/// Holds shaping results and metadata common to all shaped segments.
struct ShapingContext<'a> {
- loader: &'a dyn Loader,
+ world: &'a dyn World,
glyphs: Vec<ShapedGlyph>,
used: Vec<Font>,
styles: StyleChain<'a>,
@@ -319,7 +319,7 @@ struct ShapingContext<'a> {
/// Shape text into [`ShapedText`].
pub fn shape<'a>(
- loader: &dyn Loader,
+ world: &dyn World,
text: &'a str,
styles: StyleChain<'a>,
dir: Dir,
@@ -327,7 +327,7 @@ pub fn shape<'a>(
let size = styles.get(TextNode::SIZE);
let mut ctx = ShapingContext {
- loader,
+ world,
size,
glyphs: vec![],
used: vec![],
@@ -368,10 +368,10 @@ fn shape_segment<'a>(
}
// Find the next available family.
- let book = ctx.loader.book();
+ let book = ctx.world.book();
let mut selection = families.find_map(|family| {
book.select(family, ctx.variant)
- .and_then(|id| ctx.loader.font(id).ok())
+ .and_then(|id| ctx.world.font(id).ok())
.filter(|font| !ctx.used.contains(font))
});
@@ -380,7 +380,7 @@ fn shape_segment<'a>(
let first = ctx.used.first().map(Font::info);
selection = book
.select_fallback(first, ctx.variant, text)
- .and_then(|id| ctx.loader.font(id).ok())
+ .and_then(|id| ctx.world.font(id).ok())
.filter(|font| !ctx.used.contains(font));
}
diff --git a/src/library/text/shift.rs b/src/library/text/shift.rs
index 75b2a579..5da36da1 100644
--- a/src/library/text/shift.rs
+++ b/src/library/text/shift.rs
@@ -28,7 +28,7 @@ impl<const S: ScriptKind> ShiftNode<S> {
/// The font size for synthetic sub- and superscripts.
pub const SIZE: TextSize = TextSize(Em::new(0.6).into());
- fn construct(_: &mut Machine, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
Ok(Content::show(Self(args.expect("body")?)))
}
}
@@ -42,11 +42,11 @@ impl<const S: ScriptKind> Show for ShiftNode<S> {
dict! { "body" => Value::Content(self.0.clone()) }
}
- fn realize(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Content> {
+ fn realize(&self, world: &dyn World, styles: StyleChain) -> TypResult<Content> {
let mut transformed = None;
if styles.get(Self::TYPOGRAPHIC) {
if let Some(text) = search_text(&self.0, S) {
- if is_shapable(ctx.loader.as_ref(), &text, styles) {
+ if is_shapable(world, &text, styles) {
transformed = Some(Content::Text(text));
}
}
@@ -91,12 +91,12 @@ fn search_text(content: &Content, mode: ScriptKind) -> Option<EcoString> {
/// Checks whether the first retrievable family contains all code points of the
/// given string.
-fn is_shapable(loader: &dyn Loader, text: &str, styles: StyleChain) -> bool {
- let book = loader.book();
+fn is_shapable(world: &dyn World, text: &str, styles: StyleChain) -> bool {
for family in styles.get(TextNode::FAMILY).iter() {
- if let Some(font) = book
+ if let Some(font) = world
+ .book()
.select(family.as_str(), variant(styles))
- .and_then(|id| loader.font(id).ok())
+ .and_then(|id| world.font(id).ok())
{
return text.chars().all(|c| font.ttf().glyph_index(c).is_some());
}