Skip to main content

style/values/computed/
text.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! Computed types for text properties.
6
7use crate::derives::*;
8use crate::typed_om::{KeywordValue, ToTyped, TypedValue};
9use crate::values::computed::length::{Length, LengthPercentage};
10use crate::values::generics::text::{
11    GenericHyphenateLimitChars, GenericInitialLetter, GenericTextDecorationInset,
12    GenericTextDecorationLength, GenericTextIndent,
13};
14use crate::values::generics::NumberOrAuto;
15use crate::values::specified::text as specified;
16use crate::values::specified::text::{TextEmphasisFillMode, TextEmphasisShapeKeyword};
17use crate::values::{CSSFloat, CSSInteger};
18use crate::Zero;
19use std::fmt::{self, Write};
20use style_traits::{CssString, CssWriter, ToCss};
21use thin_vec::ThinVec;
22
23pub use crate::values::specified::text::{
24    HyphenateCharacter, LineBreak, MozControlCharacterVisibility, OverflowWrap, RubyPosition,
25    TextAlignLast, TextAutospace, TextBoxEdge, TextBoxTrim, TextDecorationLine,
26    TextDecorationSkipInk, TextEmphasisPosition, TextJustify, TextOverflow, TextTransform,
27    TextUnderlinePosition, WordBreak,
28};
29
30/// A computed value for the `initial-letter` property.
31pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>;
32
33/// Implements type for `text-decoration-thickness` property.
34pub type TextDecorationLength = GenericTextDecorationLength<LengthPercentage>;
35
36/// Implements type for `text-decoration-inset` property.
37pub type TextDecorationInset = GenericTextDecorationInset<Length>;
38
39/// The computed value of `text-align`.
40pub type TextAlign = specified::TextAlignKeyword;
41
42/// The computed value of `text-indent`.
43pub type TextIndent = GenericTextIndent<LengthPercentage>;
44
45/// A computed value for the `hyphenate-character` property.
46pub type HyphenateLimitChars = GenericHyphenateLimitChars<CSSInteger>;
47
48impl HyphenateLimitChars {
49    /// Return the `auto` value, which has all three component values as `auto`.
50    #[inline]
51    pub fn auto() -> Self {
52        Self {
53            total_word_length: NumberOrAuto::Auto,
54            pre_hyphen_length: NumberOrAuto::Auto,
55            post_hyphen_length: NumberOrAuto::Auto,
56        }
57    }
58}
59
60/// A computed value for the `letter-spacing` property.
61#[repr(transparent)]
62#[derive(
63    Animate,
64    Clone,
65    ComputeSquaredDistance,
66    Copy,
67    Debug,
68    MallocSizeOf,
69    PartialEq,
70    ToAnimatedValue,
71    ToAnimatedZero,
72    ToResolvedValue,
73)]
74pub struct GenericLetterSpacing<L>(pub L);
75/// This is generic just to make the #[derive()] code do the right thing for lengths.
76pub type LetterSpacing = GenericLetterSpacing<LengthPercentage>;
77
78impl LetterSpacing {
79    /// Return the `normal` computed value, which is just zero.
80    #[inline]
81    pub fn normal() -> Self {
82        Self(LengthPercentage::zero())
83    }
84}
85
86impl ToCss for LetterSpacing {
87    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
88    where
89        W: Write,
90    {
91        // https://drafts.csswg.org/css-text/#propdef-letter-spacing
92        //
93        // For legacy reasons, a computed letter-spacing of zero yields a
94        // resolved value (getComputedStyle() return value) of normal.
95        if self.0.is_zero() {
96            return dest.write_str("normal");
97        }
98        self.0.to_css(dest)
99    }
100}
101
102impl ToTyped for LetterSpacing {
103    // Note: The specification does not currently define how letter spacing
104    // should be reified into Typed OM. The current behavior follows existing
105    // WPT coverage (letter-spacing.html). Syncing spec with UA/WPT behavior
106    // tracked in https://github.com/w3c/csswg-drafts/issues/13907
107    fn to_typed(&self, dest: &mut ThinVec<TypedValue>) -> Result<(), ()> {
108        if !self.0.has_percentage() && self.0.is_zero() {
109            dest.push(TypedValue::Keyword(KeywordValue(CssString::from("normal"))));
110            return Ok(());
111        }
112        self.0.to_typed(dest)
113    }
114}
115
116/// A computed value for the `word-spacing` property.
117pub type WordSpacing = LengthPercentage;
118
119impl WordSpacing {
120    /// Return the `normal` computed value, which is just zero.
121    #[inline]
122    pub fn normal() -> Self {
123        LengthPercentage::zero()
124    }
125}
126
127/// Computed value for the text-emphasis-style property
128#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue, ToTyped)]
129#[allow(missing_docs)]
130#[repr(C, u8)]
131#[typed(todo_derive_fields)]
132pub enum TextEmphasisStyle {
133    /// [ <fill> || <shape> ]
134    Keyword {
135        #[css(skip_if = "TextEmphasisFillMode::is_filled")]
136        fill: TextEmphasisFillMode,
137        shape: TextEmphasisShapeKeyword,
138    },
139    /// `none`
140    None,
141    /// `<string>` (of which only the first grapheme cluster will be used).
142    String(crate::OwnedStr),
143}