counters.rs (7901B)
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 counters-related CSS values. 6 7 #[cfg(feature = "servo")] 8 use crate::computed_values::list_style_type::T as ListStyleType; 9 #[cfg(feature = "gecko")] 10 use crate::counter_style::CounterStyle; 11 use crate::derives::*; 12 use crate::values::specified::Attr; 13 use crate::values::CustomIdent; 14 use std::fmt::{self, Write}; 15 use std::ops::Deref; 16 use style_traits::{CssWriter, ToCss}; 17 18 /// A name / value pair for counters. 19 #[derive( 20 Clone, 21 Debug, 22 MallocSizeOf, 23 PartialEq, 24 SpecifiedValueInfo, 25 ToComputedValue, 26 ToResolvedValue, 27 ToShmem, 28 )] 29 #[repr(C)] 30 pub struct GenericCounterPair<Integer> { 31 /// The name of the counter. 32 pub name: CustomIdent, 33 /// The value of the counter / increment / etc. 34 pub value: Integer, 35 /// If true, then this represents `reversed(name)`. 36 /// NOTE: It can only be true on `counter-reset` values. 37 pub is_reversed: bool, 38 } 39 pub use self::GenericCounterPair as CounterPair; 40 41 impl<Integer> ToCss for CounterPair<Integer> 42 where 43 Integer: ToCss + PartialEq<i32>, 44 { 45 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result 46 where 47 W: Write, 48 { 49 if self.is_reversed { 50 dest.write_str("reversed(")?; 51 } 52 self.name.to_css(dest)?; 53 if self.is_reversed { 54 dest.write_char(')')?; 55 if self.value == i32::min_value() { 56 return Ok(()); 57 } 58 } 59 dest.write_char(' ')?; 60 self.value.to_css(dest) 61 } 62 } 63 64 /// A generic value for the `counter-increment` property. 65 #[derive( 66 Clone, 67 Debug, 68 Default, 69 MallocSizeOf, 70 PartialEq, 71 SpecifiedValueInfo, 72 ToComputedValue, 73 ToCss, 74 ToResolvedValue, 75 ToShmem, 76 ToTyped, 77 )] 78 #[repr(transparent)] 79 pub struct GenericCounterIncrement<I>(#[css(field_bound)] pub GenericCounters<I>); 80 pub use self::GenericCounterIncrement as CounterIncrement; 81 82 impl<I> CounterIncrement<I> { 83 /// Returns a new value for `counter-increment`. 84 #[inline] 85 pub fn new(counters: Vec<CounterPair<I>>) -> Self { 86 CounterIncrement(Counters(counters.into())) 87 } 88 } 89 90 impl<I> Deref for CounterIncrement<I> { 91 type Target = [CounterPair<I>]; 92 93 #[inline] 94 fn deref(&self) -> &Self::Target { 95 &(self.0).0 96 } 97 } 98 99 /// A generic value for the `counter-set` property. 100 #[derive( 101 Clone, 102 Debug, 103 Default, 104 MallocSizeOf, 105 PartialEq, 106 SpecifiedValueInfo, 107 ToComputedValue, 108 ToCss, 109 ToResolvedValue, 110 ToShmem, 111 ToTyped, 112 )] 113 #[repr(transparent)] 114 pub struct GenericCounterSet<I>(#[css(field_bound)] pub GenericCounters<I>); 115 pub use self::GenericCounterSet as CounterSet; 116 117 impl<I> CounterSet<I> { 118 /// Returns a new value for `counter-set`. 119 #[inline] 120 pub fn new(counters: Vec<CounterPair<I>>) -> Self { 121 CounterSet(Counters(counters.into())) 122 } 123 } 124 125 impl<I> Deref for CounterSet<I> { 126 type Target = [CounterPair<I>]; 127 128 #[inline] 129 fn deref(&self) -> &Self::Target { 130 &(self.0).0 131 } 132 } 133 134 /// A generic value for the `counter-reset` property. 135 #[derive( 136 Clone, 137 Debug, 138 Default, 139 MallocSizeOf, 140 PartialEq, 141 SpecifiedValueInfo, 142 ToComputedValue, 143 ToCss, 144 ToResolvedValue, 145 ToShmem, 146 ToTyped, 147 )] 148 #[repr(transparent)] 149 pub struct GenericCounterReset<I>(#[css(field_bound)] pub GenericCounters<I>); 150 pub use self::GenericCounterReset as CounterReset; 151 152 impl<I> CounterReset<I> { 153 /// Returns a new value for `counter-reset`. 154 #[inline] 155 pub fn new(counters: Vec<CounterPair<I>>) -> Self { 156 CounterReset(Counters(counters.into())) 157 } 158 } 159 160 impl<I> Deref for CounterReset<I> { 161 type Target = [CounterPair<I>]; 162 163 #[inline] 164 fn deref(&self) -> &Self::Target { 165 &(self.0).0 166 } 167 } 168 169 /// A generic value for lists of counters. 170 /// 171 /// Keyword `none` is represented by an empty vector. 172 #[derive( 173 Clone, 174 Debug, 175 Default, 176 MallocSizeOf, 177 PartialEq, 178 SpecifiedValueInfo, 179 ToComputedValue, 180 ToCss, 181 ToResolvedValue, 182 ToShmem, 183 )] 184 #[repr(transparent)] 185 pub struct GenericCounters<I>( 186 #[css(field_bound)] 187 #[css(iterable, if_empty = "none")] 188 crate::OwnedSlice<GenericCounterPair<I>>, 189 ); 190 pub use self::GenericCounters as Counters; 191 192 #[cfg(feature = "servo")] 193 type CounterStyleType = ListStyleType; 194 195 #[cfg(feature = "gecko")] 196 type CounterStyleType = CounterStyle; 197 198 #[cfg(feature = "servo")] 199 #[inline] 200 fn is_decimal(counter_type: &CounterStyleType) -> bool { 201 *counter_type == ListStyleType::Decimal 202 } 203 204 #[cfg(feature = "gecko")] 205 #[inline] 206 fn is_decimal(counter_type: &CounterStyleType) -> bool { 207 *counter_type == CounterStyle::decimal() 208 } 209 210 /// The non-normal, non-none values of the content property. 211 #[derive( 212 Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem, 213 )] 214 #[repr(C)] 215 pub struct GenericContentItems<Image> { 216 /// The actual content items. Note that, past the alt marker, only some subset (strings, 217 /// attr(), counter()) 218 pub items: thin_vec::ThinVec<GenericContentItem<Image>>, 219 /// The index at which alt text starts, always non-zero. If equal to items.len(), no alt text 220 /// exists. 221 pub alt_start: usize, 222 } 223 224 impl<Image> ToCss for GenericContentItems<Image> 225 where 226 Image: ToCss, 227 { 228 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result 229 where 230 W: Write, 231 { 232 for (i, item) in self.items.iter().enumerate() { 233 if i == self.alt_start { 234 dest.write_str(" /")?; 235 } 236 if i != 0 { 237 dest.write_str(" ")?; 238 } 239 item.to_css(dest)?; 240 } 241 Ok(()) 242 } 243 } 244 245 /// The specified value for the `content` property. 246 /// 247 /// https://drafts.csswg.org/css-content/#propdef-content 248 #[derive( 249 Clone, 250 Debug, 251 Eq, 252 MallocSizeOf, 253 PartialEq, 254 SpecifiedValueInfo, 255 ToComputedValue, 256 ToCss, 257 ToShmem, 258 ToTyped, 259 )] 260 #[repr(u8)] 261 pub enum GenericContent<Image> { 262 /// `normal` reserved keyword. 263 Normal, 264 /// `none` reserved keyword. 265 None, 266 /// Content items. 267 Items(GenericContentItems<Image>), 268 } 269 270 pub use self::GenericContent as Content; 271 272 impl<Image> Content<Image> { 273 /// Whether `self` represents list of items. 274 #[inline] 275 pub fn is_items(&self) -> bool { 276 matches!(*self, Self::Items(..)) 277 } 278 279 /// Set `content` property to `normal`. 280 #[inline] 281 pub fn normal() -> Self { 282 Content::Normal 283 } 284 } 285 286 /// Items for the `content` property. 287 #[derive( 288 Clone, 289 Debug, 290 Eq, 291 MallocSizeOf, 292 PartialEq, 293 ToComputedValue, 294 SpecifiedValueInfo, 295 ToCss, 296 ToResolvedValue, 297 ToShmem, 298 )] 299 #[repr(u8)] 300 pub enum GenericContentItem<I> { 301 /// Literal string content. 302 String(crate::OwnedStr), 303 /// `counter(name, style)`. 304 #[css(comma, function)] 305 Counter(CustomIdent, #[css(skip_if = "is_decimal")] CounterStyleType), 306 /// `counters(name, separator, style)`. 307 #[css(comma, function)] 308 Counters( 309 CustomIdent, 310 crate::OwnedStr, 311 #[css(skip_if = "is_decimal")] CounterStyleType, 312 ), 313 /// `open-quote`. 314 OpenQuote, 315 /// `close-quote`. 316 CloseQuote, 317 /// `no-open-quote`. 318 NoOpenQuote, 319 /// `no-close-quote`. 320 NoCloseQuote, 321 /// `-moz-alt-content`. 322 #[cfg(feature = "gecko")] 323 MozAltContent, 324 /// `-moz-label-content`. 325 /// This is needed to make `accesskey` work for XUL labels. It's basically 326 /// attr(value) otherwise. 327 #[cfg(feature = "gecko")] 328 MozLabelContent, 329 /// `attr([namespace? `|`]? ident)` 330 Attr(Attr), 331 /// image-set(url) | url(url) 332 Image(I), 333 } 334 335 pub use self::GenericContentItem as ContentItem;