/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
//! Computed values.
useself::transform::DirectionVector; usesuper::animated::ToAnimatedValue; usesuper::generics::grid::GridTemplateComponent as GenericGridTemplateComponent; usesuper::generics::grid::ImplicitGridTracks as GenericImplicitGridTracks; usesuper::generics::grid::{GenericGridLine, GenericTrackBreadth}; usesuper::generics::grid::{GenericTrackSize, TrackList as GenericTrackList}; usesuper::generics::transform::IsParallelTo; usesuper::generics::{self, GreaterThanOrEqualToOne, NonNegative, ZeroToOne}; usesuper::specified; usesuper::{CSSFloat, CSSInteger}; usecrate::computed_value_flags::ComputedValueFlags; usecrate::context::{QuirksMode, TreeCountingCaches}; usecrate::custom_properties::ComputedCustomProperties; usecrate::derives::*; usecrate::device::Device; usecrate::dom::DummyElementContext; usecrate::dom::ElementContext; usecrate::font_metrics::{FontMetrics, FontMetricsOrientation}; #[cfg(feature = "gecko")] usecrate::properties; usecrate::properties::{ComputedValues, StyleBuilder}; usecrate::rule_cache::RuleCacheConditions; usecrate::rule_tree::{CascadeLevel, RuleCascadeFlags}; usecrate::stylesheets::container_rule::{
ContainerInfo, ContainerSizeQuery, ContainerSizeQueryResult,
}; usecrate::stylist::Stylist; usecrate::values::generics::ClampToNonNegative; usecrate::values::specified::font::QueryFontMetricsFlags; usecrate::values::specified::length::FontBaseSize; usecrate::{ArcSlice, Atom, One}; use euclid::{default, Point2D, Rect, Size2D}; use servo_arc::Arc; use std::cell::RefCell; use std::cmp; use std::f32; use std::ops::{Add, Sub};
/// A `Context` is all the data a specified value could ever need to compute /// itself and be transformed to a computed value. pubstruct Context<'a> { /// Values accessed through this need to be in the properties "computed /// early": color, text-decoration, font-size, display, position, float, /// border-*-style, outline-style, font-family, writing-mode... pub builder: StyleBuilder<'a>,
/// A cached computed system font value, for use by gecko. /// /// See properties/longhands/font.mako.rs #[cfg(feature = "gecko")] pub cached_system_font: Option<properties::gecko::system_font::ComputedSystemFont>,
/// A dummy option for servo so initializing a computed::Context isn't /// painful. /// /// TODO(emilio): Make constructors for Context, and drop this. #[cfg(feature = "servo")] pub cached_system_font: Option<()>,
/// Whether or not we are computing the media list in a media query. pub in_media_query: bool,
/// Whether or not we are computing the container query condition. pub in_container_query: bool,
/// The quirks mode of this context. pub quirks_mode: QuirksMode,
/// Whether this computation is being done for animation. /// /// Allows opacity to interpolate out-of-range values pub for_animation: bool,
/// Returns the container information to evaluate a given container query. pub container_info: Option<ContainerInfo>,
/// Whether we're computing a value for a non-inherited property. /// False if we are computed a value for an inherited property or not computing for a property /// at all (e.g. in a media query evaluation). pub for_non_inherited_property: bool,
/// The conditions to cache a rule node on the rule cache. /// /// FIXME(emilio): Drop the refcell. pub rule_cache_conditions: RefCell<&'a mut RuleCacheConditions>,
/// The cascade level in the shadow tree hierarchy. pub scope: CascadeLevel,
/// The set of RuleCascadeFlags whose rules should be included during the /// cascade. STARTING_STYLE is set from the caller for re-cascade. /// APPEARANCE_BASE is added dynamically after the appearance property is /// resolved to a non-None value. pub included_cascade_flags: RuleCascadeFlags,
/// Container size query for this context.
container_size_query: RefCell<ContainerSizeQuery<'a>>,
/// Element context for the element being styled, used to resolve tree-counting functions /// (`sibling-index()`, `sibling-count()`) and attribute values (`attr()`).
element_context: &'a dyn ElementContext,
/// Caches for evaluation of tree-counting functions. pub tree_counting_caches: RefCell<&'a mut TreeCountingCaches>,
}
/// Creates a context suitable for computing the initial value of @property. pubfn new_for_initial_at_property_value(
stylist: &'a Stylist,
rule_cache_conditions: &'a mut RuleCacheConditions,
tree_counting_caches: &'a mut TreeCountingCaches,
) -> Self { Self {
builder: StyleBuilder::new(stylist.device(), Some(stylist), None, None, None, false),
cached_system_font: None, // Because font-relative values are disallowed in @property initial values, we do not // need to keep track of whether we're in a media query, whether we're in a container // query, and so on.
in_media_query: false,
in_container_query: false,
quirks_mode: stylist.quirks_mode(),
container_info: None,
for_animation: false,
for_non_inherited_property: false,
rule_cache_conditions: RefCell::new(rule_cache_conditions),
scope: CascadeLevel::same_tree_author_normal(),
included_cascade_flags: RuleCascadeFlags::empty(),
container_size_query: RefCell::new(ContainerSizeQuery::none()),
element_context: &DummyElementContext {},
tree_counting_caches: RefCell::new(tree_counting_caches),
}
}
/// The current device. pubfn device(&self) -> &Device { self.builder.device
}
/// Get the inherited custom properties map. pubfn inherited_custom_properties(&self) -> &ComputedCustomProperties {
&self.builder.inherited_custom_properties()
}
/// Whether the style is for the root element. pubfn is_root_element(&self) -> bool { self.builder.is_root_element
}
let (wm, font) = match base_size {
FontBaseSize::CurrentStyle => (style.writing_mode, style.get_font()), // This is only used for font-size computation.
FontBaseSize::InheritedStyle => {
(*style.inherited_writing_mode(), style.get_parent_font())
},
};
/// The current viewport size, used to resolve viewport units. pubfn viewport_size_for_viewport_unit_resolution(
&self,
variant: ViewportVariant,
) -> default::Size2D<Au> { self.builder
.add_flags(ComputedValueFlags::USES_VIEWPORT_UNITS); self.builder
.device
.au_viewport_size_for_viewport_unit_resolution(variant)
}
fn resolve_tree_counting_result(&self) -> TreeCountingResult { // https://drafts.csswg.org/css-values-5/#tree-counting // > A tree-counting function is a type of loosely-matched tree-scoped reference. // // As a loosely-matched reference, the tree-counting function can only match if // the declaration is in the same or descendant shadow tree of the element. It // does not match if the declaration is in a containing tree, so it must return 0. ifself
.current_scope()
.shadow_order()
.is_in_same_or_containing_tree()
{ return TreeCountingResult::default();
}
/// Returns the number of siblings of the element that matches the declaration /// (including the element itself). Also marks the style as depending on sibling-count(). pubfn query_sibling_count(&self) -> u32 { self.builder
.add_flags(ComputedValueFlags::USES_SIBLING_COUNT); self.resolve_tree_counting_result().sibling_count
}
/// Returns the 1-based index of the element that matches the declaration amongst its /// siblings. Also marks the style as depending on sibling-index(). pubfn query_sibling_index(&self) -> u32 { self.builder
.add_flags(ComputedValueFlags::USES_SIBLING_INDEX); self.rule_cache_conditions.borrow_mut().set_uncacheable(); self.resolve_tree_counting_result().sibling_index
}
/// Whether we're in a media or container query. pubfn in_media_or_container_query(&self) -> bool { self.in_media_query || self.in_container_query
}
/// A trait to represent the conversion between computed and specified values. /// /// This trait is derivable with `#[derive(ToComputedValue)]`. The derived /// implementation just calls `ToComputedValue::to_computed_value` on each field /// of the passed value. The deriving code assumes that if the type isn't /// generic, then the trait can be implemented as simple `Clone::clone` calls, /// this means that a manual implementation with `ComputedValue = Self` is bogus /// if it returns anything else than a clone. pubtrait ToComputedValue { /// The computed value type we're going to be converted to. type ComputedValue;
/// Convert a specified value to a computed value, using itself and the data /// inside the `Context`. fn to_computed_value(&self, context: &Context) -> Self::ComputedValue;
/// Convert a computed value to specified value form. /// /// This will be used for recascading during animation. /// Such from_computed_valued values should recompute to the same value. fn from_computed_value(computed: &Self::ComputedValue) -> Self;
}
impl<A, B> ToComputedValue for (A, B) where
A: ToComputedValue,
B: ToComputedValue,
{ type ComputedValue = (
<A as ToComputedValue>::ComputedValue,
<B as ToComputedValue>::ComputedValue,
);
impl<T> ToComputedValue for default::Size2D<T> where
T: ToComputedValue,
{ type ComputedValue = default::Size2D<<T as ToComputedValue>::ComputedValue>;
impl<T> ToComputedValue forcrate::OwnedSlice<T> where
T: ToComputedValue,
{ type ComputedValue = crate::OwnedSlice<<T as ToComputedValue>::ComputedValue>;
impl<T> ToComputedValue for thin_vec::ThinVec<T> where
T: ToComputedValue,
{ type ComputedValue = thin_vec::ThinVec<<T as ToComputedValue>::ComputedValue>;
// NOTE(emilio): This is implementable more generically, but it's unlikely // what you want there, as it forces you to have an extra allocation. // // We could do that if needed, ideally with specialization for the case where // ComputedValue = T. But we don't need it for now. impl<T> ToComputedValue for Arc<T> where
T: ToComputedValue<ComputedValue = T>,
{ type ComputedValue = Self;
/// A `<number>` value. pubtype Number = CSSFloat;
impl IsParallelTo for (Number, Number, Number) { fn is_parallel_to(&self, vector: &DirectionVector) -> bool { use euclid::approxeq::ApproxEq; // If a and b is parallel, the angle between them is 0deg, so // a x b = |a|*|b|*sin(0)*n = 0 * n, |a x b| == 0. let self_vector = DirectionVector::new(self.0, self.1, self.2);
self_vector
.cross(*vector)
.square_length()
.approx_eq(&0.0f32)
}
}
/// A wrapper of Number, but the value >= 0. pubtype NonNegativeNumber = NonNegative<CSSFloat>;
impl NumberOrPercentage { /// Get the underlying value of this number or percentage. pubfn value(&self) -> f32 { matchself {
NumberOrPercentage::Percentage(p) => p.0,
NumberOrPercentage::Number(n) => *n,
}
}
}
/// rect(...) | auto pubtype ClipRect = generics::GenericClipRect<LengthOrAuto>;
/// rect(...) | auto pubtype ClipRectOrAuto = generics::GenericClipRectOrAuto<ClipRect>;
/// The computed value of a grid `<track-breadth>` pubtype TrackBreadth = GenericTrackBreadth<LengthPercentage>;
/// The computed value of a grid `<track-size>` pubtype TrackSize = GenericTrackSize<LengthPercentage>;
/// The computed value of a grid `<track-size>+` pubtype ImplicitGridTracks = GenericImplicitGridTracks<TrackSize>;
/// The computed value of a grid `<track-list>` /// (could also be `<auto-track-list>` or `<explicit-track-list>`) pubtype TrackList = GenericTrackList<LengthPercentage, Integer>;
/// The computed value of a `<grid-line>`. pubtype GridLine = GenericGridLine<Integer>;
impl ClipRect { /// Given a border box, resolves the clip rect against the border box /// in the same space the border box is in pubfn for_border_rect<T: Copy + From<Length> + Add<Output = T> + Sub<Output = T>, U>(
&self,
border_box: Rect<T, U>,
) -> Rect<T, U> { fn extract_clip_component<T: From<Length>>(p: &LengthOrAuto, or: T) -> T { match *p {
LengthOrAuto::Auto => or,
LengthOrAuto::LengthPercentage(ref length) => T::from(*length),
}
}
let clip_origin = Point2D::new(
From::from(self.left.auto_is(|| Length::new(0.))),
From::from(self.top.auto_is(|| Length::new(0.))),
); let right = extract_clip_component(&self.right, border_box.size.width); let bottom = extract_clip_component(&self.bottom, border_box.size.height); let clip_size = Size2D::new(right - clip_origin.x, bottom - clip_origin.y);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.