diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-12-15 11:11:57 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-12-15 11:11:57 +0100 |
| commit | ae38be9097bbb32142ef776e77e627ac12379000 (patch) | |
| tree | f365a348d4c77d2d607d37fee3bc65a601d00a64 /src/library/deco.rs | |
| parent | fe21c4d399d291e75165b664762f0aa8bdc4724a (diff) | |
Set Rules Episode IV: A New Fold
Diffstat (limited to 'src/library/deco.rs')
| -rw-r--r-- | src/library/deco.rs | 133 |
1 files changed, 0 insertions, 133 deletions
diff --git a/src/library/deco.rs b/src/library/deco.rs deleted file mode 100644 index d12f60b0..00000000 --- a/src/library/deco.rs +++ /dev/null @@ -1,133 +0,0 @@ -use super::prelude::*; -use crate::util::EcoString; - -/// `strike`: Typeset striken-through text. -pub fn strike(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { - line_impl(args, LineKind::Strikethrough) -} - -/// `underline`: Typeset underlined text. -pub fn underline(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { - line_impl(args, LineKind::Underline) -} - -/// `overline`: Typeset text with an overline. -pub fn overline(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { - line_impl(args, LineKind::Overline) -} - -fn line_impl(args: &mut Args, kind: LineKind) -> TypResult<Value> { - let stroke = args.named("stroke")?.or_else(|| args.find()); - let thickness = args.named::<Linear>("thickness")?.or_else(|| args.find()); - let offset = args.named("offset")?; - let extent = args.named("extent")?.unwrap_or_default(); - let body: Node = args.expect("body")?; - Ok(Value::Node(body.decorated(Decoration::Line( - LineDecoration { kind, stroke, thickness, offset, extent }, - )))) -} - -/// `link`: Typeset text as a link. -pub fn link(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { - let url = args.expect::<EcoString>("url")?; - let body = args.find().unwrap_or_else(|| { - let mut text = url.as_str(); - for prefix in ["mailto:", "tel:"] { - text = text.trim_start_matches(prefix); - } - Node::Text(text.into()) - }); - Ok(Value::Node(body.decorated(Decoration::Link(url)))) -} - -/// A decoration for a frame. -#[derive(Debug, Clone, Eq, PartialEq, Hash)] -pub enum Decoration { - /// A link to an external resource. - Link(EcoString), - /// An underline/strikethrough/overline decoration. - Line(LineDecoration), -} - -impl Decoration { - /// Apply a decoration to a child's frame. - pub fn apply(&self, ctx: &LayoutContext, frame: &mut Frame) { - match self { - Decoration::Link(href) => { - let link = Element::Link(href.to_string(), frame.size); - frame.push(Point::zero(), link); - } - Decoration::Line(line) => { - line.apply(ctx, frame); - } - } - } -} - -/// Defines a line that is positioned over, under or on top of text. -#[derive(Debug, Clone, Eq, PartialEq, Hash)] -pub struct LineDecoration { - /// The kind of line. - pub kind: LineKind, - /// Stroke color of the line, defaults to the text color if `None`. - pub stroke: Option<Paint>, - /// Thickness of the line's strokes (dependent on scaled font size), read - /// from the font tables if `None`. - pub thickness: Option<Linear>, - /// Position of the line relative to the baseline (dependent on scaled font - /// size), read from the font tables if `None`. - pub offset: Option<Linear>, - /// Amount that the line will be longer or shorter than its associated text - /// (dependent on scaled font size). - pub extent: Linear, -} - -/// The kind of line decoration. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum LineKind { - /// A line under text. - Underline, - /// A line through text. - Strikethrough, - /// A line over text. - Overline, -} - -impl LineDecoration { - /// Apply a line decoration to a all text elements in a frame. - pub fn apply(&self, ctx: &LayoutContext, frame: &mut Frame) { - for i in 0 .. frame.elements.len() { - let (pos, child) = &frame.elements[i]; - if let Element::Text(text) = child { - let face = ctx.fonts.get(text.face_id); - let metrics = match self.kind { - LineKind::Underline => face.underline, - LineKind::Strikethrough => face.strikethrough, - LineKind::Overline => face.overline, - }; - - let thickness = self - .thickness - .map(|s| s.resolve(text.size)) - .unwrap_or(metrics.thickness.to_length(text.size)); - - let stroke = Stroke { - paint: self.stroke.unwrap_or(text.fill), - thickness, - }; - - let offset = self - .offset - .map(|s| s.resolve(text.size)) - .unwrap_or(-metrics.position.to_length(text.size)); - - let extent = self.extent.resolve(text.size); - - let subpos = Point::new(pos.x - extent, pos.y + offset); - let target = Point::new(text.width() + 2.0 * extent, Length::zero()); - let shape = Shape::stroked(Geometry::Line(target), stroke); - frame.push(subpos, Element::Shape(shape)); - } - } - } -} |
