diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-09-20 13:05:55 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-09-20 16:37:15 +0200 |
| commit | 757a701c1aa2a6fb80033c7e75666661818da6f9 (patch) | |
| tree | 0415fec94d3856f4ebc97a1744cf2ba75fe8e7aa /src/library/text | |
| parent | e29f55bb294cc298daad97accf6d8a76976b409c (diff) | |
A New World
Diffstat (limited to 'src/library/text')
| -rw-r--r-- | src/library/text/deco.rs | 4 | ||||
| -rw-r--r-- | src/library/text/link.rs | 6 | ||||
| -rw-r--r-- | src/library/text/mod.rs | 16 | ||||
| -rw-r--r-- | src/library/text/par.rs | 66 | ||||
| -rw-r--r-- | src/library/text/raw.rs | 6 | ||||
| -rw-r--r-- | src/library/text/repeat.rs | 6 | ||||
| -rw-r--r-- | src/library/text/shaping.rs | 32 | ||||
| -rw-r--r-- | src/library/text/shift.rs | 14 |
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, ®ions, width)?; + let frame = commit(p, world, line, ®ions, 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()); } |
