mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Auto merge of #24204 - emilio:gecko-sync, r=emilio
style: Sync changes from mozilla-central. See each individual commit for details. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/24204) <!-- Reviewable:end -->
This commit is contained in:
commit
75bc72b29f
49 changed files with 1124 additions and 1192 deletions
|
@ -61,11 +61,11 @@ use style::properties::{style_structs, ComputedValues};
|
||||||
use style::servo::restyle_damage::ServoRestyleDamage;
|
use style::servo::restyle_damage::ServoRestyleDamage;
|
||||||
use style::values::computed::effects::SimpleShadow;
|
use style::values::computed::effects::SimpleShadow;
|
||||||
use style::values::computed::image::{Image, ImageLayer};
|
use style::values::computed::image::{Image, ImageLayer};
|
||||||
use style::values::computed::{Gradient, LengthOrAuto};
|
use style::values::computed::{ClipRectOrAuto, Gradient, LengthOrAuto};
|
||||||
use style::values::generics::background::BackgroundSize;
|
use style::values::generics::background::BackgroundSize;
|
||||||
use style::values::generics::image::{GradientKind, PaintWorklet};
|
use style::values::generics::image::{GradientKind, PaintWorklet};
|
||||||
use style::values::specified::ui::CursorKind;
|
use style::values::specified::ui::CursorKind;
|
||||||
use style::values::{Either, RGBA};
|
use style::values::RGBA;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use webrender_api::units::{LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D};
|
use webrender_api::units::{LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D};
|
||||||
use webrender_api::{self, BorderDetails, BorderRadius, BorderSide, BoxShadowClipMode, ColorF};
|
use webrender_api::{self, BorderDetails, BorderRadius, BorderSide, BoxShadowClipMode, ColorF};
|
||||||
|
@ -2632,8 +2632,8 @@ impl BlockFlow {
|
||||||
) {
|
) {
|
||||||
// Account for `clip` per CSS 2.1 § 11.1.2.
|
// Account for `clip` per CSS 2.1 § 11.1.2.
|
||||||
let style_clip_rect = match self.fragment.style().get_effects().clip {
|
let style_clip_rect = match self.fragment.style().get_effects().clip {
|
||||||
Either::First(style_clip_rect) => style_clip_rect,
|
ClipRectOrAuto::Rect(ref r) => r,
|
||||||
_ => return,
|
ClipRectOrAuto::Auto => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
// CSS `clip` should only apply to position:absolute or positione:fixed elements.
|
// CSS `clip` should only apply to position:absolute or positione:fixed elements.
|
||||||
|
|
|
@ -1497,11 +1497,10 @@ impl LayoutThread {
|
||||||
// Create a layout context for use throughout the following passes.
|
// Create a layout context for use throughout the following passes.
|
||||||
let mut layout_context = self.build_layout_context(guards.clone(), true, &map);
|
let mut layout_context = self.build_layout_context(guards.clone(), true, &map);
|
||||||
|
|
||||||
|
let pool;
|
||||||
let (thread_pool, num_threads) = if self.parallel_flag {
|
let (thread_pool, num_threads) = if self.parallel_flag {
|
||||||
(
|
pool = STYLE_THREAD_POOL.pool();
|
||||||
STYLE_THREAD_POOL.style_thread_pool.as_ref(),
|
(pool.as_ref(), STYLE_THREAD_POOL.num_threads)
|
||||||
STYLE_THREAD_POOL.num_threads,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
(None, 1)
|
(None, 1)
|
||||||
};
|
};
|
||||||
|
@ -1859,8 +1858,10 @@ impl LayoutThread {
|
||||||
|| {
|
|| {
|
||||||
let profiler_metadata = self.profiler_metadata();
|
let profiler_metadata = self.profiler_metadata();
|
||||||
|
|
||||||
|
let pool;
|
||||||
let thread_pool = if self.parallel_flag {
|
let thread_pool = if self.parallel_flag {
|
||||||
STYLE_THREAD_POOL.style_thread_pool.as_ref()
|
pool = STYLE_THREAD_POOL.pool();
|
||||||
|
pool.as_ref()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
|
@ -64,7 +64,7 @@ pub type BloomFilter = CountingBloomFilter<BloomStorageU8>;
|
||||||
/// Similarly, using a KeySize of 10 would lead to a 4% false
|
/// Similarly, using a KeySize of 10 would lead to a 4% false
|
||||||
/// positive rate for N == 100 and to quite bad false positive
|
/// positive rate for N == 100 and to quite bad false positive
|
||||||
/// rates for larger N.
|
/// rates for larger N.
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Default)]
|
||||||
pub struct CountingBloomFilter<S>
|
pub struct CountingBloomFilter<S>
|
||||||
where
|
where
|
||||||
S: BloomStorage,
|
S: BloomStorage,
|
||||||
|
@ -79,9 +79,7 @@ where
|
||||||
/// Creates a new bloom filter.
|
/// Creates a new bloom filter.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
CountingBloomFilter {
|
Default::default()
|
||||||
storage: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -13,13 +13,20 @@ use owning_ref::OwningHandle;
|
||||||
use selectors::bloom::BloomFilter;
|
use selectors::bloom::BloomFilter;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
use std::mem::ManuallyDrop;
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
/// Bloom filters are large allocations, so we store them in thread-local storage
|
/// Bloom filters are large allocations, so we store them in thread-local storage
|
||||||
/// such that they can be reused across style traversals. StyleBloom is responsible
|
/// such that they can be reused across style traversals. StyleBloom is responsible
|
||||||
/// for ensuring that the bloom filter is zeroed when it is dropped.
|
/// for ensuring that the bloom filter is zeroed when it is dropped.
|
||||||
static BLOOM_KEY: Arc<AtomicRefCell<BloomFilter>> =
|
///
|
||||||
Arc::new_leaked(AtomicRefCell::new(BloomFilter::new()));
|
/// We intentionally leak this from TLS because we don't have the guarantee
|
||||||
|
/// of TLS destructors to run in worker threads.
|
||||||
|
///
|
||||||
|
/// We could change this once https://github.com/rayon-rs/rayon/issues/688
|
||||||
|
/// is fixed, hopefully.
|
||||||
|
static BLOOM_KEY: ManuallyDrop<Arc<AtomicRefCell<BloomFilter>>> =
|
||||||
|
ManuallyDrop::new(Arc::new_leaked(Default::default()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A struct that allows us to fast-reject deep descendant selectors avoiding
|
/// A struct that allows us to fast-reject deep descendant selectors avoiding
|
||||||
|
@ -128,7 +135,7 @@ impl<E: TElement> StyleBloom<E> {
|
||||||
// See https://github.com/servo/servo/pull/18420#issuecomment-328769322
|
// See https://github.com/servo/servo/pull/18420#issuecomment-328769322
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let bloom_arc = BLOOM_KEY.with(|b| b.clone());
|
let bloom_arc = BLOOM_KEY.with(|b| Arc::clone(&*b));
|
||||||
let filter =
|
let filter =
|
||||||
OwningHandle::new_with_fn(bloom_arc, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
|
OwningHandle::new_with_fn(bloom_arc, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
|
@ -136,7 +143,7 @@ impl<E: TElement> StyleBloom<E> {
|
||||||
"Forgot to zero the bloom filter last time"
|
"Forgot to zero the bloom filter last time"
|
||||||
);
|
);
|
||||||
StyleBloom {
|
StyleBloom {
|
||||||
filter: filter,
|
filter,
|
||||||
elements: Default::default(),
|
elements: Default::default(),
|
||||||
pushed_hashes: Default::default(),
|
pushed_hashes: Default::default(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,7 +104,7 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
let size = get_size(device);
|
let size = get_size(device);
|
||||||
let value = AspectRatio(size.width.0 as u32, size.height.0 as u32);
|
let value = AspectRatio(size.width.0 as f32, size.height.0 as f32);
|
||||||
RangeOrOperator::evaluate_with_query_value(range_or_operator, query_value, value)
|
RangeOrOperator::evaluate_with_query_value(range_or_operator, query_value, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,7 +559,7 @@ lazy_static! {
|
||||||
feature!(
|
feature!(
|
||||||
atom!("aspect-ratio"),
|
atom!("aspect-ratio"),
|
||||||
AllowsRanges::Yes,
|
AllowsRanges::Yes,
|
||||||
Evaluator::IntRatio(eval_aspect_ratio),
|
Evaluator::NumberRatio(eval_aspect_ratio),
|
||||||
ParsingRequirements::empty(),
|
ParsingRequirements::empty(),
|
||||||
),
|
),
|
||||||
feature!(
|
feature!(
|
||||||
|
@ -583,7 +583,7 @@ lazy_static! {
|
||||||
feature!(
|
feature!(
|
||||||
atom!("device-aspect-ratio"),
|
atom!("device-aspect-ratio"),
|
||||||
AllowsRanges::Yes,
|
AllowsRanges::Yes,
|
||||||
Evaluator::IntRatio(eval_device_aspect_ratio),
|
Evaluator::NumberRatio(eval_device_aspect_ratio),
|
||||||
ParsingRequirements::empty(),
|
ParsingRequirements::empty(),
|
||||||
),
|
),
|
||||||
feature!(
|
feature!(
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
use crate::counter_style::{Symbol, Symbols};
|
use crate::counter_style::{Symbol, Symbols};
|
||||||
use crate::gecko_bindings::structs::CounterStylePtr;
|
use crate::gecko_bindings::structs::CounterStylePtr;
|
||||||
use crate::values::generics::CounterStyleOrNone;
|
use crate::values::generics::CounterStyle;
|
||||||
use crate::values::Either;
|
use crate::values::Either;
|
||||||
use crate::Atom;
|
use crate::Atom;
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
|
@ -49,19 +49,17 @@ pub fn round_border_to_device_pixels(width: Au, au_per_device_px: Au) -> Au {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CounterStyleOrNone {
|
impl CounterStyle {
|
||||||
/// Convert this counter style to a Gecko CounterStylePtr.
|
/// Convert this counter style to a Gecko CounterStylePtr.
|
||||||
pub fn to_gecko_value(self, gecko_value: &mut CounterStylePtr) {
|
pub fn to_gecko_value(self, gecko_value: &mut CounterStylePtr) {
|
||||||
use crate::gecko_bindings::bindings::Gecko_SetCounterStyleToName as set_name;
|
use crate::gecko_bindings::bindings::Gecko_SetCounterStyleToName as set_name;
|
||||||
use crate::gecko_bindings::bindings::Gecko_SetCounterStyleToSymbols as set_symbols;
|
use crate::gecko_bindings::bindings::Gecko_SetCounterStyleToSymbols as set_symbols;
|
||||||
match self {
|
match self {
|
||||||
CounterStyleOrNone::None => unsafe {
|
CounterStyle::Name(name) => unsafe {
|
||||||
set_name(gecko_value, atom!("none").into_addrefed());
|
debug_assert_ne!(name.0, atom!("none"));
|
||||||
},
|
|
||||||
CounterStyleOrNone::Name(name) => unsafe {
|
|
||||||
set_name(gecko_value, name.0.into_addrefed());
|
set_name(gecko_value, name.0.into_addrefed());
|
||||||
},
|
},
|
||||||
CounterStyleOrNone::Symbols(symbols_type, symbols) => {
|
CounterStyle::Symbols(symbols_type, symbols) => {
|
||||||
let symbols: Vec<_> = symbols
|
let symbols: Vec<_> = symbols
|
||||||
.0
|
.0
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -86,7 +84,7 @@ impl CounterStyleOrNone {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert Gecko CounterStylePtr to CounterStyleOrNone or String.
|
/// Convert Gecko CounterStylePtr to CounterStyle or String.
|
||||||
pub fn from_gecko_value(gecko_value: &CounterStylePtr) -> Either<Self, String> {
|
pub fn from_gecko_value(gecko_value: &CounterStylePtr) -> Either<Self, String> {
|
||||||
use crate::gecko_bindings::bindings;
|
use crate::gecko_bindings::bindings;
|
||||||
use crate::values::generics::SymbolsType;
|
use crate::values::generics::SymbolsType;
|
||||||
|
@ -95,11 +93,8 @@ impl CounterStyleOrNone {
|
||||||
let name = unsafe { bindings::Gecko_CounterStyle_GetName(gecko_value) };
|
let name = unsafe { bindings::Gecko_CounterStyle_GetName(gecko_value) };
|
||||||
if !name.is_null() {
|
if !name.is_null() {
|
||||||
let name = unsafe { Atom::from_raw(name) };
|
let name = unsafe { Atom::from_raw(name) };
|
||||||
if name == atom!("none") {
|
debug_assert_ne!(name, atom!("none"));
|
||||||
Either::First(CounterStyleOrNone::None)
|
Either::First(CounterStyle::Name(CustomIdent(name)))
|
||||||
} else {
|
|
||||||
Either::First(CounterStyleOrNone::Name(CustomIdent(name)))
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let anonymous =
|
let anonymous =
|
||||||
unsafe { bindings::Gecko_CounterStyle_GetAnonymous(gecko_value).as_ref() }.unwrap();
|
unsafe { bindings::Gecko_CounterStyle_GetAnonymous(gecko_value).as_ref() }.unwrap();
|
||||||
|
@ -113,7 +108,7 @@ impl CounterStyleOrNone {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|gecko_symbol| Symbol::String(gecko_symbol.to_string().into()))
|
.map(|gecko_symbol| Symbol::String(gecko_symbol.to_string().into()))
|
||||||
.collect();
|
.collect();
|
||||||
Either::First(CounterStyleOrNone::Symbols(symbol_type, Symbols(symbols)))
|
Either::First(CounterStyle::Symbols(symbol_type, Symbols(symbols)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -706,44 +706,6 @@ impl<'le> GeckoElement<'le> {
|
||||||
!self.xbl_binding_with_content().is_none()
|
!self.xbl_binding_with_content().is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This duplicates the logic in Gecko's virtual nsINode::GetBindingParent
|
|
||||||
/// function, which only has two implementations: one for XUL elements, and
|
|
||||||
/// one for other elements.
|
|
||||||
///
|
|
||||||
/// We just hard code in our knowledge of those two implementations here.
|
|
||||||
fn xbl_binding_parent(&self) -> Option<Self> {
|
|
||||||
if self.is_xul_element() {
|
|
||||||
// FIXME(heycam): Having trouble with bindgen on nsXULElement,
|
|
||||||
// where the binding parent is stored in a member variable
|
|
||||||
// rather than in slots. So just get it through FFI for now.
|
|
||||||
unsafe {
|
|
||||||
bindings::Gecko_GetBindingParent(self.0)
|
|
||||||
.as_ref()
|
|
||||||
.map(GeckoElement)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let binding_parent =
|
|
||||||
unsafe { self.non_xul_xbl_binding_parent().as_ref() }.map(GeckoElement);
|
|
||||||
|
|
||||||
debug_assert!(
|
|
||||||
binding_parent ==
|
|
||||||
unsafe {
|
|
||||||
bindings::Gecko_GetBindingParent(self.0)
|
|
||||||
.as_ref()
|
|
||||||
.map(GeckoElement)
|
|
||||||
}
|
|
||||||
);
|
|
||||||
binding_parent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn non_xul_xbl_binding_parent(&self) -> *mut RawGeckoElement {
|
|
||||||
debug_assert!(!self.is_xul_element());
|
|
||||||
self.extended_slots()
|
|
||||||
.map_or(ptr::null_mut(), |slots| slots._base.mBindingParent.mRawPtr)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn namespace_id(&self) -> i32 {
|
fn namespace_id(&self) -> i32 {
|
||||||
self.as_node().node_info().mInner.mNamespaceID
|
self.as_node().node_info().mInner.mNamespaceID
|
||||||
|
@ -865,19 +827,9 @@ impl<'le> GeckoElement<'le> {
|
||||||
return self.flags() & (NODE_IS_NATIVE_ANONYMOUS_ROOT as u32) != 0;
|
return self.flags() & (NODE_IS_NATIVE_ANONYMOUS_ROOT as u32) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This logic is duplicated in Gecko's nsIContent::IsInAnonymousSubtree.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_in_anonymous_subtree(&self) -> bool {
|
fn is_in_anonymous_subtree(&self) -> bool {
|
||||||
if self.is_in_native_anonymous_subtree() {
|
unsafe { bindings::Gecko_IsInAnonymousSubtree(self.0) }
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let binding_parent = match self.xbl_binding_parent() {
|
|
||||||
Some(p) => p,
|
|
||||||
None => return false,
|
|
||||||
};
|
|
||||||
|
|
||||||
binding_parent.shadow_root().is_none()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this node is the shadow root of an use-element shadow tree.
|
/// Returns true if this node is the shadow root of an use-element shadow tree.
|
||||||
|
|
|
@ -10,8 +10,10 @@ use crate::gecko_bindings::bindings;
|
||||||
use crate::parallel::STYLE_THREAD_STACK_SIZE_KB;
|
use crate::parallel::STYLE_THREAD_STACK_SIZE_KB;
|
||||||
use crate::shared_lock::SharedRwLock;
|
use crate::shared_lock::SharedRwLock;
|
||||||
use crate::thread_state;
|
use crate::thread_state;
|
||||||
|
use parking_lot::{RwLock, RwLockReadGuard};
|
||||||
use rayon;
|
use rayon;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
/// Global style data
|
/// Global style data
|
||||||
pub struct GlobalStyleData {
|
pub struct GlobalStyleData {
|
||||||
|
@ -22,20 +24,28 @@ pub struct GlobalStyleData {
|
||||||
pub options: StyleSystemOptions,
|
pub options: StyleSystemOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Global thread pool
|
/// Global thread pool.
|
||||||
pub struct StyleThreadPool {
|
pub struct StyleThreadPool {
|
||||||
/// How many threads parallel styling can use.
|
/// How many threads parallel styling can use.
|
||||||
pub num_threads: usize,
|
pub num_threads: usize,
|
||||||
|
|
||||||
/// The parallel styling thread pool.
|
/// The parallel styling thread pool.
|
||||||
pub style_thread_pool: Option<rayon::ThreadPool>,
|
///
|
||||||
|
/// For leak-checking purposes, we want to terminate the thread-pool, which
|
||||||
|
/// waits for all the async jobs to complete. Thus the RwLock.
|
||||||
|
style_thread_pool: RwLock<Option<rayon::ThreadPool>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn thread_name(index: usize) -> String {
|
fn thread_name(index: usize) -> String {
|
||||||
format!("StyleThread#{}", index)
|
format!("StyleThread#{}", index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A counter so that we can wait for shutdown of all threads. See
|
||||||
|
// StyleThreadPool::shutdown.
|
||||||
|
static ALIVE_WORKER_THREADS: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
fn thread_startup(_index: usize) {
|
fn thread_startup(_index: usize) {
|
||||||
|
ALIVE_WORKER_THREADS.fetch_add(1, Ordering::Relaxed);
|
||||||
thread_state::initialize_layout_worker_thread();
|
thread_state::initialize_layout_worker_thread();
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -55,6 +65,43 @@ fn thread_shutdown(_: usize) {
|
||||||
bindings::Gecko_UnregisterProfilerThread();
|
bindings::Gecko_UnregisterProfilerThread();
|
||||||
bindings::Gecko_SetJemallocThreadLocalArena(false);
|
bindings::Gecko_SetJemallocThreadLocalArena(false);
|
||||||
}
|
}
|
||||||
|
ALIVE_WORKER_THREADS.fetch_sub(1, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StyleThreadPool {
|
||||||
|
/// Shuts down the thread pool, waiting for all work to complete.
|
||||||
|
pub fn shutdown() {
|
||||||
|
if ALIVE_WORKER_THREADS.load(Ordering::Relaxed) == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Drop the pool.
|
||||||
|
let _ = STYLE_THREAD_POOL.style_thread_pool.write().take();
|
||||||
|
}
|
||||||
|
// Spin until all our threads are done. This will usually be pretty
|
||||||
|
// fast, as on shutdown there should be basically no threads left
|
||||||
|
// running.
|
||||||
|
//
|
||||||
|
// This still _technically_ doesn't give us the guarantee of TLS
|
||||||
|
// destructors running on the worker threads. For that we'd need help
|
||||||
|
// from rayon to properly join the threads.
|
||||||
|
//
|
||||||
|
// See https://github.com/rayon-rs/rayon/issues/688
|
||||||
|
//
|
||||||
|
// So we instead intentionally leak TLS stuff (see BLOOM_KEY and co) for
|
||||||
|
// now until that's fixed.
|
||||||
|
while ALIVE_WORKER_THREADS.load(Ordering::Relaxed) != 0 {
|
||||||
|
std::thread::yield_now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a reference to the thread pool.
|
||||||
|
///
|
||||||
|
/// We only really want to give read-only access to the pool, except
|
||||||
|
/// for shutdown().
|
||||||
|
pub fn pool(&self) -> RwLockReadGuard<Option<rayon::ThreadPool>> {
|
||||||
|
self.style_thread_pool.read()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
@ -113,10 +160,11 @@ lazy_static! {
|
||||||
};
|
};
|
||||||
|
|
||||||
StyleThreadPool {
|
StyleThreadPool {
|
||||||
num_threads: num_threads,
|
num_threads,
|
||||||
style_thread_pool: pool,
|
style_thread_pool: RwLock::new(pool),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Global style data
|
/// Global style data
|
||||||
pub static ref GLOBAL_STYLE_DATA: GlobalStyleData = GlobalStyleData {
|
pub static ref GLOBAL_STYLE_DATA: GlobalStyleData = GlobalStyleData {
|
||||||
shared_lock: SharedRwLock::new_leaked(),
|
shared_lock: SharedRwLock::new_leaked(),
|
||||||
|
|
|
@ -16,7 +16,7 @@ use crate::invalidation::element::invalidator::{Invalidation, InvalidationProces
|
||||||
use crate::invalidation::element::restyle_hints::RestyleHint;
|
use crate::invalidation::element::restyle_hints::RestyleHint;
|
||||||
use crate::selector_map::SelectorMap;
|
use crate::selector_map::SelectorMap;
|
||||||
use crate::selector_parser::Snapshot;
|
use crate::selector_parser::Snapshot;
|
||||||
use crate::stylesheets::origin::{Origin, OriginSet};
|
use crate::stylesheets::origin::OriginSet;
|
||||||
use crate::{Atom, WeakAtom};
|
use crate::{Atom, WeakAtom};
|
||||||
use selectors::attr::CaseSensitivity;
|
use selectors::attr::CaseSensitivity;
|
||||||
use selectors::matching::matches_selector;
|
use selectors::matching::matches_selector;
|
||||||
|
@ -246,7 +246,7 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
let document_origins = if !matches_document_author_rules {
|
let document_origins = if !matches_document_author_rules {
|
||||||
Origin::UserAgent.into()
|
OriginSet::ORIGIN_USER_AGENT | OriginSet::ORIGIN_USER
|
||||||
} else {
|
} else {
|
||||||
OriginSet::all()
|
OriginSet::all()
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,16 +26,48 @@ pub enum InlineBaseDirection {
|
||||||
// TODO: improve the readability of the WritingMode serialization, refer to the Debug:fmt()
|
// TODO: improve the readability of the WritingMode serialization, refer to the Debug:fmt()
|
||||||
bitflags!(
|
bitflags!(
|
||||||
#[cfg_attr(feature = "servo", derive(MallocSizeOf, Serialize))]
|
#[cfg_attr(feature = "servo", derive(MallocSizeOf, Serialize))]
|
||||||
|
#[repr(C)]
|
||||||
pub struct WritingMode: u8 {
|
pub struct WritingMode: u8 {
|
||||||
const RTL = 1 << 0;
|
/// A vertical writing mode; writing-mode is vertical-rl,
|
||||||
const VERTICAL = 1 << 1;
|
/// vertical-lr, sideways-lr, or sideways-rl.
|
||||||
|
const VERTICAL = 1 << 0;
|
||||||
|
/// The inline flow direction is reversed against the physical
|
||||||
|
/// direction (i.e. right-to-left or bottom-to-top); writing-mode is
|
||||||
|
/// sideways-lr or direction is rtl (but not both).
|
||||||
|
///
|
||||||
|
/// (This bit can be derived from the others, but we store it for
|
||||||
|
/// convenience.)
|
||||||
|
const INLINE_REVERSED = 1 << 1;
|
||||||
|
/// A vertical writing mode whose block progression direction is left-
|
||||||
|
/// to-right; writing-mode is vertical-lr or sideways-lr.
|
||||||
|
///
|
||||||
|
/// Never set without VERTICAL.
|
||||||
const VERTICAL_LR = 1 << 2;
|
const VERTICAL_LR = 1 << 2;
|
||||||
/// For vertical writing modes only. When set, line-over/line-under
|
/// The line-over/line-under sides are inverted with respect to the
|
||||||
/// sides are inverted from block-start/block-end. This flag is
|
/// block-start/block-end edge; writing-mode is vertical-lr.
|
||||||
/// set when sideways-lr is used.
|
///
|
||||||
|
/// Never set without VERTICAL and VERTICAL_LR.
|
||||||
const LINE_INVERTED = 1 << 3;
|
const LINE_INVERTED = 1 << 3;
|
||||||
const SIDEWAYS = 1 << 4;
|
/// direction is rtl.
|
||||||
const UPRIGHT = 1 << 5;
|
const RTL = 1 << 4;
|
||||||
|
/// Horizontal text within a vertical writing mode is displayed sideways
|
||||||
|
/// and runs top-to-bottom or bottom-to-top; set in these cases:
|
||||||
|
///
|
||||||
|
/// * writing-mode: vertical-rl; text-orientation: sideways;
|
||||||
|
/// * writing-mode: vertical-lr; text-orientation: sideways;
|
||||||
|
/// * writing-mode: sideways-rl;
|
||||||
|
/// * writing-mode: sideways-lr;
|
||||||
|
///
|
||||||
|
/// Never set without VERTICAL.
|
||||||
|
const SIDEWAYS = 1 << 5;
|
||||||
|
/// Horizontal text within a vertical writing mode is displayed with each
|
||||||
|
/// glyph upright; set in these cases:
|
||||||
|
///
|
||||||
|
/// * writing-mode: vertical-rl; text-orientation: upright;
|
||||||
|
/// * writing-mode: vertical-lr: text-orientation: upright;
|
||||||
|
///
|
||||||
|
/// Never set without VERTICAL.
|
||||||
|
const UPRIGHT = 1 << 6;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -47,33 +79,52 @@ impl WritingMode {
|
||||||
|
|
||||||
let mut flags = WritingMode::empty();
|
let mut flags = WritingMode::empty();
|
||||||
|
|
||||||
match inheritedbox_style.clone_direction() {
|
let direction = inheritedbox_style.clone_direction();
|
||||||
|
let writing_mode = inheritedbox_style.clone_writing_mode();
|
||||||
|
|
||||||
|
match direction {
|
||||||
Direction::Ltr => {},
|
Direction::Ltr => {},
|
||||||
Direction::Rtl => {
|
Direction::Rtl => {
|
||||||
flags.insert(WritingMode::RTL);
|
flags.insert(WritingMode::RTL);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
match inheritedbox_style.clone_writing_mode() {
|
match writing_mode {
|
||||||
SpecifiedWritingMode::HorizontalTb => {},
|
SpecifiedWritingMode::HorizontalTb => {
|
||||||
|
if direction == Direction::Rtl {
|
||||||
|
flags.insert(WritingMode::INLINE_REVERSED);
|
||||||
|
}
|
||||||
|
},
|
||||||
SpecifiedWritingMode::VerticalRl => {
|
SpecifiedWritingMode::VerticalRl => {
|
||||||
flags.insert(WritingMode::VERTICAL);
|
flags.insert(WritingMode::VERTICAL);
|
||||||
|
if direction == Direction::Rtl {
|
||||||
|
flags.insert(WritingMode::INLINE_REVERSED);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
SpecifiedWritingMode::VerticalLr => {
|
SpecifiedWritingMode::VerticalLr => {
|
||||||
flags.insert(WritingMode::VERTICAL);
|
flags.insert(WritingMode::VERTICAL);
|
||||||
flags.insert(WritingMode::VERTICAL_LR);
|
flags.insert(WritingMode::VERTICAL_LR);
|
||||||
|
flags.insert(WritingMode::LINE_INVERTED);
|
||||||
|
if direction == Direction::Rtl {
|
||||||
|
flags.insert(WritingMode::INLINE_REVERSED);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
SpecifiedWritingMode::SidewaysRl => {
|
SpecifiedWritingMode::SidewaysRl => {
|
||||||
flags.insert(WritingMode::VERTICAL);
|
flags.insert(WritingMode::VERTICAL);
|
||||||
flags.insert(WritingMode::SIDEWAYS);
|
flags.insert(WritingMode::SIDEWAYS);
|
||||||
|
if direction == Direction::Rtl {
|
||||||
|
flags.insert(WritingMode::INLINE_REVERSED);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
SpecifiedWritingMode::SidewaysLr => {
|
SpecifiedWritingMode::SidewaysLr => {
|
||||||
flags.insert(WritingMode::VERTICAL);
|
flags.insert(WritingMode::VERTICAL);
|
||||||
flags.insert(WritingMode::VERTICAL_LR);
|
flags.insert(WritingMode::VERTICAL_LR);
|
||||||
flags.insert(WritingMode::LINE_INVERTED);
|
|
||||||
flags.insert(WritingMode::SIDEWAYS);
|
flags.insert(WritingMode::SIDEWAYS);
|
||||||
|
if direction == Direction::Ltr {
|
||||||
|
flags.insert(WritingMode::INLINE_REVERSED);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,19 +132,21 @@ impl WritingMode {
|
||||||
{
|
{
|
||||||
use crate::properties::longhands::text_orientation::computed_value::T as TextOrientation;
|
use crate::properties::longhands::text_orientation::computed_value::T as TextOrientation;
|
||||||
|
|
||||||
// If FLAG_SIDEWAYS is already set, this means writing-mode is
|
// text-orientation only has an effect for vertical-rl and
|
||||||
// either sideways-rl or sideways-lr, and for both of these values,
|
// vertical-lr values of writing-mode.
|
||||||
// text-orientation has no effect.
|
match writing_mode {
|
||||||
if !flags.intersects(WritingMode::SIDEWAYS) {
|
SpecifiedWritingMode::VerticalRl | SpecifiedWritingMode::VerticalLr => {
|
||||||
match inheritedbox_style.clone_text_orientation() {
|
match inheritedbox_style.clone_text_orientation() {
|
||||||
TextOrientation::Mixed => {},
|
TextOrientation::Mixed => {},
|
||||||
TextOrientation::Upright => {
|
TextOrientation::Upright => {
|
||||||
flags.insert(WritingMode::UPRIGHT);
|
flags.insert(WritingMode::UPRIGHT);
|
||||||
},
|
},
|
||||||
TextOrientation::Sideways => {
|
TextOrientation::Sideways => {
|
||||||
flags.insert(WritingMode::SIDEWAYS);
|
flags.insert(WritingMode::SIDEWAYS);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +168,7 @@ impl WritingMode {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_inline_tb(&self) -> bool {
|
pub fn is_inline_tb(&self) -> bool {
|
||||||
// https://drafts.csswg.org/css-writing-modes-3/#logical-to-physical
|
// https://drafts.csswg.org/css-writing-modes-3/#logical-to-physical
|
||||||
self.intersects(WritingMode::RTL) == self.intersects(WritingMode::LINE_INVERTED)
|
!self.intersects(WritingMode::INLINE_REVERSED)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -44,8 +44,8 @@ pub enum Evaluator {
|
||||||
Integer(MediaFeatureEvaluator<u32>),
|
Integer(MediaFeatureEvaluator<u32>),
|
||||||
Float(MediaFeatureEvaluator<f32>),
|
Float(MediaFeatureEvaluator<f32>),
|
||||||
BoolInteger(MediaFeatureEvaluator<bool>),
|
BoolInteger(MediaFeatureEvaluator<bool>),
|
||||||
/// An integer ratio, such as the one from device-pixel-ratio.
|
/// A non-negative number ratio, such as the one from device-pixel-ratio.
|
||||||
IntRatio(MediaFeatureEvaluator<AspectRatio>),
|
NumberRatio(MediaFeatureEvaluator<AspectRatio>),
|
||||||
/// A resolution.
|
/// A resolution.
|
||||||
Resolution(MediaFeatureEvaluator<Resolution>),
|
Resolution(MediaFeatureEvaluator<Resolution>),
|
||||||
/// A keyword value.
|
/// A keyword value.
|
||||||
|
|
|
@ -16,6 +16,8 @@ use crate::parser::{Parse, ParserContext};
|
||||||
use crate::servo::media_queries::MEDIA_FEATURES;
|
use crate::servo::media_queries::MEDIA_FEATURES;
|
||||||
use crate::str::{starts_with_ignore_ascii_case, string_as_ascii_lowercase};
|
use crate::str::{starts_with_ignore_ascii_case, string_as_ascii_lowercase};
|
||||||
use crate::values::computed::{self, ToComputedValue};
|
use crate::values::computed::{self, ToComputedValue};
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
use crate::values::specified::NonNegativeNumber;
|
||||||
use crate::values::specified::{Integer, Length, Number, Resolution};
|
use crate::values::specified::{Integer, Length, Number, Resolution};
|
||||||
use crate::values::{serialize_atom_identifier, CSSFloat};
|
use crate::values::{serialize_atom_identifier, CSSFloat};
|
||||||
use crate::{Atom, Zero};
|
use crate::{Atom, Zero};
|
||||||
|
@ -25,8 +27,8 @@ use std::fmt::{self, Write};
|
||||||
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
||||||
|
|
||||||
/// An aspect ratio, with a numerator and denominator.
|
/// An aspect ratio, with a numerator and denominator.
|
||||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
|
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToShmem)]
|
||||||
pub struct AspectRatio(pub u32, pub u32);
|
pub struct AspectRatio(pub CSSFloat, pub CSSFloat);
|
||||||
|
|
||||||
impl ToCss for AspectRatio {
|
impl ToCss for AspectRatio {
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
|
@ -41,9 +43,9 @@ impl ToCss for AspectRatio {
|
||||||
|
|
||||||
impl PartialOrd for AspectRatio {
|
impl PartialOrd for AspectRatio {
|
||||||
fn partial_cmp(&self, other: &AspectRatio) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &AspectRatio) -> Option<Ordering> {
|
||||||
u64::partial_cmp(
|
f64::partial_cmp(
|
||||||
&(self.0 as u64 * other.1 as u64),
|
&(self.0 as f64 * other.1 as f64),
|
||||||
&(self.1 as u64 * other.0 as u64),
|
&(self.1 as f64 * other.0 as f64),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -429,9 +431,11 @@ impl MediaFeatureExpression {
|
||||||
eval(device, expect!(Integer).cloned(), self.range_or_operator)
|
eval(device, expect!(Integer).cloned(), self.range_or_operator)
|
||||||
},
|
},
|
||||||
Evaluator::Float(eval) => eval(device, expect!(Float).cloned(), self.range_or_operator),
|
Evaluator::Float(eval) => eval(device, expect!(Float).cloned(), self.range_or_operator),
|
||||||
Evaluator::IntRatio(eval) => {
|
Evaluator::NumberRatio(eval) => eval(
|
||||||
eval(device, expect!(IntRatio).cloned(), self.range_or_operator)
|
device,
|
||||||
},
|
expect!(NumberRatio).cloned(),
|
||||||
|
self.range_or_operator,
|
||||||
|
),
|
||||||
Evaluator::Resolution(eval) => {
|
Evaluator::Resolution(eval) => {
|
||||||
let computed = expect!(Resolution).map(|specified| {
|
let computed = expect!(Resolution).map(|specified| {
|
||||||
computed::Context::for_media_query_evaluation(device, quirks_mode, |context| {
|
computed::Context::for_media_query_evaluation(device, quirks_mode, |context| {
|
||||||
|
@ -456,7 +460,7 @@ impl MediaFeatureExpression {
|
||||||
/// A value found or expected in a media expression.
|
/// A value found or expected in a media expression.
|
||||||
///
|
///
|
||||||
/// FIXME(emilio): How should calc() serialize in the Number / Integer /
|
/// FIXME(emilio): How should calc() serialize in the Number / Integer /
|
||||||
/// BoolInteger / IntRatio case, as computed or as specified value?
|
/// BoolInteger / NumberRatio case, as computed or as specified value?
|
||||||
///
|
///
|
||||||
/// If the first, this would need to store the relevant values.
|
/// If the first, this would need to store the relevant values.
|
||||||
///
|
///
|
||||||
|
@ -471,9 +475,9 @@ pub enum MediaExpressionValue {
|
||||||
Float(CSSFloat),
|
Float(CSSFloat),
|
||||||
/// A boolean value, specified as an integer (i.e., either 0 or 1).
|
/// A boolean value, specified as an integer (i.e., either 0 or 1).
|
||||||
BoolInteger(bool),
|
BoolInteger(bool),
|
||||||
/// Two integers separated by '/', with optional whitespace on either side
|
/// A single non-negative number or two non-negative numbers separated by '/',
|
||||||
/// of the '/'.
|
/// with optional whitespace on either side of the '/'.
|
||||||
IntRatio(AspectRatio),
|
NumberRatio(AspectRatio),
|
||||||
/// A resolution.
|
/// A resolution.
|
||||||
Resolution(Resolution),
|
Resolution(Resolution),
|
||||||
/// An enumerated value, defined by the variant keyword table in the
|
/// An enumerated value, defined by the variant keyword table in the
|
||||||
|
@ -493,7 +497,7 @@ impl MediaExpressionValue {
|
||||||
MediaExpressionValue::Integer(v) => v.to_css(dest),
|
MediaExpressionValue::Integer(v) => v.to_css(dest),
|
||||||
MediaExpressionValue::Float(v) => v.to_css(dest),
|
MediaExpressionValue::Float(v) => v.to_css(dest),
|
||||||
MediaExpressionValue::BoolInteger(v) => dest.write_str(if v { "1" } else { "0" }),
|
MediaExpressionValue::BoolInteger(v) => dest.write_str(if v { "1" } else { "0" }),
|
||||||
MediaExpressionValue::IntRatio(ratio) => ratio.to_css(dest),
|
MediaExpressionValue::NumberRatio(ratio) => ratio.to_css(dest),
|
||||||
MediaExpressionValue::Resolution(ref r) => r.to_css(dest),
|
MediaExpressionValue::Resolution(ref r) => r.to_css(dest),
|
||||||
MediaExpressionValue::Ident(ref ident) => serialize_atom_identifier(ident, dest),
|
MediaExpressionValue::Ident(ref ident) => serialize_atom_identifier(ident, dest),
|
||||||
MediaExpressionValue::Enumerated(value) => match for_expr.feature().evaluator {
|
MediaExpressionValue::Enumerated(value) => match for_expr.feature().evaluator {
|
||||||
|
@ -529,11 +533,26 @@ impl MediaExpressionValue {
|
||||||
let number = Number::parse(context, input)?;
|
let number = Number::parse(context, input)?;
|
||||||
MediaExpressionValue::Float(number.get())
|
MediaExpressionValue::Float(number.get())
|
||||||
},
|
},
|
||||||
Evaluator::IntRatio(..) => {
|
Evaluator::NumberRatio(..) => {
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
{
|
||||||
|
if static_prefs::pref!("layout.css.aspect-ratio-number.enabled") {
|
||||||
|
let a = NonNegativeNumber::parse(context, input)?.0.get();
|
||||||
|
let b = match input.try_parse(|input| input.expect_delim('/')) {
|
||||||
|
Ok(()) => NonNegativeNumber::parse(context, input)?.0.get(),
|
||||||
|
_ => 1.0,
|
||||||
|
};
|
||||||
|
return Ok(MediaExpressionValue::NumberRatio(AspectRatio(a, b)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let a = Integer::parse_positive(context, input)?;
|
let a = Integer::parse_positive(context, input)?;
|
||||||
input.expect_delim('/')?;
|
input.expect_delim('/')?;
|
||||||
let b = Integer::parse_positive(context, input)?;
|
let b = Integer::parse_positive(context, input)?;
|
||||||
MediaExpressionValue::IntRatio(AspectRatio(a.value() as u32, b.value() as u32))
|
MediaExpressionValue::NumberRatio(AspectRatio(
|
||||||
|
a.value() as CSSFloat,
|
||||||
|
b.value() as CSSFloat,
|
||||||
|
))
|
||||||
},
|
},
|
||||||
Evaluator::Resolution(..) => {
|
Evaluator::Resolution(..) => {
|
||||||
MediaExpressionValue::Resolution(Resolution::parse(context, input)?)
|
MediaExpressionValue::Resolution(Resolution::parse(context, input)?)
|
||||||
|
|
128
components/style/properties/counted_unknown_properties.py
Normal file
128
components/style/properties/counted_unknown_properties.py
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
# 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 http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
# The following properties are under development, so they are not in this list.
|
||||||
|
# FIXME: We should handle the developing properties properly by Bug 1577358:
|
||||||
|
# "backdrop-filter",
|
||||||
|
# "text-decoration-skip-ink",
|
||||||
|
# "column-span",
|
||||||
|
# "offset-distance",
|
||||||
|
# "offset-path",
|
||||||
|
# "offset-rotate"
|
||||||
|
COUNTED_UNKNOWN_PROPERTIES = [
|
||||||
|
"-webkit-font-smoothing",
|
||||||
|
"zoom",
|
||||||
|
"-webkit-tap-highlight-color",
|
||||||
|
"speak",
|
||||||
|
"text-size-adjust",
|
||||||
|
"-webkit-font-feature-settings",
|
||||||
|
"-webkit-user-drag",
|
||||||
|
"size",
|
||||||
|
"-webkit-clip-path",
|
||||||
|
"orphans",
|
||||||
|
"widows",
|
||||||
|
"-webkit-user-modify",
|
||||||
|
"-webkit-margin-before",
|
||||||
|
"-webkit-margin-after",
|
||||||
|
"tab-size",
|
||||||
|
"-webkit-margin-start",
|
||||||
|
"-webkit-column-break-inside",
|
||||||
|
"-webkit-padding-start",
|
||||||
|
"-webkit-margin-end",
|
||||||
|
"-webkit-box-reflect",
|
||||||
|
"-webkit-print-color-adjust",
|
||||||
|
"-webkit-mask-box-image",
|
||||||
|
"-webkit-line-break",
|
||||||
|
"-webkit-text-security",
|
||||||
|
"alignment-baseline",
|
||||||
|
"-webkit-writing-mode",
|
||||||
|
"baseline-shift",
|
||||||
|
"-webkit-hyphenate-character",
|
||||||
|
"page",
|
||||||
|
"text-underline-position",
|
||||||
|
"-webkit-highlight",
|
||||||
|
"background-repeat-x",
|
||||||
|
"-webkit-padding-end",
|
||||||
|
"background-repeat-y",
|
||||||
|
"-webkit-text-emphasis-color",
|
||||||
|
"-webkit-margin-top-collapse",
|
||||||
|
"-webkit-rtl-ordering",
|
||||||
|
"-webkit-padding-before",
|
||||||
|
"-webkit-text-decorations-in-effect",
|
||||||
|
"-webkit-border-vertical-spacing",
|
||||||
|
"-webkit-locale",
|
||||||
|
"-webkit-padding-after",
|
||||||
|
"-webkit-border-horizontal-spacing",
|
||||||
|
"color-rendering",
|
||||||
|
"-webkit-column-break-before",
|
||||||
|
"-webkit-transform-origin-x",
|
||||||
|
"-webkit-transform-origin-y",
|
||||||
|
"-webkit-text-emphasis-position",
|
||||||
|
"buffered-rendering",
|
||||||
|
"-webkit-text-orientation",
|
||||||
|
"-webkit-text-combine",
|
||||||
|
"-webkit-text-emphasis-style",
|
||||||
|
"-webkit-text-emphasis",
|
||||||
|
"d",
|
||||||
|
"-webkit-mask-box-image-width",
|
||||||
|
"-webkit-mask-box-image-source",
|
||||||
|
"-webkit-mask-box-image-outset",
|
||||||
|
"-webkit-mask-box-image-slice",
|
||||||
|
"-webkit-mask-box-image-repeat",
|
||||||
|
"-webkit-margin-after-collapse",
|
||||||
|
"-webkit-border-before-color",
|
||||||
|
"-webkit-border-before-width",
|
||||||
|
"-webkit-perspective-origin-x",
|
||||||
|
"-webkit-perspective-origin-y",
|
||||||
|
"-webkit-margin-before-collapse",
|
||||||
|
"-webkit-border-before-style",
|
||||||
|
"scroll-snap-stop",
|
||||||
|
"-webkit-margin-bottom-collapse",
|
||||||
|
"-webkit-ruby-position",
|
||||||
|
"-webkit-column-break-after",
|
||||||
|
"-webkit-margin-collapse",
|
||||||
|
"offset",
|
||||||
|
"-webkit-border-before",
|
||||||
|
"-webkit-border-end",
|
||||||
|
"-webkit-border-after",
|
||||||
|
"-webkit-border-start",
|
||||||
|
"-webkit-min-logical-width",
|
||||||
|
"-webkit-logical-height",
|
||||||
|
"-webkit-transform-origin-z",
|
||||||
|
"-webkit-font-size-delta",
|
||||||
|
"-webkit-logical-width",
|
||||||
|
"-webkit-max-logical-width",
|
||||||
|
"-webkit-min-logical-height",
|
||||||
|
"-webkit-max-logical-height",
|
||||||
|
"-webkit-border-end-color",
|
||||||
|
"-webkit-border-end-width",
|
||||||
|
"-webkit-border-start-color",
|
||||||
|
"-webkit-border-start-width",
|
||||||
|
"-webkit-border-after-color",
|
||||||
|
"-webkit-border-after-width",
|
||||||
|
"-webkit-border-end-style",
|
||||||
|
"-webkit-border-after-style",
|
||||||
|
"-webkit-border-start-style",
|
||||||
|
"-webkit-mask-repeat-x",
|
||||||
|
"-webkit-mask-repeat-y",
|
||||||
|
"user-zoom",
|
||||||
|
"min-zoom",
|
||||||
|
"-webkit-box-decoration-break",
|
||||||
|
"orientation",
|
||||||
|
"max-zoom",
|
||||||
|
"-webkit-app-region",
|
||||||
|
"-webkit-column-rule",
|
||||||
|
"-webkit-column-span",
|
||||||
|
"-webkit-column-gap",
|
||||||
|
"-webkit-shape-outside",
|
||||||
|
"-webkit-column-rule-width",
|
||||||
|
"-webkit-column-count",
|
||||||
|
"-webkit-opacity",
|
||||||
|
"-webkit-column-width",
|
||||||
|
"-webkit-shape-image-threshold",
|
||||||
|
"-webkit-column-rule-style",
|
||||||
|
"-webkit-columns",
|
||||||
|
"-webkit-column-rule-color",
|
||||||
|
"-webkit-shape-margin",
|
||||||
|
]
|
|
@ -3,6 +3,7 @@
|
||||||
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
from counted_unknown_properties import COUNTED_UNKNOWN_PROPERTIES
|
||||||
|
|
||||||
PHYSICAL_SIDES = ["top", "right", "bottom", "left"]
|
PHYSICAL_SIDES = ["top", "right", "bottom", "left"]
|
||||||
LOGICAL_SIDES = ["block-start", "block-end", "inline-start", "inline-end"]
|
LOGICAL_SIDES = ["block-start", "block-end", "inline-start", "inline-end"]
|
||||||
|
@ -574,6 +575,7 @@ class PropertiesData(object):
|
||||||
self.shorthands = []
|
self.shorthands = []
|
||||||
self.shorthands_by_name = {}
|
self.shorthands_by_name = {}
|
||||||
self.shorthand_aliases = []
|
self.shorthand_aliases = []
|
||||||
|
self.counted_unknown_properties = [CountedUnknownProperty(p) for p in COUNTED_UNKNOWN_PROPERTIES]
|
||||||
|
|
||||||
def new_style_struct(self, *args, **kwargs):
|
def new_style_struct(self, *args, **kwargs):
|
||||||
style_struct = StyleStruct(*args, **kwargs)
|
style_struct = StyleStruct(*args, **kwargs)
|
||||||
|
@ -794,3 +796,10 @@ class PropertyRestrictions:
|
||||||
+ PropertyRestrictions.shorthand(data, "background")
|
+ PropertyRestrictions.shorthand(data, "background")
|
||||||
+ PropertyRestrictions.shorthand(data, "outline")
|
+ PropertyRestrictions.shorthand(data, "outline")
|
||||||
+ PropertyRestrictions.shorthand(data, "font"))
|
+ PropertyRestrictions.shorthand(data, "font"))
|
||||||
|
|
||||||
|
|
||||||
|
class CountedUnknownProperty:
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
self.ident = to_rust_ident(name)
|
||||||
|
self.camel_case = to_camel_case(self.ident)
|
||||||
|
|
|
@ -6,34 +6,36 @@
|
||||||
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
|
use super::*;
|
||||||
use crate::context::QuirksMode;
|
use crate::context::QuirksMode;
|
||||||
use cssparser::{DeclarationListParser, parse_important, ParserInput, CowRcStr};
|
use crate::custom_properties::{CssEnvironment, CustomPropertiesBuilder};
|
||||||
use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter, ParseErrorKind};
|
use crate::error_reporting::{ContextualParseError, ParseErrorReporter};
|
||||||
use crate::custom_properties::{CustomPropertiesBuilder, CssEnvironment};
|
|
||||||
use crate::error_reporting::{ParseErrorReporter, ContextualParseError};
|
|
||||||
use itertools::Itertools;
|
|
||||||
use crate::parser::ParserContext;
|
use crate::parser::ParserContext;
|
||||||
use crate::properties::animated_properties::{AnimationValue, AnimationValueMap};
|
use crate::properties::animated_properties::{AnimationValue, AnimationValueMap};
|
||||||
|
use crate::selector_parser::SelectorImpl;
|
||||||
use crate::shared_lock::Locked;
|
use crate::shared_lock::Locked;
|
||||||
|
use crate::str::{CssString, CssStringBorrow, CssStringWriter};
|
||||||
|
use crate::stylesheets::{CssRuleType, Origin, UrlExtraData};
|
||||||
|
use crate::values::computed::Context;
|
||||||
|
use cssparser::{parse_important, CowRcStr, DeclarationListParser, ParserInput};
|
||||||
|
use cssparser::{AtRuleParser, DeclarationParser, Delimiter, ParseErrorKind, Parser};
|
||||||
|
use itertools::Itertools;
|
||||||
|
use selectors::SelectorList;
|
||||||
use smallbitvec::{self, SmallBitVec};
|
use smallbitvec::{self, SmallBitVec};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use std::iter::{DoubleEndedIterator, Zip};
|
use std::iter::{DoubleEndedIterator, Zip};
|
||||||
use std::slice::Iter;
|
use std::slice::Iter;
|
||||||
use crate::str::{CssString, CssStringBorrow, CssStringWriter};
|
|
||||||
use style_traits::{CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCss};
|
use style_traits::{CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCss};
|
||||||
use crate::stylesheets::{CssRuleType, Origin, UrlExtraData};
|
|
||||||
use super::*;
|
|
||||||
use crate::values::computed::Context;
|
|
||||||
use crate::selector_parser::SelectorImpl;
|
|
||||||
use selectors::SelectorList;
|
|
||||||
|
|
||||||
/// The animation rules.
|
/// The animation rules.
|
||||||
///
|
///
|
||||||
/// The first one is for Animation cascade level, and the second one is for
|
/// The first one is for Animation cascade level, and the second one is for
|
||||||
/// Transition cascade level.
|
/// Transition cascade level.
|
||||||
pub struct AnimationRules(pub Option<Arc<Locked<PropertyDeclarationBlock>>>,
|
pub struct AnimationRules(
|
||||||
pub Option<Arc<Locked<PropertyDeclarationBlock>>>);
|
pub Option<Arc<Locked<PropertyDeclarationBlock>>>,
|
||||||
|
pub Option<Arc<Locked<PropertyDeclarationBlock>>>,
|
||||||
|
);
|
||||||
|
|
||||||
impl AnimationRules {
|
impl AnimationRules {
|
||||||
/// Returns whether these animation rules represents an actual rule or not.
|
/// Returns whether these animation rules represents an actual rule or not.
|
||||||
|
@ -122,8 +124,16 @@ impl<'a> Iterator for DeclarationImportanceIterator<'a> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
self.iter.next().map(|(decl, important)|
|
self.iter.next().map(|(decl, important)| {
|
||||||
(decl, if important { Importance::Important } else { Importance::Normal }))
|
(
|
||||||
|
decl,
|
||||||
|
if important {
|
||||||
|
Importance::Important
|
||||||
|
} else {
|
||||||
|
Importance::Normal
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -135,13 +145,21 @@ impl<'a> Iterator for DeclarationImportanceIterator<'a> {
|
||||||
impl<'a> DoubleEndedIterator for DeclarationImportanceIterator<'a> {
|
impl<'a> DoubleEndedIterator for DeclarationImportanceIterator<'a> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn next_back(&mut self) -> Option<Self::Item> {
|
fn next_back(&mut self) -> Option<Self::Item> {
|
||||||
self.iter.next_back().map(|(decl, important)|
|
self.iter.next_back().map(|(decl, important)| {
|
||||||
(decl, if important { Importance::Important } else { Importance::Normal }))
|
(
|
||||||
|
decl,
|
||||||
|
if important {
|
||||||
|
Importance::Important
|
||||||
|
} else {
|
||||||
|
Importance::Normal
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterator for AnimationValue to be generated from PropertyDeclarationBlock.
|
/// Iterator for AnimationValue to be generated from PropertyDeclarationBlock.
|
||||||
pub struct AnimationValueIterator<'a, 'cx, 'cx_a:'cx> {
|
pub struct AnimationValueIterator<'a, 'cx, 'cx_a: 'cx> {
|
||||||
iter: DeclarationImportanceIterator<'a>,
|
iter: DeclarationImportanceIterator<'a>,
|
||||||
context: &'cx mut Context<'cx_a>,
|
context: &'cx mut Context<'cx_a>,
|
||||||
default_values: &'a ComputedValues,
|
default_values: &'a ComputedValues,
|
||||||
|
@ -149,7 +167,7 @@ pub struct AnimationValueIterator<'a, 'cx, 'cx_a:'cx> {
|
||||||
extra_custom_properties: Option<&'a Arc<crate::custom_properties::CustomPropertiesMap>>,
|
extra_custom_properties: Option<&'a Arc<crate::custom_properties::CustomPropertiesMap>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'cx, 'cx_a:'cx> AnimationValueIterator<'a, 'cx, 'cx_a> {
|
impl<'a, 'cx, 'cx_a: 'cx> AnimationValueIterator<'a, 'cx, 'cx_a> {
|
||||||
fn new(
|
fn new(
|
||||||
declarations: &'a PropertyDeclarationBlock,
|
declarations: &'a PropertyDeclarationBlock,
|
||||||
context: &'cx mut Context<'cx_a>,
|
context: &'cx mut Context<'cx_a>,
|
||||||
|
@ -165,7 +183,7 @@ impl<'a, 'cx, 'cx_a:'cx> AnimationValueIterator<'a, 'cx, 'cx_a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'cx, 'cx_a:'cx> Iterator for AnimationValueIterator<'a, 'cx, 'cx_a> {
|
impl<'a, 'cx, 'cx_a: 'cx> Iterator for AnimationValueIterator<'a, 'cx, 'cx_a> {
|
||||||
type Item = AnimationValue;
|
type Item = AnimationValue;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
@ -256,7 +274,7 @@ impl PropertyDeclarationBlock {
|
||||||
|
|
||||||
/// Return an iterator of (AnimatableLonghand, AnimationValue).
|
/// Return an iterator of (AnimatableLonghand, AnimationValue).
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_animation_value_iter<'a, 'cx, 'cx_a:'cx>(
|
pub fn to_animation_value_iter<'a, 'cx, 'cx_a: 'cx>(
|
||||||
&'a self,
|
&'a self,
|
||||||
context: &'cx mut Context<'cx_a>,
|
context: &'cx mut Context<'cx_a>,
|
||||||
default_values: &'a ComputedValues,
|
default_values: &'a ComputedValues,
|
||||||
|
@ -300,7 +318,10 @@ impl PropertyDeclarationBlock {
|
||||||
/// NOTE: This is linear time in the case of custom properties or in the
|
/// NOTE: This is linear time in the case of custom properties or in the
|
||||||
/// case the longhand is actually in the declaration block.
|
/// case the longhand is actually in the declaration block.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get(&self, property: PropertyDeclarationId) -> Option<(&PropertyDeclaration, Importance)> {
|
pub fn get(
|
||||||
|
&self,
|
||||||
|
property: PropertyDeclarationId,
|
||||||
|
) -> Option<(&PropertyDeclaration, Importance)> {
|
||||||
if let PropertyDeclarationId::Longhand(id) = property {
|
if let PropertyDeclarationId::Longhand(id) = property {
|
||||||
if !self.contains(id) {
|
if !self.contains(id) {
|
||||||
return None;
|
return None;
|
||||||
|
@ -350,9 +371,7 @@ impl PropertyDeclarationBlock {
|
||||||
// We don't print !important when serializing individual properties,
|
// We don't print !important when serializing individual properties,
|
||||||
// so we treat this as a normal-importance property
|
// so we treat this as a normal-importance property
|
||||||
match shorthand.get_shorthand_appendable_value(list.iter().cloned()) {
|
match shorthand.get_shorthand_appendable_value(list.iter().cloned()) {
|
||||||
Some(appendable_value) => {
|
Some(appendable_value) => append_declaration_value(dest, appendable_value),
|
||||||
append_declaration_value(dest, appendable_value)
|
|
||||||
}
|
|
||||||
None => return Ok(()),
|
None => return Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -360,7 +379,11 @@ impl PropertyDeclarationBlock {
|
||||||
/// Find the value of the given property in this block and serialize it
|
/// Find the value of the given property in this block and serialize it
|
||||||
///
|
///
|
||||||
/// <https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-getpropertyvalue>
|
/// <https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-getpropertyvalue>
|
||||||
pub fn property_value_to_css(&self, property: &PropertyId, dest: &mut CssStringWriter) -> fmt::Result {
|
pub fn property_value_to_css(
|
||||||
|
&self,
|
||||||
|
property: &PropertyId,
|
||||||
|
dest: &mut CssStringWriter,
|
||||||
|
) -> fmt::Result {
|
||||||
// Step 1.1: done when parsing a string to PropertyId
|
// Step 1.1: done when parsing a string to PropertyId
|
||||||
|
|
||||||
// Step 1.2
|
// Step 1.2
|
||||||
|
@ -394,11 +417,12 @@ impl PropertyDeclarationBlock {
|
||||||
} else {
|
} else {
|
||||||
Importance::Normal
|
Importance::Normal
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
Err(longhand_or_custom) => {
|
Err(longhand_or_custom) => {
|
||||||
// Step 3
|
// Step 3
|
||||||
self.get(longhand_or_custom).map_or(Importance::Normal, |(_, importance)| importance)
|
self.get(longhand_or_custom)
|
||||||
}
|
.map_or(Importance::Normal, |(_, importance)| importance)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,7 +431,9 @@ impl PropertyDeclarationBlock {
|
||||||
/// and it doesn't exist in the block, and returns false otherwise.
|
/// and it doesn't exist in the block, and returns false otherwise.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_definitely_new(&self, decl: &PropertyDeclaration) -> bool {
|
fn is_definitely_new(&self, decl: &PropertyDeclaration) -> bool {
|
||||||
decl.id().as_longhand().map_or(false, |id| !self.longhands.contains(id))
|
decl.id()
|
||||||
|
.as_longhand()
|
||||||
|
.map_or(false, |id| !self.longhands.contains(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds or overrides the declaration for a given property in this block.
|
/// Adds or overrides the declaration for a given property in this block.
|
||||||
|
@ -421,11 +447,11 @@ impl PropertyDeclarationBlock {
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let all_shorthand_len = match drain.all_shorthand {
|
let all_shorthand_len = match drain.all_shorthand {
|
||||||
AllShorthand::NotSet => 0,
|
AllShorthand::NotSet => 0,
|
||||||
AllShorthand::CSSWideKeyword(_) |
|
AllShorthand::CSSWideKeyword(_) | AllShorthand::WithVariables(_) => {
|
||||||
AllShorthand::WithVariables(_) => shorthands::ALL_SHORTHAND_MAX_LEN,
|
shorthands::ALL_SHORTHAND_MAX_LEN
|
||||||
|
},
|
||||||
};
|
};
|
||||||
let push_calls_count =
|
let push_calls_count = drain.declarations.len() + all_shorthand_len;
|
||||||
drain.declarations.len() + all_shorthand_len;
|
|
||||||
|
|
||||||
// With deduplication the actual length increase may be less than this.
|
// With deduplication the actual length increase may be less than this.
|
||||||
self.declarations.reserve(push_calls_count);
|
self.declarations.reserve(push_calls_count);
|
||||||
|
@ -434,9 +460,12 @@ impl PropertyDeclarationBlock {
|
||||||
for decl in &mut drain.declarations {
|
for decl in &mut drain.declarations {
|
||||||
changed |= self.push(decl, importance);
|
changed |= self.push(decl, importance);
|
||||||
}
|
}
|
||||||
drain.all_shorthand.declarations().fold(changed, |changed, decl| {
|
drain
|
||||||
changed | self.push(decl, importance)
|
.all_shorthand
|
||||||
})
|
.declarations()
|
||||||
|
.fold(changed, |changed, decl| {
|
||||||
|
changed | self.push(decl, importance)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds or overrides the declaration for a given property in this block.
|
/// Adds or overrides the declaration for a given property in this block.
|
||||||
|
@ -444,11 +473,7 @@ impl PropertyDeclarationBlock {
|
||||||
/// Returns whether the declaration has changed.
|
/// Returns whether the declaration has changed.
|
||||||
///
|
///
|
||||||
/// This is only used for parsing and internal use.
|
/// This is only used for parsing and internal use.
|
||||||
pub fn push(
|
pub fn push(&mut self, declaration: PropertyDeclaration, importance: Importance) -> bool {
|
||||||
&mut self,
|
|
||||||
declaration: PropertyDeclaration,
|
|
||||||
importance: Importance,
|
|
||||||
) -> bool {
|
|
||||||
if !self.is_definitely_new(&declaration) {
|
if !self.is_definitely_new(&declaration) {
|
||||||
let mut index_to_remove = None;
|
let mut index_to_remove = None;
|
||||||
for (i, slot) in self.declarations.iter_mut().enumerate() {
|
for (i, slot) in self.declarations.iter_mut().enumerate() {
|
||||||
|
@ -498,78 +523,92 @@ impl PropertyDeclarationBlock {
|
||||||
// Check whether we are updating for an all shorthand change.
|
// Check whether we are updating for an all shorthand change.
|
||||||
if !matches!(source_declarations.all_shorthand, AllShorthand::NotSet) {
|
if !matches!(source_declarations.all_shorthand, AllShorthand::NotSet) {
|
||||||
debug_assert!(source_declarations.declarations.is_empty());
|
debug_assert!(source_declarations.declarations.is_empty());
|
||||||
return source_declarations.all_shorthand.declarations().any(|decl| {
|
return source_declarations
|
||||||
self.is_definitely_new(&decl) ||
|
.all_shorthand
|
||||||
self.declarations.iter().enumerate()
|
.declarations()
|
||||||
.find(|&(_, ref d)| d.id() == decl.id())
|
.any(|decl| {
|
||||||
.map_or(true, |(i, d)| {
|
self.is_definitely_new(&decl) ||
|
||||||
let important = self.declarations_importance[i];
|
self.declarations
|
||||||
*d != decl || important != importance.important()
|
.iter()
|
||||||
})
|
.enumerate()
|
||||||
});
|
.find(|&(_, ref d)| d.id() == decl.id())
|
||||||
|
.map_or(true, |(i, d)| {
|
||||||
|
let important = self.declarations_importance[i];
|
||||||
|
*d != decl || important != importance.important()
|
||||||
|
})
|
||||||
|
});
|
||||||
}
|
}
|
||||||
// Fill `updates` with update information.
|
// Fill `updates` with update information.
|
||||||
let mut any_update = false;
|
let mut any_update = false;
|
||||||
let new_count = &mut updates.new_count;
|
let new_count = &mut updates.new_count;
|
||||||
let any_removal = &mut updates.any_removal;
|
let any_removal = &mut updates.any_removal;
|
||||||
let updates = &mut updates.updates;
|
let updates = &mut updates.updates;
|
||||||
updates.extend(source_declarations.declarations.iter().map(|declaration| {
|
updates.extend(
|
||||||
if self.is_definitely_new(declaration) {
|
source_declarations
|
||||||
return DeclarationUpdate::Append;
|
.declarations
|
||||||
}
|
.iter()
|
||||||
let longhand_id = declaration.id().as_longhand();
|
.map(|declaration| {
|
||||||
if let Some(longhand_id) = longhand_id {
|
if self.is_definitely_new(declaration) {
|
||||||
if let Some(logical_group) = longhand_id.logical_group() {
|
return DeclarationUpdate::Append;
|
||||||
let mut needs_append = false;
|
}
|
||||||
for (pos, decl) in self.declarations.iter().enumerate().rev() {
|
let longhand_id = declaration.id().as_longhand();
|
||||||
let id = match decl.id().as_longhand() {
|
if let Some(longhand_id) = longhand_id {
|
||||||
Some(id) => id,
|
if let Some(logical_group) = longhand_id.logical_group() {
|
||||||
None => continue,
|
let mut needs_append = false;
|
||||||
};
|
for (pos, decl) in self.declarations.iter().enumerate().rev() {
|
||||||
if id == longhand_id {
|
let id = match decl.id().as_longhand() {
|
||||||
if needs_append {
|
Some(id) => id,
|
||||||
return DeclarationUpdate::AppendAndRemove { pos };
|
None => continue,
|
||||||
|
};
|
||||||
|
if id == longhand_id {
|
||||||
|
if needs_append {
|
||||||
|
return DeclarationUpdate::AppendAndRemove { pos };
|
||||||
|
}
|
||||||
|
let important = self.declarations_importance[pos];
|
||||||
|
if decl == declaration && important == importance.important() {
|
||||||
|
return DeclarationUpdate::None;
|
||||||
|
}
|
||||||
|
return DeclarationUpdate::UpdateInPlace { pos };
|
||||||
|
}
|
||||||
|
if !needs_append &&
|
||||||
|
id.logical_group() == Some(logical_group) &&
|
||||||
|
id.is_logical() != longhand_id.is_logical()
|
||||||
|
{
|
||||||
|
needs_append = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
unreachable!("Longhand should be found in loop above");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.declarations
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find(|&(_, ref decl)| decl.id() == declaration.id())
|
||||||
|
.map_or(DeclarationUpdate::Append, |(pos, decl)| {
|
||||||
let important = self.declarations_importance[pos];
|
let important = self.declarations_importance[pos];
|
||||||
if decl == declaration && important == importance.important() {
|
if decl == declaration && important == importance.important() {
|
||||||
return DeclarationUpdate::None;
|
DeclarationUpdate::None
|
||||||
|
} else {
|
||||||
|
DeclarationUpdate::UpdateInPlace { pos }
|
||||||
}
|
}
|
||||||
return DeclarationUpdate::UpdateInPlace { pos };
|
})
|
||||||
}
|
|
||||||
if !needs_append &&
|
|
||||||
id.logical_group() == Some(logical_group) &&
|
|
||||||
id.is_logical() != longhand_id.is_logical() {
|
|
||||||
needs_append = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unreachable!("Longhand should be found in loop above");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.declarations.iter().enumerate()
|
|
||||||
.find(|&(_, ref decl)| decl.id() == declaration.id())
|
|
||||||
.map_or(DeclarationUpdate::Append, |(pos, decl)| {
|
|
||||||
let important = self.declarations_importance[pos];
|
|
||||||
if decl == declaration && important == importance.important() {
|
|
||||||
DeclarationUpdate::None
|
|
||||||
} else {
|
|
||||||
DeclarationUpdate::UpdateInPlace { pos }
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}).inspect(|update| {
|
.inspect(|update| {
|
||||||
if matches!(update, DeclarationUpdate::None) {
|
if matches!(update, DeclarationUpdate::None) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
any_update = true;
|
any_update = true;
|
||||||
match update {
|
match update {
|
||||||
DeclarationUpdate::Append => {
|
DeclarationUpdate::Append => {
|
||||||
*new_count += 1;
|
*new_count += 1;
|
||||||
}
|
},
|
||||||
DeclarationUpdate::AppendAndRemove { .. } => {
|
DeclarationUpdate::AppendAndRemove { .. } => {
|
||||||
*any_removal = true;
|
*any_removal = true;
|
||||||
}
|
},
|
||||||
_ => {}
|
_ => {},
|
||||||
}
|
}
|
||||||
}));
|
}),
|
||||||
|
);
|
||||||
any_update
|
any_update
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,8 +629,12 @@ impl PropertyDeclarationBlock {
|
||||||
self.declarations_importance.push(important);
|
self.declarations_importance.push(important);
|
||||||
self.longhands.insert(longhand_id);
|
self.longhands.insert(longhand_id);
|
||||||
} else {
|
} else {
|
||||||
let (idx, slot) = self.declarations.iter_mut()
|
let (idx, slot) = self
|
||||||
.enumerate().find(|&(_, ref d)| d.id() == decl.id()).unwrap();
|
.declarations
|
||||||
|
.iter_mut()
|
||||||
|
.enumerate()
|
||||||
|
.find(|&(_, ref d)| d.id() == decl.id())
|
||||||
|
.unwrap();
|
||||||
*slot = decl;
|
*slot = decl;
|
||||||
self.declarations_importance.set(idx, important);
|
self.declarations_importance.set(idx, important);
|
||||||
}
|
}
|
||||||
|
@ -607,19 +650,24 @@ impl PropertyDeclarationBlock {
|
||||||
pos: usize,
|
pos: usize,
|
||||||
remove: bool,
|
remove: bool,
|
||||||
}
|
}
|
||||||
let mut updates_and_removals: SubpropertiesVec<UpdateOrRemoval> =
|
let mut updates_and_removals: SubpropertiesVec<UpdateOrRemoval> = updates
|
||||||
updates.updates.iter_mut().filter_map(|item| {
|
.updates
|
||||||
|
.iter_mut()
|
||||||
|
.filter_map(|item| {
|
||||||
let (pos, remove) = match *item {
|
let (pos, remove) = match *item {
|
||||||
DeclarationUpdate::UpdateInPlace { pos } => (pos, false),
|
DeclarationUpdate::UpdateInPlace { pos } => (pos, false),
|
||||||
DeclarationUpdate::AppendAndRemove { pos } => (pos, true),
|
DeclarationUpdate::AppendAndRemove { pos } => (pos, true),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
Some(UpdateOrRemoval { item, pos, remove })
|
Some(UpdateOrRemoval { item, pos, remove })
|
||||||
}).collect();
|
})
|
||||||
|
.collect();
|
||||||
// Execute removals. It's important to do it in reverse index order,
|
// Execute removals. It's important to do it in reverse index order,
|
||||||
// so that removing doesn't invalidate following positions.
|
// so that removing doesn't invalidate following positions.
|
||||||
updates_and_removals.sort_unstable_by_key(|update| update.pos);
|
updates_and_removals.sort_unstable_by_key(|update| update.pos);
|
||||||
updates_and_removals.iter().rev()
|
updates_and_removals
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
.filter(|update| update.remove)
|
.filter(|update| update.remove)
|
||||||
.for_each(|update| {
|
.for_each(|update| {
|
||||||
self.declarations.remove(update.pos);
|
self.declarations.remove(update.pos);
|
||||||
|
@ -637,7 +685,7 @@ impl PropertyDeclarationBlock {
|
||||||
DeclarationUpdate::UpdateInPlace { pos: update.pos }
|
DeclarationUpdate::UpdateInPlace { pos: update.pos }
|
||||||
);
|
);
|
||||||
*update.item = DeclarationUpdate::UpdateInPlace {
|
*update.item = DeclarationUpdate::UpdateInPlace {
|
||||||
pos: update.pos - removed_count
|
pos: update.pos - removed_count,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -645,18 +693,17 @@ impl PropertyDeclarationBlock {
|
||||||
for (decl, update) in drain.declarations.zip_eq(updates.updates.iter()) {
|
for (decl, update) in drain.declarations.zip_eq(updates.updates.iter()) {
|
||||||
match *update {
|
match *update {
|
||||||
DeclarationUpdate::None => {},
|
DeclarationUpdate::None => {},
|
||||||
DeclarationUpdate::Append |
|
DeclarationUpdate::Append | DeclarationUpdate::AppendAndRemove { .. } => {
|
||||||
DeclarationUpdate::AppendAndRemove { .. } => {
|
|
||||||
if let Some(id) = decl.id().as_longhand() {
|
if let Some(id) = decl.id().as_longhand() {
|
||||||
self.longhands.insert(id);
|
self.longhands.insert(id);
|
||||||
}
|
}
|
||||||
self.declarations.push(decl);
|
self.declarations.push(decl);
|
||||||
self.declarations_importance.push(important);
|
self.declarations_importance.push(important);
|
||||||
}
|
},
|
||||||
DeclarationUpdate::UpdateInPlace { pos } => {
|
DeclarationUpdate::UpdateInPlace { pos } => {
|
||||||
self.declarations[pos] = decl;
|
self.declarations[pos] = decl;
|
||||||
self.declarations_importance.set(pos, important);
|
self.declarations_importance.set(pos, important);
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updates.updates.clear();
|
updates.updates.clear();
|
||||||
|
@ -665,19 +712,16 @@ impl PropertyDeclarationBlock {
|
||||||
/// Returns the first declaration that would be removed by removing
|
/// Returns the first declaration that would be removed by removing
|
||||||
/// `property`.
|
/// `property`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn first_declaration_to_remove(
|
pub fn first_declaration_to_remove(&self, property: &PropertyId) -> Option<usize> {
|
||||||
&self,
|
|
||||||
property: &PropertyId,
|
|
||||||
) -> Option<usize> {
|
|
||||||
if let Some(id) = property.longhand_id() {
|
if let Some(id) = property.longhand_id() {
|
||||||
if !self.longhands.contains(id) {
|
if !self.longhands.contains(id) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.declarations.iter().position(|declaration| {
|
self.declarations
|
||||||
declaration.id().is_or_is_longhand_of(property)
|
.iter()
|
||||||
})
|
.position(|declaration| declaration.id().is_or_is_longhand_of(property))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes a given declaration at a given index.
|
/// Removes a given declaration at a given index.
|
||||||
|
@ -698,16 +742,14 @@ impl PropertyDeclarationBlock {
|
||||||
/// `first_declaration` needs to be the result of
|
/// `first_declaration` needs to be the result of
|
||||||
/// `first_declaration_to_remove`.
|
/// `first_declaration_to_remove`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn remove_property(
|
pub fn remove_property(&mut self, property: &PropertyId, first_declaration: usize) {
|
||||||
&mut self,
|
|
||||||
property: &PropertyId,
|
|
||||||
first_declaration: usize,
|
|
||||||
) {
|
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
Some(first_declaration),
|
Some(first_declaration),
|
||||||
self.first_declaration_to_remove(property)
|
self.first_declaration_to_remove(property)
|
||||||
);
|
);
|
||||||
debug_assert!(self.declarations[first_declaration].id().is_or_is_longhand_of(property));
|
debug_assert!(self.declarations[first_declaration]
|
||||||
|
.id()
|
||||||
|
.is_or_is_longhand_of(property));
|
||||||
|
|
||||||
self.remove_declaration_at(first_declaration);
|
self.remove_declaration_at(first_declaration);
|
||||||
|
|
||||||
|
@ -776,16 +818,16 @@ impl PropertyDeclarationBlock {
|
||||||
// getKeyframes() implementation for CSS animations, if
|
// getKeyframes() implementation for CSS animations, if
|
||||||
// |computed_values| is supplied, we use it to expand such variable
|
// |computed_values| is supplied, we use it to expand such variable
|
||||||
// declarations. This will be fixed properly in Gecko bug 1391537.
|
// declarations. This will be fixed properly in Gecko bug 1391537.
|
||||||
(
|
(&PropertyDeclaration::WithVariables(ref declaration), Some(ref _computed_values)) => {
|
||||||
&PropertyDeclaration::WithVariables(ref declaration),
|
declaration
|
||||||
Some(ref _computed_values),
|
.value
|
||||||
) => {
|
.substitute_variables(
|
||||||
declaration.value.substitute_variables(
|
declaration.id,
|
||||||
declaration.id,
|
custom_properties.as_ref(),
|
||||||
custom_properties.as_ref(),
|
QuirksMode::NoQuirks,
|
||||||
QuirksMode::NoQuirks,
|
&env,
|
||||||
&env,
|
)
|
||||||
).to_css(dest)
|
.to_css(dest)
|
||||||
},
|
},
|
||||||
(ref d, _) => d.to_css(dest),
|
(ref d, _) => d.to_css(dest),
|
||||||
}
|
}
|
||||||
|
@ -798,8 +840,8 @@ impl PropertyDeclarationBlock {
|
||||||
let mut longhands = LonghandIdSet::new();
|
let mut longhands = LonghandIdSet::new();
|
||||||
|
|
||||||
for (property, animation_value) in animation_value_map.iter() {
|
for (property, animation_value) in animation_value_map.iter() {
|
||||||
longhands.insert(*property);
|
longhands.insert(*property);
|
||||||
declarations.push(animation_value.uncompute());
|
declarations.push(animation_value.uncompute());
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyDeclarationBlock {
|
PropertyDeclarationBlock {
|
||||||
|
@ -814,13 +856,12 @@ impl PropertyDeclarationBlock {
|
||||||
pub fn has_css_wide_keyword(&self, property: &PropertyId) -> bool {
|
pub fn has_css_wide_keyword(&self, property: &PropertyId) -> bool {
|
||||||
if let Some(id) = property.longhand_id() {
|
if let Some(id) = property.longhand_id() {
|
||||||
if !self.longhands.contains(id) {
|
if !self.longhands.contains(id) {
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.declarations.iter().any(|decl|
|
self.declarations.iter().any(|decl| {
|
||||||
decl.id().is_or_is_longhand_of(property) &&
|
decl.id().is_or_is_longhand_of(property) && decl.get_css_wide_keyword().is_some()
|
||||||
decl.get_css_wide_keyword().is_some()
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a custom properties map which is the result of cascading custom
|
/// Returns a custom properties map which is the result of cascading custom
|
||||||
|
@ -844,10 +885,7 @@ impl PropertyDeclarationBlock {
|
||||||
inherited_custom_properties: Option<&Arc<crate::custom_properties::CustomPropertiesMap>>,
|
inherited_custom_properties: Option<&Arc<crate::custom_properties::CustomPropertiesMap>>,
|
||||||
environment: &CssEnvironment,
|
environment: &CssEnvironment,
|
||||||
) -> Option<Arc<crate::custom_properties::CustomPropertiesMap>> {
|
) -> Option<Arc<crate::custom_properties::CustomPropertiesMap>> {
|
||||||
let mut builder = CustomPropertiesBuilder::new(
|
let mut builder = CustomPropertiesBuilder::new(inherited_custom_properties, environment);
|
||||||
inherited_custom_properties,
|
|
||||||
environment,
|
|
||||||
);
|
|
||||||
|
|
||||||
for declaration in self.normal_declaration_iter() {
|
for declaration in self.normal_declaration_iter() {
|
||||||
if let PropertyDeclaration::Custom(ref declaration) = *declaration {
|
if let PropertyDeclaration::Custom(ref declaration) = *declaration {
|
||||||
|
@ -899,7 +937,7 @@ impl PropertyDeclarationBlock {
|
||||||
&mut is_first_serialization,
|
&mut is_first_serialization,
|
||||||
)?;
|
)?;
|
||||||
continue;
|
continue;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 3.2
|
// Step 3.2
|
||||||
|
@ -928,22 +966,19 @@ impl PropertyDeclarationBlock {
|
||||||
let mut important_count = 0;
|
let mut important_count = 0;
|
||||||
let mut found_system = None;
|
let mut found_system = None;
|
||||||
|
|
||||||
let is_system_font =
|
let is_system_font = shorthand == ShorthandId::Font &&
|
||||||
shorthand == ShorthandId::Font &&
|
self.declarations.iter().any(|l| match l.id() {
|
||||||
self.declarations.iter().any(|l| {
|
PropertyDeclarationId::Longhand(id) => {
|
||||||
match l.id() {
|
if already_serialized.contains(id.into()) {
|
||||||
PropertyDeclarationId::Longhand(id) => {
|
return false;
|
||||||
if already_serialized.contains(id.into()) {
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
l.get_system().is_some()
|
l.get_system().is_some()
|
||||||
}
|
},
|
||||||
PropertyDeclarationId::Custom(..) => {
|
PropertyDeclarationId::Custom(..) => {
|
||||||
debug_assert!(l.get_system().is_none());
|
debug_assert!(l.get_system().is_none());
|
||||||
false
|
false
|
||||||
}
|
},
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if is_system_font {
|
if is_system_font {
|
||||||
|
@ -951,7 +986,7 @@ impl PropertyDeclarationBlock {
|
||||||
if longhand.get_system().is_some() || longhand.is_default_line_height() {
|
if longhand.get_system().is_some() || longhand.is_default_line_height() {
|
||||||
current_longhands.push(longhand);
|
current_longhands.push(longhand);
|
||||||
if found_system.is_none() {
|
if found_system.is_none() {
|
||||||
found_system = longhand.get_system();
|
found_system = longhand.get_system();
|
||||||
}
|
}
|
||||||
if importance.important() {
|
if importance.important() {
|
||||||
important_count += 1;
|
important_count += 1;
|
||||||
|
@ -967,11 +1002,11 @@ impl PropertyDeclarationBlock {
|
||||||
if importance.important() {
|
if importance.important() {
|
||||||
important_count += 1;
|
important_count += 1;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
None => {
|
None => {
|
||||||
contains_all_longhands = false;
|
contains_all_longhands = false;
|
||||||
break;
|
break;
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -994,23 +1029,30 @@ impl PropertyDeclarationBlock {
|
||||||
|
|
||||||
// Substep 5 - Let value be the result of invoking serialize
|
// Substep 5 - Let value be the result of invoking serialize
|
||||||
// a CSS value of current longhands.
|
// a CSS value of current longhands.
|
||||||
let appendable_value =
|
let appendable_value = match shorthand
|
||||||
match shorthand.get_shorthand_appendable_value(current_longhands.iter().cloned()) {
|
.get_shorthand_appendable_value(current_longhands.iter().cloned())
|
||||||
None => continue,
|
{
|
||||||
Some(appendable_value) => appendable_value,
|
None => continue,
|
||||||
};
|
Some(appendable_value) => appendable_value,
|
||||||
|
};
|
||||||
|
|
||||||
// We avoid re-serializing if we're already an
|
// We avoid re-serializing if we're already an
|
||||||
// AppendableValue::Css.
|
// AppendableValue::Css.
|
||||||
let mut v = CssString::new();
|
let mut v = CssString::new();
|
||||||
let value = match (appendable_value, found_system) {
|
let value = match (appendable_value, found_system) {
|
||||||
(AppendableValue::Css { css, with_variables }, _) => {
|
(
|
||||||
|
AppendableValue::Css {
|
||||||
|
css,
|
||||||
|
with_variables,
|
||||||
|
},
|
||||||
|
_,
|
||||||
|
) => {
|
||||||
debug_assert!(!css.is_empty());
|
debug_assert!(!css.is_empty());
|
||||||
AppendableValue::Css {
|
AppendableValue::Css {
|
||||||
css: css,
|
css: css,
|
||||||
with_variables: with_variables,
|
with_variables: with_variables,
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
(_, Some(sys)) => {
|
(_, Some(sys)) => {
|
||||||
sys.to_css(&mut CssWriter::new(&mut v))?;
|
sys.to_css(&mut CssWriter::new(&mut v))?;
|
||||||
|
@ -1018,7 +1060,7 @@ impl PropertyDeclarationBlock {
|
||||||
css: CssStringBorrow::from(&v),
|
css: CssStringBorrow::from(&v),
|
||||||
with_variables: false,
|
with_variables: false,
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
(other, _) => {
|
(other, _) => {
|
||||||
append_declaration_value(&mut v, other)?;
|
append_declaration_value(&mut v, other)?;
|
||||||
|
|
||||||
|
@ -1031,7 +1073,7 @@ impl PropertyDeclarationBlock {
|
||||||
css: CssStringBorrow::from(&v),
|
css: CssStringBorrow::from(&v),
|
||||||
with_variables: false,
|
with_variables: false,
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Substeps 7 and 8
|
// Substeps 7 and 8
|
||||||
|
@ -1091,7 +1133,8 @@ impl PropertyDeclarationBlock {
|
||||||
/// A convenient enum to represent different kinds of stuff that can represent a
|
/// A convenient enum to represent different kinds of stuff that can represent a
|
||||||
/// _value_ in the serialization of a property declaration.
|
/// _value_ in the serialization of a property declaration.
|
||||||
pub enum AppendableValue<'a, I>
|
pub enum AppendableValue<'a, I>
|
||||||
where I: Iterator<Item=&'a PropertyDeclaration>,
|
where
|
||||||
|
I: Iterator<Item = &'a PropertyDeclaration>,
|
||||||
{
|
{
|
||||||
/// A given declaration, of which we'll serialize just the value.
|
/// A given declaration, of which we'll serialize just the value.
|
||||||
Declaration(&'a PropertyDeclaration),
|
Declaration(&'a PropertyDeclaration),
|
||||||
|
@ -1107,14 +1150,11 @@ pub enum AppendableValue<'a, I>
|
||||||
css: CssStringBorrow<'a>,
|
css: CssStringBorrow<'a>,
|
||||||
/// Whether the original serialization contained variables or not.
|
/// Whether the original serialization contained variables or not.
|
||||||
with_variables: bool,
|
with_variables: bool,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Potentially appends whitespace after the first (property: value;) pair.
|
/// Potentially appends whitespace after the first (property: value;) pair.
|
||||||
fn handle_first_serialization<W>(
|
fn handle_first_serialization<W>(dest: &mut W, is_first_serialization: &mut bool) -> fmt::Result
|
||||||
dest: &mut W,
|
|
||||||
is_first_serialization: &mut bool,
|
|
||||||
) -> fmt::Result
|
|
||||||
where
|
where
|
||||||
W: Write,
|
W: Write,
|
||||||
{
|
{
|
||||||
|
@ -1132,18 +1172,14 @@ pub fn append_declaration_value<'a, I>(
|
||||||
appendable_value: AppendableValue<'a, I>,
|
appendable_value: AppendableValue<'a, I>,
|
||||||
) -> fmt::Result
|
) -> fmt::Result
|
||||||
where
|
where
|
||||||
I: Iterator<Item=&'a PropertyDeclaration>,
|
I: Iterator<Item = &'a PropertyDeclaration>,
|
||||||
{
|
{
|
||||||
match appendable_value {
|
match appendable_value {
|
||||||
AppendableValue::Css { css, .. } => {
|
AppendableValue::Css { css, .. } => css.append_to(dest),
|
||||||
css.append_to(dest)
|
AppendableValue::Declaration(decl) => decl.to_css(dest),
|
||||||
},
|
|
||||||
AppendableValue::Declaration(decl) => {
|
|
||||||
decl.to_css(dest)
|
|
||||||
},
|
|
||||||
AppendableValue::DeclarationsForShorthand(shorthand, decls) => {
|
AppendableValue::DeclarationsForShorthand(shorthand, decls) => {
|
||||||
shorthand.longhands_to_css(decls, &mut CssWriter::new(dest))
|
shorthand.longhands_to_css(decls, &mut CssWriter::new(dest))
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1153,10 +1189,10 @@ pub fn append_serialization<'a, I, N>(
|
||||||
property_name: &N,
|
property_name: &N,
|
||||||
appendable_value: AppendableValue<'a, I>,
|
appendable_value: AppendableValue<'a, I>,
|
||||||
importance: Importance,
|
importance: Importance,
|
||||||
is_first_serialization: &mut bool
|
is_first_serialization: &mut bool,
|
||||||
) -> fmt::Result
|
) -> fmt::Result
|
||||||
where
|
where
|
||||||
I: Iterator<Item=&'a PropertyDeclaration>,
|
I: Iterator<Item = &'a PropertyDeclaration>,
|
||||||
N: ToCss,
|
N: ToCss,
|
||||||
{
|
{
|
||||||
handle_first_serialization(dest, is_first_serialization)?;
|
handle_first_serialization(dest, is_first_serialization)?;
|
||||||
|
@ -1176,7 +1212,7 @@ where
|
||||||
if !with_variables {
|
if !with_variables {
|
||||||
dest.write_str(" ")?
|
dest.write_str(" ")?
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
// Currently append_serialization is only called with a Css or
|
// Currently append_serialization is only called with a Css or
|
||||||
// a Declaration AppendableValue.
|
// a Declaration AppendableValue.
|
||||||
AppendableValue::DeclarationsForShorthand(..) => unreachable!(),
|
AppendableValue::DeclarationsForShorthand(..) => unreachable!(),
|
||||||
|
@ -1228,7 +1264,7 @@ pub fn parse_one_declaration_into(
|
||||||
url_data: &UrlExtraData,
|
url_data: &UrlExtraData,
|
||||||
error_reporter: Option<&dyn ParseErrorReporter>,
|
error_reporter: Option<&dyn ParseErrorReporter>,
|
||||||
parsing_mode: ParsingMode,
|
parsing_mode: ParsingMode,
|
||||||
quirks_mode: QuirksMode
|
quirks_mode: QuirksMode,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ()> {
|
||||||
let context = ParserContext::new(
|
let context = ParserContext::new(
|
||||||
Origin::Author,
|
Origin::Author,
|
||||||
|
@ -1249,20 +1285,22 @@ pub fn parse_one_declaration_into(
|
||||||
let mut input = ParserInput::new(input);
|
let mut input = ParserInput::new(input);
|
||||||
let mut parser = Parser::new(&mut input);
|
let mut parser = Parser::new(&mut input);
|
||||||
let start_position = parser.position();
|
let start_position = parser.position();
|
||||||
parser.parse_entirely(|parser| {
|
parser
|
||||||
PropertyDeclaration::parse_into(declarations, id, &context, parser)
|
.parse_entirely(|parser| {
|
||||||
}).map_err(|err| {
|
PropertyDeclaration::parse_into(declarations, id, &context, parser)
|
||||||
if context.error_reporting_enabled() {
|
})
|
||||||
report_one_css_error(
|
.map_err(|err| {
|
||||||
&context,
|
if context.error_reporting_enabled() {
|
||||||
None,
|
report_one_css_error(
|
||||||
None,
|
&context,
|
||||||
err,
|
None,
|
||||||
parser.slice_from(start_position),
|
None,
|
||||||
property_id_for_error_reporting,
|
err,
|
||||||
)
|
parser.slice_from(start_position),
|
||||||
}
|
property_id_for_error_reporting,
|
||||||
})
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A struct to parse property declarations.
|
/// A struct to parse property declarations.
|
||||||
|
@ -1273,7 +1311,6 @@ struct PropertyDeclarationParser<'a, 'b: 'a> {
|
||||||
last_parsed_property_id: Option<PropertyId>,
|
last_parsed_property_id: Option<PropertyId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Default methods reject all at rules.
|
/// Default methods reject all at rules.
|
||||||
impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b> {
|
impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b> {
|
||||||
type PreludeNoBlock = ();
|
type PreludeNoBlock = ();
|
||||||
|
@ -1284,8 +1321,7 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b> {
|
||||||
|
|
||||||
/// Based on NonMozillaVendorIdentifier from Gecko's CSS parser.
|
/// Based on NonMozillaVendorIdentifier from Gecko's CSS parser.
|
||||||
fn is_non_mozilla_vendor_identifier(name: &str) -> bool {
|
fn is_non_mozilla_vendor_identifier(name: &str) -> bool {
|
||||||
(name.starts_with("-") && !name.starts_with("-moz-")) ||
|
(name.starts_with("-") && !name.starts_with("-moz-")) || name.starts_with("_")
|
||||||
name.starts_with("_")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b> {
|
impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b> {
|
||||||
|
@ -1301,10 +1337,8 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b> {
|
||||||
Ok(id) => id,
|
Ok(id) => id,
|
||||||
Err(..) => {
|
Err(..) => {
|
||||||
self.last_parsed_property_id = None;
|
self.last_parsed_property_id = None;
|
||||||
return Err(input.new_custom_error(
|
return Err(input.new_custom_error(StyleParseErrorKind::UnknownProperty(name)));
|
||||||
StyleParseErrorKind::UnknownProperty(name)
|
},
|
||||||
));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
if self.context.error_reporting_enabled() {
|
if self.context.error_reporting_enabled() {
|
||||||
self.last_parsed_property_id = Some(id.clone());
|
self.last_parsed_property_id = Some(id.clone());
|
||||||
|
@ -1344,10 +1378,8 @@ fn report_one_css_error<'i>(
|
||||||
|
|
||||||
fn all_properties_in_block(block: &PropertyDeclarationBlock, property: &PropertyId) -> bool {
|
fn all_properties_in_block(block: &PropertyDeclarationBlock, property: &PropertyId) -> bool {
|
||||||
match *property {
|
match *property {
|
||||||
PropertyId::LonghandAlias(id, _) |
|
PropertyId::LonghandAlias(id, _) | PropertyId::Longhand(id) => block.contains(id),
|
||||||
PropertyId::Longhand(id) => block.contains(id),
|
PropertyId::ShorthandAlias(id, _) | PropertyId::Shorthand(id) => {
|
||||||
PropertyId::ShorthandAlias(id, _) |
|
|
||||||
PropertyId::Shorthand(id) => {
|
|
||||||
id.longhands().all(|longhand| block.contains(longhand))
|
id.longhands().all(|longhand| block.contains(longhand))
|
||||||
},
|
},
|
||||||
// NOTE(emilio): We could do this, but it seems of limited utility,
|
// NOTE(emilio): We could do this, but it seems of limited utility,
|
||||||
|
@ -1382,7 +1414,9 @@ fn report_one_css_error<'i>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
error = match *property {
|
error = match *property {
|
||||||
PropertyId::Custom(ref c) => StyleParseErrorKind::new_invalid(format!("--{}", c), error),
|
PropertyId::Custom(ref c) => {
|
||||||
|
StyleParseErrorKind::new_invalid(format!("--{}", c), error)
|
||||||
|
},
|
||||||
_ => StyleParseErrorKind::new_invalid(property.non_custom_id().unwrap().name(), error),
|
_ => StyleParseErrorKind::new_invalid(property.non_custom_id().unwrap().name(), error),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1409,7 +1443,7 @@ fn report_css_errors(
|
||||||
pub fn parse_property_declaration_list(
|
pub fn parse_property_declaration_list(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser,
|
||||||
selectors: Option<&SelectorList<SelectorImpl>>
|
selectors: Option<&SelectorList<SelectorImpl>>,
|
||||||
) -> PropertyDeclarationBlock {
|
) -> PropertyDeclarationBlock {
|
||||||
let mut declarations = SourcePropertyDeclaration::new();
|
let mut declarations = SourcePropertyDeclaration::new();
|
||||||
let mut block = PropertyDeclarationBlock::new();
|
let mut block = PropertyDeclarationBlock::new();
|
||||||
|
@ -1423,11 +1457,8 @@ pub fn parse_property_declaration_list(
|
||||||
while let Some(declaration) = iter.next() {
|
while let Some(declaration) = iter.next() {
|
||||||
match declaration {
|
match declaration {
|
||||||
Ok(importance) => {
|
Ok(importance) => {
|
||||||
block.extend(
|
block.extend(iter.parser.declarations.drain(), importance);
|
||||||
iter.parser.declarations.drain(),
|
},
|
||||||
importance,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Err((error, slice)) => {
|
Err((error, slice)) => {
|
||||||
iter.parser.declarations.clear();
|
iter.parser.declarations.clear();
|
||||||
|
|
||||||
|
@ -1435,7 +1466,7 @@ pub fn parse_property_declaration_list(
|
||||||
let property = iter.parser.last_parsed_property_id.take();
|
let property = iter.parser.last_parsed_property_id.take();
|
||||||
errors.push((error, slice, property));
|
errors.push((error, slice, property));
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -321,18 +321,6 @@ impl ${style_struct.gecko_struct_name} {
|
||||||
}
|
}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="impl_coord_copy(ident, gecko_ffi_name)">
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
|
||||||
self.gecko.${gecko_ffi_name}.copy_from(&other.gecko.${gecko_ffi_name});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub fn reset_${ident}(&mut self, other: &Self) {
|
|
||||||
self.copy_${ident}_from(other)
|
|
||||||
}
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%!
|
<%!
|
||||||
def get_gecko_property(ffi_name, self_param = "self"):
|
def get_gecko_property(ffi_name, self_param = "self"):
|
||||||
return "%s.gecko.%s" % (self_param, ffi_name)
|
return "%s.gecko.%s" % (self_param, ffi_name)
|
||||||
|
@ -357,10 +345,7 @@ def set_gecko_property(ffi_name, expr):
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="impl_keyword_clone(ident, gecko_ffi_name, keyword, cast_type='u8')">
|
<%def name="impl_keyword_clone(ident, gecko_ffi_name, keyword, cast_type='u8')">
|
||||||
// FIXME: We introduced non_upper_case_globals for -moz-appearance only
|
#[allow(non_snake_case)]
|
||||||
// since the prefix of Gecko value starts with ThemeWidgetType_NS_THEME.
|
|
||||||
// We should remove this after fix bug 1371809.
|
|
||||||
#[allow(non_snake_case, non_upper_case_globals)]
|
|
||||||
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
|
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
|
||||||
use crate::properties::longhands::${ident}::computed_value::T as Keyword;
|
use crate::properties::longhands::${ident}::computed_value::T as Keyword;
|
||||||
// FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts
|
// FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts
|
||||||
|
@ -1146,7 +1131,7 @@ fn static_assert() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_font_size(&mut self, v: FontSize) {
|
pub fn set_font_size(&mut self, v: FontSize) {
|
||||||
use crate::values::generics::font::KeywordSize;
|
use crate::values::specified::font::KeywordSize;
|
||||||
|
|
||||||
let size = v.size();
|
let size = v.size();
|
||||||
self.gecko.mScriptUnconstrainedSize = size.0;
|
self.gecko.mScriptUnconstrainedSize = size.0;
|
||||||
|
@ -1167,7 +1152,7 @@ fn static_assert() {
|
||||||
KeywordSize::XXXLarge => structs::NS_STYLE_FONT_SIZE_XXXLARGE,
|
KeywordSize::XXXLarge => structs::NS_STYLE_FONT_SIZE_XXXLARGE,
|
||||||
} as u8;
|
} as u8;
|
||||||
self.gecko.mFontSizeFactor = info.factor;
|
self.gecko.mFontSizeFactor = info.factor;
|
||||||
self.gecko.mFontSizeOffset = info.offset.0.to_i32_au();
|
self.gecko.mFontSizeOffset = info.offset.to_i32_au();
|
||||||
} else {
|
} else {
|
||||||
self.gecko.mFontSizeKeyword = structs::NS_STYLE_FONT_SIZE_NO_KEYWORD as u8;
|
self.gecko.mFontSizeKeyword = structs::NS_STYLE_FONT_SIZE_NO_KEYWORD as u8;
|
||||||
self.gecko.mFontSizeFactor = 1.;
|
self.gecko.mFontSizeFactor = 1.;
|
||||||
|
@ -1176,7 +1161,7 @@ fn static_assert() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clone_font_size(&self) -> FontSize {
|
pub fn clone_font_size(&self) -> FontSize {
|
||||||
use crate::values::generics::font::{KeywordInfo, KeywordSize};
|
use crate::values::specified::font::{KeywordInfo, KeywordSize};
|
||||||
let size = Au(self.gecko.mSize).into();
|
let size = Au(self.gecko.mSize).into();
|
||||||
let kw = match self.gecko.mFontSizeKeyword as u32 {
|
let kw = match self.gecko.mFontSizeKeyword as u32 {
|
||||||
structs::NS_STYLE_FONT_SIZE_XXSMALL => KeywordSize::XXSmall,
|
structs::NS_STYLE_FONT_SIZE_XXSMALL => KeywordSize::XXSmall,
|
||||||
|
@ -1259,6 +1244,8 @@ fn static_assert() {
|
||||||
|
|
||||||
${impl_simple_type_with_conversion("font_synthesis", "mFont.synthesis")}
|
${impl_simple_type_with_conversion("font_synthesis", "mFont.synthesis")}
|
||||||
|
|
||||||
|
${impl_simple("font_variant_alternates", "mFont.variantAlternates")}
|
||||||
|
|
||||||
pub fn set_font_size_adjust(&mut self, v: longhands::font_size_adjust::computed_value::T) {
|
pub fn set_font_size_adjust(&mut self, v: longhands::font_size_adjust::computed_value::T) {
|
||||||
use crate::properties::longhands::font_size_adjust::computed_value::T;
|
use crate::properties::longhands::font_size_adjust::computed_value::T;
|
||||||
match v {
|
match v {
|
||||||
|
@ -1331,122 +1318,6 @@ fn static_assert() {
|
||||||
${impl_simple("_moz_script_level", "mScriptLevel")}
|
${impl_simple("_moz_script_level", "mScriptLevel")}
|
||||||
<% impl_simple_type_with_conversion("font_language_override", "mFont.languageOverride") %>
|
<% impl_simple_type_with_conversion("font_language_override", "mFont.languageOverride") %>
|
||||||
|
|
||||||
pub fn set_font_variant_alternates(
|
|
||||||
&mut self,
|
|
||||||
v: values::computed::font::FontVariantAlternates,
|
|
||||||
) {
|
|
||||||
use crate::gecko_bindings::bindings::{Gecko_ClearAlternateValues, Gecko_AppendAlternateValues};
|
|
||||||
% for value in "normal swash stylistic ornaments annotation styleset character_variant historical".split():
|
|
||||||
use crate::gecko_bindings::structs::NS_FONT_VARIANT_ALTERNATES_${value.upper()};
|
|
||||||
% endfor
|
|
||||||
use crate::values::specified::font::VariantAlternates;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
Gecko_ClearAlternateValues(&mut self.gecko.mFont, v.len());
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.0.is_empty() {
|
|
||||||
self.gecko.mFont.variantAlternates = NS_FONT_VARIANT_ALTERNATES_NORMAL as u16;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for val in v.0.iter() {
|
|
||||||
match *val {
|
|
||||||
% for value in "Swash Stylistic Ornaments Annotation".split():
|
|
||||||
VariantAlternates::${value}(ref ident) => {
|
|
||||||
self.gecko.mFont.variantAlternates |= NS_FONT_VARIANT_ALTERNATES_${value.upper()} as u16;
|
|
||||||
unsafe {
|
|
||||||
Gecko_AppendAlternateValues(&mut self.gecko.mFont,
|
|
||||||
NS_FONT_VARIANT_ALTERNATES_${value.upper()},
|
|
||||||
ident.0.as_ptr());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
% endfor
|
|
||||||
% for value in "styleset character_variant".split():
|
|
||||||
VariantAlternates::${to_camel_case(value)}(ref slice) => {
|
|
||||||
self.gecko.mFont.variantAlternates |= NS_FONT_VARIANT_ALTERNATES_${value.upper()} as u16;
|
|
||||||
for ident in slice.iter() {
|
|
||||||
unsafe {
|
|
||||||
Gecko_AppendAlternateValues(&mut self.gecko.mFont,
|
|
||||||
NS_FONT_VARIANT_ALTERNATES_${value.upper()},
|
|
||||||
ident.0.as_ptr());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
% endfor
|
|
||||||
VariantAlternates::HistoricalForms => {
|
|
||||||
self.gecko.mFont.variantAlternates |= NS_FONT_VARIANT_ALTERNATES_HISTORICAL as u16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub fn copy_font_variant_alternates_from(&mut self, other: &Self) {
|
|
||||||
use crate::gecko_bindings::bindings::Gecko_CopyAlternateValuesFrom;
|
|
||||||
|
|
||||||
self.gecko.mFont.variantAlternates = other.gecko.mFont.variantAlternates;
|
|
||||||
unsafe {
|
|
||||||
Gecko_CopyAlternateValuesFrom(&mut self.gecko.mFont, &other.gecko.mFont);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reset_font_variant_alternates(&mut self, other: &Self) {
|
|
||||||
self.copy_font_variant_alternates_from(other)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clone_font_variant_alternates(&self) -> values::computed::font::FontVariantAlternates {
|
|
||||||
% for value in "normal swash stylistic ornaments annotation styleset character_variant historical".split():
|
|
||||||
use crate::gecko_bindings::structs::NS_FONT_VARIANT_ALTERNATES_${value.upper()};
|
|
||||||
% endfor
|
|
||||||
use crate::values::specified::font::VariantAlternates;
|
|
||||||
use crate::values::specified::font::VariantAlternatesList;
|
|
||||||
use crate::values::CustomIdent;
|
|
||||||
|
|
||||||
if self.gecko.mFont.variantAlternates == NS_FONT_VARIANT_ALTERNATES_NORMAL as u16 {
|
|
||||||
return VariantAlternatesList(vec![].into_boxed_slice());
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut alternates = Vec::with_capacity(self.gecko.mFont.alternateValues.len());
|
|
||||||
if self.gecko.mFont.variantAlternates & (NS_FONT_VARIANT_ALTERNATES_HISTORICAL as u16) != 0 {
|
|
||||||
alternates.push(VariantAlternates::HistoricalForms);
|
|
||||||
}
|
|
||||||
|
|
||||||
<%
|
|
||||||
property_need_ident_list = "styleset character_variant".split()
|
|
||||||
%>
|
|
||||||
% for value in property_need_ident_list:
|
|
||||||
let mut ${value}_list = Vec::new();
|
|
||||||
% endfor
|
|
||||||
|
|
||||||
for gecko_alternate_value in self.gecko.mFont.alternateValues.iter() {
|
|
||||||
let ident = Atom::from(gecko_alternate_value.value.to_string());
|
|
||||||
match gecko_alternate_value.alternate {
|
|
||||||
% for value in "Swash Stylistic Ornaments Annotation".split():
|
|
||||||
NS_FONT_VARIANT_ALTERNATES_${value.upper()} => {
|
|
||||||
alternates.push(VariantAlternates::${value}(CustomIdent(ident)));
|
|
||||||
},
|
|
||||||
% endfor
|
|
||||||
% for value in property_need_ident_list:
|
|
||||||
NS_FONT_VARIANT_ALTERNATES_${value.upper()} => {
|
|
||||||
${value}_list.push(CustomIdent(ident));
|
|
||||||
},
|
|
||||||
% endfor
|
|
||||||
_ => {
|
|
||||||
panic!("Found unexpected value for font-variant-alternates");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
% for value in property_need_ident_list:
|
|
||||||
if !${value}_list.is_empty() {
|
|
||||||
alternates.push(VariantAlternates::${to_camel_case(value)}(${value}_list.into_boxed_slice()));
|
|
||||||
}
|
|
||||||
% endfor
|
|
||||||
|
|
||||||
VariantAlternatesList(alternates.into_boxed_slice())
|
|
||||||
}
|
|
||||||
|
|
||||||
${impl_simple_type_with_conversion("font_variant_ligatures", "mFont.variantLigatures")}
|
${impl_simple_type_with_conversion("font_variant_ligatures", "mFont.variantLigatures")}
|
||||||
${impl_simple_type_with_conversion("font_variant_east_asian", "mFont.variantEastAsian")}
|
${impl_simple_type_with_conversion("font_variant_east_asian", "mFont.variantEastAsian")}
|
||||||
${impl_simple_type_with_conversion("font_variant_numeric", "mFont.variantNumeric")}
|
${impl_simple_type_with_conversion("font_variant_numeric", "mFont.variantNumeric")}
|
||||||
|
@ -2291,7 +2162,7 @@ fn static_assert() {
|
||||||
</%self:impl_trait>
|
</%self:impl_trait>
|
||||||
|
|
||||||
<%self:impl_trait style_struct_name="List"
|
<%self:impl_trait style_struct_name="List"
|
||||||
skip_longhands="list-style-image list-style-type -moz-image-region">
|
skip_longhands="list-style-image list-style-type">
|
||||||
|
|
||||||
pub fn set_list_style_image(&mut self, image: longhands::list_style_image::computed_value::T) {
|
pub fn set_list_style_image(&mut self, image: longhands::list_style_image::computed_value::T) {
|
||||||
match image {
|
match image {
|
||||||
|
@ -2328,10 +2199,15 @@ fn static_assert() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_list_style_type(&mut self, v: longhands::list_style_type::computed_value::T) {
|
pub fn set_list_style_type(&mut self, v: longhands::list_style_type::computed_value::T) {
|
||||||
|
use crate::gecko_bindings::bindings::Gecko_SetCounterStyleToName;
|
||||||
use crate::gecko_bindings::bindings::Gecko_SetCounterStyleToString;
|
use crate::gecko_bindings::bindings::Gecko_SetCounterStyleToString;
|
||||||
use nsstring::{nsACString, nsCStr};
|
use nsstring::{nsACString, nsCStr};
|
||||||
use self::longhands::list_style_type::computed_value::T;
|
use self::longhands::list_style_type::computed_value::T;
|
||||||
match v {
|
match v {
|
||||||
|
T::None => unsafe {
|
||||||
|
Gecko_SetCounterStyleToName(&mut self.gecko.mCounterStyle,
|
||||||
|
atom!("none").into_addrefed());
|
||||||
|
}
|
||||||
T::CounterStyle(s) => s.to_gecko_value(&mut self.gecko.mCounterStyle),
|
T::CounterStyle(s) => s.to_gecko_value(&mut self.gecko.mCounterStyle),
|
||||||
T::String(s) => unsafe {
|
T::String(s) => unsafe {
|
||||||
Gecko_SetCounterStyleToString(&mut self.gecko.mCounterStyle,
|
Gecko_SetCounterStyleToString(&mut self.gecko.mCounterStyle,
|
||||||
|
@ -2353,199 +2229,30 @@ fn static_assert() {
|
||||||
pub fn clone_list_style_type(&self) -> longhands::list_style_type::computed_value::T {
|
pub fn clone_list_style_type(&self) -> longhands::list_style_type::computed_value::T {
|
||||||
use self::longhands::list_style_type::computed_value::T;
|
use self::longhands::list_style_type::computed_value::T;
|
||||||
use crate::values::Either;
|
use crate::values::Either;
|
||||||
use crate::values::generics::CounterStyleOrNone;
|
use crate::values::generics::CounterStyle;
|
||||||
|
use crate::gecko_bindings::bindings;
|
||||||
|
|
||||||
let result = CounterStyleOrNone::from_gecko_value(&self.gecko.mCounterStyle);
|
let name = unsafe {
|
||||||
|
bindings::Gecko_CounterStyle_GetName(&self.gecko.mCounterStyle)
|
||||||
|
};
|
||||||
|
if !name.is_null() {
|
||||||
|
let name = unsafe { Atom::from_raw(name) };
|
||||||
|
if name == atom!("none") {
|
||||||
|
return T::None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let result = CounterStyle::from_gecko_value(&self.gecko.mCounterStyle);
|
||||||
match result {
|
match result {
|
||||||
Either::First(counter_style) => T::CounterStyle(counter_style),
|
Either::First(counter_style) => T::CounterStyle(counter_style),
|
||||||
Either::Second(string) => T::String(string),
|
Either::Second(string) => T::String(string),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub fn set__moz_image_region(&mut self, v: longhands::_moz_image_region::computed_value::T) {
|
|
||||||
use crate::values::Either;
|
|
||||||
use crate::values::generics::length::LengthPercentageOrAuto::*;
|
|
||||||
|
|
||||||
match v {
|
|
||||||
Either::Second(_auto) => {
|
|
||||||
self.gecko.mImageRegion.x = 0;
|
|
||||||
self.gecko.mImageRegion.y = 0;
|
|
||||||
self.gecko.mImageRegion.width = 0;
|
|
||||||
self.gecko.mImageRegion.height = 0;
|
|
||||||
}
|
|
||||||
Either::First(rect) => {
|
|
||||||
self.gecko.mImageRegion.x = match rect.left {
|
|
||||||
LengthPercentage(v) => v.to_i32_au(),
|
|
||||||
Auto => 0,
|
|
||||||
};
|
|
||||||
self.gecko.mImageRegion.y = match rect.top {
|
|
||||||
LengthPercentage(v) => v.to_i32_au(),
|
|
||||||
Auto => 0,
|
|
||||||
};
|
|
||||||
self.gecko.mImageRegion.height = match rect.bottom {
|
|
||||||
LengthPercentage(value) => (Au::from(value) - Au(self.gecko.mImageRegion.y)).0,
|
|
||||||
Auto => 0,
|
|
||||||
};
|
|
||||||
self.gecko.mImageRegion.width = match rect.right {
|
|
||||||
LengthPercentage(value) => (Au::from(value) - Au(self.gecko.mImageRegion.x)).0,
|
|
||||||
Auto => 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub fn clone__moz_image_region(&self) -> longhands::_moz_image_region::computed_value::T {
|
|
||||||
use crate::values::{Auto, Either};
|
|
||||||
use crate::values::generics::length::LengthPercentageOrAuto::*;
|
|
||||||
use crate::values::computed::ClipRect;
|
|
||||||
|
|
||||||
// There is no ideal way to detect auto type for structs::nsRect and its components, so
|
|
||||||
// if all components are zero, we use Auto.
|
|
||||||
if self.gecko.mImageRegion.x == 0 &&
|
|
||||||
self.gecko.mImageRegion.y == 0 &&
|
|
||||||
self.gecko.mImageRegion.width == 0 &&
|
|
||||||
self.gecko.mImageRegion.height == 0 {
|
|
||||||
return Either::Second(Auto);
|
|
||||||
}
|
|
||||||
|
|
||||||
Either::First(ClipRect {
|
|
||||||
top: LengthPercentage(Au(self.gecko.mImageRegion.y).into()),
|
|
||||||
right: LengthPercentage(Au(self.gecko.mImageRegion.width + self.gecko.mImageRegion.x).into()),
|
|
||||||
bottom: LengthPercentage(Au(self.gecko.mImageRegion.height + self.gecko.mImageRegion.y).into()),
|
|
||||||
left: LengthPercentage(Au(self.gecko.mImageRegion.x).into()),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
${impl_simple_copy('_moz_image_region', 'mImageRegion')}
|
|
||||||
|
|
||||||
</%self:impl_trait>
|
</%self:impl_trait>
|
||||||
|
|
||||||
<%self:impl_trait style_struct_name="Table" skip_longhands="-x-span">
|
<%self:impl_trait style_struct_name="Table">
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub fn set__x_span(&mut self, v: longhands::_x_span::computed_value::T) {
|
|
||||||
self.gecko.mSpan = v.0
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub fn clone__x_span(&self) -> longhands::_x_span::computed_value::T {
|
|
||||||
longhands::_x_span::computed_value::T(
|
|
||||||
self.gecko.mSpan
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
${impl_simple_copy('_x_span', 'mSpan')}
|
|
||||||
</%self:impl_trait>
|
</%self:impl_trait>
|
||||||
|
|
||||||
<%self:impl_trait style_struct_name="Effects" skip_longhands="clip">
|
<%self:impl_trait style_struct_name="Effects">
|
||||||
pub fn set_clip(&mut self, v: longhands::clip::computed_value::T) {
|
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CLIP_AUTO;
|
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CLIP_RECT;
|
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CLIP_LEFT_AUTO;
|
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CLIP_TOP_AUTO;
|
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CLIP_RIGHT_AUTO;
|
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CLIP_BOTTOM_AUTO;
|
|
||||||
use crate::values::generics::length::LengthPercentageOrAuto::*;
|
|
||||||
use crate::values::Either;
|
|
||||||
|
|
||||||
match v {
|
|
||||||
Either::First(rect) => {
|
|
||||||
self.gecko.mClipFlags = NS_STYLE_CLIP_RECT as u8;
|
|
||||||
self.gecko.mClip.x = match rect.left {
|
|
||||||
LengthPercentage(l) => l.to_i32_au(),
|
|
||||||
Auto => {
|
|
||||||
self.gecko.mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO as u8;
|
|
||||||
0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.gecko.mClip.y = match rect.top {
|
|
||||||
LengthPercentage(l) => l.to_i32_au(),
|
|
||||||
Auto => {
|
|
||||||
self.gecko.mClipFlags |= NS_STYLE_CLIP_TOP_AUTO as u8;
|
|
||||||
0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.gecko.mClip.height = match rect.bottom {
|
|
||||||
LengthPercentage(l) => (Au::from(l) - Au(self.gecko.mClip.y)).0,
|
|
||||||
Auto => {
|
|
||||||
self.gecko.mClipFlags |= NS_STYLE_CLIP_BOTTOM_AUTO as u8;
|
|
||||||
1 << 30 // NS_MAXSIZE
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.gecko.mClip.width = match rect.right {
|
|
||||||
LengthPercentage(l) => (Au::from(l) - Au(self.gecko.mClip.x)).0,
|
|
||||||
Auto => {
|
|
||||||
self.gecko.mClipFlags |= NS_STYLE_CLIP_RIGHT_AUTO as u8;
|
|
||||||
1 << 30 // NS_MAXSIZE
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
Either::Second(_auto) => {
|
|
||||||
self.gecko.mClipFlags = NS_STYLE_CLIP_AUTO as u8;
|
|
||||||
self.gecko.mClip.x = 0;
|
|
||||||
self.gecko.mClip.y = 0;
|
|
||||||
self.gecko.mClip.width = 0;
|
|
||||||
self.gecko.mClip.height = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn copy_clip_from(&mut self, other: &Self) {
|
|
||||||
self.gecko.mClip = other.gecko.mClip;
|
|
||||||
self.gecko.mClipFlags = other.gecko.mClipFlags;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reset_clip(&mut self, other: &Self) {
|
|
||||||
self.copy_clip_from(other)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clone_clip(&self) -> longhands::clip::computed_value::T {
|
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CLIP_AUTO;
|
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CLIP_BOTTOM_AUTO;
|
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CLIP_LEFT_AUTO;
|
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CLIP_RIGHT_AUTO;
|
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CLIP_TOP_AUTO;
|
|
||||||
use crate::values::generics::length::LengthPercentageOrAuto::*;
|
|
||||||
use crate::values::computed::{ClipRect, ClipRectOrAuto};
|
|
||||||
use crate::values::Either;
|
|
||||||
|
|
||||||
if self.gecko.mClipFlags == NS_STYLE_CLIP_AUTO as u8 {
|
|
||||||
return ClipRectOrAuto::auto()
|
|
||||||
}
|
|
||||||
let left = if self.gecko.mClipFlags & NS_STYLE_CLIP_LEFT_AUTO as u8 != 0 {
|
|
||||||
debug_assert_eq!(self.gecko.mClip.x, 0);
|
|
||||||
Auto
|
|
||||||
} else {
|
|
||||||
LengthPercentage(Au(self.gecko.mClip.x).into())
|
|
||||||
};
|
|
||||||
|
|
||||||
let top = if self.gecko.mClipFlags & NS_STYLE_CLIP_TOP_AUTO as u8 != 0 {
|
|
||||||
debug_assert_eq!(self.gecko.mClip.y, 0);
|
|
||||||
Auto
|
|
||||||
} else {
|
|
||||||
LengthPercentage(Au(self.gecko.mClip.y).into())
|
|
||||||
};
|
|
||||||
|
|
||||||
let bottom = if self.gecko.mClipFlags & NS_STYLE_CLIP_BOTTOM_AUTO as u8 != 0 {
|
|
||||||
debug_assert_eq!(self.gecko.mClip.height, 1 << 30); // NS_MAXSIZE
|
|
||||||
Auto
|
|
||||||
} else {
|
|
||||||
LengthPercentage(Au(self.gecko.mClip.y + self.gecko.mClip.height).into())
|
|
||||||
};
|
|
||||||
|
|
||||||
let right = if self.gecko.mClipFlags & NS_STYLE_CLIP_RIGHT_AUTO as u8 != 0 {
|
|
||||||
debug_assert_eq!(self.gecko.mClip.width, 1 << 30); // NS_MAXSIZE
|
|
||||||
Auto
|
|
||||||
} else {
|
|
||||||
LengthPercentage(Au(self.gecko.mClip.x + self.gecko.mClip.width).into())
|
|
||||||
};
|
|
||||||
|
|
||||||
Either::First(ClipRect { top, right, bottom, left })
|
|
||||||
}
|
|
||||||
</%self:impl_trait>
|
</%self:impl_trait>
|
||||||
|
|
||||||
<%self:impl_trait style_struct_name="InheritedBox">
|
<%self:impl_trait style_struct_name="InheritedBox">
|
||||||
|
@ -2725,18 +2432,7 @@ clip-path
|
||||||
</%self:impl_trait>
|
</%self:impl_trait>
|
||||||
|
|
||||||
<%self:impl_trait style_struct_name="InheritedSVG"
|
<%self:impl_trait style_struct_name="InheritedSVG"
|
||||||
skip_longhands="paint-order stroke-dasharray">
|
skip_longhands="stroke-dasharray">
|
||||||
pub fn set_paint_order(&mut self, v: longhands::paint_order::computed_value::T) {
|
|
||||||
self.gecko.mPaintOrder = v.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
${impl_simple_copy('paint_order', 'mPaintOrder')}
|
|
||||||
|
|
||||||
pub fn clone_paint_order(&self) -> longhands::paint_order::computed_value::T {
|
|
||||||
use crate::properties::longhands::paint_order::computed_value::T;
|
|
||||||
T(self.gecko.mPaintOrder)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_stroke_dasharray(&mut self, v: longhands::stroke_dasharray::computed_value::T) {
|
pub fn set_stroke_dasharray(&mut self, v: longhands::stroke_dasharray::computed_value::T) {
|
||||||
use crate::gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE;
|
use crate::gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE;
|
||||||
use crate::values::generics::svg::SVGStrokeDashArray;
|
use crate::values::generics::svg::SVGStrokeDashArray;
|
||||||
|
@ -2883,8 +2579,7 @@ clip-path
|
||||||
${impl_simple('column_rule_style', 'mColumnRuleStyle')}
|
${impl_simple('column_rule_style', 'mColumnRuleStyle')}
|
||||||
</%self:impl_trait>
|
</%self:impl_trait>
|
||||||
|
|
||||||
<%self:impl_trait style_struct_name="Counters"
|
<%self:impl_trait style_struct_name="Counters" skip_longhands="content">
|
||||||
skip_longhands="content counter-increment counter-reset counter-set">
|
|
||||||
pub fn ineffective_content_property(&self) -> bool {
|
pub fn ineffective_content_property(&self) -> bool {
|
||||||
self.gecko.mContents.is_empty()
|
self.gecko.mContents.is_empty()
|
||||||
}
|
}
|
||||||
|
@ -2892,7 +2587,7 @@ clip-path
|
||||||
pub fn set_content(&mut self, v: longhands::content::computed_value::T) {
|
pub fn set_content(&mut self, v: longhands::content::computed_value::T) {
|
||||||
use crate::values::CustomIdent;
|
use crate::values::CustomIdent;
|
||||||
use crate::values::generics::counters::{Content, ContentItem};
|
use crate::values::generics::counters::{Content, ContentItem};
|
||||||
use crate::values::generics::CounterStyleOrNone;
|
use crate::values::generics::CounterStyle;
|
||||||
use crate::gecko_bindings::structs::nsStyleContentData;
|
use crate::gecko_bindings::structs::nsStyleContentData;
|
||||||
use crate::gecko_bindings::structs::nsStyleContentAttr;
|
use crate::gecko_bindings::structs::nsStyleContentAttr;
|
||||||
use crate::gecko_bindings::structs::StyleContentType;
|
use crate::gecko_bindings::structs::StyleContentType;
|
||||||
|
@ -2913,7 +2608,7 @@ clip-path
|
||||||
content_type: StyleContentType,
|
content_type: StyleContentType,
|
||||||
name: CustomIdent,
|
name: CustomIdent,
|
||||||
sep: &str,
|
sep: &str,
|
||||||
style: CounterStyleOrNone,
|
style: CounterStyle,
|
||||||
) {
|
) {
|
||||||
debug_assert!(content_type == StyleContentType::Counter ||
|
debug_assert!(content_type == StyleContentType::Counter ||
|
||||||
content_type == StyleContentType::Counters);
|
content_type == StyleContentType::Counters);
|
||||||
|
@ -3043,7 +2738,7 @@ clip-path
|
||||||
use crate::gecko_bindings::structs::StyleContentType;
|
use crate::gecko_bindings::structs::StyleContentType;
|
||||||
use crate::values::generics::counters::{Content, ContentItem};
|
use crate::values::generics::counters::{Content, ContentItem};
|
||||||
use crate::values::{CustomIdent, Either};
|
use crate::values::{CustomIdent, Either};
|
||||||
use crate::values::generics::CounterStyleOrNone;
|
use crate::values::generics::CounterStyle;
|
||||||
use crate::values::specified::Attr;
|
use crate::values::specified::Attr;
|
||||||
|
|
||||||
if self.gecko.mContents.is_empty() {
|
if self.gecko.mContents.is_empty() {
|
||||||
|
@ -3088,7 +2783,7 @@ clip-path
|
||||||
Atom::from_raw(gecko_function.mIdent.mRawPtr)
|
Atom::from_raw(gecko_function.mIdent.mRawPtr)
|
||||||
});
|
});
|
||||||
let style =
|
let style =
|
||||||
CounterStyleOrNone::from_gecko_value(&gecko_function.mCounterStyle);
|
CounterStyle::from_gecko_value(&gecko_function.mCounterStyle);
|
||||||
let style = match style {
|
let style = match style {
|
||||||
Either::First(counter_style) => counter_style,
|
Either::First(counter_style) => counter_style,
|
||||||
Either::Second(_) =>
|
Either::Second(_) =>
|
||||||
|
@ -3115,70 +2810,13 @@ clip-path
|
||||||
}).collect::<Vec<_>>().into_boxed_slice()
|
}).collect::<Vec<_>>().into_boxed_slice()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
% for counter_property in ["Increment", "Reset", "Set"]:
|
|
||||||
pub fn set_counter_${counter_property.lower()}(
|
|
||||||
&mut self,
|
|
||||||
v: longhands::counter_${counter_property.lower()}::computed_value::T
|
|
||||||
) {
|
|
||||||
unsafe {
|
|
||||||
bindings::Gecko_ClearAndResizeCounter${counter_property}s(&mut *self.gecko, v.len() as u32);
|
|
||||||
for (i, pair) in v.0.into_vec().into_iter().enumerate() {
|
|
||||||
self.gecko.m${counter_property}s[i].mCounter.set_move(
|
|
||||||
RefPtr::from_addrefed(pair.name.0.into_addrefed())
|
|
||||||
);
|
|
||||||
self.gecko.m${counter_property}s[i].mValue = pair.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn copy_counter_${counter_property.lower()}_from(&mut self, other: &Self) {
|
|
||||||
unsafe {
|
|
||||||
bindings::Gecko_CopyCounter${counter_property}sFrom(&mut *self.gecko, &*other.gecko)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reset_counter_${counter_property.lower()}(&mut self, other: &Self) {
|
|
||||||
self.copy_counter_${counter_property.lower()}_from(other)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clone_counter_${counter_property.lower()}(
|
|
||||||
&self
|
|
||||||
) -> longhands::counter_${counter_property.lower()}::computed_value::T {
|
|
||||||
use crate::values::generics::counters::CounterPair;
|
|
||||||
use crate::values::CustomIdent;
|
|
||||||
|
|
||||||
longhands::counter_${counter_property.lower()}::computed_value::T::new(
|
|
||||||
self.gecko.m${counter_property}s.iter().map(|ref gecko_counter| {
|
|
||||||
CounterPair {
|
|
||||||
name: CustomIdent(unsafe {
|
|
||||||
Atom::from_raw(gecko_counter.mCounter.mRawPtr)
|
|
||||||
}),
|
|
||||||
value: gecko_counter.mValue,
|
|
||||||
}
|
|
||||||
}).collect()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
% endfor
|
|
||||||
</%self:impl_trait>
|
</%self:impl_trait>
|
||||||
|
|
||||||
<%self:impl_trait style_struct_name="UI" skip_longhands="-moz-force-broken-image-icon">
|
<%self:impl_trait style_struct_name="UI" skip_longhands="-moz-force-broken-image-icon">
|
||||||
${impl_simple_type_with_conversion("_moz_force_broken_image_icon", "mForceBrokenImageIcon")}
|
${impl_simple_type_with_conversion("_moz_force_broken_image_icon", "mForceBrokenImageIcon")}
|
||||||
</%self:impl_trait>
|
</%self:impl_trait>
|
||||||
|
|
||||||
<%self:impl_trait style_struct_name="XUL"
|
<%self:impl_trait style_struct_name="XUL">
|
||||||
skip_longhands="-moz-box-ordinal-group">
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub fn set__moz_box_ordinal_group(&mut self, v: i32) {
|
|
||||||
self.gecko.mBoxOrdinal = v as u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
${impl_simple_copy("_moz_box_ordinal_group", "mBoxOrdinal")}
|
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub fn clone__moz_box_ordinal_group(&self) -> i32 {
|
|
||||||
self.gecko.mBoxOrdinal as i32
|
|
||||||
}
|
|
||||||
</%self:impl_trait>
|
</%self:impl_trait>
|
||||||
|
|
||||||
% for style_struct in data.style_structs:
|
% for style_struct in data.style_structs:
|
||||||
|
|
|
@ -80,7 +80,7 @@ ${helpers.predefined_type(
|
||||||
engines="gecko",
|
engines="gecko",
|
||||||
initial_value="computed::FontSizeAdjust::none()",
|
initial_value="computed::FontSizeAdjust::none()",
|
||||||
initial_specified_value="specified::FontSizeAdjust::none()",
|
initial_specified_value="specified::FontSizeAdjust::none()",
|
||||||
animation_value_type="ComputedValue",
|
animation_value_type="FontSizeAdjust",
|
||||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust",
|
spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust",
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -401,7 +401,7 @@ ${helpers.predefined_type(
|
||||||
is_system_font: true,
|
is_system_font: true,
|
||||||
},
|
},
|
||||||
font_size: FontSize {
|
font_size: FontSize {
|
||||||
size: cx.maybe_zoom_text(Au(system.size).into()),
|
size: NonNegative(cx.maybe_zoom_text(Au(system.size).into())),
|
||||||
keyword_info: None
|
keyword_info: None
|
||||||
},
|
},
|
||||||
font_weight,
|
font_weight,
|
||||||
|
|
|
@ -76,6 +76,7 @@ ${helpers.predefined_type(
|
||||||
"ClipRectOrAuto",
|
"ClipRectOrAuto",
|
||||||
"computed::ClipRectOrAuto::auto()",
|
"computed::ClipRectOrAuto::auto()",
|
||||||
engines="gecko",
|
engines="gecko",
|
||||||
|
gecko_ffi_name="mImageRegion",
|
||||||
animation_value_type="ComputedValue",
|
animation_value_type="ComputedValue",
|
||||||
boxed=True,
|
boxed=True,
|
||||||
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-image-region)",
|
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-image-region)",
|
||||||
|
|
|
@ -18,8 +18,8 @@ ${helpers.single_keyword(
|
||||||
|
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
"-x-span",
|
"-x-span",
|
||||||
"XSpan",
|
"Integer",
|
||||||
"computed::XSpan(1)",
|
"1",
|
||||||
engines="gecko",
|
engines="gecko",
|
||||||
spec="Internal-only (for `<col span>` pres attr)",
|
spec="Internal-only (for `<col span>` pres attr)",
|
||||||
animation_value_type="none",
|
animation_value_type="none",
|
||||||
|
|
|
@ -38,6 +38,7 @@ use style_traits::{CssWriter, KeywordsCollectFn, ParseError, ParsingMode};
|
||||||
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
|
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
|
||||||
use to_shmem::impl_trivial_to_shmem;
|
use to_shmem::impl_trivial_to_shmem;
|
||||||
use crate::stylesheets::{CssRuleType, Origin, UrlExtraData};
|
use crate::stylesheets::{CssRuleType, Origin, UrlExtraData};
|
||||||
|
use crate::use_counters::UseCounters;
|
||||||
use crate::values::generics::text::LineHeight;
|
use crate::values::generics::text::LineHeight;
|
||||||
use crate::values::{computed, resolved};
|
use crate::values::{computed, resolved};
|
||||||
use crate::values::computed::NonNegativeLength;
|
use crate::values::computed::NonNegativeLength;
|
||||||
|
@ -427,6 +428,9 @@ pub struct NonCustomPropertyId(usize);
|
||||||
pub const NON_CUSTOM_PROPERTY_ID_COUNT: usize =
|
pub const NON_CUSTOM_PROPERTY_ID_COUNT: usize =
|
||||||
${len(data.longhands) + len(data.shorthands) + len(data.all_aliases())};
|
${len(data.longhands) + len(data.shorthands) + len(data.all_aliases())};
|
||||||
|
|
||||||
|
/// The length of all counted unknown properties.
|
||||||
|
pub const COUNTED_UNKNOWN_PROPERTY_COUNT: usize = ${len(data.counted_unknown_properties)};
|
||||||
|
|
||||||
% if engine == "gecko":
|
% if engine == "gecko":
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
unsafe fn static_assert_nscsspropertyid() {
|
unsafe fn static_assert_nscsspropertyid() {
|
||||||
|
@ -1788,6 +1792,45 @@ impl ToCss for PropertyId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The counted unknown property list which is used for css use counters.
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum CountedUnknownProperty {
|
||||||
|
% for prop in data.counted_unknown_properties:
|
||||||
|
/// ${prop.name}
|
||||||
|
${prop.camel_case},
|
||||||
|
% endfor
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CountedUnknownProperty {
|
||||||
|
/// Parse the counted unknown property.
|
||||||
|
pub fn parse_for_test(property_name: &str) -> Option<Self> {
|
||||||
|
ascii_case_insensitive_phf_map! {
|
||||||
|
unknown_id -> CountedUnknownProperty = {
|
||||||
|
% for property in data.counted_unknown_properties:
|
||||||
|
"${property.name}" => CountedUnknownProperty::${property.camel_case},
|
||||||
|
% endfor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unknown_id(property_name).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the underlying index, used for use counter.
|
||||||
|
pub fn bit(self) -> usize {
|
||||||
|
self as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
fn is_counted_unknown_use_counters_enabled() -> bool {
|
||||||
|
static_prefs::pref!("layout.css.use-counters-unimplemented.enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
|
fn is_counted_unknown_use_counters_enabled() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
impl PropertyId {
|
impl PropertyId {
|
||||||
/// Return the longhand id that this property id represents.
|
/// Return the longhand id that this property id represents.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1801,16 +1844,30 @@ impl PropertyId {
|
||||||
|
|
||||||
/// Returns a given property from the string `s`.
|
/// Returns a given property from the string `s`.
|
||||||
///
|
///
|
||||||
/// Returns Err(()) for unknown non-custom properties.
|
/// Returns Err(()) for unknown properties.
|
||||||
fn parse_unchecked(property_name: &str) -> Result<Self, ()> {
|
fn parse_unchecked(
|
||||||
|
property_name: &str,
|
||||||
|
use_counters: Option< &UseCounters>,
|
||||||
|
) -> Result<Self, ()> {
|
||||||
|
// A special id for css use counters.
|
||||||
|
// ShorthandAlias is not used in the Servo build.
|
||||||
|
// That's why we need to allow dead_code.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum StaticId {
|
||||||
|
Longhand(LonghandId),
|
||||||
|
Shorthand(ShorthandId),
|
||||||
|
LonghandAlias(LonghandId, AliasId),
|
||||||
|
ShorthandAlias(ShorthandId, AliasId),
|
||||||
|
CountedUnknown(CountedUnknownProperty),
|
||||||
|
}
|
||||||
ascii_case_insensitive_phf_map! {
|
ascii_case_insensitive_phf_map! {
|
||||||
property_id -> PropertyId = {
|
static_id -> StaticId = {
|
||||||
% for (kind, properties) in [("Longhand", data.longhands), ("Shorthand", data.shorthands)]:
|
% for (kind, properties) in [("Longhand", data.longhands), ("Shorthand", data.shorthands)]:
|
||||||
% for property in properties:
|
% for property in properties:
|
||||||
"${property.name}" => PropertyId::${kind}(${kind}Id::${property.camel_case}),
|
"${property.name}" => StaticId::${kind}(${kind}Id::${property.camel_case}),
|
||||||
% for alias in property.alias:
|
% for alias in property.alias:
|
||||||
"${alias.name}" => {
|
"${alias.name}" => {
|
||||||
PropertyId::${kind}Alias(
|
StaticId::${kind}Alias(
|
||||||
${kind}Id::${property.camel_case},
|
${kind}Id::${property.camel_case},
|
||||||
AliasId::${alias.camel_case},
|
AliasId::${alias.camel_case},
|
||||||
)
|
)
|
||||||
|
@ -1818,11 +1875,31 @@ impl PropertyId {
|
||||||
% endfor
|
% endfor
|
||||||
% endfor
|
% endfor
|
||||||
% endfor
|
% endfor
|
||||||
|
% for property in data.counted_unknown_properties:
|
||||||
|
"${property.name}" => {
|
||||||
|
StaticId::CountedUnknown(CountedUnknownProperty::${property.camel_case})
|
||||||
|
},
|
||||||
|
% endfor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(id) = property_id(property_name) {
|
if let Some(id) = static_id(property_name) {
|
||||||
return Ok(id.clone())
|
return Ok(match *id {
|
||||||
|
StaticId::Longhand(id) => PropertyId::Longhand(id),
|
||||||
|
StaticId::Shorthand(id) => PropertyId::Shorthand(id),
|
||||||
|
StaticId::LonghandAlias(id, alias) => PropertyId::LonghandAlias(id, alias),
|
||||||
|
StaticId::ShorthandAlias(id, alias) => PropertyId::ShorthandAlias(id, alias),
|
||||||
|
StaticId::CountedUnknown(unknown_prop) => {
|
||||||
|
if is_counted_unknown_use_counters_enabled() {
|
||||||
|
if let Some(counters) = use_counters {
|
||||||
|
counters.counted_unknown_properties.record(unknown_prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always return Err(()) because these aren't valid custom property names.
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = crate::custom_properties::parse_name(property_name)?;
|
let name = crate::custom_properties::parse_name(property_name)?;
|
||||||
|
@ -1833,7 +1910,7 @@ impl PropertyId {
|
||||||
/// enabled for all content.
|
/// enabled for all content.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_enabled_for_all_content(name: &str) -> Result<Self, ()> {
|
pub fn parse_enabled_for_all_content(name: &str) -> Result<Self, ()> {
|
||||||
let id = Self::parse_unchecked(name)?;
|
let id = Self::parse_unchecked(name, None)?;
|
||||||
|
|
||||||
if !id.enabled_for_all_content() {
|
if !id.enabled_for_all_content() {
|
||||||
return Err(());
|
return Err(());
|
||||||
|
@ -1847,7 +1924,7 @@ impl PropertyId {
|
||||||
/// allowed in this context.
|
/// allowed in this context.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse(name: &str, context: &ParserContext) -> Result<Self, ()> {
|
pub fn parse(name: &str, context: &ParserContext) -> Result<Self, ()> {
|
||||||
let id = Self::parse_unchecked(name)?;
|
let id = Self::parse_unchecked(name, context.use_counters)?;
|
||||||
|
|
||||||
if !id.allowed_in(context) {
|
if !id.allowed_in(context) {
|
||||||
return Err(());
|
return Err(());
|
||||||
|
@ -1865,7 +1942,7 @@ impl PropertyId {
|
||||||
name: &str,
|
name: &str,
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
) -> Result<Self, ()> {
|
) -> Result<Self, ()> {
|
||||||
let id = Self::parse_unchecked(name)?;
|
let id = Self::parse_unchecked(name, None)?;
|
||||||
|
|
||||||
if !id.allowed_in_ignoring_rule_type(context) {
|
if !id.allowed_in_ignoring_rule_type(context) {
|
||||||
return Err(());
|
return Err(());
|
||||||
|
|
|
@ -61,31 +61,23 @@
|
||||||
|
|
||||||
let position = unwrap_or_initial!(list_style_position, position);
|
let position = unwrap_or_initial!(list_style_position, position);
|
||||||
|
|
||||||
fn list_style_type_none() -> list_style_type::SpecifiedValue {
|
|
||||||
% if engine == "gecko":
|
|
||||||
use crate::values::generics::CounterStyleOrNone;
|
|
||||||
list_style_type::SpecifiedValue::CounterStyle(CounterStyleOrNone::None)
|
|
||||||
% else:
|
|
||||||
list_style_type::SpecifiedValue::None
|
|
||||||
% endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there are two `none`s, then we can't have a type or image; if there is one `none`,
|
// If there are two `none`s, then we can't have a type or image; if there is one `none`,
|
||||||
// then we can't have both a type *and* an image; if there is no `none` then we're fine as
|
// then we can't have both a type *and* an image; if there is no `none` then we're fine as
|
||||||
// long as we parsed something.
|
// long as we parsed something.
|
||||||
|
use self::list_style_type::SpecifiedValue as ListStyleType;
|
||||||
match (any, nones, list_style_type, image) {
|
match (any, nones, list_style_type, image) {
|
||||||
(true, 2, None, None) => {
|
(true, 2, None, None) => {
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
list_style_position: position,
|
list_style_position: position,
|
||||||
list_style_image: ImageUrlOrNone::none(),
|
list_style_image: ImageUrlOrNone::none(),
|
||||||
list_style_type: list_style_type_none(),
|
list_style_type: ListStyleType::None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
(true, 1, None, Some(image)) => {
|
(true, 1, None, Some(image)) => {
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
list_style_position: position,
|
list_style_position: position,
|
||||||
list_style_image: image,
|
list_style_image: image,
|
||||||
list_style_type: list_style_type_none(),
|
list_style_type: ListStyleType::None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
(true, 1, Some(list_style_type), None) => {
|
(true, 1, Some(list_style_type), None) => {
|
||||||
|
@ -99,7 +91,7 @@
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
list_style_position: position,
|
list_style_position: position,
|
||||||
list_style_image: ImageUrlOrNone::none(),
|
list_style_image: ImageUrlOrNone::none(),
|
||||||
list_style_type: list_style_type_none(),
|
list_style_type: ListStyleType::None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
(true, 0, list_style_type, image) => {
|
(true, 0, list_style_type, image) => {
|
||||||
|
|
|
@ -73,26 +73,51 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
||||||
|
#[allow(unused)]
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
|
||||||
self.text_decoration_line.to_css(dest)?;
|
use crate::values::specified::TextDecorationLine;
|
||||||
|
|
||||||
|
let (is_solid_style, is_current_color, is_auto_thickness) =
|
||||||
|
(
|
||||||
|
% if engine == "gecko":
|
||||||
|
*self.text_decoration_style == text_decoration_style::SpecifiedValue::Solid,
|
||||||
|
*self.text_decoration_color == specified::Color::CurrentColor,
|
||||||
|
self.text_decoration_thickness.map_or(true, |t| t.is_auto())
|
||||||
|
% else:
|
||||||
|
true, true, true
|
||||||
|
% endif
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut has_value = false;
|
||||||
|
let is_none = *self.text_decoration_line == TextDecorationLine::none();
|
||||||
|
if (is_solid_style && is_current_color && is_auto_thickness) || !is_none {
|
||||||
|
self.text_decoration_line.to_css(dest)?;
|
||||||
|
has_value = true;
|
||||||
|
}
|
||||||
|
|
||||||
% if engine == "gecko":
|
% if engine == "gecko":
|
||||||
if *self.text_decoration_style != text_decoration_style::SpecifiedValue::Solid {
|
if !is_solid_style {
|
||||||
|
if has_value {
|
||||||
dest.write_str(" ")?;
|
dest.write_str(" ")?;
|
||||||
self.text_decoration_style.to_css(dest)?;
|
|
||||||
}
|
}
|
||||||
|
self.text_decoration_style.to_css(dest)?;
|
||||||
|
has_value = true;
|
||||||
|
}
|
||||||
|
|
||||||
if *self.text_decoration_color != specified::Color::CurrentColor {
|
if !is_current_color {
|
||||||
|
if has_value {
|
||||||
dest.write_str(" ")?;
|
dest.write_str(" ")?;
|
||||||
self.text_decoration_color.to_css(dest)?;
|
|
||||||
}
|
}
|
||||||
|
self.text_decoration_color.to_css(dest)?;
|
||||||
|
has_value = true;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(text_decoration_thickness) = self.text_decoration_thickness {
|
if !is_auto_thickness {
|
||||||
if !text_decoration_thickness.is_auto() {
|
if has_value {
|
||||||
dest.write_str(" ")?;
|
dest.write_str(" ")?;
|
||||||
self.text_decoration_thickness.to_css(dest)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
self.text_decoration_thickness.to_css(dest)?;
|
||||||
|
}
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -15,6 +15,9 @@ use std::ops::DerefMut;
|
||||||
///
|
///
|
||||||
/// We use this on Servo to construct thread-local contexts, but clear them once
|
/// We use this on Servo to construct thread-local contexts, but clear them once
|
||||||
/// we're done with restyling.
|
/// we're done with restyling.
|
||||||
|
///
|
||||||
|
/// Note that the cleanup is done on the thread that owns the scoped TLS, thus
|
||||||
|
/// the Send bound.
|
||||||
pub struct ScopedTLS<'scope, T: Send> {
|
pub struct ScopedTLS<'scope, T: Send> {
|
||||||
pool: &'scope rayon::ThreadPool,
|
pool: &'scope rayon::ThreadPool,
|
||||||
slots: Box<[RefCell<Option<T>>]>,
|
slots: Box<[RefCell<Option<T>>]>,
|
||||||
|
|
|
@ -82,7 +82,7 @@ use servo_arc::Arc;
|
||||||
use smallbitvec::SmallBitVec;
|
use smallbitvec::SmallBitVec;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem;
|
use std::mem::{self, ManuallyDrop};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
use uluru::{Entry, LRUCache};
|
use uluru::{Entry, LRUCache};
|
||||||
|
@ -477,10 +477,9 @@ type TypelessSharingCache = SharingCacheBase<FakeCandidate>;
|
||||||
type StoredSharingCache = Arc<AtomicRefCell<TypelessSharingCache>>;
|
type StoredSharingCache = Arc<AtomicRefCell<TypelessSharingCache>>;
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
// TODO(emilio): Looks like a few of these should just be Rc<RefCell<>> or
|
// See the comment on bloom.rs about why do we leak this.
|
||||||
// something. No need for atomics in the thread-local code.
|
static SHARING_CACHE_KEY: ManuallyDrop<StoredSharingCache> =
|
||||||
static SHARING_CACHE_KEY: StoredSharingCache =
|
ManuallyDrop::new(Arc::new_leaked(Default::default()));
|
||||||
Arc::new_leaked(AtomicRefCell::new(TypelessSharingCache::default()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An LRU cache of the last few nodes seen, so that we can aggressively try to
|
/// An LRU cache of the last few nodes seen, so that we can aggressively try to
|
||||||
|
@ -533,7 +532,7 @@ impl<E: TElement> StyleSharingCache<E> {
|
||||||
mem::align_of::<SharingCache<E>>(),
|
mem::align_of::<SharingCache<E>>(),
|
||||||
mem::align_of::<TypelessSharingCache>()
|
mem::align_of::<TypelessSharingCache>()
|
||||||
);
|
);
|
||||||
let cache_arc = SHARING_CACHE_KEY.with(|c| c.clone());
|
let cache_arc = SHARING_CACHE_KEY.with(|c| Arc::clone(&*c));
|
||||||
let cache =
|
let cache =
|
||||||
OwningHandle::new_with_fn(cache_arc, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
|
OwningHandle::new_with_fn(cache_arc, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
|
||||||
debug_assert!(cache.is_empty());
|
debug_assert!(cache.is_empty());
|
||||||
|
|
|
@ -283,6 +283,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
|
||||||
fn adjust_for_text_combine_upright(&mut self) {
|
fn adjust_for_text_combine_upright(&mut self) {
|
||||||
use crate::computed_values::text_combine_upright::T as TextCombineUpright;
|
use crate::computed_values::text_combine_upright::T as TextCombineUpright;
|
||||||
use crate::computed_values::writing_mode::T as WritingMode;
|
use crate::computed_values::writing_mode::T as WritingMode;
|
||||||
|
use crate::logical_geometry;
|
||||||
|
|
||||||
let writing_mode = self.style.get_inherited_box().clone_writing_mode();
|
let writing_mode = self.style.get_inherited_box().clone_writing_mode();
|
||||||
let text_combine_upright = self.style.get_inherited_text().clone_text_combine_upright();
|
let text_combine_upright = self.style.get_inherited_text().clone_text_combine_upright();
|
||||||
|
@ -294,6 +295,8 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
|
||||||
self.style
|
self.style
|
||||||
.mutate_inherited_box()
|
.mutate_inherited_box()
|
||||||
.set_writing_mode(WritingMode::HorizontalTb);
|
.set_writing_mode(WritingMode::HorizontalTb);
|
||||||
|
self.style.writing_mode =
|
||||||
|
logical_geometry::WritingMode::new(self.style.get_inherited_box());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use crate::gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
|
use crate::gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
|
||||||
|
use crate::properties::{CountedUnknownProperty, COUNTED_UNKNOWN_PROPERTY_COUNT};
|
||||||
use crate::properties::{NonCustomPropertyId, NON_CUSTOM_PROPERTY_ID_COUNT};
|
use crate::properties::{NonCustomPropertyId, NON_CUSTOM_PROPERTY_ID_COUNT};
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
|
@ -15,46 +16,62 @@ const BITS_PER_ENTRY: usize = 64;
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
const BITS_PER_ENTRY: usize = 32;
|
const BITS_PER_ENTRY: usize = 32;
|
||||||
|
|
||||||
|
/// One bit per each non-custom CSS property.
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct CountedUnknownPropertyUseCounters {
|
||||||
|
storage: [Cell<usize>; (COUNTED_UNKNOWN_PROPERTY_COUNT - 1 + BITS_PER_ENTRY) / BITS_PER_ENTRY],
|
||||||
|
}
|
||||||
|
|
||||||
/// One bit per each non-custom CSS property.
|
/// One bit per each non-custom CSS property.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct NonCustomPropertyUseCounters {
|
pub struct NonCustomPropertyUseCounters {
|
||||||
storage: [Cell<usize>; (NON_CUSTOM_PROPERTY_ID_COUNT - 1 + BITS_PER_ENTRY) / BITS_PER_ENTRY],
|
storage: [Cell<usize>; (NON_CUSTOM_PROPERTY_ID_COUNT - 1 + BITS_PER_ENTRY) / BITS_PER_ENTRY],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NonCustomPropertyUseCounters {
|
macro_rules! property_use_counters_methods {
|
||||||
/// Returns the bucket a given property belongs in, and the bitmask for that
|
($id: ident) => {
|
||||||
/// property.
|
/// Returns the bucket a given property belongs in, and the bitmask for that
|
||||||
#[inline(always)]
|
/// property.
|
||||||
fn bucket_and_pattern(id: NonCustomPropertyId) -> (usize, usize) {
|
#[inline(always)]
|
||||||
let bit = id.bit();
|
fn bucket_and_pattern(id: $id) -> (usize, usize) {
|
||||||
let bucket = bit / BITS_PER_ENTRY;
|
let bit = id.bit();
|
||||||
let bit_in_bucket = bit % BITS_PER_ENTRY;
|
let bucket = bit / BITS_PER_ENTRY;
|
||||||
(bucket, 1 << bit_in_bucket)
|
let bit_in_bucket = bit % BITS_PER_ENTRY;
|
||||||
}
|
(bucket, 1 << bit_in_bucket)
|
||||||
|
|
||||||
/// Record that a given non-custom property ID has been parsed.
|
|
||||||
#[inline]
|
|
||||||
pub fn record(&self, id: NonCustomPropertyId) {
|
|
||||||
let (bucket, pattern) = Self::bucket_and_pattern(id);
|
|
||||||
let bucket = &self.storage[bucket];
|
|
||||||
bucket.set(bucket.get() | pattern)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns whether a given non-custom property ID has been recorded
|
|
||||||
/// earlier.
|
|
||||||
#[inline]
|
|
||||||
pub fn recorded(&self, id: NonCustomPropertyId) -> bool {
|
|
||||||
let (bucket, pattern) = Self::bucket_and_pattern(id);
|
|
||||||
self.storage[bucket].get() & pattern != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Merge `other` into `self`.
|
|
||||||
#[inline]
|
|
||||||
fn merge(&self, other: &Self) {
|
|
||||||
for (bucket, other_bucket) in self.storage.iter().zip(other.storage.iter()) {
|
|
||||||
bucket.set(bucket.get() | other_bucket.get())
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/// Record that a given property ID has been parsed.
|
||||||
|
#[inline]
|
||||||
|
pub fn record(&self, id: $id) {
|
||||||
|
let (bucket, pattern) = Self::bucket_and_pattern(id);
|
||||||
|
let bucket = &self.storage[bucket];
|
||||||
|
bucket.set(bucket.get() | pattern)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether a given property ID has been recorded
|
||||||
|
/// earlier.
|
||||||
|
#[inline]
|
||||||
|
pub fn recorded(&self, id: $id) -> bool {
|
||||||
|
let (bucket, pattern) = Self::bucket_and_pattern(id);
|
||||||
|
self.storage[bucket].get() & pattern != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Merge `other` into `self`.
|
||||||
|
#[inline]
|
||||||
|
fn merge(&self, other: &Self) {
|
||||||
|
for (bucket, other_bucket) in self.storage.iter().zip(other.storage.iter()) {
|
||||||
|
bucket.set(bucket.get() | other_bucket.get())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CountedUnknownPropertyUseCounters {
|
||||||
|
property_use_counters_methods!(CountedUnknownProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NonCustomPropertyUseCounters {
|
||||||
|
property_use_counters_methods!(NonCustomPropertyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The use-counter data related to a given document we want to store.
|
/// The use-counter data related to a given document we want to store.
|
||||||
|
@ -63,6 +80,8 @@ pub struct UseCounters {
|
||||||
/// The counters for non-custom properties that have been parsed in the
|
/// The counters for non-custom properties that have been parsed in the
|
||||||
/// document's stylesheets.
|
/// document's stylesheets.
|
||||||
pub non_custom_properties: NonCustomPropertyUseCounters,
|
pub non_custom_properties: NonCustomPropertyUseCounters,
|
||||||
|
/// The counters for css properties which we haven't implemented yet.
|
||||||
|
pub counted_unknown_properties: CountedUnknownPropertyUseCounters,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UseCounters {
|
impl UseCounters {
|
||||||
|
@ -72,7 +91,9 @@ impl UseCounters {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn merge(&self, other: &Self) {
|
pub fn merge(&self, other: &Self) {
|
||||||
self.non_custom_properties
|
self.non_custom_properties
|
||||||
.merge(&other.non_custom_properties)
|
.merge(&other.non_custom_properties);
|
||||||
|
self.counted_unknown_properties
|
||||||
|
.merge(&other.counted_unknown_properties);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,15 @@ use crate::gecko_bindings::sugar::refptr::RefPtr;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use crate::gecko_bindings::{bindings, structs};
|
use crate::gecko_bindings::{bindings, structs};
|
||||||
use crate::values::animated::{ToAnimatedValue, ToAnimatedZero};
|
use crate::values::animated::{ToAnimatedValue, ToAnimatedZero};
|
||||||
use crate::values::computed::{Angle, Context, Integer, NonNegativeLength, NonNegativePercentage};
|
use crate::values::computed::{
|
||||||
|
Angle, Context, Integer, Length, NonNegativeLength, NonNegativePercentage,
|
||||||
|
};
|
||||||
use crate::values::computed::{Number, Percentage, ToComputedValue};
|
use crate::values::computed::{Number, Percentage, ToComputedValue};
|
||||||
use crate::values::generics::font as generics;
|
|
||||||
use crate::values::generics::font::{FeatureTagValue, FontSettings, VariationValue};
|
use crate::values::generics::font::{FeatureTagValue, FontSettings, VariationValue};
|
||||||
use crate::values::specified::font::{self as specified, MAX_FONT_WEIGHT, MIN_FONT_WEIGHT};
|
use crate::values::generics::{font as generics, NonNegative};
|
||||||
|
use crate::values::specified::font::{
|
||||||
|
self as specified, KeywordInfo, MAX_FONT_WEIGHT, MIN_FONT_WEIGHT,
|
||||||
|
};
|
||||||
use crate::values::specified::length::{FontBaseSize, NoCalcLength};
|
use crate::values::specified::length::{FontBaseSize, NoCalcLength};
|
||||||
use crate::values::CSSFloat;
|
use crate::values::CSSFloat;
|
||||||
use crate::Atom;
|
use crate::Atom;
|
||||||
|
@ -88,9 +92,6 @@ pub struct FontSize {
|
||||||
pub keyword_info: Option<KeywordInfo>,
|
pub keyword_info: Option<KeywordInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Additional information for computed keyword-derived font sizes.
|
|
||||||
pub type KeywordInfo = generics::KeywordInfo<NonNegativeLength>;
|
|
||||||
|
|
||||||
impl FontWeight {
|
impl FontWeight {
|
||||||
/// Value for normal
|
/// Value for normal
|
||||||
pub fn normal() -> Self {
|
pub fn normal() -> Self {
|
||||||
|
@ -162,17 +163,17 @@ impl FontSize {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToAnimatedValue for FontSize {
|
impl ToAnimatedValue for FontSize {
|
||||||
type AnimatedValue = NonNegativeLength;
|
type AnimatedValue = Length;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_animated_value(self) -> Self::AnimatedValue {
|
fn to_animated_value(self) -> Self::AnimatedValue {
|
||||||
self.size
|
self.size.0
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
||||||
FontSize {
|
FontSize {
|
||||||
size: animated.clamp(),
|
size: NonNegative(animated.clamp_to_non_negative()),
|
||||||
keyword_info: None,
|
keyword_info: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -647,10 +648,10 @@ impl ToAnimatedValue for FontSizeAdjust {
|
||||||
pub type FontVariantAlternates = specified::VariantAlternatesList;
|
pub type FontVariantAlternates = specified::VariantAlternatesList;
|
||||||
|
|
||||||
impl FontVariantAlternates {
|
impl FontVariantAlternates {
|
||||||
#[inline]
|
|
||||||
/// Get initial value with VariantAlternatesList
|
/// Get initial value with VariantAlternatesList
|
||||||
|
#[inline]
|
||||||
pub fn get_initial_value() -> Self {
|
pub fn get_initial_value() -> Self {
|
||||||
specified::VariantAlternatesList(vec![].into_boxed_slice())
|
Self::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -297,7 +297,7 @@ impl specified::CalcLengthPercentage {
|
||||||
) -> LengthPercentage {
|
) -> LengthPercentage {
|
||||||
self.to_computed_value_with_zoom(
|
self.to_computed_value_with_zoom(
|
||||||
context,
|
context,
|
||||||
|abs| context.maybe_zoom_text(abs.into()).0,
|
|abs| context.maybe_zoom_text(abs.into()),
|
||||||
base_size,
|
base_size,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -360,8 +360,8 @@ impl LengthPercentage {
|
||||||
self.unclamped_length().px() == 0.0 && self.percentage.0 == 0.0
|
self.unclamped_length().px() == 0.0 && self.percentage.0 == 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
// CSSFloat doesn't implement Hash, so does CSSPixelLength. Therefore, we still use Au as the
|
// CSSFloat doesn't implement Hash, so does CSSPixelLength. Therefore, we
|
||||||
// hash key.
|
// still use Au as the hash key.
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub fn to_hash_key(&self) -> (Au, NotNan<f32>) {
|
pub fn to_hash_key(&self) -> (Au, NotNan<f32>) {
|
||||||
(
|
(
|
||||||
|
@ -840,14 +840,6 @@ impl NonNegativeLength {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scale this NonNegativeLength.
|
|
||||||
/// We scale NonNegativeLength by zero if the factor is negative because it doesn't
|
|
||||||
/// make sense to scale a negative factor on a non-negative length.
|
|
||||||
#[inline]
|
|
||||||
pub fn scale_by(&self, factor: f32) -> Self {
|
|
||||||
Self::new(self.0.px() * factor.max(0.))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Length> for NonNegativeLength {
|
impl From<Length> for NonNegativeLength {
|
||||||
|
|
|
@ -75,7 +75,6 @@ pub use self::resolution::Resolution;
|
||||||
pub use self::svg::MozContextProperties;
|
pub use self::svg::MozContextProperties;
|
||||||
pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind};
|
pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind};
|
||||||
pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
|
pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
|
||||||
pub use self::table::XSpan;
|
|
||||||
pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight};
|
pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight};
|
||||||
pub use self::text::{OverflowWrap, TextOverflow, WordBreak, WordSpacing};
|
pub use self::text::{OverflowWrap, TextOverflow, WordBreak, WordSpacing};
|
||||||
pub use self::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle};
|
pub use self::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle};
|
||||||
|
@ -116,7 +115,6 @@ pub mod position;
|
||||||
pub mod rect;
|
pub mod rect;
|
||||||
pub mod resolution;
|
pub mod resolution;
|
||||||
pub mod svg;
|
pub mod svg;
|
||||||
pub mod table;
|
|
||||||
pub mod text;
|
pub mod text;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
pub mod transform;
|
pub mod transform;
|
||||||
|
@ -230,7 +228,7 @@ impl<'a> Context<'a> {
|
||||||
|
|
||||||
/// Apply text-zoom if enabled.
|
/// Apply text-zoom if enabled.
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub fn maybe_zoom_text(&self, size: NonNegativeLength) -> NonNegativeLength {
|
pub fn maybe_zoom_text(&self, size: CSSPixelLength) -> CSSPixelLength {
|
||||||
// We disable zoom for <svg:text> by unsetting the
|
// We disable zoom for <svg:text> by unsetting the
|
||||||
// -x-text-zoom property, which leads to a false value
|
// -x-text-zoom property, which leads to a false value
|
||||||
// in mAllowZoom
|
// in mAllowZoom
|
||||||
|
@ -243,7 +241,7 @@ impl<'a> Context<'a> {
|
||||||
|
|
||||||
/// (Servo doesn't do text-zoom)
|
/// (Servo doesn't do text-zoom)
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
pub fn maybe_zoom_text(&self, size: NonNegativeLength) -> NonNegativeLength {
|
pub fn maybe_zoom_text(&self, size: CSSPixelLength) -> CSSPixelLength {
|
||||||
size
|
size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -685,11 +683,11 @@ impl From<CSSInteger> for PositiveInteger {
|
||||||
/// A computed positive `<integer>` value or `none`.
|
/// A computed positive `<integer>` value or `none`.
|
||||||
pub type PositiveIntegerOrNone = Either<PositiveInteger, None_>;
|
pub type PositiveIntegerOrNone = Either<PositiveInteger, None_>;
|
||||||
|
|
||||||
/// rect(...)
|
/// rect(...) | auto
|
||||||
pub type ClipRect = generics::ClipRect<LengthOrAuto>;
|
pub type ClipRect = generics::GenericClipRect<LengthOrAuto>;
|
||||||
|
|
||||||
/// rect(...) | auto
|
/// rect(...) | auto
|
||||||
pub type ClipRectOrAuto = Either<ClipRect, Auto>;
|
pub type ClipRectOrAuto = generics::GenericClipRectOrAuto<ClipRect>;
|
||||||
|
|
||||||
/// The computed value of a grid `<track-breadth>`
|
/// The computed value of a grid `<track-breadth>`
|
||||||
pub type TrackBreadth = GenericTrackBreadth<LengthPercentage>;
|
pub type TrackBreadth = GenericTrackBreadth<LengthPercentage>;
|
||||||
|
@ -709,18 +707,3 @@ pub type GridLine = GenericGridLine<Integer>;
|
||||||
|
|
||||||
/// `<grid-template-rows> | <grid-template-columns>`
|
/// `<grid-template-rows> | <grid-template-columns>`
|
||||||
pub type GridTemplateComponent = GenericGridTemplateComponent<LengthPercentage, Integer>;
|
pub type GridTemplateComponent = GenericGridTemplateComponent<LengthPercentage, Integer>;
|
||||||
|
|
||||||
impl ClipRectOrAuto {
|
|
||||||
/// Return an auto (default for clip-rect and image-region) value
|
|
||||||
pub fn auto() -> Self {
|
|
||||||
Either::Second(Auto)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if it is auto
|
|
||||||
pub fn is_auto(&self) -> bool {
|
|
||||||
match *self {
|
|
||||||
Either::Second(_) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
//! Computed types for table properties.
|
|
||||||
|
|
||||||
pub use crate::values::specified::table::XSpan;
|
|
|
@ -198,8 +198,6 @@ impl TextDecorationsInEffect {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computed value for the text-emphasis-style property
|
/// Computed value for the text-emphasis-style property
|
||||||
///
|
|
||||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue)]
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue)]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
#[repr(C, u8)]
|
#[repr(C, u8)]
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
use crate::computed_values::list_style_type::T as ListStyleType;
|
use crate::computed_values::list_style_type::T as ListStyleType;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use crate::values::generics::CounterStyleOrNone;
|
use crate::values::generics::CounterStyle;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use crate::values::specified::Attr;
|
use crate::values::specified::Attr;
|
||||||
use crate::values::CustomIdent;
|
use crate::values::CustomIdent;
|
||||||
|
@ -25,12 +25,14 @@ use std::ops::Deref;
|
||||||
ToResolvedValue,
|
ToResolvedValue,
|
||||||
ToShmem,
|
ToShmem,
|
||||||
)]
|
)]
|
||||||
pub struct CounterPair<Integer> {
|
#[repr(C)]
|
||||||
|
pub struct GenericCounterPair<Integer> {
|
||||||
/// The name of the counter.
|
/// The name of the counter.
|
||||||
pub name: CustomIdent,
|
pub name: CustomIdent,
|
||||||
/// The value of the counter / increment / etc.
|
/// The value of the counter / increment / etc.
|
||||||
pub value: Integer,
|
pub value: Integer,
|
||||||
}
|
}
|
||||||
|
pub use self::GenericCounterPair as CounterPair;
|
||||||
|
|
||||||
/// A generic value for the `counter-increment` property.
|
/// A generic value for the `counter-increment` property.
|
||||||
#[derive(
|
#[derive(
|
||||||
|
@ -45,13 +47,15 @@ pub struct CounterPair<Integer> {
|
||||||
ToResolvedValue,
|
ToResolvedValue,
|
||||||
ToShmem,
|
ToShmem,
|
||||||
)]
|
)]
|
||||||
pub struct CounterIncrement<I>(pub Counters<I>);
|
#[repr(transparent)]
|
||||||
|
pub struct GenericCounterIncrement<I>(pub GenericCounters<I>);
|
||||||
|
pub use self::GenericCounterIncrement as CounterIncrement;
|
||||||
|
|
||||||
impl<I> CounterIncrement<I> {
|
impl<I> CounterIncrement<I> {
|
||||||
/// Returns a new value for `counter-increment`.
|
/// Returns a new value for `counter-increment`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(counters: Vec<CounterPair<I>>) -> Self {
|
pub fn new(counters: Vec<CounterPair<I>>) -> Self {
|
||||||
CounterIncrement(Counters(counters.into_boxed_slice()))
|
CounterIncrement(Counters(counters.into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,13 +81,15 @@ impl<I> Deref for CounterIncrement<I> {
|
||||||
ToResolvedValue,
|
ToResolvedValue,
|
||||||
ToShmem,
|
ToShmem,
|
||||||
)]
|
)]
|
||||||
pub struct CounterSetOrReset<I>(pub Counters<I>);
|
#[repr(transparent)]
|
||||||
|
pub struct GenericCounterSetOrReset<I>(pub GenericCounters<I>);
|
||||||
|
pub use self::GenericCounterSetOrReset as CounterSetOrReset;
|
||||||
|
|
||||||
impl<I> CounterSetOrReset<I> {
|
impl<I> CounterSetOrReset<I> {
|
||||||
/// Returns a new value for `counter-set` / `counter-reset`.
|
/// Returns a new value for `counter-set` / `counter-reset`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(counters: Vec<CounterPair<I>>) -> Self {
|
pub fn new(counters: Vec<CounterPair<I>>) -> Self {
|
||||||
CounterSetOrReset(Counters(counters.into_boxed_slice()))
|
CounterSetOrReset(Counters(counters.into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,23 +117,17 @@ impl<I> Deref for CounterSetOrReset<I> {
|
||||||
ToResolvedValue,
|
ToResolvedValue,
|
||||||
ToShmem,
|
ToShmem,
|
||||||
)]
|
)]
|
||||||
pub struct Counters<I>(#[css(iterable, if_empty = "none")] Box<[CounterPair<I>]>);
|
#[repr(transparent)]
|
||||||
|
pub struct GenericCounters<I>(
|
||||||
impl<I> Counters<I> {
|
#[css(iterable, if_empty = "none")] crate::OwnedSlice<GenericCounterPair<I>>,
|
||||||
/// Move out the Box into a vector. This could just return the Box<>, but
|
);
|
||||||
/// Vec<> is a bit more convenient because Box<[T]> doesn't implement
|
pub use self::GenericCounters as Counters;
|
||||||
/// IntoIter: https://github.com/rust-lang/rust/issues/59878
|
|
||||||
#[inline]
|
|
||||||
pub fn into_vec(self) -> Vec<CounterPair<I>> {
|
|
||||||
self.0.into_vec()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
type CounterStyleType = ListStyleType;
|
type CounterStyleType = ListStyleType;
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
type CounterStyleType = CounterStyleOrNone;
|
type CounterStyleType = CounterStyle;
|
||||||
|
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -138,7 +138,7 @@ fn is_decimal(counter_type: &CounterStyleType) -> bool {
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_decimal(counter_type: &CounterStyleType) -> bool {
|
fn is_decimal(counter_type: &CounterStyleType) -> bool {
|
||||||
*counter_type == CounterStyleOrNone::decimal()
|
*counter_type == CounterStyle::decimal()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The specified value for the `content` property.
|
/// The specified value for the `content` property.
|
||||||
|
|
|
@ -34,8 +34,6 @@ pub struct GenericBoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
|
||||||
pub use self::GenericBoxShadow as BoxShadow;
|
pub use self::GenericBoxShadow as BoxShadow;
|
||||||
|
|
||||||
/// A generic value for a single `filter`.
|
/// A generic value for a single `filter`.
|
||||||
///
|
|
||||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
|
||||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||||
#[animation(no_bound(U))]
|
#[animation(no_bound(U))]
|
||||||
#[derive(
|
#[derive(
|
||||||
|
|
|
@ -5,14 +5,13 @@
|
||||||
//! Generic types for font stuff.
|
//! Generic types for font stuff.
|
||||||
|
|
||||||
use crate::parser::{Parse, ParserContext};
|
use crate::parser::{Parse, ParserContext};
|
||||||
use app_units::Au;
|
|
||||||
use byteorder::{BigEndian, ReadBytesExt};
|
use byteorder::{BigEndian, ReadBytesExt};
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use num_traits::One;
|
use num_traits::One;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use style_traits::{CssWriter, KeywordsCollectFn, ParseError};
|
use style_traits::{CssWriter, ParseError};
|
||||||
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
|
use style_traits::{StyleParseErrorKind, ToCss};
|
||||||
|
|
||||||
/// https://drafts.csswg.org/css-fonts-4/#feature-tag-value
|
/// https://drafts.csswg.org/css-fonts-4/#feature-tag-value
|
||||||
#[derive(
|
#[derive(
|
||||||
|
@ -172,105 +171,6 @@ impl Parse for FontTag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
|
||||||
Animate,
|
|
||||||
Clone,
|
|
||||||
ComputeSquaredDistance,
|
|
||||||
Copy,
|
|
||||||
Debug,
|
|
||||||
MallocSizeOf,
|
|
||||||
PartialEq,
|
|
||||||
ToAnimatedValue,
|
|
||||||
ToAnimatedZero,
|
|
||||||
ToCss,
|
|
||||||
ToShmem,
|
|
||||||
)]
|
|
||||||
/// Additional information for keyword-derived font sizes.
|
|
||||||
pub struct KeywordInfo<Length> {
|
|
||||||
/// The keyword used
|
|
||||||
pub kw: KeywordSize,
|
|
||||||
/// A factor to be multiplied by the computed size of the keyword
|
|
||||||
#[css(skip)]
|
|
||||||
pub factor: f32,
|
|
||||||
/// An additional Au offset to add to the kw*factor in the case of calcs
|
|
||||||
#[css(skip)]
|
|
||||||
pub offset: Length,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<L> KeywordInfo<L>
|
|
||||||
where
|
|
||||||
Au: Into<L>,
|
|
||||||
{
|
|
||||||
/// KeywordInfo value for font-size: medium
|
|
||||||
pub fn medium() -> Self {
|
|
||||||
KeywordSize::Medium.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<L> From<KeywordSize> for KeywordInfo<L>
|
|
||||||
where
|
|
||||||
Au: Into<L>,
|
|
||||||
{
|
|
||||||
fn from(x: KeywordSize) -> Self {
|
|
||||||
KeywordInfo {
|
|
||||||
kw: x,
|
|
||||||
factor: 1.,
|
|
||||||
offset: Au(0).into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<L> SpecifiedValueInfo for KeywordInfo<L> {
|
|
||||||
fn collect_completion_keywords(f: KeywordsCollectFn) {
|
|
||||||
<KeywordSize as SpecifiedValueInfo>::collect_completion_keywords(f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// CSS font keywords
|
|
||||||
#[derive(
|
|
||||||
Animate,
|
|
||||||
Clone,
|
|
||||||
ComputeSquaredDistance,
|
|
||||||
Copy,
|
|
||||||
Debug,
|
|
||||||
MallocSizeOf,
|
|
||||||
Parse,
|
|
||||||
PartialEq,
|
|
||||||
SpecifiedValueInfo,
|
|
||||||
ToAnimatedValue,
|
|
||||||
ToAnimatedZero,
|
|
||||||
ToCss,
|
|
||||||
ToShmem,
|
|
||||||
)]
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
pub enum KeywordSize {
|
|
||||||
#[css(keyword = "xx-small")]
|
|
||||||
XXSmall,
|
|
||||||
XSmall,
|
|
||||||
Small,
|
|
||||||
Medium,
|
|
||||||
Large,
|
|
||||||
XLarge,
|
|
||||||
#[css(keyword = "xx-large")]
|
|
||||||
XXLarge,
|
|
||||||
#[css(keyword = "xxx-large")]
|
|
||||||
XXXLarge,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl KeywordSize {
|
|
||||||
/// Convert to an HTML <font size> value
|
|
||||||
#[inline]
|
|
||||||
pub fn html_size(self) -> u8 {
|
|
||||||
self as u8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for KeywordSize {
|
|
||||||
fn default() -> Self {
|
|
||||||
KeywordSize::Medium
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A generic value for the `font-style` property.
|
/// A generic value for the `font-style` property.
|
||||||
///
|
///
|
||||||
/// https://drafts.csswg.org/css-fonts-4/#font-style-prop
|
/// https://drafts.csswg.org/css-fonts-4/#font-style-prop
|
||||||
|
|
|
@ -185,8 +185,6 @@ impl Parse for GridLine<specified::Integer> {
|
||||||
/// avoid re-implementing it for the computed type.
|
/// avoid re-implementing it for the computed type.
|
||||||
///
|
///
|
||||||
/// <https://drafts.csswg.org/css-grid/#typedef-track-breadth>
|
/// <https://drafts.csswg.org/css-grid/#typedef-track-breadth>
|
||||||
///
|
|
||||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Animate,
|
Animate,
|
||||||
Clone,
|
Clone,
|
||||||
|
@ -230,8 +228,6 @@ impl<L> TrackBreadth<L> {
|
||||||
/// generic only to avoid code bloat. It only takes `<length-percentage>`
|
/// generic only to avoid code bloat. It only takes `<length-percentage>`
|
||||||
///
|
///
|
||||||
/// <https://drafts.csswg.org/css-grid/#typedef-track-size>
|
/// <https://drafts.csswg.org/css-grid/#typedef-track-size>
|
||||||
///
|
|
||||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone,
|
Clone,
|
||||||
Debug,
|
Debug,
|
||||||
|
@ -494,8 +490,6 @@ impl<L: ToCss, I: ToCss> ToCss for TrackRepeat<L, I> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Track list values. Can be <track-size> or <track-repeat>
|
/// Track list values. Can be <track-size> or <track-repeat>
|
||||||
///
|
|
||||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Animate,
|
Animate,
|
||||||
Clone,
|
Clone,
|
||||||
|
@ -729,8 +723,6 @@ impl ToCss for LineNameList {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Variants for `<grid-template-rows> | <grid-template-columns>`
|
/// Variants for `<grid-template-rows> | <grid-template-columns>`
|
||||||
///
|
|
||||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Animate,
|
Animate,
|
||||||
Clone,
|
Clone,
|
||||||
|
|
|
@ -92,13 +92,10 @@ impl SymbolsType {
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/css-counter-styles/#typedef-counter-style>
|
/// <https://drafts.csswg.org/css-counter-styles/#typedef-counter-style>
|
||||||
///
|
///
|
||||||
/// Since wherever <counter-style> is used, 'none' is a valid value as
|
/// Note that 'none' is not a valid name.
|
||||||
/// well, we combine them into one type to make code simpler.
|
|
||||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss, ToResolvedValue, ToShmem)]
|
#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss, ToResolvedValue, ToShmem)]
|
||||||
pub enum CounterStyleOrNone {
|
pub enum CounterStyle {
|
||||||
/// `none`
|
|
||||||
None,
|
|
||||||
/// `<counter-style-name>`
|
/// `<counter-style-name>`
|
||||||
Name(CustomIdent),
|
Name(CustomIdent),
|
||||||
/// `symbols()`
|
/// `symbols()`
|
||||||
|
@ -111,28 +108,25 @@ fn is_symbolic(symbols_type: &SymbolsType) -> bool {
|
||||||
*symbols_type == SymbolsType::Symbolic
|
*symbols_type == SymbolsType::Symbolic
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CounterStyleOrNone {
|
impl CounterStyle {
|
||||||
/// disc value
|
/// disc value
|
||||||
pub fn disc() -> Self {
|
pub fn disc() -> Self {
|
||||||
CounterStyleOrNone::Name(CustomIdent(atom!("disc")))
|
CounterStyle::Name(CustomIdent(atom!("disc")))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// decimal value
|
/// decimal value
|
||||||
pub fn decimal() -> Self {
|
pub fn decimal() -> Self {
|
||||||
CounterStyleOrNone::Name(CustomIdent(atom!("decimal")))
|
CounterStyle::Name(CustomIdent(atom!("decimal")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for CounterStyleOrNone {
|
impl Parse for CounterStyle {
|
||||||
fn parse<'i, 't>(
|
fn parse<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(name) = input.try(|i| parse_counter_style_name(i)) {
|
if let Ok(name) = input.try(|i| parse_counter_style_name(i)) {
|
||||||
return Ok(CounterStyleOrNone::Name(name));
|
return Ok(CounterStyle::Name(name));
|
||||||
}
|
|
||||||
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
|
||||||
return Ok(CounterStyleOrNone::None);
|
|
||||||
}
|
}
|
||||||
input.expect_function_matching("symbols")?;
|
input.expect_function_matching("symbols")?;
|
||||||
input.parse_nested_block(|input| {
|
input.parse_nested_block(|input| {
|
||||||
|
@ -151,12 +145,12 @@ impl Parse for CounterStyleOrNone {
|
||||||
if symbols.0.iter().any(|sym| !sym.is_allowed_in_symbols()) {
|
if symbols.0.iter().any(|sym| !sym.is_allowed_in_symbols()) {
|
||||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||||
}
|
}
|
||||||
Ok(CounterStyleOrNone::Symbols(symbols_type, symbols))
|
Ok(CounterStyle::Symbols(symbols_type, symbols))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecifiedValueInfo for CounterStyleOrNone {
|
impl SpecifiedValueInfo for CounterStyle {
|
||||||
fn collect_completion_keywords(f: KeywordsCollectFn) {
|
fn collect_completion_keywords(f: KeywordsCollectFn) {
|
||||||
// XXX The best approach for implementing this is probably
|
// XXX The best approach for implementing this is probably
|
||||||
// having a CounterStyleName type wrapping CustomIdent, and
|
// having a CounterStyleName type wrapping CustomIdent, and
|
||||||
|
@ -165,7 +159,7 @@ impl SpecifiedValueInfo for CounterStyleOrNone {
|
||||||
// approach here.
|
// approach here.
|
||||||
macro_rules! predefined {
|
macro_rules! predefined {
|
||||||
($($name:expr,)+) => {
|
($($name:expr,)+) => {
|
||||||
f(&["none", "symbols", $($name,)+]);
|
f(&["symbols", $($name,)+]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
include!("../../counter_style/predefined.rs");
|
include!("../../counter_style/predefined.rs");
|
||||||
|
@ -272,9 +266,53 @@ pub struct ZeroToOne<T>(pub T);
|
||||||
ToShmem,
|
ToShmem,
|
||||||
)]
|
)]
|
||||||
#[css(function = "rect", comma)]
|
#[css(function = "rect", comma)]
|
||||||
pub struct ClipRect<LengthOrAuto> {
|
#[repr(C)]
|
||||||
|
pub struct GenericClipRect<LengthOrAuto> {
|
||||||
pub top: LengthOrAuto,
|
pub top: LengthOrAuto,
|
||||||
pub right: LengthOrAuto,
|
pub right: LengthOrAuto,
|
||||||
pub bottom: LengthOrAuto,
|
pub bottom: LengthOrAuto,
|
||||||
pub left: LengthOrAuto,
|
pub left: LengthOrAuto,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub use self::GenericClipRect as ClipRect;
|
||||||
|
|
||||||
|
/// Either a clip-rect or `auto`.
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
#[derive(
|
||||||
|
Animate,
|
||||||
|
Clone,
|
||||||
|
ComputeSquaredDistance,
|
||||||
|
Copy,
|
||||||
|
Debug,
|
||||||
|
MallocSizeOf,
|
||||||
|
Parse,
|
||||||
|
PartialEq,
|
||||||
|
SpecifiedValueInfo,
|
||||||
|
ToAnimatedValue,
|
||||||
|
ToAnimatedZero,
|
||||||
|
ToComputedValue,
|
||||||
|
ToCss,
|
||||||
|
ToResolvedValue,
|
||||||
|
ToShmem,
|
||||||
|
)]
|
||||||
|
#[repr(C, u8)]
|
||||||
|
pub enum GenericClipRectOrAuto<R> {
|
||||||
|
Auto,
|
||||||
|
Rect(R),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use self::GenericClipRectOrAuto as ClipRectOrAuto;
|
||||||
|
|
||||||
|
impl<L> ClipRectOrAuto<L> {
|
||||||
|
/// Returns the `auto` value.
|
||||||
|
#[inline]
|
||||||
|
pub fn auto() -> Self {
|
||||||
|
ClipRectOrAuto::Auto
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether this value is the `auto` value.
|
||||||
|
#[inline]
|
||||||
|
pub fn is_auto(&self) -> bool {
|
||||||
|
matches!(*self, ClipRectOrAuto::Auto)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ use cssparser::Parser;
|
||||||
use style_traits::ParseError;
|
use style_traits::ParseError;
|
||||||
|
|
||||||
/// The fallback of an SVG paint server value.
|
/// The fallback of an SVG paint server value.
|
||||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Animate,
|
Animate,
|
||||||
Clone,
|
Clone,
|
||||||
|
@ -43,8 +42,6 @@ pub use self::GenericSVGPaintFallback as SVGPaintFallback;
|
||||||
/// An SVG paint value
|
/// An SVG paint value
|
||||||
///
|
///
|
||||||
/// <https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint>
|
/// <https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint>
|
||||||
///
|
|
||||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
|
||||||
#[animation(no_bound(Url))]
|
#[animation(no_bound(Url))]
|
||||||
#[derive(
|
#[derive(
|
||||||
Animate,
|
Animate,
|
||||||
|
@ -84,8 +81,6 @@ impl<C, U> Default for SVGPaint<C, U> {
|
||||||
///
|
///
|
||||||
/// Whereas the spec only allows PaintServer to have a fallback, Gecko lets the
|
/// Whereas the spec only allows PaintServer to have a fallback, Gecko lets the
|
||||||
/// context properties have a fallback as well.
|
/// context properties have a fallback as well.
|
||||||
///
|
|
||||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
|
||||||
#[animation(no_bound(U))]
|
#[animation(no_bound(U))]
|
||||||
#[derive(
|
#[derive(
|
||||||
Animate,
|
Animate,
|
||||||
|
|
|
@ -151,7 +151,6 @@ fn is_same<N: PartialEq>(x: &N, y: &N) -> bool {
|
||||||
)]
|
)]
|
||||||
#[repr(C, u8)]
|
#[repr(C, u8)]
|
||||||
/// A single operation in the list of a `transform` value
|
/// A single operation in the list of a `transform` value
|
||||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
|
||||||
pub enum GenericTransformOperation<Angle, Number, Length, Integer, LengthPercentage>
|
pub enum GenericTransformOperation<Angle, Number, Length, Integer, LengthPercentage>
|
||||||
where
|
where
|
||||||
Angle: Zero,
|
Angle: Zero,
|
||||||
|
|
|
@ -5,8 +5,6 @@
|
||||||
//! Generic types for url properties.
|
//! Generic types for url properties.
|
||||||
|
|
||||||
/// An image url or none, used for example in list-style-image
|
/// An image url or none, used for example in list-style-image
|
||||||
///
|
|
||||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Animate,
|
Animate,
|
||||||
Clone,
|
Clone,
|
||||||
|
|
|
@ -105,16 +105,12 @@ pub enum DisplayInside {
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
MozGrid,
|
MozGrid,
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
MozInlineGrid,
|
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
MozGridGroup,
|
MozGridGroup,
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
MozGridLine,
|
MozGridLine,
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
MozStack,
|
MozStack,
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
MozInlineStack,
|
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
MozDeck,
|
MozDeck,
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
MozGroupbox,
|
MozGroupbox,
|
||||||
|
@ -243,16 +239,12 @@ impl Display {
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub const MozGrid: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozGrid);
|
pub const MozGrid: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozGrid);
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub const MozInlineGrid: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozInlineGrid);
|
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
pub const MozGridGroup: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozGridGroup);
|
pub const MozGridGroup: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozGridGroup);
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub const MozGridLine: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozGridLine);
|
pub const MozGridLine: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozGridLine);
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub const MozStack: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozStack);
|
pub const MozStack: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozStack);
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub const MozInlineStack: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozInlineStack);
|
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
pub const MozDeck: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozDeck);
|
pub const MozDeck: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozDeck);
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub const MozGroupbox: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozGroupbox);
|
pub const MozGroupbox: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozGroupbox);
|
||||||
|
@ -422,7 +414,6 @@ impl Display {
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
DisplayOutside::XUL => match self.inside() {
|
DisplayOutside::XUL => match self.inside() {
|
||||||
DisplayInside::MozBox => Display::MozInlineBox,
|
DisplayInside::MozBox => Display::MozInlineBox,
|
||||||
DisplayInside::MozStack => Display::MozInlineStack,
|
|
||||||
_ => *self,
|
_ => *self,
|
||||||
},
|
},
|
||||||
_ => *self,
|
_ => *self,
|
||||||
|
@ -469,10 +460,6 @@ impl ToCss for Display {
|
||||||
Display::WebkitInlineBox => dest.write_str("-webkit-inline-box"),
|
Display::WebkitInlineBox => dest.write_str("-webkit-inline-box"),
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
Display::MozInlineBox => dest.write_str("-moz-inline-box"),
|
Display::MozInlineBox => dest.write_str("-moz-inline-box"),
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
Display::MozInlineGrid => dest.write_str("-moz-inline-grid"),
|
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
Display::MozInlineStack => dest.write_str("-moz-inline-stack"),
|
|
||||||
#[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
|
#[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
|
||||||
Display::TableCaption => dest.write_str("table-caption"),
|
Display::TableCaption => dest.write_str("table-caption"),
|
||||||
_ => match (outside, inside) {
|
_ => match (outside, inside) {
|
||||||
|
@ -662,16 +649,12 @@ impl Parse for Display {
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
"-moz-grid" if moz_display_values_enabled(context) => Display::MozGrid,
|
"-moz-grid" if moz_display_values_enabled(context) => Display::MozGrid,
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
"-moz-inline-grid" if moz_display_values_enabled(context) => Display::MozInlineGrid,
|
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
"-moz-grid-group" if moz_display_values_enabled(context) => Display::MozGridGroup,
|
"-moz-grid-group" if moz_display_values_enabled(context) => Display::MozGridGroup,
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
"-moz-grid-line" if moz_display_values_enabled(context) => Display::MozGridLine,
|
"-moz-grid-line" if moz_display_values_enabled(context) => Display::MozGridLine,
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
"-moz-stack" if moz_display_values_enabled(context) => Display::MozStack,
|
"-moz-stack" if moz_display_values_enabled(context) => Display::MozStack,
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
"-moz-inline-stack" if moz_display_values_enabled(context) => Display::MozInlineStack,
|
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
"-moz-deck" if moz_display_values_enabled(context) => Display::MozDeck,
|
"-moz-deck" if moz_display_values_enabled(context) => Display::MozDeck,
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
"-moz-groupbox" if moz_display_values_enabled(context) => Display::MozGroupbox,
|
"-moz-groupbox" if moz_display_values_enabled(context) => Display::MozGroupbox,
|
||||||
|
@ -688,6 +671,7 @@ impl SpecifiedValueInfo for Display {
|
||||||
"contents",
|
"contents",
|
||||||
"flex",
|
"flex",
|
||||||
"flow-root",
|
"flow-root",
|
||||||
|
"flow-root list-item",
|
||||||
"grid",
|
"grid",
|
||||||
"inline",
|
"inline",
|
||||||
"inline-block",
|
"inline-block",
|
||||||
|
|
|
@ -8,11 +8,11 @@
|
||||||
use crate::computed_values::list_style_type::T as ListStyleType;
|
use crate::computed_values::list_style_type::T as ListStyleType;
|
||||||
use crate::parser::{Parse, ParserContext};
|
use crate::parser::{Parse, ParserContext};
|
||||||
use crate::values::generics::counters as generics;
|
use crate::values::generics::counters as generics;
|
||||||
use crate::values::generics::counters::CounterIncrement as GenericCounterIncrement;
|
|
||||||
use crate::values::generics::counters::CounterPair;
|
use crate::values::generics::counters::CounterPair;
|
||||||
use crate::values::generics::counters::CounterSetOrReset as GenericCounterSetOrReset;
|
use crate::values::generics::counters::GenericCounterIncrement;
|
||||||
|
use crate::values::generics::counters::GenericCounterSetOrReset;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use crate::values::generics::CounterStyleOrNone;
|
use crate::values::generics::CounterStyle;
|
||||||
use crate::values::specified::url::SpecifiedImageUrl;
|
use crate::values::specified::url::SpecifiedImageUrl;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use crate::values::specified::Attr;
|
use crate::values::specified::Attr;
|
||||||
|
@ -98,13 +98,13 @@ impl Content {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
fn parse_counter_style(context: &ParserContext, input: &mut Parser) -> CounterStyleOrNone {
|
fn parse_counter_style(context: &ParserContext, input: &mut Parser) -> CounterStyle {
|
||||||
input
|
input
|
||||||
.try(|input| {
|
.try(|input| {
|
||||||
input.expect_comma()?;
|
input.expect_comma()?;
|
||||||
CounterStyleOrNone::parse(context, input)
|
CounterStyle::parse(context, input)
|
||||||
})
|
})
|
||||||
.unwrap_or(CounterStyleOrNone::decimal())
|
.unwrap_or(CounterStyle::decimal())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,9 @@ use crate::properties::longhands::system_font::SystemFont;
|
||||||
use crate::values::computed::font::{FamilyName, FontFamilyList, FontStyleAngle, SingleFontFamily};
|
use crate::values::computed::font::{FamilyName, FontFamilyList, FontStyleAngle, SingleFontFamily};
|
||||||
use crate::values::computed::{font as computed, Length, NonNegativeLength};
|
use crate::values::computed::{font as computed, Length, NonNegativeLength};
|
||||||
use crate::values::computed::{Angle as ComputedAngle, Percentage as ComputedPercentage};
|
use crate::values::computed::{Angle as ComputedAngle, Percentage as ComputedPercentage};
|
||||||
use crate::values::computed::{Context, ToComputedValue};
|
use crate::values::computed::{CSSPixelLength, Context, ToComputedValue};
|
||||||
|
use crate::values::generics::font::VariationValue;
|
||||||
use crate::values::generics::font::{self as generics, FeatureTagValue, FontSettings, FontTag};
|
use crate::values::generics::font::{self as generics, FeatureTagValue, FontSettings, FontTag};
|
||||||
use crate::values::generics::font::{KeywordSize, VariationValue};
|
|
||||||
use crate::values::generics::NonNegative;
|
use crate::values::generics::NonNegative;
|
||||||
use crate::values::specified::length::{FontBaseSize, AU_PER_PT, AU_PER_PX};
|
use crate::values::specified::length::{FontBaseSize, AU_PER_PT, AU_PER_PX};
|
||||||
use crate::values::specified::{AllowQuirks, Angle, Integer, LengthPercentage};
|
use crate::values::specified::{AllowQuirks, Angle, Integer, LengthPercentage};
|
||||||
|
@ -481,6 +481,115 @@ impl ToComputedValue for FontStretch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// CSS font keywords
|
||||||
|
#[derive(
|
||||||
|
Animate,
|
||||||
|
Clone,
|
||||||
|
ComputeSquaredDistance,
|
||||||
|
Copy,
|
||||||
|
Debug,
|
||||||
|
MallocSizeOf,
|
||||||
|
Parse,
|
||||||
|
PartialEq,
|
||||||
|
SpecifiedValueInfo,
|
||||||
|
ToAnimatedValue,
|
||||||
|
ToAnimatedZero,
|
||||||
|
ToCss,
|
||||||
|
ToShmem,
|
||||||
|
)]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub enum KeywordSize {
|
||||||
|
#[css(keyword = "xx-small")]
|
||||||
|
XXSmall,
|
||||||
|
XSmall,
|
||||||
|
Small,
|
||||||
|
Medium,
|
||||||
|
Large,
|
||||||
|
XLarge,
|
||||||
|
#[css(keyword = "xx-large")]
|
||||||
|
XXLarge,
|
||||||
|
#[css(keyword = "xxx-large")]
|
||||||
|
XXXLarge,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KeywordSize {
|
||||||
|
/// Convert to an HTML <font size> value
|
||||||
|
#[inline]
|
||||||
|
pub fn html_size(self) -> u8 {
|
||||||
|
self as u8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for KeywordSize {
|
||||||
|
fn default() -> Self {
|
||||||
|
KeywordSize::Medium
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Animate,
|
||||||
|
Clone,
|
||||||
|
ComputeSquaredDistance,
|
||||||
|
Copy,
|
||||||
|
Debug,
|
||||||
|
MallocSizeOf,
|
||||||
|
PartialEq,
|
||||||
|
ToAnimatedValue,
|
||||||
|
ToAnimatedZero,
|
||||||
|
ToCss,
|
||||||
|
ToShmem,
|
||||||
|
)]
|
||||||
|
/// Additional information for keyword-derived font sizes.
|
||||||
|
pub struct KeywordInfo {
|
||||||
|
/// The keyword used
|
||||||
|
pub kw: KeywordSize,
|
||||||
|
/// A factor to be multiplied by the computed size of the keyword
|
||||||
|
#[css(skip)]
|
||||||
|
pub factor: f32,
|
||||||
|
/// An additional fixed offset to add to the kw * factor in the case of
|
||||||
|
/// `calc()`.
|
||||||
|
#[css(skip)]
|
||||||
|
pub offset: CSSPixelLength,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KeywordInfo {
|
||||||
|
/// KeywordInfo value for font-size: medium
|
||||||
|
pub fn medium() -> Self {
|
||||||
|
Self::new(KeywordSize::Medium)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(kw: KeywordSize) -> Self {
|
||||||
|
KeywordInfo {
|
||||||
|
kw,
|
||||||
|
factor: 1.,
|
||||||
|
offset: CSSPixelLength::new(0.),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the final size for this font-size keyword, accounting for
|
||||||
|
/// text-zoom.
|
||||||
|
fn to_computed_value(&self, context: &Context) -> CSSPixelLength {
|
||||||
|
let base = context.maybe_zoom_text(self.kw.to_computed_value(context).0);
|
||||||
|
base * self.factor + context.maybe_zoom_text(self.offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Given a parent keyword info (self), apply an additional factor/offset to
|
||||||
|
/// it.
|
||||||
|
pub fn compose(self, factor: f32, offset: CSSPixelLength) -> Self {
|
||||||
|
KeywordInfo {
|
||||||
|
kw: self.kw,
|
||||||
|
factor: self.factor * factor,
|
||||||
|
offset: self.offset * factor + offset,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpecifiedValueInfo for KeywordInfo {
|
||||||
|
fn collect_completion_keywords(f: KeywordsCollectFn) {
|
||||||
|
<KeywordSize as SpecifiedValueInfo>::collect_completion_keywords(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
|
||||||
/// A specified font-size value
|
/// A specified font-size value
|
||||||
pub enum FontSize {
|
pub enum FontSize {
|
||||||
|
@ -652,27 +761,6 @@ impl ToComputedValue for FontSizeAdjust {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Additional information for specified keyword-derived font sizes.
|
|
||||||
pub type KeywordInfo = generics::KeywordInfo<NonNegativeLength>;
|
|
||||||
|
|
||||||
impl KeywordInfo {
|
|
||||||
/// Computes the final size for this font-size keyword, accounting for
|
|
||||||
/// text-zoom.
|
|
||||||
pub fn to_computed_value(&self, context: &Context) -> NonNegativeLength {
|
|
||||||
let base = context.maybe_zoom_text(self.kw.to_computed_value(context));
|
|
||||||
base.scale_by(self.factor) + context.maybe_zoom_text(self.offset)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given a parent keyword info (self), apply an additional factor/offset to it
|
|
||||||
pub fn compose(self, factor: f32, offset: NonNegativeLength) -> Self {
|
|
||||||
KeywordInfo {
|
|
||||||
kw: self.kw,
|
|
||||||
factor: self.factor * factor,
|
|
||||||
offset: self.offset.scale_by(factor) + offset,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This is the ratio applied for font-size: larger
|
/// This is the ratio applied for font-size: larger
|
||||||
/// and smaller by both Firefox and Chrome
|
/// and smaller by both Firefox and Chrome
|
||||||
const LARGER_FONT_SIZE_RATIO: f32 = 1.2;
|
const LARGER_FONT_SIZE_RATIO: f32 = 1.2;
|
||||||
|
@ -789,20 +877,17 @@ impl ToComputedValue for KeywordSize {
|
||||||
impl FontSize {
|
impl FontSize {
|
||||||
/// <https://html.spec.whatwg.org/multipage/#rules-for-parsing-a-legacy-font-size>
|
/// <https://html.spec.whatwg.org/multipage/#rules-for-parsing-a-legacy-font-size>
|
||||||
pub fn from_html_size(size: u8) -> Self {
|
pub fn from_html_size(size: u8) -> Self {
|
||||||
FontSize::Keyword(
|
FontSize::Keyword(KeywordInfo::new(match size {
|
||||||
match size {
|
// If value is less than 1, let it be 1.
|
||||||
// If value is less than 1, let it be 1.
|
0 | 1 => KeywordSize::XSmall,
|
||||||
0 | 1 => KeywordSize::XSmall,
|
2 => KeywordSize::Small,
|
||||||
2 => KeywordSize::Small,
|
3 => KeywordSize::Medium,
|
||||||
3 => KeywordSize::Medium,
|
4 => KeywordSize::Large,
|
||||||
4 => KeywordSize::Large,
|
5 => KeywordSize::XLarge,
|
||||||
5 => KeywordSize::XLarge,
|
6 => KeywordSize::XXLarge,
|
||||||
6 => KeywordSize::XXLarge,
|
// If value is greater than 7, let it be 7.
|
||||||
// If value is greater than 7, let it be 7.
|
_ => KeywordSize::XXXLarge,
|
||||||
_ => KeywordSize::XXXLarge,
|
}))
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compute it against a given base font size
|
/// Compute it against a given base font size
|
||||||
|
@ -819,7 +904,7 @@ impl FontSize {
|
||||||
.get_parent_font()
|
.get_parent_font()
|
||||||
.clone_font_size()
|
.clone_font_size()
|
||||||
.keyword_info
|
.keyword_info
|
||||||
.map(|i| i.compose(factor, Au(0).into()))
|
.map(|i| i.compose(factor, CSSPixelLength::new(0.)))
|
||||||
};
|
};
|
||||||
let mut info = None;
|
let mut info = None;
|
||||||
let size = match *self {
|
let size = match *self {
|
||||||
|
@ -829,17 +914,15 @@ impl FontSize {
|
||||||
// Tack the em unit onto the factor
|
// Tack the em unit onto the factor
|
||||||
info = compose_keyword(em);
|
info = compose_keyword(em);
|
||||||
}
|
}
|
||||||
value.to_computed_value(context, base_size).into()
|
value.to_computed_value(context, base_size)
|
||||||
},
|
},
|
||||||
FontSize::Length(LengthPercentage::Length(NoCalcLength::ServoCharacterWidth(
|
FontSize::Length(LengthPercentage::Length(NoCalcLength::ServoCharacterWidth(
|
||||||
value,
|
value,
|
||||||
))) => value.to_computed_value(base_size.resolve(context)).into(),
|
))) => value.to_computed_value(base_size.resolve(context)),
|
||||||
FontSize::Length(LengthPercentage::Length(NoCalcLength::Absolute(ref l))) => {
|
FontSize::Length(LengthPercentage::Length(NoCalcLength::Absolute(ref l))) => {
|
||||||
context.maybe_zoom_text(l.to_computed_value(context).into())
|
context.maybe_zoom_text(l.to_computed_value(context))
|
||||||
},
|
|
||||||
FontSize::Length(LengthPercentage::Length(ref l)) => {
|
|
||||||
l.to_computed_value(context).into()
|
|
||||||
},
|
},
|
||||||
|
FontSize::Length(LengthPercentage::Length(ref l)) => l.to_computed_value(context),
|
||||||
FontSize::Length(LengthPercentage::Percentage(pc)) => {
|
FontSize::Length(LengthPercentage::Percentage(pc)) => {
|
||||||
// If the parent font was keyword-derived, this is too.
|
// If the parent font was keyword-derived, this is too.
|
||||||
// Tack the % onto the factor
|
// Tack the % onto the factor
|
||||||
|
@ -871,29 +954,32 @@ impl FontSize {
|
||||||
context,
|
context,
|
||||||
FontBaseSize::InheritedStyleButStripEmUnits,
|
FontBaseSize::InheritedStyleButStripEmUnits,
|
||||||
)
|
)
|
||||||
.length_component();
|
.unclamped_length();
|
||||||
|
|
||||||
info = parent.keyword_info.map(|i| i.compose(ratio, abs.into()));
|
info = parent.keyword_info.map(|i| i.compose(ratio, abs));
|
||||||
}
|
}
|
||||||
let calc = calc.to_computed_value_zoomed(context, base_size);
|
let calc = calc.to_computed_value_zoomed(context, base_size);
|
||||||
calc.to_used_value(base_size.resolve(context)).into()
|
// FIXME(emilio): we _could_ use clamp_to_non_negative()
|
||||||
|
// everywhere, without affecting behavior in theory, since the
|
||||||
|
// others should reject negatives during parsing. But SMIL
|
||||||
|
// allows parsing negatives, and relies on us _not_ doing that
|
||||||
|
// clamping. That's so bonkers :(
|
||||||
|
CSSPixelLength::from(calc.to_used_value(base_size.resolve(context)))
|
||||||
|
.clamp_to_non_negative()
|
||||||
},
|
},
|
||||||
FontSize::Keyword(i) => {
|
FontSize::Keyword(i) => {
|
||||||
// As a specified keyword, this is keyword derived
|
// As a specified keyword, this is keyword derived
|
||||||
info = Some(i);
|
info = Some(i);
|
||||||
i.to_computed_value(context)
|
i.to_computed_value(context).clamp_to_non_negative()
|
||||||
},
|
},
|
||||||
FontSize::Smaller => {
|
FontSize::Smaller => {
|
||||||
info = compose_keyword(1. / LARGER_FONT_SIZE_RATIO);
|
info = compose_keyword(1. / LARGER_FONT_SIZE_RATIO);
|
||||||
FontRelativeLength::Em(1. / LARGER_FONT_SIZE_RATIO)
|
FontRelativeLength::Em(1. / LARGER_FONT_SIZE_RATIO)
|
||||||
.to_computed_value(context, base_size)
|
.to_computed_value(context, base_size)
|
||||||
.into()
|
|
||||||
},
|
},
|
||||||
FontSize::Larger => {
|
FontSize::Larger => {
|
||||||
info = compose_keyword(LARGER_FONT_SIZE_RATIO);
|
info = compose_keyword(LARGER_FONT_SIZE_RATIO);
|
||||||
FontRelativeLength::Em(LARGER_FONT_SIZE_RATIO)
|
FontRelativeLength::Em(LARGER_FONT_SIZE_RATIO).to_computed_value(context, base_size)
|
||||||
.to_computed_value(context, base_size)
|
|
||||||
.into()
|
|
||||||
},
|
},
|
||||||
|
|
||||||
FontSize::System(_) => {
|
FontSize::System(_) => {
|
||||||
|
@ -903,12 +989,18 @@ impl FontSize {
|
||||||
}
|
}
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
{
|
{
|
||||||
context.cached_system_font.as_ref().unwrap().font_size.size
|
context
|
||||||
|
.cached_system_font
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.font_size
|
||||||
|
.size
|
||||||
|
.0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
computed::FontSize {
|
computed::FontSize {
|
||||||
size: size,
|
size: NonNegative(size),
|
||||||
keyword_info: info,
|
keyword_info: info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -952,7 +1044,7 @@ impl FontSize {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(kw) = input.try(KeywordSize::parse) {
|
if let Ok(kw) = input.try(KeywordSize::parse) {
|
||||||
return Ok(FontSize::Keyword(kw.into()));
|
return Ok(FontSize::Keyword(KeywordInfo::new(kw)));
|
||||||
}
|
}
|
||||||
|
|
||||||
try_match_ident_ignore_ascii_case! { input,
|
try_match_ident_ignore_ascii_case! { input,
|
||||||
|
@ -998,6 +1090,7 @@ bitflags! {
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToResolvedValue, ToShmem,
|
Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToResolvedValue, ToShmem,
|
||||||
)]
|
)]
|
||||||
|
#[repr(C, u8)]
|
||||||
/// Set of variant alternates
|
/// Set of variant alternates
|
||||||
pub enum VariantAlternates {
|
pub enum VariantAlternates {
|
||||||
/// Enables display of stylistic alternates
|
/// Enables display of stylistic alternates
|
||||||
|
@ -1005,10 +1098,10 @@ pub enum VariantAlternates {
|
||||||
Stylistic(CustomIdent),
|
Stylistic(CustomIdent),
|
||||||
/// Enables display with stylistic sets
|
/// Enables display with stylistic sets
|
||||||
#[css(comma, function)]
|
#[css(comma, function)]
|
||||||
Styleset(#[css(iterable)] Box<[CustomIdent]>),
|
Styleset(#[css(iterable)] crate::OwnedSlice<CustomIdent>),
|
||||||
/// Enables display of specific character variants
|
/// Enables display of specific character variants
|
||||||
#[css(comma, function)]
|
#[css(comma, function)]
|
||||||
CharacterVariant(#[css(iterable)] Box<[CustomIdent]>),
|
CharacterVariant(#[css(iterable)] crate::OwnedSlice<CustomIdent>),
|
||||||
/// Enables display of swash glyphs
|
/// Enables display of swash glyphs
|
||||||
#[css(function)]
|
#[css(function)]
|
||||||
Swash(CustomIdent),
|
Swash(CustomIdent),
|
||||||
|
@ -1023,11 +1116,20 @@ pub enum VariantAlternates {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToResolvedValue, ToShmem,
|
Clone,
|
||||||
|
Debug,
|
||||||
|
Default,
|
||||||
|
MallocSizeOf,
|
||||||
|
PartialEq,
|
||||||
|
SpecifiedValueInfo,
|
||||||
|
ToCss,
|
||||||
|
ToResolvedValue,
|
||||||
|
ToShmem,
|
||||||
)]
|
)]
|
||||||
|
#[repr(transparent)]
|
||||||
/// List of Variant Alternates
|
/// List of Variant Alternates
|
||||||
pub struct VariantAlternatesList(
|
pub struct VariantAlternatesList(
|
||||||
#[css(if_empty = "normal", iterable)] pub Box<[VariantAlternates]>,
|
#[css(if_empty = "normal", iterable)] crate::OwnedSlice<VariantAlternates>,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl VariantAlternatesList {
|
impl VariantAlternatesList {
|
||||||
|
@ -1059,7 +1161,7 @@ impl FontVariantAlternates {
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Get initial specified value with VariantAlternatesList
|
/// Get initial specified value with VariantAlternatesList
|
||||||
pub fn get_initial_specified_value() -> Self {
|
pub fn get_initial_specified_value() -> Self {
|
||||||
FontVariantAlternates::Value(VariantAlternatesList(vec![].into_boxed_slice()))
|
FontVariantAlternates::Value(Default::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
system_font_methods!(FontVariantAlternates, font_variant_alternates);
|
system_font_methods!(FontVariantAlternates, font_variant_alternates);
|
||||||
|
@ -1093,16 +1195,14 @@ impl Parse for FontVariantAlternates {
|
||||||
_: &ParserContext,
|
_: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
) -> Result<FontVariantAlternates, ParseError<'i>> {
|
) -> Result<FontVariantAlternates, ParseError<'i>> {
|
||||||
let mut alternates = Vec::new();
|
|
||||||
if input
|
if input
|
||||||
.try(|input| input.expect_ident_matching("normal"))
|
.try(|input| input.expect_ident_matching("normal"))
|
||||||
.is_ok()
|
.is_ok()
|
||||||
{
|
{
|
||||||
return Ok(FontVariantAlternates::Value(VariantAlternatesList(
|
return Ok(FontVariantAlternates::Value(Default::default()));
|
||||||
alternates.into_boxed_slice(),
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut alternates = Vec::new();
|
||||||
let mut parsed_alternates = VariantAlternatesParsingFlags::empty();
|
let mut parsed_alternates = VariantAlternatesParsingFlags::empty();
|
||||||
macro_rules! check_if_parsed(
|
macro_rules! check_if_parsed(
|
||||||
($input:expr, $flag:path) => (
|
($input:expr, $flag:path) => (
|
||||||
|
@ -1156,7 +1256,7 @@ impl Parse for FontVariantAlternates {
|
||||||
let location = i.current_source_location();
|
let location = i.current_source_location();
|
||||||
CustomIdent::from_ident(location, i.expect_ident()?, &[])
|
CustomIdent::from_ident(location, i.expect_ident()?, &[])
|
||||||
})?;
|
})?;
|
||||||
alternates.push(VariantAlternates::Styleset(idents.into_boxed_slice()));
|
alternates.push(VariantAlternates::Styleset(idents.into()));
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
"character-variant" => {
|
"character-variant" => {
|
||||||
|
@ -1165,7 +1265,7 @@ impl Parse for FontVariantAlternates {
|
||||||
let location = i.current_source_location();
|
let location = i.current_source_location();
|
||||||
CustomIdent::from_ident(location, i.expect_ident()?, &[])
|
CustomIdent::from_ident(location, i.expect_ident()?, &[])
|
||||||
})?;
|
})?;
|
||||||
alternates.push(VariantAlternates::CharacterVariant(idents.into_boxed_slice()));
|
alternates.push(VariantAlternates::CharacterVariant(idents.into()));
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
_ => return Err(i.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
|
_ => return Err(i.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
|
||||||
|
@ -1179,7 +1279,7 @@ impl Parse for FontVariantAlternates {
|
||||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||||
}
|
}
|
||||||
Ok(FontVariantAlternates::Value(VariantAlternatesList(
|
Ok(FontVariantAlternates::Value(VariantAlternatesList(
|
||||||
alternates.into_boxed_slice(),
|
alternates.into(),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
use crate::parser::{Parse, ParserContext};
|
use crate::parser::{Parse, ParserContext};
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use crate::values::generics::CounterStyleOrNone;
|
use crate::values::generics::CounterStyle;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use crate::values::CustomIdent;
|
use crate::values::CustomIdent;
|
||||||
use cssparser::{Parser, Token};
|
use cssparser::{Parser, Token};
|
||||||
|
@ -27,8 +27,10 @@ use style_traits::{ParseError, StyleParseErrorKind};
|
||||||
ToShmem,
|
ToShmem,
|
||||||
)]
|
)]
|
||||||
pub enum ListStyleType {
|
pub enum ListStyleType {
|
||||||
/// <counter-style> | none
|
/// `none`
|
||||||
CounterStyle(CounterStyleOrNone),
|
None,
|
||||||
|
/// <counter-style>
|
||||||
|
CounterStyle(CounterStyle),
|
||||||
/// <string>
|
/// <string>
|
||||||
String(String),
|
String(String),
|
||||||
}
|
}
|
||||||
|
@ -38,7 +40,7 @@ impl ListStyleType {
|
||||||
/// Initial specified value for `list-style-type`.
|
/// Initial specified value for `list-style-type`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn disc() -> Self {
|
pub fn disc() -> Self {
|
||||||
ListStyleType::CounterStyle(CounterStyleOrNone::disc())
|
ListStyleType::CounterStyle(CounterStyle::disc())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert from gecko keyword to list-style-type.
|
/// Convert from gecko keyword to list-style-type.
|
||||||
|
@ -50,10 +52,10 @@ impl ListStyleType {
|
||||||
use crate::gecko_bindings::structs;
|
use crate::gecko_bindings::structs;
|
||||||
|
|
||||||
if value == structs::NS_STYLE_LIST_STYLE_NONE {
|
if value == structs::NS_STYLE_LIST_STYLE_NONE {
|
||||||
return ListStyleType::CounterStyle(CounterStyleOrNone::None);
|
return ListStyleType::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
ListStyleType::CounterStyle(CounterStyleOrNone::Name(CustomIdent(match value {
|
ListStyleType::CounterStyle(CounterStyle::Name(CustomIdent(match value {
|
||||||
structs::NS_STYLE_LIST_STYLE_DISC => atom!("disc"),
|
structs::NS_STYLE_LIST_STYLE_DISC => atom!("disc"),
|
||||||
structs::NS_STYLE_LIST_STYLE_CIRCLE => atom!("circle"),
|
structs::NS_STYLE_LIST_STYLE_CIRCLE => atom!("circle"),
|
||||||
structs::NS_STYLE_LIST_STYLE_SQUARE => atom!("square"),
|
structs::NS_STYLE_LIST_STYLE_SQUARE => atom!("square"),
|
||||||
|
@ -73,10 +75,12 @@ impl Parse for ListStyleType {
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(style) = input.try(|i| CounterStyleOrNone::parse(context, i)) {
|
if let Ok(style) = input.try(|i| CounterStyle::parse(context, i)) {
|
||||||
return Ok(ListStyleType::CounterStyle(style));
|
return Ok(ListStyleType::CounterStyle(style));
|
||||||
}
|
}
|
||||||
|
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
||||||
|
return Ok(ListStyleType::None);
|
||||||
|
}
|
||||||
Ok(ListStyleType::String(
|
Ok(ListStyleType::String(
|
||||||
input.expect_string()?.as_ref().to_owned(),
|
input.expect_string()?.as_ref().to_owned(),
|
||||||
))
|
))
|
||||||
|
@ -126,8 +130,6 @@ pub struct QuoteList(
|
||||||
|
|
||||||
/// Specified and computed `quotes` property: `auto`, `none`, or a list
|
/// Specified and computed `quotes` property: `auto`, `none`, or a list
|
||||||
/// of characters.
|
/// of characters.
|
||||||
///
|
|
||||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone,
|
Clone,
|
||||||
Debug,
|
Debug,
|
||||||
|
|
|
@ -13,7 +13,7 @@ use super::generics::grid::{GridLine as GenericGridLine, TrackBreadth as Generic
|
||||||
use super::generics::grid::{TrackList as GenericTrackList, TrackSize as GenericTrackSize};
|
use super::generics::grid::{TrackList as GenericTrackList, TrackSize as GenericTrackSize};
|
||||||
use super::generics::transform::IsParallelTo;
|
use super::generics::transform::IsParallelTo;
|
||||||
use super::generics::{self, GreaterThanOrEqualToOne, NonNegative};
|
use super::generics::{self, GreaterThanOrEqualToOne, NonNegative};
|
||||||
use super::{Auto, CSSFloat, CSSInteger, Either, None_};
|
use super::{CSSFloat, CSSInteger, Either, None_};
|
||||||
use crate::context::QuirksMode;
|
use crate::context::QuirksMode;
|
||||||
use crate::parser::{Parse, ParserContext};
|
use crate::parser::{Parse, ParserContext};
|
||||||
use crate::values::serialize_atom_identifier;
|
use crate::values::serialize_atom_identifier;
|
||||||
|
@ -78,7 +78,6 @@ pub use self::svg::MozContextProperties;
|
||||||
pub use self::svg::{SVGLength, SVGOpacity, SVGPaint};
|
pub use self::svg::{SVGLength, SVGOpacity, SVGPaint};
|
||||||
pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
|
pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
|
||||||
pub use self::svg_path::SVGPathData;
|
pub use self::svg_path::SVGPathData;
|
||||||
pub use self::table::XSpan;
|
|
||||||
pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight, TextAlign};
|
pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight, TextAlign};
|
||||||
pub use self::text::{OverflowWrap, TextEmphasisPosition, TextEmphasisStyle, WordBreak};
|
pub use self::text::{OverflowWrap, TextEmphasisPosition, TextEmphasisStyle, WordBreak};
|
||||||
pub use self::text::{TextAlignKeyword, TextDecorationLine, TextOverflow, WordSpacing};
|
pub use self::text::{TextAlignKeyword, TextDecorationLine, TextOverflow, WordSpacing};
|
||||||
|
@ -122,7 +121,6 @@ pub mod resolution;
|
||||||
pub mod source_size_list;
|
pub mod source_size_list;
|
||||||
pub mod svg;
|
pub mod svg;
|
||||||
pub mod svg_path;
|
pub mod svg_path;
|
||||||
pub mod table;
|
|
||||||
pub mod text;
|
pub mod text;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
pub mod transform;
|
pub mod transform;
|
||||||
|
@ -641,7 +639,7 @@ pub type GridLine = GenericGridLine<Integer>;
|
||||||
pub type GridTemplateComponent = GenericGridTemplateComponent<LengthPercentage, Integer>;
|
pub type GridTemplateComponent = GenericGridTemplateComponent<LengthPercentage, Integer>;
|
||||||
|
|
||||||
/// rect(...)
|
/// rect(...)
|
||||||
pub type ClipRect = generics::ClipRect<LengthOrAuto>;
|
pub type ClipRect = generics::GenericClipRect<LengthOrAuto>;
|
||||||
|
|
||||||
impl Parse for ClipRect {
|
impl Parse for ClipRect {
|
||||||
fn parse<'i, 't>(
|
fn parse<'i, 't>(
|
||||||
|
@ -654,7 +652,7 @@ impl Parse for ClipRect {
|
||||||
|
|
||||||
impl ClipRect {
|
impl ClipRect {
|
||||||
/// Parses a rect(<top>, <left>, <bottom>, <right>), allowing quirks.
|
/// Parses a rect(<top>, <left>, <bottom>, <right>), allowing quirks.
|
||||||
pub fn parse_quirky<'i, 't>(
|
fn parse_quirky<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks,
|
allow_quirks: AllowQuirks,
|
||||||
|
@ -698,7 +696,7 @@ impl ClipRect {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// rect(...) | auto
|
/// rect(...) | auto
|
||||||
pub type ClipRectOrAuto = Either<ClipRect, Auto>;
|
pub type ClipRectOrAuto = generics::GenericClipRectOrAuto<ClipRect>;
|
||||||
|
|
||||||
impl ClipRectOrAuto {
|
impl ClipRectOrAuto {
|
||||||
/// Parses a ClipRect or Auto, allowing quirks.
|
/// Parses a ClipRect or Auto, allowing quirks.
|
||||||
|
@ -708,10 +706,10 @@ impl ClipRectOrAuto {
|
||||||
allow_quirks: AllowQuirks,
|
allow_quirks: AllowQuirks,
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(v) = input.try(|i| ClipRect::parse_quirky(context, i, allow_quirks)) {
|
if let Ok(v) = input.try(|i| ClipRect::parse_quirky(context, i, allow_quirks)) {
|
||||||
Ok(Either::First(v))
|
return Ok(generics::GenericClipRectOrAuto::Rect(v));
|
||||||
} else {
|
|
||||||
Auto::parse(context, input).map(Either::Second)
|
|
||||||
}
|
}
|
||||||
|
input.expect_ident_matching("auto")?;
|
||||||
|
Ok(generics::GenericClipRectOrAuto::Auto)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ use style_traits::{ParseError, StyleParseErrorKind};
|
||||||
/// The offset-path value.
|
/// The offset-path value.
|
||||||
///
|
///
|
||||||
/// https://drafts.fxtf.org/motion-1/#offset-path-property
|
/// https://drafts.fxtf.org/motion-1/#offset-path-property
|
||||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Animate,
|
Animate,
|
||||||
Clone,
|
Clone,
|
||||||
|
|
|
@ -707,8 +707,6 @@ fn is_name_code_point(c: char) -> bool {
|
||||||
/// The syntax of this property also provides a visualization of the structure
|
/// The syntax of this property also provides a visualization of the structure
|
||||||
/// of the grid, making the overall layout of the grid container easier to
|
/// of the grid, making the overall layout of the grid container easier to
|
||||||
/// understand.
|
/// understand.
|
||||||
///
|
|
||||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
|
||||||
#[repr(C, u8)]
|
#[repr(C, u8)]
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone,
|
Clone,
|
||||||
|
|
|
@ -106,13 +106,13 @@ pub enum PaintOrder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Number of non-normal components
|
/// Number of non-normal components
|
||||||
const PAINT_ORDER_COUNT: u8 = 3;
|
pub const PAINT_ORDER_COUNT: u8 = 3;
|
||||||
|
|
||||||
/// Number of bits for each component
|
/// Number of bits for each component
|
||||||
const PAINT_ORDER_SHIFT: u8 = 2;
|
pub const PAINT_ORDER_SHIFT: u8 = 2;
|
||||||
|
|
||||||
/// Mask with above bits set
|
/// Mask with above bits set
|
||||||
const PAINT_ORDER_MASK: u8 = 0b11;
|
pub const PAINT_ORDER_MASK: u8 = 0b11;
|
||||||
|
|
||||||
/// The specified value is tree `PaintOrder` values packed into the
|
/// The specified value is tree `PaintOrder` values packed into the
|
||||||
/// bitfields below, as a six-bit field, of 3 two-bit pairs
|
/// bitfields below, as a six-bit field, of 3 two-bit pairs
|
||||||
|
@ -135,6 +135,7 @@ const PAINT_ORDER_MASK: u8 = 0b11;
|
||||||
ToResolvedValue,
|
ToResolvedValue,
|
||||||
ToShmem,
|
ToShmem,
|
||||||
)]
|
)]
|
||||||
|
#[repr(transparent)]
|
||||||
pub struct SVGPaintOrder(pub u8);
|
pub struct SVGPaintOrder(pub u8);
|
||||||
|
|
||||||
impl SVGPaintOrder {
|
impl SVGPaintOrder {
|
||||||
|
@ -146,7 +147,7 @@ impl SVGPaintOrder {
|
||||||
/// Get variant of `paint-order`
|
/// Get variant of `paint-order`
|
||||||
pub fn order_at(&self, pos: u8) -> PaintOrder {
|
pub fn order_at(&self, pos: u8) -> PaintOrder {
|
||||||
// Safe because PaintOrder covers all possible patterns.
|
// Safe because PaintOrder covers all possible patterns.
|
||||||
unsafe { ::std::mem::transmute((self.0 >> pos * PAINT_ORDER_SHIFT) & PAINT_ORDER_MASK) }
|
unsafe { std::mem::transmute((self.0 >> pos * PAINT_ORDER_SHIFT) & PAINT_ORDER_MASK) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
//! Specified types for table properties.
|
|
||||||
|
|
||||||
use crate::parser::{Parse, ParserContext};
|
|
||||||
use cssparser::Parser;
|
|
||||||
use style_traits::{ParseError, StyleParseErrorKind};
|
|
||||||
|
|
||||||
#[derive(
|
|
||||||
Clone,
|
|
||||||
Copy,
|
|
||||||
Debug,
|
|
||||||
MallocSizeOf,
|
|
||||||
PartialEq,
|
|
||||||
SpecifiedValueInfo,
|
|
||||||
ToComputedValue,
|
|
||||||
ToCss,
|
|
||||||
ToResolvedValue,
|
|
||||||
ToShmem,
|
|
||||||
)]
|
|
||||||
/// span. for `<col span>` pres attr
|
|
||||||
pub struct XSpan(#[css(skip)] pub i32);
|
|
||||||
|
|
||||||
impl Parse for XSpan {
|
|
||||||
// never parse it, only set via presentation attribute
|
|
||||||
fn parse<'i, 't>(
|
|
||||||
_: &ParserContext,
|
|
||||||
input: &mut Parser<'i, 't>,
|
|
||||||
) -> Result<XSpan, ParseError<'i>> {
|
|
||||||
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -89,9 +89,7 @@ impl ToComputedValue for LineHeight {
|
||||||
GenericLineHeight::Length(ref non_negative_lp) => {
|
GenericLineHeight::Length(ref non_negative_lp) => {
|
||||||
let result = match non_negative_lp.0 {
|
let result = match non_negative_lp.0 {
|
||||||
LengthPercentage::Length(NoCalcLength::Absolute(ref abs)) => {
|
LengthPercentage::Length(NoCalcLength::Absolute(ref abs)) => {
|
||||||
context
|
context.maybe_zoom_text(abs.to_computed_value(context))
|
||||||
.maybe_zoom_text(abs.to_computed_value(context).into())
|
|
||||||
.0
|
|
||||||
},
|
},
|
||||||
LengthPercentage::Length(ref length) => length.to_computed_value(context),
|
LengthPercentage::Length(ref length) => length.to_computed_value(context),
|
||||||
LengthPercentage::Percentage(ref p) => FontRelativeLength::Em(p.0)
|
LengthPercentage::Percentage(ref p) => FontRelativeLength::Em(p.0)
|
||||||
|
@ -133,7 +131,6 @@ impl ToComputedValue for LineHeight {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A generic value for the `text-overflow` property.
|
/// A generic value for the `text-overflow` property.
|
||||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
|
||||||
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
|
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
|
||||||
#[repr(C, u8)]
|
#[repr(C, u8)]
|
||||||
pub enum TextOverflowSide {
|
pub enum TextOverflowSide {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue