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)]
55#[typed(todo_derive_fields)]
56pub struct GenericHyphenateLimitChars<Integer> {
57    /// Required minimum number of characters in a hyphenated word.
58    pub total_word_length: NumberOrAuto<Integer>,
59    /// Required minumum number of characters before the hyphen.
60    pub pre_hyphen_length: NumberOrAuto<Integer>,
61    /// Required minumum number of characters after the hyphen.
62    pub post_hyphen_length: NumberOrAuto<Integer>,
63}
64
65impl<Integer: ToCss + PartialEq> ToCss for GenericHyphenateLimitChars<Integer> {
66    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
67    where
68        W: Write,
69    {
70        self.total_word_length.to_css(dest)?;
71
72        if self.pre_hyphen_length != NumberOrAuto::Auto
73            || self.post_hyphen_length != self.pre_hyphen_length
74        {
75            dest.write_char(' ')?;
76            self.pre_hyphen_length.to_css(dest)?;
77            if self.post_hyphen_length != self.pre_hyphen_length {
78                dest.write_char(' ')?;
79                self.post_hyphen_length.to_css(dest)?;
80            }
81        }
82
83        Ok(())
84    }
85}
86
87/// A generic value for the `initial-letter` property.
88#[derive(
89    Clone,
90    Copy,
91    Debug,
92    MallocSizeOf,
93    PartialEq,
94    SpecifiedValueInfo,
95    ToComputedValue,
96    ToResolvedValue,
97    ToShmem,
98    ToTyped,
99)]
100#[repr(C)]
101pub struct GenericInitialLetter<Number, Integer> {
102    /// The size, >=1, or 0 if `normal`.
103    pub size: Number,
104    /// The sink, >=1, if specified, 0 otherwise.
105    pub sink: Integer,
106}
107
108pub use self::GenericInitialLetter as InitialLetter;
109impl<N: Zero, I: Zero> InitialLetter<N, I> {
110    /// Returns `normal`.
111    #[inline]
112    pub fn normal() -> Self {
113        InitialLetter {
114            size: N::zero(),
115            sink: I::zero(),
116        }
117    }
118}
119
120impl<N: ToCss + Zero, I: ToCss + Zero> ToCss for InitialLetter<N, I> {
121    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
122    where
123        W: Write,
124    {
125        if self.size.is_zero() {
126            return dest.write_str("normal");
127        }
128        self.size.to_css(dest)?;
129        if !self.sink.is_zero() {
130            dest.write_char(' ')?;
131            self.sink.to_css(dest)?;
132        }
133        Ok(())
134    }
135}
136
137/// Implements type for text-decoration-thickness
138/// which takes the grammar of auto | from-font | <length> | <percentage>
139///
140/// https://drafts.csswg.org/css-text-decor-4/
141#[repr(C, u8)]
142#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
143#[derive(
144    Animate,
145    Clone,
146    Copy,
147    ComputeSquaredDistance,
148    Debug,
149    Eq,
150    MallocSizeOf,
151    Parse,
152    PartialEq,
153    SpecifiedValueInfo,
154    ToAnimatedValue,
155    ToAnimatedZero,
156    ToComputedValue,
157    ToCss,
158    ToResolvedValue,
159    ToShmem,
160    ToTyped,
161)]
162#[allow(missing_docs)]
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)]
249#[typed(todo_derive_fields)]
250pub struct GenericTextIndent<LengthPercentage> {
251    /// The amount of indent to be applied to the inline-start of the first line.
252    pub length: LengthPercentage,
253    /// Apply indent to non-first lines instead of first.
254    #[animation(constant)]
255    #[css(represents_keyword)]
256    pub hanging: bool,
257    /// Apply to each line after a hard break, not only first in block.
258    #[animation(constant)]
259    #[css(represents_keyword)]
260    pub each_line: bool,
261}
262
263impl<LengthPercentage: Zero> GenericTextIndent<LengthPercentage> {
264    /// Return the initial zero value.
265    pub fn zero() -> Self {
266        Self {
267            length: LengthPercentage::zero(),
268            hanging: false,
269            each_line: false,
270        }
271    }
272}