style/values/generics/
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//! Generic types for text properties.
6
7use crate::Zero;
8use std::fmt::{self, Write};
9use style_traits::{CssWriter, ToCss};
10
11/// A generic value that is either a number or `auto`.
12#[derive(
13    Animate,
14    Clone,
15    ComputeSquaredDistance,
16    Copy,
17    Debug,
18    MallocSizeOf,
19    Parse,
20    PartialEq,
21    SpecifiedValueInfo,
22    ToAnimatedValue,
23    ToAnimatedZero,
24    ToComputedValue,
25    ToCss,
26    ToResolvedValue,
27    ToShmem,
28)]
29#[repr(C, u8)]
30pub enum NumberOrAuto<N> {
31    /// `auto`
32    Auto,
33    /// `<number>`
34    Number(N),
35}
36
37/// A generic value for the `hyphenate-limit-chars` property.
38#[derive(
39    Animate,
40    Clone,
41    ComputeSquaredDistance,
42    Debug,
43    MallocSizeOf,
44    PartialEq,
45    SpecifiedValueInfo,
46    ToAnimatedValue,
47    ToAnimatedZero,
48    ToComputedValue,
49    ToResolvedValue,
50    ToShmem,
51    ToTyped,
52)]
53#[repr(C)]
54pub struct GenericHyphenateLimitChars<Integer> {
55    /// Required minimum number of characters in a hyphenated word.
56    pub total_word_length: NumberOrAuto<Integer>,
57    /// Required minumum number of characters before the hyphen.
58    pub pre_hyphen_length: NumberOrAuto<Integer>,
59    /// Required minumum number of characters after the hyphen.
60    pub post_hyphen_length: NumberOrAuto<Integer>,
61}
62
63impl<Integer: ToCss + PartialEq> ToCss for GenericHyphenateLimitChars<Integer> {
64    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
65    where
66        W: Write,
67    {
68        self.total_word_length.to_css(dest)?;
69
70        if self.pre_hyphen_length != NumberOrAuto::Auto
71            || self.post_hyphen_length != self.pre_hyphen_length
72        {
73            dest.write_char(' ')?;
74            self.pre_hyphen_length.to_css(dest)?;
75            if self.post_hyphen_length != self.pre_hyphen_length {
76                dest.write_char(' ')?;
77                self.post_hyphen_length.to_css(dest)?;
78            }
79        }
80
81        Ok(())
82    }
83}
84
85/// A generic value for the `initial-letter` property.
86#[derive(
87    Clone,
88    Copy,
89    Debug,
90    MallocSizeOf,
91    PartialEq,
92    SpecifiedValueInfo,
93    ToComputedValue,
94    ToResolvedValue,
95    ToShmem,
96    ToTyped,
97)]
98#[repr(C)]
99pub struct GenericInitialLetter<Number, Integer> {
100    /// The size, >=1, or 0 if `normal`.
101    pub size: Number,
102    /// The sink, >=1, if specified, 0 otherwise.
103    pub sink: Integer,
104}
105
106pub use self::GenericInitialLetter as InitialLetter;
107impl<N: Zero, I: Zero> InitialLetter<N, I> {
108    /// Returns `normal`.
109    #[inline]
110    pub fn normal() -> Self {
111        InitialLetter {
112            size: N::zero(),
113            sink: I::zero(),
114        }
115    }
116}
117
118impl<N: ToCss + Zero, I: ToCss + Zero> ToCss for InitialLetter<N, I> {
119    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
120    where
121        W: Write,
122    {
123        if self.size.is_zero() {
124            return dest.write_str("normal");
125        }
126        self.size.to_css(dest)?;
127        if !self.sink.is_zero() {
128            dest.write_char(' ')?;
129            self.sink.to_css(dest)?;
130        }
131        Ok(())
132    }
133}
134
135/// Implements type for text-decoration-thickness
136/// which takes the grammar of auto | from-font | <length> | <percentage>
137///
138/// https://drafts.csswg.org/css-text-decor-4/
139#[repr(C, u8)]
140#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
141#[derive(
142    Animate,
143    Clone,
144    Copy,
145    ComputeSquaredDistance,
146    Debug,
147    Eq,
148    MallocSizeOf,
149    Parse,
150    PartialEq,
151    SpecifiedValueInfo,
152    ToAnimatedValue,
153    ToAnimatedZero,
154    ToComputedValue,
155    ToCss,
156    ToResolvedValue,
157    ToShmem,
158    ToTyped,
159)]
160#[allow(missing_docs)]
161pub enum GenericTextDecorationLength<L> {
162    LengthPercentage(L),
163    Auto,
164    FromFont,
165}
166
167/// Text decoration trim values.
168///
169/// https://drafts.csswg.org/css-text-decor-4/#propdef-text-decoration-trim
170#[repr(C, u8)]
171#[derive(
172    Animate,
173    Clone,
174    ComputeSquaredDistance,
175    Debug,
176    Eq,
177    MallocSizeOf,
178    PartialEq,
179    SpecifiedValueInfo,
180    ToAnimatedValue,
181    ToAnimatedZero,
182    ToComputedValue,
183    ToResolvedValue,
184    ToShmem,
185    ToTyped,
186)]
187pub enum GenericTextDecorationTrim<L> {
188    /// `auto` value
189    Auto,
190    /// Start and end length values.
191    #[allow(missing_docs)]
192    Length { start: L, end: L },
193}
194
195impl<L: Zero> GenericTextDecorationTrim<L> {
196    /// Gets the initial value (zero)
197    #[inline]
198    pub fn get_initial_value() -> Self {
199        GenericTextDecorationTrim::Length {
200            start: L::zero(),
201            end: L::zero(),
202        }
203    }
204}
205
206impl<L: ToCss + PartialEq> ToCss for GenericTextDecorationTrim<L> {
207    fn to_css<W>(&self, dst: &mut CssWriter<W>) -> fmt::Result
208    where
209        W: Write,
210    {
211        match self {
212            GenericTextDecorationTrim::Auto => dst.write_str("auto"),
213            GenericTextDecorationTrim::Length { start, end } => {
214                start.to_css(dst)?;
215                if start != end {
216                    dst.write_char(' ')?;
217                    end.to_css(dst)?;
218                }
219                Ok(())
220            },
221        }
222    }
223}
224
225/// Implements type for text-indent
226/// which takes the grammar of [<length-percentage>] && hanging? && each-line?
227///
228/// https://drafts.csswg.org/css-text/#propdef-text-indent
229#[repr(C)]
230#[derive(
231    Animate,
232    Clone,
233    ComputeSquaredDistance,
234    Debug,
235    Eq,
236    MallocSizeOf,
237    PartialEq,
238    SpecifiedValueInfo,
239    ToAnimatedValue,
240    ToAnimatedZero,
241    ToComputedValue,
242    ToCss,
243    ToResolvedValue,
244    ToShmem,
245    ToTyped,
246)]
247pub struct GenericTextIndent<LengthPercentage> {
248    /// The amount of indent to be applied to the inline-start of the first line.
249    pub length: LengthPercentage,
250    /// Apply indent to non-first lines instead of first.
251    #[animation(constant)]
252    #[css(represents_keyword)]
253    pub hanging: bool,
254    /// Apply to each line after a hard break, not only first in block.
255    #[animation(constant)]
256    #[css(represents_keyword)]
257    pub each_line: bool,
258}
259
260impl<LengthPercentage: Zero> GenericTextIndent<LengthPercentage> {
261    /// Return the initial zero value.
262    pub fn zero() -> Self {
263        Self {
264            length: LengthPercentage::zero(),
265            hanging: false,
266            each_line: false,
267        }
268    }
269}