summaryrefslogtreecommitdiffstats
path: root/servo/components/style/values/mod.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /servo/components/style/values/mod.rs
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--servo/components/style/values/mod.rs425
1 files changed, 425 insertions, 0 deletions
diff --git a/servo/components/style/values/mod.rs b/servo/components/style/values/mod.rs
new file mode 100644
index 0000000000..9587b52648
--- /dev/null
+++ b/servo/components/style/values/mod.rs
@@ -0,0 +1,425 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+//! Common [values][values] used in CSS.
+//!
+//! [values]: https://drafts.csswg.org/css-values/
+
+#![deny(missing_docs)]
+
+use crate::parser::{Parse, ParserContext};
+use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
+use crate::Atom;
+pub use cssparser::{serialize_identifier, serialize_name, CowRcStr, Parser};
+pub use cssparser::{SourceLocation, Token, RGBA};
+use precomputed_hash::PrecomputedHash;
+use selectors::parser::SelectorParseErrorKind;
+use std::fmt::{self, Debug, Write};
+use std::hash;
+use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
+use to_shmem::impl_trivial_to_shmem;
+
+#[cfg(feature = "gecko")]
+pub use crate::gecko::url::CssUrl;
+#[cfg(feature = "servo")]
+pub use crate::servo::url::CssUrl;
+
+pub mod animated;
+pub mod computed;
+pub mod distance;
+pub mod generics;
+pub mod resolved;
+pub mod specified;
+
+/// A CSS float value.
+pub type CSSFloat = f32;
+
+/// Normalizes a float value to zero after a set of operations that might turn
+/// it into NaN.
+#[inline]
+pub fn normalize(v: CSSFloat) -> CSSFloat {
+ if v.is_nan() {
+ 0.0
+ } else {
+ v
+ }
+}
+
+/// A CSS integer value.
+pub type CSSInteger = i32;
+
+define_keyword_type!(None_, "none");
+define_keyword_type!(Auto, "auto");
+
+/// Serialize an identifier which is represented as an atom.
+#[cfg(feature = "gecko")]
+pub fn serialize_atom_identifier<W>(ident: &Atom, dest: &mut W) -> fmt::Result
+where
+ W: Write,
+{
+ ident.with_str(|s| serialize_identifier(s, dest))
+}
+
+/// Serialize an identifier which is represented as an atom.
+#[cfg(feature = "servo")]
+pub fn serialize_atom_identifier<Static, W>(
+ ident: &::string_cache::Atom<Static>,
+ dest: &mut W,
+) -> fmt::Result
+where
+ Static: ::string_cache::StaticAtomSet,
+ W: Write,
+{
+ serialize_identifier(&ident, dest)
+}
+
+/// Serialize a name which is represented as an Atom.
+#[cfg(feature = "gecko")]
+pub fn serialize_atom_name<W>(ident: &Atom, dest: &mut W) -> fmt::Result
+where
+ W: Write,
+{
+ ident.with_str(|s| serialize_name(s, dest))
+}
+
+/// Serialize a name which is represented as an Atom.
+#[cfg(feature = "servo")]
+pub fn serialize_atom_name<Static, W>(
+ ident: &::string_cache::Atom<Static>,
+ dest: &mut W,
+) -> fmt::Result
+where
+ Static: ::string_cache::StaticAtomSet,
+ W: Write,
+{
+ serialize_name(&ident, dest)
+}
+
+/// A CSS string stored as an `Atom`.
+#[repr(transparent)]
+#[derive(
+ Clone,
+ Debug,
+ Default,
+ Deref,
+ Eq,
+ Hash,
+ MallocSizeOf,
+ PartialEq,
+ SpecifiedValueInfo,
+ ToComputedValue,
+ ToResolvedValue,
+ ToShmem,
+)]
+pub struct AtomString(pub Atom);
+
+impl cssparser::ToCss for AtomString {
+ fn to_css<W>(&self, dest: &mut W) -> fmt::Result
+ where
+ W: Write,
+ {
+ self.0
+ .with_str(|s| cssparser::CssStringWriter::new(dest).write_str(s))
+ }
+}
+
+impl PrecomputedHash for AtomString {
+ #[inline]
+ fn precomputed_hash(&self) -> u32 {
+ self.0.precomputed_hash()
+ }
+}
+
+impl<'a> From<&'a str> for AtomString {
+ #[inline]
+ fn from(string: &str) -> Self {
+ Self(Atom::from(string))
+ }
+}
+
+/// A CSS `<ident>` stored as an `Atom`.
+#[repr(transparent)]
+#[derive(
+ Clone,
+ Debug,
+ Default,
+ Deref,
+ Eq,
+ Hash,
+ MallocSizeOf,
+ PartialEq,
+ SpecifiedValueInfo,
+ ToComputedValue,
+ ToResolvedValue,
+ ToShmem,
+)]
+pub struct AtomIdent(pub Atom);
+
+impl cssparser::ToCss for AtomIdent {
+ fn to_css<W>(&self, dest: &mut W) -> fmt::Result
+ where
+ W: Write,
+ {
+ serialize_atom_identifier(&self.0, dest)
+ }
+}
+
+impl PrecomputedHash for AtomIdent {
+ #[inline]
+ fn precomputed_hash(&self) -> u32 {
+ self.0.precomputed_hash()
+ }
+}
+
+impl<'a> From<&'a str> for AtomIdent {
+ #[inline]
+ fn from(string: &str) -> Self {
+ Self(Atom::from(string))
+ }
+}
+
+impl AtomIdent {
+ /// Like `Atom::with` but for `AtomIdent`.
+ #[cfg(feature = "gecko")]
+ pub unsafe fn with<F, R>(ptr: *const crate::gecko_bindings::structs::nsAtom, callback: F) -> R
+ where
+ F: FnOnce(&Self) -> R,
+ {
+ Atom::with(ptr, |atom: &Atom| {
+ // safety: repr(transparent)
+ let atom = atom as *const Atom as *const AtomIdent;
+ callback(&*atom)
+ })
+ }
+}
+
+#[cfg(feature = "gecko")]
+impl std::borrow::Borrow<crate::gecko_string_cache::WeakAtom> for AtomIdent {
+ #[inline]
+ fn borrow(&self) -> &crate::gecko_string_cache::WeakAtom {
+ self.0.borrow()
+ }
+}
+
+/// Serialize a normalized value into percentage.
+pub fn serialize_percentage<W>(value: CSSFloat, dest: &mut CssWriter<W>) -> fmt::Result
+where
+ W: Write,
+{
+ (value * 100.).to_css(dest)?;
+ dest.write_str("%")
+}
+
+/// Convenience void type to disable some properties and values through types.
+#[cfg_attr(feature = "servo", derive(Deserialize, MallocSizeOf, Serialize))]
+#[derive(
+ Clone,
+ Copy,
+ Debug,
+ PartialEq,
+ SpecifiedValueInfo,
+ ToAnimatedValue,
+ ToComputedValue,
+ ToCss,
+ ToResolvedValue,
+)]
+pub enum Impossible {}
+
+// FIXME(nox): This should be derived but the derive code cannot cope
+// with uninhabited enums.
+impl ComputeSquaredDistance for Impossible {
+ #[inline]
+ fn compute_squared_distance(&self, _other: &Self) -> Result<SquaredDistance, ()> {
+ match *self {}
+ }
+}
+
+impl_trivial_to_shmem!(Impossible);
+
+impl Parse for Impossible {
+ fn parse<'i, 't>(
+ _context: &ParserContext,
+ input: &mut Parser<'i, 't>,
+ ) -> Result<Self, ParseError<'i>> {
+ Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
+ }
+}
+
+/// A struct representing one of two kinds of values.
+#[derive(
+ Animate,
+ Clone,
+ ComputeSquaredDistance,
+ Copy,
+ MallocSizeOf,
+ PartialEq,
+ Parse,
+ SpecifiedValueInfo,
+ ToAnimatedValue,
+ ToAnimatedZero,
+ ToComputedValue,
+ ToCss,
+ ToResolvedValue,
+ ToShmem,
+)]
+pub enum Either<A, B> {
+ /// The first value.
+ First(A),
+ /// The second kind of value.
+ Second(B),
+}
+
+impl<A: Debug, B: Debug> Debug for Either<A, B> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ Either::First(ref v) => v.fmt(f),
+ Either::Second(ref v) => v.fmt(f),
+ }
+ }
+}
+
+/// <https://drafts.csswg.org/css-values-4/#custom-idents>
+#[derive(
+ Clone,
+ Debug,
+ Eq,
+ Hash,
+ MallocSizeOf,
+ PartialEq,
+ SpecifiedValueInfo,
+ ToComputedValue,
+ ToResolvedValue,
+ ToShmem,
+)]
+#[repr(C)]
+pub struct CustomIdent(pub Atom);
+
+impl CustomIdent {
+ /// Parse an already-tokenizer identifier
+ pub fn from_ident<'i>(
+ location: SourceLocation,
+ ident: &CowRcStr<'i>,
+ excluding: &[&str],
+ ) -> Result<Self, ParseError<'i>> {
+ let valid = match_ignore_ascii_case! { ident,
+ "initial" | "inherit" | "unset" | "default" | "revert" => false,
+ _ => true
+ };
+ if !valid {
+ return Err(
+ location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone()))
+ );
+ }
+ if excluding.iter().any(|s| ident.eq_ignore_ascii_case(s)) {
+ Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError))
+ } else {
+ Ok(CustomIdent(Atom::from(ident.as_ref())))
+ }
+ }
+}
+
+impl ToCss for CustomIdent {
+ fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
+ where
+ W: Write,
+ {
+ serialize_atom_identifier(&self.0, dest)
+ }
+}
+
+/// <https://drafts.csswg.org/css-animations/#typedef-keyframes-name>
+#[derive(
+ Clone, Debug, MallocSizeOf, SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem,
+)]
+pub enum KeyframesName {
+ /// <custom-ident>
+ Ident(CustomIdent),
+ /// <string>
+ QuotedString(Atom),
+}
+
+impl KeyframesName {
+ /// <https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-name>
+ pub fn from_ident(value: &str) -> Self {
+ let location = SourceLocation { line: 0, column: 0 };
+ let custom_ident = CustomIdent::from_ident(location, &value.into(), &["none"]).ok();
+ match custom_ident {
+ Some(ident) => KeyframesName::Ident(ident),
+ None => KeyframesName::QuotedString(value.into()),
+ }
+ }
+
+ /// Create a new KeyframesName from Atom.
+ #[cfg(feature = "gecko")]
+ pub fn from_atom(atom: Atom) -> Self {
+ debug_assert_ne!(atom, atom!(""));
+
+ // FIXME: We might want to preserve <string>, but currently Gecko
+ // stores both of <custom-ident> and <string> into nsAtom, so
+ // we can't tell it.
+ KeyframesName::Ident(CustomIdent(atom))
+ }
+
+ /// The name as an Atom
+ pub fn as_atom(&self) -> &Atom {
+ match *self {
+ KeyframesName::Ident(ref ident) => &ident.0,
+ KeyframesName::QuotedString(ref atom) => atom,
+ }
+ }
+}
+
+impl Eq for KeyframesName {}
+
+/// A trait that returns whether a given type is the `auto` value or not. So far
+/// only needed for background-size serialization, which special-cases `auto`.
+pub trait IsAuto {
+ /// Returns whether the value is the `auto` value.
+ fn is_auto(&self) -> bool;
+}
+
+impl PartialEq for KeyframesName {
+ fn eq(&self, other: &Self) -> bool {
+ self.as_atom() == other.as_atom()
+ }
+}
+
+impl hash::Hash for KeyframesName {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: hash::Hasher,
+ {
+ self.as_atom().hash(state)
+ }
+}
+
+impl Parse for KeyframesName {
+ fn parse<'i, 't>(
+ _context: &ParserContext,
+ input: &mut Parser<'i, 't>,
+ ) -> Result<Self, ParseError<'i>> {
+ let location = input.current_source_location();
+ match *input.next()? {
+ Token::Ident(ref s) => Ok(KeyframesName::Ident(CustomIdent::from_ident(
+ location,
+ s,
+ &["none"],
+ )?)),
+ Token::QuotedString(ref s) => Ok(KeyframesName::QuotedString(Atom::from(s.as_ref()))),
+ ref t => Err(location.new_unexpected_token_error(t.clone())),
+ }
+ }
+}
+
+impl ToCss for KeyframesName {
+ fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
+ where
+ W: Write,
+ {
+ match *self {
+ KeyframesName::Ident(ref ident) => ident.to_css(dest),
+ KeyframesName::QuotedString(ref atom) => atom.to_string().to_css(dest),
+ }
+ }
+}