summaryrefslogtreecommitdiff
path: root/src/library/text.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/library/text.rs')
-rw-r--r--src/library/text.rs125
1 files changed, 56 insertions, 69 deletions
diff --git a/src/library/text.rs b/src/library/text.rs
index fb0f7e08..1ccbb1c6 100644
--- a/src/library/text.rs
+++ b/src/library/text.rs
@@ -24,13 +24,14 @@ pub struct TextNode;
#[class]
impl TextNode {
/// A prioritized sequence of font families.
- pub const FAMILY_LIST: Vec<FontFamily> = vec![FontFamily::SansSerif];
+ #[variadic]
+ pub const FAMILY: Vec<FontFamily> = vec![FontFamily::SansSerif];
/// The serif font family/families.
- pub const SERIF_LIST: Vec<NamedFamily> = vec![NamedFamily::new("IBM Plex Serif")];
+ pub const SERIF: Vec<NamedFamily> = vec![NamedFamily::new("IBM Plex Serif")];
/// The sans-serif font family/families.
- pub const SANS_SERIF_LIST: Vec<NamedFamily> = vec![NamedFamily::new("IBM Plex Sans")];
+ pub const SANS_SERIF: Vec<NamedFamily> = vec![NamedFamily::new("IBM Plex Sans")];
/// The monospace font family/families.
- pub const MONOSPACE_LIST: Vec<NamedFamily> = vec![NamedFamily::new("IBM Plex Mono")];
+ pub const MONOSPACE: Vec<NamedFamily> = vec![NamedFamily::new("IBM Plex Mono")];
/// Whether to allow font fallback when the primary font list contains no
/// match.
pub const FALLBACK: bool = true;
@@ -41,23 +42,12 @@ impl TextNode {
pub const WEIGHT: FontWeight = FontWeight::REGULAR;
/// The width of the glyphs.
pub const STRETCH: FontStretch = FontStretch::NORMAL;
- /// Whether the font weight should be increased by 300.
- #[fold(bool::bitxor)]
- pub const STRONG: bool = false;
- /// Whether the the font style should be inverted.
- #[fold(bool::bitxor)]
- pub const EMPH: bool = false;
- /// Whether a monospace font should be preferred.
- pub const MONOSPACE: bool = false;
/// The glyph fill color.
+ #[shorthand]
pub const FILL: Paint = Color::BLACK.into();
- /// Decorative lines.
- #[fold(|a, b| a.into_iter().chain(b).collect())]
- pub const LINES: Vec<Decoration> = vec![];
- /// An URL the text should link to.
- pub const LINK: Option<EcoString> = None;
/// The size of the glyphs.
+ #[shorthand]
#[fold(Linear::compose)]
pub const SIZE: Linear = Length::pt(11.0).into();
/// The amount of space that should be added between characters.
@@ -94,73 +84,64 @@ impl TextNode {
/// Raw OpenType features to apply.
pub const FEATURES: Vec<(Tag, u32)> = vec![];
+ /// Whether the font weight should be increased by 300.
+ #[skip]
+ #[fold(bool::bitxor)]
+ pub const STRONG: bool = false;
+ /// Whether the the font style should be inverted.
+ #[skip]
+ #[fold(bool::bitxor)]
+ pub const EMPH: bool = false;
+ /// Whether a monospace font should be preferred.
+ #[skip]
+ pub const MONOSPACED: bool = false;
+ /// Decorative lines.
+ #[skip]
+ #[fold(|a, b| a.into_iter().chain(b).collect())]
+ pub const LINES: Vec<Decoration> = vec![];
+ /// An URL the text should link to.
+ #[skip]
+ pub const LINK: Option<EcoString> = None;
+
fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> {
// 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.
args.expect("body")
}
-
- fn set(args: &mut Args, styles: &mut StyleMap) -> TypResult<()> {
- let list = args.named("family")?.or_else(|| {
- let families: Vec<_> = args.all().collect();
- (!families.is_empty()).then(|| families)
- });
-
- styles.set_opt(Self::FAMILY_LIST, list);
- styles.set_opt(Self::SERIF_LIST, args.named("serif")?);
- styles.set_opt(Self::SANS_SERIF_LIST, args.named("sans-serif")?);
- styles.set_opt(Self::MONOSPACE_LIST, args.named("monospace")?);
- styles.set_opt(Self::FALLBACK, args.named("fallback")?);
- styles.set_opt(Self::STYLE, args.named("style")?);
- styles.set_opt(Self::WEIGHT, args.named("weight")?);
- styles.set_opt(Self::STRETCH, args.named("stretch")?);
- styles.set_opt(Self::FILL, args.named("fill")?.or_else(|| args.find()));
- styles.set_opt(Self::SIZE, args.named("size")?.or_else(|| args.find()));
- styles.set_opt(Self::TRACKING, args.named("tracking")?.map(Em::new));
- styles.set_opt(Self::TOP_EDGE, args.named("top-edge")?);
- styles.set_opt(Self::BOTTOM_EDGE, args.named("bottom-edge")?);
- styles.set_opt(Self::KERNING, args.named("kerning")?);
- styles.set_opt(Self::SMALLCAPS, args.named("smallcaps")?);
- styles.set_opt(Self::ALTERNATES, args.named("alternates")?);
- styles.set_opt(Self::STYLISTIC_SET, args.named("stylistic-set")?);
- styles.set_opt(Self::LIGATURES, args.named("ligatures")?);
- styles.set_opt(
- Self::DISCRETIONARY_LIGATURES,
- args.named("discretionary-ligatures")?,
- );
- styles.set_opt(
- Self::HISTORICAL_LIGATURES,
- args.named("historical-ligatures")?,
- );
- styles.set_opt(Self::NUMBER_TYPE, args.named("number-type")?);
- styles.set_opt(Self::NUMBER_WIDTH, args.named("number-width")?);
- styles.set_opt(Self::NUMBER_POSITION, args.named("number-position")?);
- styles.set_opt(Self::SLASHED_ZERO, args.named("slashed-zero")?);
- styles.set_opt(Self::FRACTIONS, args.named("fractions")?);
- styles.set_opt(Self::FEATURES, args.named("features")?);
-
- Ok(())
- }
}
/// Strong text, rendered in boldface.
-pub struct StrongNode;
+#[derive(Debug, Hash)]
+pub struct StrongNode(pub Template);
#[class]
impl StrongNode {
fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> {
- Ok(args.expect::<Template>("body")?.styled(TextNode::STRONG, true))
+ Ok(Template::show(Self(args.expect("body")?)))
+ }
+}
+
+impl Show for StrongNode {
+ fn show(&self, _: StyleChain) -> Template {
+ self.0.clone().styled(TextNode::STRONG, true)
}
}
/// Emphasized text, rendered with an italic face.
-pub struct EmphNode;
+#[derive(Debug, Hash)]
+pub struct EmphNode(pub Template);
#[class]
impl EmphNode {
fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Template> {
- Ok(args.expect::<Template>("body")?.styled(TextNode::EMPH, true))
+ Ok(Template::show(Self(args.expect("body")?)))
+ }
+}
+
+impl Show for EmphNode {
+ fn show(&self, _: StyleChain) -> Template {
+ self.0.clone().styled(TextNode::EMPH, true)
}
}
@@ -275,6 +256,12 @@ castable! {
}
castable! {
+ Em,
+ Expected: "float",
+ Value::Float(v) => Self::new(v),
+}
+
+castable! {
VerticalFontMetric,
Expected: "linear or string",
Value::Length(v) => Self::Linear(v.into()),
@@ -644,18 +631,18 @@ fn variant(styles: StyleChain) -> FontVariant {
/// Resolve a prioritized iterator over the font families.
fn families(styles: StyleChain) -> impl Iterator<Item = &str> + Clone {
- let head = if styles.get(TextNode::MONOSPACE) {
- styles.get_ref(TextNode::MONOSPACE_LIST).as_slice()
+ let head = if styles.get(TextNode::MONOSPACED) {
+ styles.get_ref(TextNode::MONOSPACE).as_slice()
} else {
&[]
};
- let core = styles.get_ref(TextNode::FAMILY_LIST).iter().flat_map(move |family| {
+ let core = styles.get_ref(TextNode::FAMILY).iter().flat_map(move |family| {
match family {
FontFamily::Named(name) => std::slice::from_ref(name),
- FontFamily::Serif => styles.get_ref(TextNode::SERIF_LIST),
- FontFamily::SansSerif => styles.get_ref(TextNode::SANS_SERIF_LIST),
- FontFamily::Monospace => styles.get_ref(TextNode::MONOSPACE_LIST),
+ FontFamily::Serif => styles.get_ref(TextNode::SERIF),
+ FontFamily::SansSerif => styles.get_ref(TextNode::SANS_SERIF),
+ FontFamily::Monospace => styles.get_ref(TextNode::MONOSPACE),
}
});