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