Skip to main content

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)]
162#[typed_value(derive_fields)]
163pub enum GenericTextDecorationLength<L> {
164    LengthPercentage(L),
165    Auto,
166    FromFont,
167}
168
169/// Text decoration inset values.
170///
171/// https://drafts.csswg.org/css-text-decor-4/#text-decoration-skip-inset-property
172#[repr(C, u8)]
173#[derive(
174    Animate,
175    Clone,
176    ComputeSquaredDistance,
177    Debug,
178    Eq,
179    MallocSizeOf,
180    PartialEq,
181    SpecifiedValueInfo,
182    ToAnimatedValue,
183    ToAnimatedZero,
184    ToComputedValue,
185    ToResolvedValue,
186    ToShmem,
187    ToTyped,
188)]
189pub enum GenericTextDecorationInset<L> {
190    /// `auto` value
191    Auto,
192    /// Start and end length values.
193    #[allow(missing_docs)]
194    Length { start: L, end: L },
195}
196
197impl<L: Zero> GenericTextDecorationInset<L> {
198    /// Gets the initial value (zero)
199    #[inline]
200    pub fn get_initial_value() -> Self {
201        GenericTextDecorationInset::Length {
202            start: L::zero(),
203            end: L::zero(),
204        }
205    }
206}
207
208impl<L: ToCss + PartialEq> ToCss for GenericTextDecorationInset<L> {
209    fn to_css<W>(&self, dst: &mut CssWriter<W>) -> fmt::Result
210    where
211        W: Write,
212    {
213        match self {
214            GenericTextDecorationInset::Auto => dst.write_str("auto"),
215            GenericTextDecorationInset::Length { start, end } => {
216                start.to_css(dst)?;
217                if start != end {
218                    dst.write_char(' ')?;
219                    end.to_css(dst)?;
220                }
221                Ok(())
222            },
223        }
224    }
225}
226
227/// Implements type for text-indent
228/// which takes the grammar of [<length-percentage>] && hanging? && each-line?
229///
230/// https://drafts.csswg.org/css-text/#propdef-text-indent
231#[repr(C)]
232#[derive(
233    Animate,
234    Clone,
235    ComputeSquaredDistance,
236    Debug,
237    Eq,
238    MallocSizeOf,
239    PartialEq,
240    SpecifiedValueInfo,
241    ToAnimatedValue,
242    ToAnimatedZero,
243    ToComputedValue,
244    ToCss,
245    ToResolvedValue,
246    ToShmem,
247    ToTyped,
248)]
249pub struct GenericTextIndent<LengthPercentage> {
250    /// The amount of indent to be applied to the inline-start of the first line.
251    pub length: LengthPercentage,
252    /// Apply indent to non-first lines instead of first.
253    #[animation(constant)]
254    #[css(represents_keyword)]
255    pub hanging: bool,
256    /// Apply to each line after a hard break, not only first in block.
257    #[animation(constant)]
258    #[css(represents_keyword)]
259    pub each_line: bool,
260}
261
262impl<LengthPercentage: Zero> GenericTextIndent<LengthPercentage> {
263    /// Return the initial zero value.
264    pub fn zero() -> Self {
265        Self {
266            length: LengthPercentage::zero(),
267            hanging: false,
268            each_line: false,
269        }
270    }
271}