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::values::computed::length::{Length, LengthPercentage};
9use crate::values::generics::text::{
10    GenericHyphenateLimitChars, GenericInitialLetter, GenericTextDecorationInset,
11    GenericTextDecorationLength, GenericTextIndent,
12};
13use crate::values::generics::NumberOrAuto;
14use crate::values::specified::text as specified;
15use crate::values::specified::text::{TextEmphasisFillMode, TextEmphasisShapeKeyword};
16use crate::values::{CSSFloat, CSSInteger};
17use crate::Zero;
18use std::fmt::{self, Write};
19use style_traits::{CssString, CssWriter, KeywordValue, ToCss, ToTyped, TypedValue};
20use thin_vec::ThinVec;
21
22pub use crate::values::specified::text::{
23    HyphenateCharacter, LineBreak, MozControlCharacterVisibility, OverflowWrap, RubyPosition,
24    TextAlignLast, TextAutospace, TextBoxEdge, TextBoxTrim, TextDecorationLine,
25    TextDecorationSkipInk, TextEmphasisPosition, TextJustify, TextOverflow, TextTransform,
26    TextUnderlinePosition, WordBreak,
27};
28
29/// A computed value for the `initial-letter` property.
30pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>;
31
32/// Implements type for `text-decoration-thickness` property.
33pub type TextDecorationLength = GenericTextDecorationLength<LengthPercentage>;
34
35/// Implements type for `text-decoration-inset` property.
36pub type TextDecorationInset = GenericTextDecorationInset<Length>;
37
38/// The computed value of `text-align`.
39pub type TextAlign = specified::TextAlignKeyword;
40
41/// The computed value of `text-indent`.
42pub type TextIndent = GenericTextIndent<LengthPercentage>;
43
44/// A computed value for the `hyphenate-character` property.
45pub type HyphenateLimitChars = GenericHyphenateLimitChars<CSSInteger>;
46
47impl HyphenateLimitChars {
48    /// Return the `auto` value, which has all three component values as `auto`.
49    #[inline]
50    pub fn auto() -> Self {
51        Self {
52            total_word_length: NumberOrAuto::Auto,
53            pre_hyphen_length: NumberOrAuto::Auto,
54            post_hyphen_length: NumberOrAuto::Auto,
55        }
56    }
57}
58
59/// A computed value for the `letter-spacing` property.
60#[repr(transparent)]
61#[derive(
62    Animate,
63    Clone,
64    ComputeSquaredDistance,
65    Copy,
66    Debug,
67    MallocSizeOf,
68    PartialEq,
69    ToAnimatedValue,
70    ToAnimatedZero,
71    ToResolvedValue,
72)]
73pub struct GenericLetterSpacing<L>(pub L);
74/// This is generic just to make the #[derive()] code do the right thing for lengths.
75pub type LetterSpacing = GenericLetterSpacing<LengthPercentage>;
76
77impl LetterSpacing {
78    /// Return the `normal` computed value, which is just zero.
79    #[inline]
80    pub fn normal() -> Self {
81        Self(LengthPercentage::zero())
82    }
83}
84
85impl ToCss for LetterSpacing {
86    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
87    where
88        W: Write,
89    {
90        // https://drafts.csswg.org/css-text/#propdef-letter-spacing
91        //
92        // For legacy reasons, a computed letter-spacing of zero yields a
93        // resolved value (getComputedStyle() return value) of normal.
94        if self.0.is_zero() {
95            return dest.write_str("normal");
96        }
97        self.0.to_css(dest)
98    }
99}
100
101impl ToTyped for LetterSpacing {
102    // XXX The specification does not currently define how this property should
103    // be reified into Typed OM. The current behavior follows existing WPT
104    // coverage (letter-spacing.html). We may file a spec issue once more data
105    // is collected to update the Property-specific Rules section to align with
106    // observed test expectations.
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)]
131pub enum TextEmphasisStyle {
132    /// [ <fill> || <shape> ]
133    Keyword {
134        #[css(skip_if = "TextEmphasisFillMode::is_filled")]
135        fill: TextEmphasisFillMode,
136        shape: TextEmphasisShapeKeyword,
137    },
138    /// `none`
139    None,
140    /// `<string>` (of which only the first grapheme cluster will be used).
141    String(crate::OwnedStr),
142}