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