style/values/computed/
text.rs1use crate::derives::*;
8#[cfg(feature = "gecko")]
9use crate::gecko_bindings::bindings;
10use crate::typed_om::{KeywordValue, ToTyped, TypedValue};
11use crate::values::animated::text::TextDecorationInset as AnimatedTextDecorationInset;
12use crate::values::animated::{Context as AnimatedContext, ToAnimatedValue};
13use crate::values::computed::length::{CSSPixelLength, LengthPercentage};
14use crate::values::generics::text::{
15 GenericHyphenateLimitChars, GenericInitialLetter, GenericTextDecorationInset,
16 GenericTextDecorationLength, GenericTextIndent,
17};
18use crate::values::generics::NumberOrAuto;
19use crate::values::specified::text as specified;
20use crate::values::specified::text::{TextEmphasisFillMode, TextEmphasisShapeKeyword};
21use crate::values::{CSSFloat, CSSInteger, ComputeSquaredDistance};
22use crate::Zero;
23use std::fmt::{self, Write};
24use style_traits::{CssString, CssWriter, ToCss};
25use thin_vec::ThinVec;
26
27pub use crate::values::specified::text::{
28 HyphenateCharacter, LineBreak, MozControlCharacterVisibility, OverflowWrap, RubyPosition,
29 TextAlignLast, TextAutospace, TextBoxEdge, TextBoxTrim, TextDecorationLine,
30 TextDecorationSkipInk, TextEmphasisPosition, TextJustify, TextOverflow, TextTransform,
31 TextUnderlinePosition, WordBreak,
32};
33
34pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>;
36
37pub type TextDecorationLength = GenericTextDecorationLength<LengthPercentage>;
39
40pub type TextDecorationInset = GenericTextDecorationInset<LengthPercentage>;
42
43impl ToAnimatedValue for TextDecorationInset {
44 type AnimatedValue = AnimatedTextDecorationInset;
45
46 fn to_animated_value(self, context: &AnimatedContext) -> Self::AnimatedValue {
47 match self {
48 Self::Auto => {
49 let font_size_px = context
50 .style
51 .get_font()
52 .clone_font_size()
53 .computed_size()
54 .px();
55 #[cfg(feature = "gecko")]
56 let auto_length = bindings::Gecko_CalcAutoDecorationInset(font_size_px);
57 #[cfg(feature = "servo")]
58 let auto_length = {
59 let auto_inset_factor = 1.0 / 12.5;
62
63 (font_size_px * auto_inset_factor).max(1.0)
66 };
67 let auto_length = CSSPixelLength::new(auto_length);
68 Self::AnimatedValue {
69 start: LengthPercentage::new_length(auto_length),
70 end: LengthPercentage::new_length(auto_length),
71 is_auto: true,
72 }
73 },
74 Self::LengthPercentage { start, end } => Self::AnimatedValue {
75 start: start.to_animated_value(context),
76 end: end.to_animated_value(context),
77 is_auto: false,
78 },
79 }
80 }
81
82 #[inline]
83 fn from_animated_value(value: Self::AnimatedValue) -> Self {
84 if value.is_auto {
85 Self::Auto
86 } else {
87 Self::LengthPercentage {
88 start: value.start,
89 end: value.end,
90 }
91 }
92 }
93}
94
95pub type TextAlign = specified::TextAlignKeyword;
97
98pub type TextIndent = GenericTextIndent<LengthPercentage>;
100
101pub type HyphenateLimitChars = GenericHyphenateLimitChars<CSSInteger>;
103
104impl HyphenateLimitChars {
105 #[inline]
107 pub fn auto() -> Self {
108 Self {
109 total_word_length: NumberOrAuto::Auto,
110 pre_hyphen_length: NumberOrAuto::Auto,
111 post_hyphen_length: NumberOrAuto::Auto,
112 }
113 }
114}
115
116#[repr(transparent)]
118#[derive(
119 Animate,
120 Clone,
121 ComputeSquaredDistance,
122 Copy,
123 Debug,
124 MallocSizeOf,
125 PartialEq,
126 ToAnimatedValue,
127 ToAnimatedZero,
128 ToResolvedValue,
129)]
130pub struct GenericLetterSpacing<L>(pub L);
131pub type LetterSpacing = GenericLetterSpacing<LengthPercentage>;
133
134impl LetterSpacing {
135 #[inline]
137 pub fn normal() -> Self {
138 Self(LengthPercentage::zero())
139 }
140}
141
142impl ToCss for LetterSpacing {
143 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
144 where
145 W: Write,
146 {
147 if self.0.is_zero() {
152 return dest.write_str("normal");
153 }
154 self.0.to_css(dest)
155 }
156}
157
158impl ToTyped for LetterSpacing {
159 fn to_typed(&self, dest: &mut ThinVec<TypedValue>) -> Result<(), ()> {
164 if !self.0.has_percentage() && self.0.is_zero() {
165 dest.push(TypedValue::Keyword(KeywordValue(CssString::from("normal"))));
166 return Ok(());
167 }
168 self.0.to_typed(dest)
169 }
170}
171
172pub type WordSpacing = LengthPercentage;
174
175impl WordSpacing {
176 #[inline]
178 pub fn normal() -> Self {
179 LengthPercentage::zero()
180 }
181}
182
183#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue, ToTyped)]
185#[allow(missing_docs)]
186#[repr(C, u8)]
187#[typed(todo_derive_fields)]
188pub enum TextEmphasisStyle {
189 Keyword {
191 #[css(skip_if = "TextEmphasisFillMode::is_filled")]
192 fill: TextEmphasisFillMode,
193 shape: TextEmphasisShapeKeyword,
194 },
195 None,
197 String(crate::OwnedStr),
199}