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::values::computed::effects::SimpleShadow;
|
||||
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::image::{GradientKind, PaintWorklet};
|
||||
use style::values::specified::ui::CursorKind;
|
||||
use style::values::{Either, RGBA};
|
||||
use style::values::RGBA;
|
||||
use style_traits::ToCss;
|
||||
use webrender_api::units::{LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D};
|
||||
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.
|
||||
let style_clip_rect = match self.fragment.style().get_effects().clip {
|
||||
Either::First(style_clip_rect) => style_clip_rect,
|
||||
_ => return,
|
||||
ClipRectOrAuto::Rect(ref r) => r,
|
||||
ClipRectOrAuto::Auto => return,
|
||||
};
|
||||
|
||||
// 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.
|
||||
let mut layout_context = self.build_layout_context(guards.clone(), true, &map);
|
||||
|
||||
let pool;
|
||||
let (thread_pool, num_threads) = if self.parallel_flag {
|
||||
(
|
||||
STYLE_THREAD_POOL.style_thread_pool.as_ref(),
|
||||
STYLE_THREAD_POOL.num_threads,
|
||||
)
|
||||
pool = STYLE_THREAD_POOL.pool();
|
||||
(pool.as_ref(), STYLE_THREAD_POOL.num_threads)
|
||||
} else {
|
||||
(None, 1)
|
||||
};
|
||||
|
@ -1859,8 +1858,10 @@ impl LayoutThread {
|
|||
|| {
|
||||
let profiler_metadata = self.profiler_metadata();
|
||||
|
||||
let pool;
|
||||
let thread_pool = if self.parallel_flag {
|
||||
STYLE_THREAD_POOL.style_thread_pool.as_ref()
|
||||
pool = STYLE_THREAD_POOL.pool();
|
||||
pool.as_ref()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
|
@ -64,7 +64,7 @@ pub type BloomFilter = CountingBloomFilter<BloomStorageU8>;
|
|||
/// Similarly, using a KeySize of 10 would lead to a 4% false
|
||||
/// positive rate for N == 100 and to quite bad false positive
|
||||
/// rates for larger N.
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Default)]
|
||||
pub struct CountingBloomFilter<S>
|
||||
where
|
||||
S: BloomStorage,
|
||||
|
@ -79,9 +79,7 @@ where
|
|||
/// Creates a new bloom filter.
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
CountingBloomFilter {
|
||||
storage: Default::default(),
|
||||
}
|
||||
Default::default()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -13,13 +13,20 @@ use owning_ref::OwningHandle;
|
|||
use selectors::bloom::BloomFilter;
|
||||
use servo_arc::Arc;
|
||||
use smallvec::SmallVec;
|
||||
use std::mem::ManuallyDrop;
|
||||
|
||||
thread_local! {
|
||||
/// 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
|
||||
/// 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
|
||||
|
@ -128,7 +135,7 @@ impl<E: TElement> StyleBloom<E> {
|
|||
// See https://github.com/servo/servo/pull/18420#issuecomment-328769322
|
||||
#[inline(never)]
|
||||
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 =
|
||||
OwningHandle::new_with_fn(bloom_arc, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
|
||||
debug_assert!(
|
||||
|
@ -136,7 +143,7 @@ impl<E: TElement> StyleBloom<E> {
|
|||
"Forgot to zero the bloom filter last time"
|
||||
);
|
||||
StyleBloom {
|
||||
filter: filter,
|
||||
filter,
|
||||
elements: Default::default(),
|
||||
pushed_hashes: Default::default(),
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ where
|
|||
};
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -559,7 +559,7 @@ lazy_static! {
|
|||
feature!(
|
||||
atom!("aspect-ratio"),
|
||||
AllowsRanges::Yes,
|
||||
Evaluator::IntRatio(eval_aspect_ratio),
|
||||
Evaluator::NumberRatio(eval_aspect_ratio),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
|
@ -583,7 +583,7 @@ lazy_static! {
|
|||
feature!(
|
||||
atom!("device-aspect-ratio"),
|
||||
AllowsRanges::Yes,
|
||||
Evaluator::IntRatio(eval_device_aspect_ratio),
|
||||
Evaluator::NumberRatio(eval_device_aspect_ratio),
|
||||
ParsingRequirements::empty(),
|
||||
),
|
||||
feature!(
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
use crate::counter_style::{Symbol, Symbols};
|
||||
use crate::gecko_bindings::structs::CounterStylePtr;
|
||||
use crate::values::generics::CounterStyleOrNone;
|
||||
use crate::values::generics::CounterStyle;
|
||||
use crate::values::Either;
|
||||
use crate::Atom;
|
||||
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.
|
||||
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_SetCounterStyleToSymbols as set_symbols;
|
||||
match self {
|
||||
CounterStyleOrNone::None => unsafe {
|
||||
set_name(gecko_value, atom!("none").into_addrefed());
|
||||
},
|
||||
CounterStyleOrNone::Name(name) => unsafe {
|
||||
CounterStyle::Name(name) => unsafe {
|
||||
debug_assert_ne!(name.0, atom!("none"));
|
||||
set_name(gecko_value, name.0.into_addrefed());
|
||||
},
|
||||
CounterStyleOrNone::Symbols(symbols_type, symbols) => {
|
||||
CounterStyle::Symbols(symbols_type, symbols) => {
|
||||
let symbols: Vec<_> = symbols
|
||||
.0
|
||||
.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> {
|
||||
use crate::gecko_bindings::bindings;
|
||||
use crate::values::generics::SymbolsType;
|
||||
|
@ -95,11 +93,8 @@ impl CounterStyleOrNone {
|
|||
let name = unsafe { bindings::Gecko_CounterStyle_GetName(gecko_value) };
|
||||
if !name.is_null() {
|
||||
let name = unsafe { Atom::from_raw(name) };
|
||||
if name == atom!("none") {
|
||||
Either::First(CounterStyleOrNone::None)
|
||||
} else {
|
||||
Either::First(CounterStyleOrNone::Name(CustomIdent(name)))
|
||||
}
|
||||
debug_assert_ne!(name, atom!("none"));
|
||||
Either::First(CounterStyle::Name(CustomIdent(name)))
|
||||
} else {
|
||||
let anonymous =
|
||||
unsafe { bindings::Gecko_CounterStyle_GetAnonymous(gecko_value).as_ref() }.unwrap();
|
||||
|
@ -113,7 +108,7 @@ impl CounterStyleOrNone {
|
|||
.iter()
|
||||
.map(|gecko_symbol| Symbol::String(gecko_symbol.to_string().into()))
|
||||
.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()
|
||||
}
|
||||
|
||||
/// 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]
|
||||
fn namespace_id(&self) -> i32 {
|
||||
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;
|
||||
}
|
||||
|
||||
/// This logic is duplicated in Gecko's nsIContent::IsInAnonymousSubtree.
|
||||
#[inline]
|
||||
fn is_in_anonymous_subtree(&self) -> bool {
|
||||
if self.is_in_native_anonymous_subtree() {
|
||||
return true;
|
||||
}
|
||||
|
||||
let binding_parent = match self.xbl_binding_parent() {
|
||||
Some(p) => p,
|
||||
None => return false,
|
||||
};
|
||||
|
||||
binding_parent.shadow_root().is_none()
|
||||
unsafe { bindings::Gecko_IsInAnonymousSubtree(self.0) }
|
||||
}
|
||||
|
||||
/// 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::shared_lock::SharedRwLock;
|
||||
use crate::thread_state;
|
||||
use parking_lot::{RwLock, RwLockReadGuard};
|
||||
use rayon;
|
||||
use std::env;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
/// Global style data
|
||||
pub struct GlobalStyleData {
|
||||
|
@ -22,20 +24,28 @@ pub struct GlobalStyleData {
|
|||
pub options: StyleSystemOptions,
|
||||
}
|
||||
|
||||
/// Global thread pool
|
||||
/// Global thread pool.
|
||||
pub struct StyleThreadPool {
|
||||
/// How many threads parallel styling can use.
|
||||
pub num_threads: usize,
|
||||
|
||||
/// 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 {
|
||||
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) {
|
||||
ALIVE_WORKER_THREADS.fetch_add(1, Ordering::Relaxed);
|
||||
thread_state::initialize_layout_worker_thread();
|
||||
#[cfg(feature = "gecko")]
|
||||
unsafe {
|
||||
|
@ -55,6 +65,43 @@ fn thread_shutdown(_: usize) {
|
|||
bindings::Gecko_UnregisterProfilerThread();
|
||||
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! {
|
||||
|
@ -113,10 +160,11 @@ lazy_static! {
|
|||
};
|
||||
|
||||
StyleThreadPool {
|
||||
num_threads: num_threads,
|
||||
style_thread_pool: pool,
|
||||
num_threads,
|
||||
style_thread_pool: RwLock::new(pool),
|
||||
}
|
||||
};
|
||||
|
||||
/// Global style data
|
||||
pub static ref GLOBAL_STYLE_DATA: GlobalStyleData = GlobalStyleData {
|
||||
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::selector_map::SelectorMap;
|
||||
use crate::selector_parser::Snapshot;
|
||||
use crate::stylesheets::origin::{Origin, OriginSet};
|
||||
use crate::stylesheets::origin::OriginSet;
|
||||
use crate::{Atom, WeakAtom};
|
||||
use selectors::attr::CaseSensitivity;
|
||||
use selectors::matching::matches_selector;
|
||||
|
@ -246,7 +246,7 @@ where
|
|||
};
|
||||
|
||||
let document_origins = if !matches_document_author_rules {
|
||||
Origin::UserAgent.into()
|
||||
OriginSet::ORIGIN_USER_AGENT | OriginSet::ORIGIN_USER
|
||||
} else {
|
||||
OriginSet::all()
|
||||
};
|
||||
|
|
|
@ -26,16 +26,48 @@ pub enum InlineBaseDirection {
|
|||
// TODO: improve the readability of the WritingMode serialization, refer to the Debug:fmt()
|
||||
bitflags!(
|
||||
#[cfg_attr(feature = "servo", derive(MallocSizeOf, Serialize))]
|
||||
#[repr(C)]
|
||||
pub struct WritingMode: u8 {
|
||||
const RTL = 1 << 0;
|
||||
const VERTICAL = 1 << 1;
|
||||
/// A vertical writing mode; writing-mode is vertical-rl,
|
||||
/// 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;
|
||||
/// For vertical writing modes only. When set, line-over/line-under
|
||||
/// sides are inverted from block-start/block-end. This flag is
|
||||
/// set when sideways-lr is used.
|
||||
/// The line-over/line-under sides are inverted with respect to the
|
||||
/// block-start/block-end edge; writing-mode is vertical-lr.
|
||||
///
|
||||
/// Never set without VERTICAL and VERTICAL_LR.
|
||||
const LINE_INVERTED = 1 << 3;
|
||||
const SIDEWAYS = 1 << 4;
|
||||
const UPRIGHT = 1 << 5;
|
||||
/// direction is rtl.
|
||||
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();
|
||||
|
||||
match inheritedbox_style.clone_direction() {
|
||||
let direction = inheritedbox_style.clone_direction();
|
||||
let writing_mode = inheritedbox_style.clone_writing_mode();
|
||||
|
||||
match direction {
|
||||
Direction::Ltr => {},
|
||||
Direction::Rtl => {
|
||||
flags.insert(WritingMode::RTL);
|
||||
},
|
||||
}
|
||||
|
||||
match inheritedbox_style.clone_writing_mode() {
|
||||
SpecifiedWritingMode::HorizontalTb => {},
|
||||
match writing_mode {
|
||||
SpecifiedWritingMode::HorizontalTb => {
|
||||
if direction == Direction::Rtl {
|
||||
flags.insert(WritingMode::INLINE_REVERSED);
|
||||
}
|
||||
},
|
||||
SpecifiedWritingMode::VerticalRl => {
|
||||
flags.insert(WritingMode::VERTICAL);
|
||||
if direction == Direction::Rtl {
|
||||
flags.insert(WritingMode::INLINE_REVERSED);
|
||||
}
|
||||
},
|
||||
SpecifiedWritingMode::VerticalLr => {
|
||||
flags.insert(WritingMode::VERTICAL);
|
||||
flags.insert(WritingMode::VERTICAL_LR);
|
||||
flags.insert(WritingMode::LINE_INVERTED);
|
||||
if direction == Direction::Rtl {
|
||||
flags.insert(WritingMode::INLINE_REVERSED);
|
||||
}
|
||||
},
|
||||
#[cfg(feature = "gecko")]
|
||||
SpecifiedWritingMode::SidewaysRl => {
|
||||
flags.insert(WritingMode::VERTICAL);
|
||||
flags.insert(WritingMode::SIDEWAYS);
|
||||
if direction == Direction::Rtl {
|
||||
flags.insert(WritingMode::INLINE_REVERSED);
|
||||
}
|
||||
},
|
||||
#[cfg(feature = "gecko")]
|
||||
SpecifiedWritingMode::SidewaysLr => {
|
||||
flags.insert(WritingMode::VERTICAL);
|
||||
flags.insert(WritingMode::VERTICAL_LR);
|
||||
flags.insert(WritingMode::LINE_INVERTED);
|
||||
flags.insert(WritingMode::SIDEWAYS);
|
||||
if direction == Direction::Ltr {
|
||||
flags.insert(WritingMode::INLINE_REVERSED);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -81,10 +132,10 @@ impl WritingMode {
|
|||
{
|
||||
use crate::properties::longhands::text_orientation::computed_value::T as TextOrientation;
|
||||
|
||||
// If FLAG_SIDEWAYS is already set, this means writing-mode is
|
||||
// either sideways-rl or sideways-lr, and for both of these values,
|
||||
// text-orientation has no effect.
|
||||
if !flags.intersects(WritingMode::SIDEWAYS) {
|
||||
// text-orientation only has an effect for vertical-rl and
|
||||
// vertical-lr values of writing-mode.
|
||||
match writing_mode {
|
||||
SpecifiedWritingMode::VerticalRl | SpecifiedWritingMode::VerticalLr => {
|
||||
match inheritedbox_style.clone_text_orientation() {
|
||||
TextOrientation::Mixed => {},
|
||||
TextOrientation::Upright => {
|
||||
|
@ -94,6 +145,8 @@ impl WritingMode {
|
|||
flags.insert(WritingMode::SIDEWAYS);
|
||||
},
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,7 +168,7 @@ impl WritingMode {
|
|||
#[inline]
|
||||
pub fn is_inline_tb(&self) -> bool {
|
||||
// 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]
|
||||
|
|
|
@ -44,8 +44,8 @@ pub enum Evaluator {
|
|||
Integer(MediaFeatureEvaluator<u32>),
|
||||
Float(MediaFeatureEvaluator<f32>),
|
||||
BoolInteger(MediaFeatureEvaluator<bool>),
|
||||
/// An integer ratio, such as the one from device-pixel-ratio.
|
||||
IntRatio(MediaFeatureEvaluator<AspectRatio>),
|
||||
/// A non-negative number ratio, such as the one from device-pixel-ratio.
|
||||
NumberRatio(MediaFeatureEvaluator<AspectRatio>),
|
||||
/// A resolution.
|
||||
Resolution(MediaFeatureEvaluator<Resolution>),
|
||||
/// A keyword value.
|
||||
|
|
|
@ -16,6 +16,8 @@ use crate::parser::{Parse, ParserContext};
|
|||
use crate::servo::media_queries::MEDIA_FEATURES;
|
||||
use crate::str::{starts_with_ignore_ascii_case, string_as_ascii_lowercase};
|
||||
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::{serialize_atom_identifier, CSSFloat};
|
||||
use crate::{Atom, Zero};
|
||||
|
@ -25,8 +27,8 @@ use std::fmt::{self, Write};
|
|||
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
||||
|
||||
/// An aspect ratio, with a numerator and denominator.
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
|
||||
pub struct AspectRatio(pub u32, pub u32);
|
||||
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToShmem)]
|
||||
pub struct AspectRatio(pub CSSFloat, pub CSSFloat);
|
||||
|
||||
impl ToCss for AspectRatio {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
|
@ -41,9 +43,9 @@ impl ToCss for AspectRatio {
|
|||
|
||||
impl PartialOrd for AspectRatio {
|
||||
fn partial_cmp(&self, other: &AspectRatio) -> Option<Ordering> {
|
||||
u64::partial_cmp(
|
||||
&(self.0 as u64 * other.1 as u64),
|
||||
&(self.1 as u64 * other.0 as u64),
|
||||
f64::partial_cmp(
|
||||
&(self.0 as f64 * other.1 as f64),
|
||||
&(self.1 as f64 * other.0 as f64),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -429,9 +431,11 @@ impl MediaFeatureExpression {
|
|||
eval(device, expect!(Integer).cloned(), self.range_or_operator)
|
||||
},
|
||||
Evaluator::Float(eval) => eval(device, expect!(Float).cloned(), self.range_or_operator),
|
||||
Evaluator::IntRatio(eval) => {
|
||||
eval(device, expect!(IntRatio).cloned(), self.range_or_operator)
|
||||
},
|
||||
Evaluator::NumberRatio(eval) => eval(
|
||||
device,
|
||||
expect!(NumberRatio).cloned(),
|
||||
self.range_or_operator,
|
||||
),
|
||||
Evaluator::Resolution(eval) => {
|
||||
let computed = expect!(Resolution).map(|specified| {
|
||||
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.
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
|
@ -471,9 +475,9 @@ pub enum MediaExpressionValue {
|
|||
Float(CSSFloat),
|
||||
/// A boolean value, specified as an integer (i.e., either 0 or 1).
|
||||
BoolInteger(bool),
|
||||
/// Two integers separated by '/', with optional whitespace on either side
|
||||
/// of the '/'.
|
||||
IntRatio(AspectRatio),
|
||||
/// A single non-negative number or two non-negative numbers separated by '/',
|
||||
/// with optional whitespace on either side of the '/'.
|
||||
NumberRatio(AspectRatio),
|
||||
/// A resolution.
|
||||
Resolution(Resolution),
|
||||
/// 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::Float(v) => v.to_css(dest),
|
||||
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::Ident(ref ident) => serialize_atom_identifier(ident, dest),
|
||||
MediaExpressionValue::Enumerated(value) => match for_expr.feature().evaluator {
|
||||
|
@ -529,11 +533,26 @@ impl MediaExpressionValue {
|
|||
let number = Number::parse(context, input)?;
|
||||
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)?;
|
||||
input.expect_delim('/')?;
|
||||
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(..) => {
|
||||
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/.
|
||||
|
||||
import re
|
||||
from counted_unknown_properties import COUNTED_UNKNOWN_PROPERTIES
|
||||
|
||||
PHYSICAL_SIDES = ["top", "right", "bottom", "left"]
|
||||
LOGICAL_SIDES = ["block-start", "block-end", "inline-start", "inline-end"]
|
||||
|
@ -574,6 +575,7 @@ class PropertiesData(object):
|
|||
self.shorthands = []
|
||||
self.shorthands_by_name = {}
|
||||
self.shorthand_aliases = []
|
||||
self.counted_unknown_properties = [CountedUnknownProperty(p) for p in COUNTED_UNKNOWN_PROPERTIES]
|
||||
|
||||
def new_style_struct(self, *args, **kwargs):
|
||||
style_struct = StyleStruct(*args, **kwargs)
|
||||
|
@ -794,3 +796,10 @@ class PropertyRestrictions:
|
|||
+ PropertyRestrictions.shorthand(data, "background")
|
||||
+ PropertyRestrictions.shorthand(data, "outline")
|
||||
+ 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)]
|
||||
|
||||
use super::*;
|
||||
use crate::context::QuirksMode;
|
||||
use cssparser::{DeclarationListParser, parse_important, ParserInput, CowRcStr};
|
||||
use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter, ParseErrorKind};
|
||||
use crate::custom_properties::{CustomPropertiesBuilder, CssEnvironment};
|
||||
use crate::error_reporting::{ParseErrorReporter, ContextualParseError};
|
||||
use itertools::Itertools;
|
||||
use crate::custom_properties::{CssEnvironment, CustomPropertiesBuilder};
|
||||
use crate::error_reporting::{ContextualParseError, ParseErrorReporter};
|
||||
use crate::parser::ParserContext;
|
||||
use crate::properties::animated_properties::{AnimationValue, AnimationValueMap};
|
||||
use crate::selector_parser::SelectorImpl;
|
||||
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 smallvec::SmallVec;
|
||||
use std::fmt::{self, Write};
|
||||
use std::iter::{DoubleEndedIterator, Zip};
|
||||
use std::slice::Iter;
|
||||
use crate::str::{CssString, CssStringBorrow, CssStringWriter};
|
||||
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 first one is for Animation cascade level, and the second one is for
|
||||
/// Transition cascade level.
|
||||
pub struct AnimationRules(pub Option<Arc<Locked<PropertyDeclarationBlock>>>,
|
||||
pub Option<Arc<Locked<PropertyDeclarationBlock>>>);
|
||||
pub struct AnimationRules(
|
||||
pub Option<Arc<Locked<PropertyDeclarationBlock>>>,
|
||||
pub Option<Arc<Locked<PropertyDeclarationBlock>>>,
|
||||
);
|
||||
|
||||
impl AnimationRules {
|
||||
/// Returns whether these animation rules represents an actual rule or not.
|
||||
|
@ -122,8 +124,16 @@ impl<'a> Iterator for DeclarationImportanceIterator<'a> {
|
|||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next().map(|(decl, important)|
|
||||
(decl, if important { Importance::Important } else { Importance::Normal }))
|
||||
self.iter.next().map(|(decl, important)| {
|
||||
(
|
||||
decl,
|
||||
if important {
|
||||
Importance::Important
|
||||
} else {
|
||||
Importance::Normal
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -135,13 +145,21 @@ impl<'a> Iterator for DeclarationImportanceIterator<'a> {
|
|||
impl<'a> DoubleEndedIterator for DeclarationImportanceIterator<'a> {
|
||||
#[inline(always)]
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next_back().map(|(decl, important)|
|
||||
(decl, if important { Importance::Important } else { Importance::Normal }))
|
||||
self.iter.next_back().map(|(decl, important)| {
|
||||
(
|
||||
decl,
|
||||
if important {
|
||||
Importance::Important
|
||||
} else {
|
||||
Importance::Normal
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// 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>,
|
||||
context: &'cx mut Context<'cx_a>,
|
||||
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>>,
|
||||
}
|
||||
|
||||
impl<'a, 'cx, 'cx_a:'cx> AnimationValueIterator<'a, 'cx, 'cx_a> {
|
||||
impl<'a, 'cx, 'cx_a: 'cx> AnimationValueIterator<'a, 'cx, 'cx_a> {
|
||||
fn new(
|
||||
declarations: &'a PropertyDeclarationBlock,
|
||||
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;
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
|
@ -256,7 +274,7 @@ impl PropertyDeclarationBlock {
|
|||
|
||||
/// Return an iterator of (AnimatableLonghand, AnimationValue).
|
||||
#[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,
|
||||
context: &'cx mut Context<'cx_a>,
|
||||
default_values: &'a ComputedValues,
|
||||
|
@ -300,7 +318,10 @@ impl PropertyDeclarationBlock {
|
|||
/// NOTE: This is linear time in the case of custom properties or in the
|
||||
/// case the longhand is actually in the declaration block.
|
||||
#[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 !self.contains(id) {
|
||||
return None;
|
||||
|
@ -350,9 +371,7 @@ impl PropertyDeclarationBlock {
|
|||
// We don't print !important when serializing individual properties,
|
||||
// so we treat this as a normal-importance property
|
||||
match shorthand.get_shorthand_appendable_value(list.iter().cloned()) {
|
||||
Some(appendable_value) => {
|
||||
append_declaration_value(dest, appendable_value)
|
||||
}
|
||||
Some(appendable_value) => append_declaration_value(dest, appendable_value),
|
||||
None => return Ok(()),
|
||||
}
|
||||
}
|
||||
|
@ -360,7 +379,11 @@ impl PropertyDeclarationBlock {
|
|||
/// Find the value of the given property in this block and serialize it
|
||||
///
|
||||
/// <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.2
|
||||
|
@ -394,11 +417,12 @@ impl PropertyDeclarationBlock {
|
|||
} else {
|
||||
Importance::Normal
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(longhand_or_custom) => {
|
||||
// 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.
|
||||
#[inline]
|
||||
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.
|
||||
|
@ -421,11 +447,11 @@ impl PropertyDeclarationBlock {
|
|||
) -> bool {
|
||||
let all_shorthand_len = match drain.all_shorthand {
|
||||
AllShorthand::NotSet => 0,
|
||||
AllShorthand::CSSWideKeyword(_) |
|
||||
AllShorthand::WithVariables(_) => shorthands::ALL_SHORTHAND_MAX_LEN,
|
||||
AllShorthand::CSSWideKeyword(_) | AllShorthand::WithVariables(_) => {
|
||||
shorthands::ALL_SHORTHAND_MAX_LEN
|
||||
},
|
||||
};
|
||||
let push_calls_count =
|
||||
drain.declarations.len() + all_shorthand_len;
|
||||
let push_calls_count = drain.declarations.len() + all_shorthand_len;
|
||||
|
||||
// With deduplication the actual length increase may be less than this.
|
||||
self.declarations.reserve(push_calls_count);
|
||||
|
@ -434,7 +460,10 @@ impl PropertyDeclarationBlock {
|
|||
for decl in &mut drain.declarations {
|
||||
changed |= self.push(decl, importance);
|
||||
}
|
||||
drain.all_shorthand.declarations().fold(changed, |changed, decl| {
|
||||
drain
|
||||
.all_shorthand
|
||||
.declarations()
|
||||
.fold(changed, |changed, decl| {
|
||||
changed | self.push(decl, importance)
|
||||
})
|
||||
}
|
||||
|
@ -444,11 +473,7 @@ impl PropertyDeclarationBlock {
|
|||
/// Returns whether the declaration has changed.
|
||||
///
|
||||
/// This is only used for parsing and internal use.
|
||||
pub fn push(
|
||||
&mut self,
|
||||
declaration: PropertyDeclaration,
|
||||
importance: Importance,
|
||||
) -> bool {
|
||||
pub fn push(&mut self, declaration: PropertyDeclaration, importance: Importance) -> bool {
|
||||
if !self.is_definitely_new(&declaration) {
|
||||
let mut index_to_remove = None;
|
||||
for (i, slot) in self.declarations.iter_mut().enumerate() {
|
||||
|
@ -498,9 +523,14 @@ impl PropertyDeclarationBlock {
|
|||
// Check whether we are updating for an all shorthand change.
|
||||
if !matches!(source_declarations.all_shorthand, AllShorthand::NotSet) {
|
||||
debug_assert!(source_declarations.declarations.is_empty());
|
||||
return source_declarations.all_shorthand.declarations().any(|decl| {
|
||||
return source_declarations
|
||||
.all_shorthand
|
||||
.declarations()
|
||||
.any(|decl| {
|
||||
self.is_definitely_new(&decl) ||
|
||||
self.declarations.iter().enumerate()
|
||||
self.declarations
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|&(_, ref d)| d.id() == decl.id())
|
||||
.map_or(true, |(i, d)| {
|
||||
let important = self.declarations_importance[i];
|
||||
|
@ -513,7 +543,11 @@ impl PropertyDeclarationBlock {
|
|||
let new_count = &mut updates.new_count;
|
||||
let any_removal = &mut updates.any_removal;
|
||||
let updates = &mut updates.updates;
|
||||
updates.extend(source_declarations.declarations.iter().map(|declaration| {
|
||||
updates.extend(
|
||||
source_declarations
|
||||
.declarations
|
||||
.iter()
|
||||
.map(|declaration| {
|
||||
if self.is_definitely_new(declaration) {
|
||||
return DeclarationUpdate::Append;
|
||||
}
|
||||
|
@ -538,14 +572,17 @@ impl PropertyDeclarationBlock {
|
|||
}
|
||||
if !needs_append &&
|
||||
id.logical_group() == Some(logical_group) &&
|
||||
id.is_logical() != longhand_id.is_logical() {
|
||||
id.is_logical() != longhand_id.is_logical()
|
||||
{
|
||||
needs_append = true;
|
||||
}
|
||||
}
|
||||
unreachable!("Longhand should be found in loop above");
|
||||
}
|
||||
}
|
||||
self.declarations.iter().enumerate()
|
||||
self.declarations
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|&(_, ref decl)| decl.id() == declaration.id())
|
||||
.map_or(DeclarationUpdate::Append, |(pos, decl)| {
|
||||
let important = self.declarations_importance[pos];
|
||||
|
@ -555,7 +592,8 @@ impl PropertyDeclarationBlock {
|
|||
DeclarationUpdate::UpdateInPlace { pos }
|
||||
}
|
||||
})
|
||||
}).inspect(|update| {
|
||||
})
|
||||
.inspect(|update| {
|
||||
if matches!(update, DeclarationUpdate::None) {
|
||||
return;
|
||||
}
|
||||
|
@ -563,13 +601,14 @@ impl PropertyDeclarationBlock {
|
|||
match update {
|
||||
DeclarationUpdate::Append => {
|
||||
*new_count += 1;
|
||||
}
|
||||
},
|
||||
DeclarationUpdate::AppendAndRemove { .. } => {
|
||||
*any_removal = true;
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}));
|
||||
}),
|
||||
);
|
||||
any_update
|
||||
}
|
||||
|
||||
|
@ -590,8 +629,12 @@ impl PropertyDeclarationBlock {
|
|||
self.declarations_importance.push(important);
|
||||
self.longhands.insert(longhand_id);
|
||||
} else {
|
||||
let (idx, slot) = self.declarations.iter_mut()
|
||||
.enumerate().find(|&(_, ref d)| d.id() == decl.id()).unwrap();
|
||||
let (idx, slot) = self
|
||||
.declarations
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.find(|&(_, ref d)| d.id() == decl.id())
|
||||
.unwrap();
|
||||
*slot = decl;
|
||||
self.declarations_importance.set(idx, important);
|
||||
}
|
||||
|
@ -607,19 +650,24 @@ impl PropertyDeclarationBlock {
|
|||
pos: usize,
|
||||
remove: bool,
|
||||
}
|
||||
let mut updates_and_removals: SubpropertiesVec<UpdateOrRemoval> =
|
||||
updates.updates.iter_mut().filter_map(|item| {
|
||||
let mut updates_and_removals: SubpropertiesVec<UpdateOrRemoval> = updates
|
||||
.updates
|
||||
.iter_mut()
|
||||
.filter_map(|item| {
|
||||
let (pos, remove) = match *item {
|
||||
DeclarationUpdate::UpdateInPlace { pos } => (pos, false),
|
||||
DeclarationUpdate::AppendAndRemove { pos } => (pos, true),
|
||||
_ => return None,
|
||||
};
|
||||
Some(UpdateOrRemoval { item, pos, remove })
|
||||
}).collect();
|
||||
})
|
||||
.collect();
|
||||
// Execute removals. It's important to do it in reverse index order,
|
||||
// so that removing doesn't invalidate following positions.
|
||||
updates_and_removals.sort_unstable_by_key(|update| update.pos);
|
||||
updates_and_removals.iter().rev()
|
||||
updates_and_removals
|
||||
.iter()
|
||||
.rev()
|
||||
.filter(|update| update.remove)
|
||||
.for_each(|update| {
|
||||
self.declarations.remove(update.pos);
|
||||
|
@ -637,7 +685,7 @@ impl PropertyDeclarationBlock {
|
|||
DeclarationUpdate::UpdateInPlace { pos: update.pos }
|
||||
);
|
||||
*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()) {
|
||||
match *update {
|
||||
DeclarationUpdate::None => {},
|
||||
DeclarationUpdate::Append |
|
||||
DeclarationUpdate::AppendAndRemove { .. } => {
|
||||
DeclarationUpdate::Append | DeclarationUpdate::AppendAndRemove { .. } => {
|
||||
if let Some(id) = decl.id().as_longhand() {
|
||||
self.longhands.insert(id);
|
||||
}
|
||||
self.declarations.push(decl);
|
||||
self.declarations_importance.push(important);
|
||||
}
|
||||
},
|
||||
DeclarationUpdate::UpdateInPlace { pos } => {
|
||||
self.declarations[pos] = decl;
|
||||
self.declarations_importance.set(pos, important);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
updates.updates.clear();
|
||||
|
@ -665,19 +712,16 @@ impl PropertyDeclarationBlock {
|
|||
/// Returns the first declaration that would be removed by removing
|
||||
/// `property`.
|
||||
#[inline]
|
||||
pub fn first_declaration_to_remove(
|
||||
&self,
|
||||
property: &PropertyId,
|
||||
) -> Option<usize> {
|
||||
pub fn first_declaration_to_remove(&self, property: &PropertyId) -> Option<usize> {
|
||||
if let Some(id) = property.longhand_id() {
|
||||
if !self.longhands.contains(id) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
self.declarations.iter().position(|declaration| {
|
||||
declaration.id().is_or_is_longhand_of(property)
|
||||
})
|
||||
self.declarations
|
||||
.iter()
|
||||
.position(|declaration| declaration.id().is_or_is_longhand_of(property))
|
||||
}
|
||||
|
||||
/// Removes a given declaration at a given index.
|
||||
|
@ -698,16 +742,14 @@ impl PropertyDeclarationBlock {
|
|||
/// `first_declaration` needs to be the result of
|
||||
/// `first_declaration_to_remove`.
|
||||
#[inline]
|
||||
pub fn remove_property(
|
||||
&mut self,
|
||||
property: &PropertyId,
|
||||
first_declaration: usize,
|
||||
) {
|
||||
pub fn remove_property(&mut self, property: &PropertyId, first_declaration: usize) {
|
||||
debug_assert_eq!(
|
||||
Some(first_declaration),
|
||||
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);
|
||||
|
||||
|
@ -776,16 +818,16 @@ impl PropertyDeclarationBlock {
|
|||
// getKeyframes() implementation for CSS animations, if
|
||||
// |computed_values| is supplied, we use it to expand such variable
|
||||
// declarations. This will be fixed properly in Gecko bug 1391537.
|
||||
(
|
||||
&PropertyDeclaration::WithVariables(ref declaration),
|
||||
Some(ref _computed_values),
|
||||
) => {
|
||||
declaration.value.substitute_variables(
|
||||
(&PropertyDeclaration::WithVariables(ref declaration), Some(ref _computed_values)) => {
|
||||
declaration
|
||||
.value
|
||||
.substitute_variables(
|
||||
declaration.id,
|
||||
custom_properties.as_ref(),
|
||||
QuirksMode::NoQuirks,
|
||||
&env,
|
||||
).to_css(dest)
|
||||
)
|
||||
.to_css(dest)
|
||||
},
|
||||
(ref d, _) => d.to_css(dest),
|
||||
}
|
||||
|
@ -814,13 +856,12 @@ impl PropertyDeclarationBlock {
|
|||
pub fn has_css_wide_keyword(&self, property: &PropertyId) -> bool {
|
||||
if let Some(id) = property.longhand_id() {
|
||||
if !self.longhands.contains(id) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
self.declarations.iter().any(|decl|
|
||||
decl.id().is_or_is_longhand_of(property) &&
|
||||
decl.get_css_wide_keyword().is_some()
|
||||
)
|
||||
self.declarations.iter().any(|decl| {
|
||||
decl.id().is_or_is_longhand_of(property) && decl.get_css_wide_keyword().is_some()
|
||||
})
|
||||
}
|
||||
|
||||
/// 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>>,
|
||||
environment: &CssEnvironment,
|
||||
) -> Option<Arc<crate::custom_properties::CustomPropertiesMap>> {
|
||||
let mut builder = CustomPropertiesBuilder::new(
|
||||
inherited_custom_properties,
|
||||
environment,
|
||||
);
|
||||
let mut builder = CustomPropertiesBuilder::new(inherited_custom_properties, environment);
|
||||
|
||||
for declaration in self.normal_declaration_iter() {
|
||||
if let PropertyDeclaration::Custom(ref declaration) = *declaration {
|
||||
|
@ -899,7 +937,7 @@ impl PropertyDeclarationBlock {
|
|||
&mut is_first_serialization,
|
||||
)?;
|
||||
continue;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Step 3.2
|
||||
|
@ -928,22 +966,19 @@ impl PropertyDeclarationBlock {
|
|||
let mut important_count = 0;
|
||||
let mut found_system = None;
|
||||
|
||||
let is_system_font =
|
||||
shorthand == ShorthandId::Font &&
|
||||
self.declarations.iter().any(|l| {
|
||||
match l.id() {
|
||||
let is_system_font = shorthand == ShorthandId::Font &&
|
||||
self.declarations.iter().any(|l| match l.id() {
|
||||
PropertyDeclarationId::Longhand(id) => {
|
||||
if already_serialized.contains(id.into()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
l.get_system().is_some()
|
||||
}
|
||||
},
|
||||
PropertyDeclarationId::Custom(..) => {
|
||||
debug_assert!(l.get_system().is_none());
|
||||
false
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
if is_system_font {
|
||||
|
@ -967,11 +1002,11 @@ impl PropertyDeclarationBlock {
|
|||
if importance.important() {
|
||||
important_count += 1;
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
contains_all_longhands = false;
|
||||
break;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -994,8 +1029,9 @@ impl PropertyDeclarationBlock {
|
|||
|
||||
// Substep 5 - Let value be the result of invoking serialize
|
||||
// a CSS value of current longhands.
|
||||
let appendable_value =
|
||||
match shorthand.get_shorthand_appendable_value(current_longhands.iter().cloned()) {
|
||||
let appendable_value = match shorthand
|
||||
.get_shorthand_appendable_value(current_longhands.iter().cloned())
|
||||
{
|
||||
None => continue,
|
||||
Some(appendable_value) => appendable_value,
|
||||
};
|
||||
|
@ -1004,13 +1040,19 @@ impl PropertyDeclarationBlock {
|
|||
// AppendableValue::Css.
|
||||
let mut v = CssString::new();
|
||||
let value = match (appendable_value, found_system) {
|
||||
(AppendableValue::Css { css, with_variables }, _) => {
|
||||
(
|
||||
AppendableValue::Css {
|
||||
css,
|
||||
with_variables,
|
||||
},
|
||||
_,
|
||||
) => {
|
||||
debug_assert!(!css.is_empty());
|
||||
AppendableValue::Css {
|
||||
css: css,
|
||||
with_variables: with_variables,
|
||||
}
|
||||
}
|
||||
},
|
||||
#[cfg(feature = "gecko")]
|
||||
(_, Some(sys)) => {
|
||||
sys.to_css(&mut CssWriter::new(&mut v))?;
|
||||
|
@ -1018,7 +1060,7 @@ impl PropertyDeclarationBlock {
|
|||
css: CssStringBorrow::from(&v),
|
||||
with_variables: false,
|
||||
}
|
||||
}
|
||||
},
|
||||
(other, _) => {
|
||||
append_declaration_value(&mut v, other)?;
|
||||
|
||||
|
@ -1031,7 +1073,7 @@ impl PropertyDeclarationBlock {
|
|||
css: CssStringBorrow::from(&v),
|
||||
with_variables: false,
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Substeps 7 and 8
|
||||
|
@ -1091,7 +1133,8 @@ impl PropertyDeclarationBlock {
|
|||
/// A convenient enum to represent different kinds of stuff that can represent a
|
||||
/// _value_ in the serialization of a property declaration.
|
||||
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.
|
||||
Declaration(&'a PropertyDeclaration),
|
||||
|
@ -1107,14 +1150,11 @@ pub enum AppendableValue<'a, I>
|
|||
css: CssStringBorrow<'a>,
|
||||
/// Whether the original serialization contained variables or not.
|
||||
with_variables: bool,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/// Potentially appends whitespace after the first (property: value;) pair.
|
||||
fn handle_first_serialization<W>(
|
||||
dest: &mut W,
|
||||
is_first_serialization: &mut bool,
|
||||
) -> fmt::Result
|
||||
fn handle_first_serialization<W>(dest: &mut W, is_first_serialization: &mut bool) -> fmt::Result
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
|
@ -1132,18 +1172,14 @@ pub fn append_declaration_value<'a, I>(
|
|||
appendable_value: AppendableValue<'a, I>,
|
||||
) -> fmt::Result
|
||||
where
|
||||
I: Iterator<Item=&'a PropertyDeclaration>,
|
||||
I: Iterator<Item = &'a PropertyDeclaration>,
|
||||
{
|
||||
match appendable_value {
|
||||
AppendableValue::Css { css, .. } => {
|
||||
css.append_to(dest)
|
||||
},
|
||||
AppendableValue::Declaration(decl) => {
|
||||
decl.to_css(dest)
|
||||
},
|
||||
AppendableValue::Css { css, .. } => css.append_to(dest),
|
||||
AppendableValue::Declaration(decl) => decl.to_css(dest),
|
||||
AppendableValue::DeclarationsForShorthand(shorthand, decls) => {
|
||||
shorthand.longhands_to_css(decls, &mut CssWriter::new(dest))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1153,10 +1189,10 @@ pub fn append_serialization<'a, I, N>(
|
|||
property_name: &N,
|
||||
appendable_value: AppendableValue<'a, I>,
|
||||
importance: Importance,
|
||||
is_first_serialization: &mut bool
|
||||
is_first_serialization: &mut bool,
|
||||
) -> fmt::Result
|
||||
where
|
||||
I: Iterator<Item=&'a PropertyDeclaration>,
|
||||
I: Iterator<Item = &'a PropertyDeclaration>,
|
||||
N: ToCss,
|
||||
{
|
||||
handle_first_serialization(dest, is_first_serialization)?;
|
||||
|
@ -1176,7 +1212,7 @@ where
|
|||
if !with_variables {
|
||||
dest.write_str(" ")?
|
||||
}
|
||||
}
|
||||
},
|
||||
// Currently append_serialization is only called with a Css or
|
||||
// a Declaration AppendableValue.
|
||||
AppendableValue::DeclarationsForShorthand(..) => unreachable!(),
|
||||
|
@ -1228,7 +1264,7 @@ pub fn parse_one_declaration_into(
|
|||
url_data: &UrlExtraData,
|
||||
error_reporter: Option<&dyn ParseErrorReporter>,
|
||||
parsing_mode: ParsingMode,
|
||||
quirks_mode: QuirksMode
|
||||
quirks_mode: QuirksMode,
|
||||
) -> Result<(), ()> {
|
||||
let context = ParserContext::new(
|
||||
Origin::Author,
|
||||
|
@ -1249,9 +1285,11 @@ pub fn parse_one_declaration_into(
|
|||
let mut input = ParserInput::new(input);
|
||||
let mut parser = Parser::new(&mut input);
|
||||
let start_position = parser.position();
|
||||
parser.parse_entirely(|parser| {
|
||||
parser
|
||||
.parse_entirely(|parser| {
|
||||
PropertyDeclaration::parse_into(declarations, id, &context, parser)
|
||||
}).map_err(|err| {
|
||||
})
|
||||
.map_err(|err| {
|
||||
if context.error_reporting_enabled() {
|
||||
report_one_css_error(
|
||||
&context,
|
||||
|
@ -1273,7 +1311,6 @@ struct PropertyDeclarationParser<'a, 'b: 'a> {
|
|||
last_parsed_property_id: Option<PropertyId>,
|
||||
}
|
||||
|
||||
|
||||
/// Default methods reject all at rules.
|
||||
impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b> {
|
||||
type PreludeNoBlock = ();
|
||||
|
@ -1284,8 +1321,7 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b> {
|
|||
|
||||
/// Based on NonMozillaVendorIdentifier from Gecko's CSS parser.
|
||||
fn is_non_mozilla_vendor_identifier(name: &str) -> bool {
|
||||
(name.starts_with("-") && !name.starts_with("-moz-")) ||
|
||||
name.starts_with("_")
|
||||
(name.starts_with("-") && !name.starts_with("-moz-")) || name.starts_with("_")
|
||||
}
|
||||
|
||||
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,
|
||||
Err(..) => {
|
||||
self.last_parsed_property_id = None;
|
||||
return Err(input.new_custom_error(
|
||||
StyleParseErrorKind::UnknownProperty(name)
|
||||
));
|
||||
}
|
||||
return Err(input.new_custom_error(StyleParseErrorKind::UnknownProperty(name)));
|
||||
},
|
||||
};
|
||||
if self.context.error_reporting_enabled() {
|
||||
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 {
|
||||
match *property {
|
||||
PropertyId::LonghandAlias(id, _) |
|
||||
PropertyId::Longhand(id) => block.contains(id),
|
||||
PropertyId::ShorthandAlias(id, _) |
|
||||
PropertyId::Shorthand(id) => {
|
||||
PropertyId::LonghandAlias(id, _) | PropertyId::Longhand(id) => block.contains(id),
|
||||
PropertyId::ShorthandAlias(id, _) | PropertyId::Shorthand(id) => {
|
||||
id.longhands().all(|longhand| block.contains(longhand))
|
||||
},
|
||||
// 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 {
|
||||
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),
|
||||
};
|
||||
}
|
||||
|
@ -1409,7 +1443,7 @@ fn report_css_errors(
|
|||
pub fn parse_property_declaration_list(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
selectors: Option<&SelectorList<SelectorImpl>>
|
||||
selectors: Option<&SelectorList<SelectorImpl>>,
|
||||
) -> PropertyDeclarationBlock {
|
||||
let mut declarations = SourcePropertyDeclaration::new();
|
||||
let mut block = PropertyDeclarationBlock::new();
|
||||
|
@ -1423,11 +1457,8 @@ pub fn parse_property_declaration_list(
|
|||
while let Some(declaration) = iter.next() {
|
||||
match declaration {
|
||||
Ok(importance) => {
|
||||
block.extend(
|
||||
iter.parser.declarations.drain(),
|
||||
importance,
|
||||
);
|
||||
}
|
||||
block.extend(iter.parser.declarations.drain(), importance);
|
||||
},
|
||||
Err((error, slice)) => {
|
||||
iter.parser.declarations.clear();
|
||||
|
||||
|
@ -1435,7 +1466,7 @@ pub fn parse_property_declaration_list(
|
|||
let property = iter.parser.last_parsed_property_id.take();
|
||||
errors.push((error, slice, property));
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -321,18 +321,6 @@ impl ${style_struct.gecko_struct_name} {
|
|||
}
|
||||
</%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"):
|
||||
return "%s.gecko.%s" % (self_param, ffi_name)
|
||||
|
@ -357,10 +345,7 @@ def set_gecko_property(ffi_name, expr):
|
|||
</%def>
|
||||
|
||||
<%def name="impl_keyword_clone(ident, gecko_ffi_name, keyword, cast_type='u8')">
|
||||
// FIXME: We introduced non_upper_case_globals for -moz-appearance only
|
||||
// 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)]
|
||||
#[allow(non_snake_case)]
|
||||
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
|
||||
use crate::properties::longhands::${ident}::computed_value::T as Keyword;
|
||||
// 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) {
|
||||
use crate::values::generics::font::KeywordSize;
|
||||
use crate::values::specified::font::KeywordSize;
|
||||
|
||||
let size = v.size();
|
||||
self.gecko.mScriptUnconstrainedSize = size.0;
|
||||
|
@ -1167,7 +1152,7 @@ fn static_assert() {
|
|||
KeywordSize::XXXLarge => structs::NS_STYLE_FONT_SIZE_XXXLARGE,
|
||||
} as u8;
|
||||
self.gecko.mFontSizeFactor = info.factor;
|
||||
self.gecko.mFontSizeOffset = info.offset.0.to_i32_au();
|
||||
self.gecko.mFontSizeOffset = info.offset.to_i32_au();
|
||||
} else {
|
||||
self.gecko.mFontSizeKeyword = structs::NS_STYLE_FONT_SIZE_NO_KEYWORD as u8;
|
||||
self.gecko.mFontSizeFactor = 1.;
|
||||
|
@ -1176,7 +1161,7 @@ fn static_assert() {
|
|||
}
|
||||
|
||||
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 kw = match self.gecko.mFontSizeKeyword as u32 {
|
||||
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("font_variant_alternates", "mFont.variantAlternates")}
|
||||
|
||||
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;
|
||||
match v {
|
||||
|
@ -1331,122 +1318,6 @@ fn static_assert() {
|
|||
${impl_simple("_moz_script_level", "mScriptLevel")}
|
||||
<% 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_east_asian", "mFont.variantEastAsian")}
|
||||
${impl_simple_type_with_conversion("font_variant_numeric", "mFont.variantNumeric")}
|
||||
|
@ -2291,7 +2162,7 @@ fn static_assert() {
|
|||
</%self:impl_trait>
|
||||
|
||||
<%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) {
|
||||
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) {
|
||||
use crate::gecko_bindings::bindings::Gecko_SetCounterStyleToName;
|
||||
use crate::gecko_bindings::bindings::Gecko_SetCounterStyleToString;
|
||||
use nsstring::{nsACString, nsCStr};
|
||||
use self::longhands::list_style_type::computed_value::T;
|
||||
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::String(s) => unsafe {
|
||||
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 {
|
||||
use self::longhands::list_style_type::computed_value::T;
|
||||
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 {
|
||||
Either::First(counter_style) => T::CounterStyle(counter_style),
|
||||
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 style_struct_name="Table" skip_longhands="-x-span">
|
||||
#[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 style_struct_name="Table">
|
||||
</%self:impl_trait>
|
||||
|
||||
<%self:impl_trait style_struct_name="Effects" skip_longhands="clip">
|
||||
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 style_struct_name="Effects">
|
||||
</%self:impl_trait>
|
||||
|
||||
<%self:impl_trait style_struct_name="InheritedBox">
|
||||
|
@ -2725,18 +2432,7 @@ clip-path
|
|||
</%self:impl_trait>
|
||||
|
||||
<%self:impl_trait style_struct_name="InheritedSVG"
|
||||
skip_longhands="paint-order 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)
|
||||
}
|
||||
|
||||
skip_longhands="stroke-dasharray">
|
||||
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::values::generics::svg::SVGStrokeDashArray;
|
||||
|
@ -2883,8 +2579,7 @@ clip-path
|
|||
${impl_simple('column_rule_style', 'mColumnRuleStyle')}
|
||||
</%self:impl_trait>
|
||||
|
||||
<%self:impl_trait style_struct_name="Counters"
|
||||
skip_longhands="content counter-increment counter-reset counter-set">
|
||||
<%self:impl_trait style_struct_name="Counters" skip_longhands="content">
|
||||
pub fn ineffective_content_property(&self) -> bool {
|
||||
self.gecko.mContents.is_empty()
|
||||
}
|
||||
|
@ -2892,7 +2587,7 @@ clip-path
|
|||
pub fn set_content(&mut self, v: longhands::content::computed_value::T) {
|
||||
use crate::values::CustomIdent;
|
||||
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::nsStyleContentAttr;
|
||||
use crate::gecko_bindings::structs::StyleContentType;
|
||||
|
@ -2913,7 +2608,7 @@ clip-path
|
|||
content_type: StyleContentType,
|
||||
name: CustomIdent,
|
||||
sep: &str,
|
||||
style: CounterStyleOrNone,
|
||||
style: CounterStyle,
|
||||
) {
|
||||
debug_assert!(content_type == StyleContentType::Counter ||
|
||||
content_type == StyleContentType::Counters);
|
||||
|
@ -3043,7 +2738,7 @@ clip-path
|
|||
use crate::gecko_bindings::structs::StyleContentType;
|
||||
use crate::values::generics::counters::{Content, ContentItem};
|
||||
use crate::values::{CustomIdent, Either};
|
||||
use crate::values::generics::CounterStyleOrNone;
|
||||
use crate::values::generics::CounterStyle;
|
||||
use crate::values::specified::Attr;
|
||||
|
||||
if self.gecko.mContents.is_empty() {
|
||||
|
@ -3088,7 +2783,7 @@ clip-path
|
|||
Atom::from_raw(gecko_function.mIdent.mRawPtr)
|
||||
});
|
||||
let style =
|
||||
CounterStyleOrNone::from_gecko_value(&gecko_function.mCounterStyle);
|
||||
CounterStyle::from_gecko_value(&gecko_function.mCounterStyle);
|
||||
let style = match style {
|
||||
Either::First(counter_style) => counter_style,
|
||||
Either::Second(_) =>
|
||||
|
@ -3115,70 +2810,13 @@ clip-path
|
|||
}).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 style_struct_name="UI" skip_longhands="-moz-force-broken-image-icon">
|
||||
${impl_simple_type_with_conversion("_moz_force_broken_image_icon", "mForceBrokenImageIcon")}
|
||||
</%self:impl_trait>
|
||||
|
||||
<%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 style_struct_name="XUL">
|
||||
</%self:impl_trait>
|
||||
|
||||
% for style_struct in data.style_structs:
|
||||
|
|
|
@ -80,7 +80,7 @@ ${helpers.predefined_type(
|
|||
engines="gecko",
|
||||
initial_value="computed::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",
|
||||
)}
|
||||
|
||||
|
@ -401,7 +401,7 @@ ${helpers.predefined_type(
|
|||
is_system_font: true,
|
||||
},
|
||||
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
|
||||
},
|
||||
font_weight,
|
||||
|
|
|
@ -76,6 +76,7 @@ ${helpers.predefined_type(
|
|||
"ClipRectOrAuto",
|
||||
"computed::ClipRectOrAuto::auto()",
|
||||
engines="gecko",
|
||||
gecko_ffi_name="mImageRegion",
|
||||
animation_value_type="ComputedValue",
|
||||
boxed=True,
|
||||
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-image-region)",
|
||||
|
|
|
@ -18,8 +18,8 @@ ${helpers.single_keyword(
|
|||
|
||||
${helpers.predefined_type(
|
||||
"-x-span",
|
||||
"XSpan",
|
||||
"computed::XSpan(1)",
|
||||
"Integer",
|
||||
"1",
|
||||
engines="gecko",
|
||||
spec="Internal-only (for `<col span>` pres attr)",
|
||||
animation_value_type="none",
|
||||
|
|
|
@ -38,6 +38,7 @@ use style_traits::{CssWriter, KeywordsCollectFn, ParseError, ParsingMode};
|
|||
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
|
||||
use to_shmem::impl_trivial_to_shmem;
|
||||
use crate::stylesheets::{CssRuleType, Origin, UrlExtraData};
|
||||
use crate::use_counters::UseCounters;
|
||||
use crate::values::generics::text::LineHeight;
|
||||
use crate::values::{computed, resolved};
|
||||
use crate::values::computed::NonNegativeLength;
|
||||
|
@ -427,6 +428,9 @@ pub struct NonCustomPropertyId(usize);
|
|||
pub const NON_CUSTOM_PROPERTY_ID_COUNT: usize =
|
||||
${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":
|
||||
#[allow(dead_code)]
|
||||
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 {
|
||||
/// Return the longhand id that this property id represents.
|
||||
#[inline]
|
||||
|
@ -1801,16 +1844,30 @@ impl PropertyId {
|
|||
|
||||
/// Returns a given property from the string `s`.
|
||||
///
|
||||
/// Returns Err(()) for unknown non-custom properties.
|
||||
fn parse_unchecked(property_name: &str) -> Result<Self, ()> {
|
||||
/// Returns Err(()) for unknown properties.
|
||||
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! {
|
||||
property_id -> PropertyId = {
|
||||
static_id -> StaticId = {
|
||||
% for (kind, properties) in [("Longhand", data.longhands), ("Shorthand", data.shorthands)]:
|
||||
% 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:
|
||||
"${alias.name}" => {
|
||||
PropertyId::${kind}Alias(
|
||||
StaticId::${kind}Alias(
|
||||
${kind}Id::${property.camel_case},
|
||||
AliasId::${alias.camel_case},
|
||||
)
|
||||
|
@ -1818,11 +1875,31 @@ impl PropertyId {
|
|||
% 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) {
|
||||
return Ok(id.clone())
|
||||
if let Some(id) = static_id(property_name) {
|
||||
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)?;
|
||||
|
@ -1833,7 +1910,7 @@ impl PropertyId {
|
|||
/// enabled for all content.
|
||||
#[inline]
|
||||
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() {
|
||||
return Err(());
|
||||
|
@ -1847,7 +1924,7 @@ impl PropertyId {
|
|||
/// allowed in this context.
|
||||
#[inline]
|
||||
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) {
|
||||
return Err(());
|
||||
|
@ -1865,7 +1942,7 @@ impl PropertyId {
|
|||
name: &str,
|
||||
context: &ParserContext,
|
||||
) -> Result<Self, ()> {
|
||||
let id = Self::parse_unchecked(name)?;
|
||||
let id = Self::parse_unchecked(name, None)?;
|
||||
|
||||
if !id.allowed_in_ignoring_rule_type(context) {
|
||||
return Err(());
|
||||
|
|
|
@ -61,31 +61,23 @@
|
|||
|
||||
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`,
|
||||
// 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.
|
||||
use self::list_style_type::SpecifiedValue as ListStyleType;
|
||||
match (any, nones, list_style_type, image) {
|
||||
(true, 2, None, None) => {
|
||||
Ok(expanded! {
|
||||
list_style_position: position,
|
||||
list_style_image: ImageUrlOrNone::none(),
|
||||
list_style_type: list_style_type_none(),
|
||||
list_style_type: ListStyleType::None,
|
||||
})
|
||||
}
|
||||
(true, 1, None, Some(image)) => {
|
||||
Ok(expanded! {
|
||||
list_style_position: position,
|
||||
list_style_image: image,
|
||||
list_style_type: list_style_type_none(),
|
||||
list_style_type: ListStyleType::None,
|
||||
})
|
||||
}
|
||||
(true, 1, Some(list_style_type), None) => {
|
||||
|
@ -99,7 +91,7 @@
|
|||
Ok(expanded! {
|
||||
list_style_position: position,
|
||||
list_style_image: ImageUrlOrNone::none(),
|
||||
list_style_type: list_style_type_none(),
|
||||
list_style_type: ListStyleType::None,
|
||||
})
|
||||
}
|
||||
(true, 0, list_style_type, image) => {
|
||||
|
|
|
@ -73,25 +73,50 @@
|
|||
}
|
||||
|
||||
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
||||
#[allow(unused)]
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
|
||||
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 *self.text_decoration_style != text_decoration_style::SpecifiedValue::Solid {
|
||||
if !is_solid_style {
|
||||
if has_value {
|
||||
dest.write_str(" ")?;
|
||||
}
|
||||
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(" ")?;
|
||||
}
|
||||
self.text_decoration_color.to_css(dest)?;
|
||||
has_value = true;
|
||||
}
|
||||
|
||||
if let Some(text_decoration_thickness) = self.text_decoration_thickness {
|
||||
if !text_decoration_thickness.is_auto() {
|
||||
if !is_auto_thickness {
|
||||
if has_value {
|
||||
dest.write_str(" ")?;
|
||||
self.text_decoration_thickness.to_css(dest)?;
|
||||
}
|
||||
self.text_decoration_thickness.to_css(dest)?;
|
||||
}
|
||||
% endif
|
||||
|
||||
|
|
|
@ -15,6 +15,9 @@ use std::ops::DerefMut;
|
|||
///
|
||||
/// We use this on Servo to construct thread-local contexts, but clear them once
|
||||
/// 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> {
|
||||
pool: &'scope rayon::ThreadPool,
|
||||
slots: Box<[RefCell<Option<T>>]>,
|
||||
|
|
|
@ -82,7 +82,7 @@ use servo_arc::Arc;
|
|||
use smallbitvec::SmallBitVec;
|
||||
use smallvec::SmallVec;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::mem::{self, ManuallyDrop};
|
||||
use std::ops::Deref;
|
||||
use std::ptr::NonNull;
|
||||
use uluru::{Entry, LRUCache};
|
||||
|
@ -477,10 +477,9 @@ type TypelessSharingCache = SharingCacheBase<FakeCandidate>;
|
|||
type StoredSharingCache = Arc<AtomicRefCell<TypelessSharingCache>>;
|
||||
|
||||
thread_local! {
|
||||
// TODO(emilio): Looks like a few of these should just be Rc<RefCell<>> or
|
||||
// something. No need for atomics in the thread-local code.
|
||||
static SHARING_CACHE_KEY: StoredSharingCache =
|
||||
Arc::new_leaked(AtomicRefCell::new(TypelessSharingCache::default()));
|
||||
// See the comment on bloom.rs about why do we leak this.
|
||||
static SHARING_CACHE_KEY: ManuallyDrop<StoredSharingCache> =
|
||||
ManuallyDrop::new(Arc::new_leaked(Default::default()));
|
||||
}
|
||||
|
||||
/// 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::<TypelessSharingCache>()
|
||||
);
|
||||
let cache_arc = SHARING_CACHE_KEY.with(|c| c.clone());
|
||||
let cache_arc = SHARING_CACHE_KEY.with(|c| Arc::clone(&*c));
|
||||
let cache =
|
||||
OwningHandle::new_with_fn(cache_arc, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
|
||||
debug_assert!(cache.is_empty());
|
||||
|
|
|
@ -283,6 +283,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
|
|||
fn adjust_for_text_combine_upright(&mut self) {
|
||||
use crate::computed_values::text_combine_upright::T as TextCombineUpright;
|
||||
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 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
|
||||
.mutate_inherited_box()
|
||||
.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")]
|
||||
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 std::cell::Cell;
|
||||
|
||||
|
@ -15,35 +16,42 @@ const BITS_PER_ENTRY: usize = 64;
|
|||
#[cfg(target_pointer_width = "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.
|
||||
#[derive(Default)]
|
||||
pub struct NonCustomPropertyUseCounters {
|
||||
storage: [Cell<usize>; (NON_CUSTOM_PROPERTY_ID_COUNT - 1 + BITS_PER_ENTRY) / BITS_PER_ENTRY],
|
||||
}
|
||||
|
||||
impl NonCustomPropertyUseCounters {
|
||||
macro_rules! property_use_counters_methods {
|
||||
($id: ident) => {
|
||||
/// Returns the bucket a given property belongs in, and the bitmask for that
|
||||
/// property.
|
||||
#[inline(always)]
|
||||
fn bucket_and_pattern(id: NonCustomPropertyId) -> (usize, usize) {
|
||||
fn bucket_and_pattern(id: $id) -> (usize, usize) {
|
||||
let bit = id.bit();
|
||||
let bucket = bit / BITS_PER_ENTRY;
|
||||
let bit_in_bucket = bit % BITS_PER_ENTRY;
|
||||
(bucket, 1 << bit_in_bucket)
|
||||
}
|
||||
|
||||
/// Record that a given non-custom property ID has been parsed.
|
||||
/// Record that a given property ID has been parsed.
|
||||
#[inline]
|
||||
pub fn record(&self, id: NonCustomPropertyId) {
|
||||
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 non-custom property ID has been recorded
|
||||
/// Returns whether a given property ID has been recorded
|
||||
/// earlier.
|
||||
#[inline]
|
||||
pub fn recorded(&self, id: NonCustomPropertyId) -> bool {
|
||||
pub fn recorded(&self, id: $id) -> bool {
|
||||
let (bucket, pattern) = Self::bucket_and_pattern(id);
|
||||
self.storage[bucket].get() & pattern != 0
|
||||
}
|
||||
|
@ -55,6 +63,15 @@ impl NonCustomPropertyUseCounters {
|
|||
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.
|
||||
|
@ -63,6 +80,8 @@ pub struct UseCounters {
|
|||
/// The counters for non-custom properties that have been parsed in the
|
||||
/// document's stylesheets.
|
||||
pub non_custom_properties: NonCustomPropertyUseCounters,
|
||||
/// The counters for css properties which we haven't implemented yet.
|
||||
pub counted_unknown_properties: CountedUnknownPropertyUseCounters,
|
||||
}
|
||||
|
||||
impl UseCounters {
|
||||
|
@ -72,7 +91,9 @@ impl UseCounters {
|
|||
#[inline]
|
||||
pub fn merge(&self, other: &Self) {
|
||||
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")]
|
||||
use crate::gecko_bindings::{bindings, structs};
|
||||
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::generics::font as generics;
|
||||
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::CSSFloat;
|
||||
use crate::Atom;
|
||||
|
@ -88,9 +92,6 @@ pub struct FontSize {
|
|||
pub keyword_info: Option<KeywordInfo>,
|
||||
}
|
||||
|
||||
/// Additional information for computed keyword-derived font sizes.
|
||||
pub type KeywordInfo = generics::KeywordInfo<NonNegativeLength>;
|
||||
|
||||
impl FontWeight {
|
||||
/// Value for normal
|
||||
pub fn normal() -> Self {
|
||||
|
@ -162,17 +163,17 @@ impl FontSize {
|
|||
}
|
||||
|
||||
impl ToAnimatedValue for FontSize {
|
||||
type AnimatedValue = NonNegativeLength;
|
||||
type AnimatedValue = Length;
|
||||
|
||||
#[inline]
|
||||
fn to_animated_value(self) -> Self::AnimatedValue {
|
||||
self.size
|
||||
self.size.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
||||
FontSize {
|
||||
size: animated.clamp(),
|
||||
size: NonNegative(animated.clamp_to_non_negative()),
|
||||
keyword_info: None,
|
||||
}
|
||||
}
|
||||
|
@ -647,10 +648,10 @@ impl ToAnimatedValue for FontSizeAdjust {
|
|||
pub type FontVariantAlternates = specified::VariantAlternatesList;
|
||||
|
||||
impl FontVariantAlternates {
|
||||
#[inline]
|
||||
/// Get initial value with VariantAlternatesList
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> Self {
|
||||
specified::VariantAlternatesList(vec![].into_boxed_slice())
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -297,7 +297,7 @@ impl specified::CalcLengthPercentage {
|
|||
) -> LengthPercentage {
|
||||
self.to_computed_value_with_zoom(
|
||||
context,
|
||||
|abs| context.maybe_zoom_text(abs.into()).0,
|
||||
|abs| context.maybe_zoom_text(abs.into()),
|
||||
base_size,
|
||||
)
|
||||
}
|
||||
|
@ -360,8 +360,8 @@ impl LengthPercentage {
|
|||
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
|
||||
// hash key.
|
||||
// CSSFloat doesn't implement Hash, so does CSSPixelLength. Therefore, we
|
||||
// still use Au as the hash key.
|
||||
#[allow(missing_docs)]
|
||||
pub fn to_hash_key(&self) -> (Au, NotNan<f32>) {
|
||||
(
|
||||
|
@ -840,14 +840,6 @@ impl NonNegativeLength {
|
|||
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 {
|
||||
|
|
|
@ -75,7 +75,6 @@ pub use self::resolution::Resolution;
|
|||
pub use self::svg::MozContextProperties;
|
||||
pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind};
|
||||
pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
|
||||
pub use self::table::XSpan;
|
||||
pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight};
|
||||
pub use self::text::{OverflowWrap, TextOverflow, WordBreak, WordSpacing};
|
||||
pub use self::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle};
|
||||
|
@ -116,7 +115,6 @@ pub mod position;
|
|||
pub mod rect;
|
||||
pub mod resolution;
|
||||
pub mod svg;
|
||||
pub mod table;
|
||||
pub mod text;
|
||||
pub mod time;
|
||||
pub mod transform;
|
||||
|
@ -230,7 +228,7 @@ impl<'a> Context<'a> {
|
|||
|
||||
/// Apply text-zoom if enabled.
|
||||
#[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
|
||||
// -x-text-zoom property, which leads to a false value
|
||||
// in mAllowZoom
|
||||
|
@ -243,7 +241,7 @@ impl<'a> Context<'a> {
|
|||
|
||||
/// (Servo doesn't do text-zoom)
|
||||
#[cfg(feature = "servo")]
|
||||
pub fn maybe_zoom_text(&self, size: NonNegativeLength) -> NonNegativeLength {
|
||||
pub fn maybe_zoom_text(&self, size: CSSPixelLength) -> CSSPixelLength {
|
||||
size
|
||||
}
|
||||
}
|
||||
|
@ -685,11 +683,11 @@ impl From<CSSInteger> for PositiveInteger {
|
|||
/// A computed positive `<integer>` value or `none`.
|
||||
pub type PositiveIntegerOrNone = Either<PositiveInteger, None_>;
|
||||
|
||||
/// rect(...)
|
||||
pub type ClipRect = generics::ClipRect<LengthOrAuto>;
|
||||
/// rect(...) | auto
|
||||
pub type ClipRect = generics::GenericClipRect<LengthOrAuto>;
|
||||
|
||||
/// rect(...) | auto
|
||||
pub type ClipRectOrAuto = Either<ClipRect, Auto>;
|
||||
pub type ClipRectOrAuto = generics::GenericClipRectOrAuto<ClipRect>;
|
||||
|
||||
/// The computed value of a grid `<track-breadth>`
|
||||
pub type TrackBreadth = GenericTrackBreadth<LengthPercentage>;
|
||||
|
@ -709,18 +707,3 @@ pub type GridLine = GenericGridLine<Integer>;
|
|||
|
||||
/// `<grid-template-rows> | <grid-template-columns>`
|
||||
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
|
||||
///
|
||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue)]
|
||||
#[allow(missing_docs)]
|
||||
#[repr(C, u8)]
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#[cfg(feature = "servo")]
|
||||
use crate::computed_values::list_style_type::T as ListStyleType;
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::values::generics::CounterStyleOrNone;
|
||||
use crate::values::generics::CounterStyle;
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::values::specified::Attr;
|
||||
use crate::values::CustomIdent;
|
||||
|
@ -25,12 +25,14 @@ use std::ops::Deref;
|
|||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
pub struct CounterPair<Integer> {
|
||||
#[repr(C)]
|
||||
pub struct GenericCounterPair<Integer> {
|
||||
/// The name of the counter.
|
||||
pub name: CustomIdent,
|
||||
/// The value of the counter / increment / etc.
|
||||
pub value: Integer,
|
||||
}
|
||||
pub use self::GenericCounterPair as CounterPair;
|
||||
|
||||
/// A generic value for the `counter-increment` property.
|
||||
#[derive(
|
||||
|
@ -45,13 +47,15 @@ pub struct CounterPair<Integer> {
|
|||
ToResolvedValue,
|
||||
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> {
|
||||
/// Returns a new value for `counter-increment`.
|
||||
#[inline]
|
||||
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,
|
||||
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> {
|
||||
/// Returns a new value for `counter-set` / `counter-reset`.
|
||||
#[inline]
|
||||
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,
|
||||
ToShmem,
|
||||
)]
|
||||
pub struct Counters<I>(#[css(iterable, if_empty = "none")] Box<[CounterPair<I>]>);
|
||||
|
||||
impl<I> Counters<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
|
||||
/// IntoIter: https://github.com/rust-lang/rust/issues/59878
|
||||
#[inline]
|
||||
pub fn into_vec(self) -> Vec<CounterPair<I>> {
|
||||
self.0.into_vec()
|
||||
}
|
||||
}
|
||||
#[repr(transparent)]
|
||||
pub struct GenericCounters<I>(
|
||||
#[css(iterable, if_empty = "none")] crate::OwnedSlice<GenericCounterPair<I>>,
|
||||
);
|
||||
pub use self::GenericCounters as Counters;
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
type CounterStyleType = ListStyleType;
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
type CounterStyleType = CounterStyleOrNone;
|
||||
type CounterStyleType = CounterStyle;
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
#[inline]
|
||||
|
@ -138,7 +138,7 @@ fn is_decimal(counter_type: &CounterStyleType) -> bool {
|
|||
#[cfg(feature = "gecko")]
|
||||
#[inline]
|
||||
fn is_decimal(counter_type: &CounterStyleType) -> bool {
|
||||
*counter_type == CounterStyleOrNone::decimal()
|
||||
*counter_type == CounterStyle::decimal()
|
||||
}
|
||||
|
||||
/// The specified value for the `content` property.
|
||||
|
|
|
@ -34,8 +34,6 @@ pub struct GenericBoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
|
|||
pub use self::GenericBoxShadow as BoxShadow;
|
||||
|
||||
/// A generic value for a single `filter`.
|
||||
///
|
||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[animation(no_bound(U))]
|
||||
#[derive(
|
||||
|
|
|
@ -5,14 +5,13 @@
|
|||
//! Generic types for font stuff.
|
||||
|
||||
use crate::parser::{Parse, ParserContext};
|
||||
use app_units::Au;
|
||||
use byteorder::{BigEndian, ReadBytesExt};
|
||||
use cssparser::Parser;
|
||||
use num_traits::One;
|
||||
use std::fmt::{self, Write};
|
||||
use std::io::Cursor;
|
||||
use style_traits::{CssWriter, KeywordsCollectFn, ParseError};
|
||||
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
|
||||
use style_traits::{CssWriter, ParseError};
|
||||
use style_traits::{StyleParseErrorKind, ToCss};
|
||||
|
||||
/// https://drafts.csswg.org/css-fonts-4/#feature-tag-value
|
||||
#[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.
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// <https://drafts.csswg.org/css-grid/#typedef-track-breadth>
|
||||
///
|
||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
||||
#[derive(
|
||||
Animate,
|
||||
Clone,
|
||||
|
@ -230,8 +228,6 @@ impl<L> TrackBreadth<L> {
|
|||
/// generic only to avoid code bloat. It only takes `<length-percentage>`
|
||||
///
|
||||
/// <https://drafts.csswg.org/css-grid/#typedef-track-size>
|
||||
///
|
||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
||||
#[derive(
|
||||
Clone,
|
||||
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>
|
||||
///
|
||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
||||
#[derive(
|
||||
Animate,
|
||||
Clone,
|
||||
|
@ -729,8 +723,6 @@ impl ToCss for LineNameList {
|
|||
}
|
||||
|
||||
/// Variants for `<grid-template-rows> | <grid-template-columns>`
|
||||
///
|
||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
||||
#[derive(
|
||||
Animate,
|
||||
Clone,
|
||||
|
|
|
@ -92,13 +92,10 @@ impl SymbolsType {
|
|||
|
||||
/// <https://drafts.csswg.org/css-counter-styles/#typedef-counter-style>
|
||||
///
|
||||
/// Since wherever <counter-style> is used, 'none' is a valid value as
|
||||
/// well, we combine them into one type to make code simpler.
|
||||
/// Note that 'none' is not a valid name.
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss, ToResolvedValue, ToShmem)]
|
||||
pub enum CounterStyleOrNone {
|
||||
/// `none`
|
||||
None,
|
||||
pub enum CounterStyle {
|
||||
/// `<counter-style-name>`
|
||||
Name(CustomIdent),
|
||||
/// `symbols()`
|
||||
|
@ -111,28 +108,25 @@ fn is_symbolic(symbols_type: &SymbolsType) -> bool {
|
|||
*symbols_type == SymbolsType::Symbolic
|
||||
}
|
||||
|
||||
impl CounterStyleOrNone {
|
||||
impl CounterStyle {
|
||||
/// disc value
|
||||
pub fn disc() -> Self {
|
||||
CounterStyleOrNone::Name(CustomIdent(atom!("disc")))
|
||||
CounterStyle::Name(CustomIdent(atom!("disc")))
|
||||
}
|
||||
|
||||
/// decimal value
|
||||
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>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
if let Ok(name) = input.try(|i| parse_counter_style_name(i)) {
|
||||
return Ok(CounterStyleOrNone::Name(name));
|
||||
}
|
||||
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(CounterStyleOrNone::None);
|
||||
return Ok(CounterStyle::Name(name));
|
||||
}
|
||||
input.expect_function_matching("symbols")?;
|
||||
input.parse_nested_block(|input| {
|
||||
|
@ -151,12 +145,12 @@ impl Parse for CounterStyleOrNone {
|
|||
if symbols.0.iter().any(|sym| !sym.is_allowed_in_symbols()) {
|
||||
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) {
|
||||
// XXX The best approach for implementing this is probably
|
||||
// having a CounterStyleName type wrapping CustomIdent, and
|
||||
|
@ -165,7 +159,7 @@ impl SpecifiedValueInfo for CounterStyleOrNone {
|
|||
// approach here.
|
||||
macro_rules! predefined {
|
||||
($($name:expr,)+) => {
|
||||
f(&["none", "symbols", $($name,)+]);
|
||||
f(&["symbols", $($name,)+]);
|
||||
}
|
||||
}
|
||||
include!("../../counter_style/predefined.rs");
|
||||
|
@ -272,9 +266,53 @@ pub struct ZeroToOne<T>(pub T);
|
|||
ToShmem,
|
||||
)]
|
||||
#[css(function = "rect", comma)]
|
||||
pub struct ClipRect<LengthOrAuto> {
|
||||
#[repr(C)]
|
||||
pub struct GenericClipRect<LengthOrAuto> {
|
||||
pub top: LengthOrAuto,
|
||||
pub right: LengthOrAuto,
|
||||
pub bottom: 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;
|
||||
|
||||
/// The fallback of an SVG paint server value.
|
||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
||||
#[derive(
|
||||
Animate,
|
||||
Clone,
|
||||
|
@ -43,8 +42,6 @@ pub use self::GenericSVGPaintFallback as SVGPaintFallback;
|
|||
/// An SVG paint value
|
||||
///
|
||||
/// <https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint>
|
||||
///
|
||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
||||
#[animation(no_bound(Url))]
|
||||
#[derive(
|
||||
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
|
||||
/// context properties have a fallback as well.
|
||||
///
|
||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
||||
#[animation(no_bound(U))]
|
||||
#[derive(
|
||||
Animate,
|
||||
|
|
|
@ -151,7 +151,6 @@ fn is_same<N: PartialEq>(x: &N, y: &N) -> bool {
|
|||
)]
|
||||
#[repr(C, u8)]
|
||||
/// 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>
|
||||
where
|
||||
Angle: Zero,
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
//! Generic types for url properties.
|
||||
|
||||
/// An image url or none, used for example in list-style-image
|
||||
///
|
||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
||||
#[derive(
|
||||
Animate,
|
||||
Clone,
|
||||
|
|
|
@ -105,16 +105,12 @@ pub enum DisplayInside {
|
|||
#[cfg(feature = "gecko")]
|
||||
MozGrid,
|
||||
#[cfg(feature = "gecko")]
|
||||
MozInlineGrid,
|
||||
#[cfg(feature = "gecko")]
|
||||
MozGridGroup,
|
||||
#[cfg(feature = "gecko")]
|
||||
MozGridLine,
|
||||
#[cfg(feature = "gecko")]
|
||||
MozStack,
|
||||
#[cfg(feature = "gecko")]
|
||||
MozInlineStack,
|
||||
#[cfg(feature = "gecko")]
|
||||
MozDeck,
|
||||
#[cfg(feature = "gecko")]
|
||||
MozGroupbox,
|
||||
|
@ -243,16 +239,12 @@ impl Display {
|
|||
#[cfg(feature = "gecko")]
|
||||
pub const MozGrid: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozGrid);
|
||||
#[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);
|
||||
#[cfg(feature = "gecko")]
|
||||
pub const MozGridLine: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozGridLine);
|
||||
#[cfg(feature = "gecko")]
|
||||
pub const MozStack: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozStack);
|
||||
#[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);
|
||||
#[cfg(feature = "gecko")]
|
||||
pub const MozGroupbox: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozGroupbox);
|
||||
|
@ -422,7 +414,6 @@ impl Display {
|
|||
#[cfg(feature = "gecko")]
|
||||
DisplayOutside::XUL => match self.inside() {
|
||||
DisplayInside::MozBox => Display::MozInlineBox,
|
||||
DisplayInside::MozStack => Display::MozInlineStack,
|
||||
_ => *self,
|
||||
},
|
||||
_ => *self,
|
||||
|
@ -469,10 +460,6 @@ impl ToCss for Display {
|
|||
Display::WebkitInlineBox => dest.write_str("-webkit-inline-box"),
|
||||
#[cfg(feature = "gecko")]
|
||||
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"))]
|
||||
Display::TableCaption => dest.write_str("table-caption"),
|
||||
_ => match (outside, inside) {
|
||||
|
@ -662,16 +649,12 @@ impl Parse for Display {
|
|||
#[cfg(feature = "gecko")]
|
||||
"-moz-grid" if moz_display_values_enabled(context) => Display::MozGrid,
|
||||
#[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,
|
||||
#[cfg(feature = "gecko")]
|
||||
"-moz-grid-line" if moz_display_values_enabled(context) => Display::MozGridLine,
|
||||
#[cfg(feature = "gecko")]
|
||||
"-moz-stack" if moz_display_values_enabled(context) => Display::MozStack,
|
||||
#[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,
|
||||
#[cfg(feature = "gecko")]
|
||||
"-moz-groupbox" if moz_display_values_enabled(context) => Display::MozGroupbox,
|
||||
|
@ -688,6 +671,7 @@ impl SpecifiedValueInfo for Display {
|
|||
"contents",
|
||||
"flex",
|
||||
"flow-root",
|
||||
"flow-root list-item",
|
||||
"grid",
|
||||
"inline",
|
||||
"inline-block",
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
use crate::computed_values::list_style_type::T as ListStyleType;
|
||||
use crate::parser::{Parse, ParserContext};
|
||||
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::CounterSetOrReset as GenericCounterSetOrReset;
|
||||
use crate::values::generics::counters::GenericCounterIncrement;
|
||||
use crate::values::generics::counters::GenericCounterSetOrReset;
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::values::generics::CounterStyleOrNone;
|
||||
use crate::values::generics::CounterStyle;
|
||||
use crate::values::specified::url::SpecifiedImageUrl;
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::values::specified::Attr;
|
||||
|
@ -98,13 +98,13 @@ impl Content {
|
|||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
fn parse_counter_style(context: &ParserContext, input: &mut Parser) -> CounterStyleOrNone {
|
||||
fn parse_counter_style(context: &ParserContext, input: &mut Parser) -> CounterStyle {
|
||||
input
|
||||
.try(|input| {
|
||||
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 as computed, Length, NonNegativeLength};
|
||||
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::{KeywordSize, VariationValue};
|
||||
use crate::values::generics::NonNegative;
|
||||
use crate::values::specified::length::{FontBaseSize, AU_PER_PT, AU_PER_PX};
|
||||
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)]
|
||||
/// A specified font-size value
|
||||
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
|
||||
/// and smaller by both Firefox and Chrome
|
||||
const LARGER_FONT_SIZE_RATIO: f32 = 1.2;
|
||||
|
@ -789,8 +877,7 @@ impl ToComputedValue for KeywordSize {
|
|||
impl FontSize {
|
||||
/// <https://html.spec.whatwg.org/multipage/#rules-for-parsing-a-legacy-font-size>
|
||||
pub fn from_html_size(size: u8) -> Self {
|
||||
FontSize::Keyword(
|
||||
match size {
|
||||
FontSize::Keyword(KeywordInfo::new(match size {
|
||||
// If value is less than 1, let it be 1.
|
||||
0 | 1 => KeywordSize::XSmall,
|
||||
2 => KeywordSize::Small,
|
||||
|
@ -800,9 +887,7 @@ impl FontSize {
|
|||
6 => KeywordSize::XXLarge,
|
||||
// If value is greater than 7, let it be 7.
|
||||
_ => KeywordSize::XXXLarge,
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
}))
|
||||
}
|
||||
|
||||
/// Compute it against a given base font size
|
||||
|
@ -819,7 +904,7 @@ impl FontSize {
|
|||
.get_parent_font()
|
||||
.clone_font_size()
|
||||
.keyword_info
|
||||
.map(|i| i.compose(factor, Au(0).into()))
|
||||
.map(|i| i.compose(factor, CSSPixelLength::new(0.)))
|
||||
};
|
||||
let mut info = None;
|
||||
let size = match *self {
|
||||
|
@ -829,17 +914,15 @@ impl FontSize {
|
|||
// Tack the em unit onto the factor
|
||||
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(
|
||||
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))) => {
|
||||
context.maybe_zoom_text(l.to_computed_value(context).into())
|
||||
},
|
||||
FontSize::Length(LengthPercentage::Length(ref l)) => {
|
||||
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),
|
||||
FontSize::Length(LengthPercentage::Percentage(pc)) => {
|
||||
// If the parent font was keyword-derived, this is too.
|
||||
// Tack the % onto the factor
|
||||
|
@ -871,29 +954,32 @@ impl FontSize {
|
|||
context,
|
||||
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);
|
||||
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) => {
|
||||
// As a specified keyword, this is keyword derived
|
||||
info = Some(i);
|
||||
i.to_computed_value(context)
|
||||
i.to_computed_value(context).clamp_to_non_negative()
|
||||
},
|
||||
FontSize::Smaller => {
|
||||
info = compose_keyword(1. / LARGER_FONT_SIZE_RATIO);
|
||||
FontRelativeLength::Em(1. / LARGER_FONT_SIZE_RATIO)
|
||||
.to_computed_value(context, base_size)
|
||||
.into()
|
||||
},
|
||||
FontSize::Larger => {
|
||||
info = compose_keyword(LARGER_FONT_SIZE_RATIO);
|
||||
FontRelativeLength::Em(LARGER_FONT_SIZE_RATIO)
|
||||
.to_computed_value(context, base_size)
|
||||
.into()
|
||||
FontRelativeLength::Em(LARGER_FONT_SIZE_RATIO).to_computed_value(context, base_size)
|
||||
},
|
||||
|
||||
FontSize::System(_) => {
|
||||
|
@ -903,12 +989,18 @@ impl FontSize {
|
|||
}
|
||||
#[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 {
|
||||
size: size,
|
||||
size: NonNegative(size),
|
||||
keyword_info: info,
|
||||
}
|
||||
}
|
||||
|
@ -952,7 +1044,7 @@ impl FontSize {
|
|||
}
|
||||
|
||||
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,
|
||||
|
@ -998,6 +1090,7 @@ bitflags! {
|
|||
#[derive(
|
||||
Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToResolvedValue, ToShmem,
|
||||
)]
|
||||
#[repr(C, u8)]
|
||||
/// Set of variant alternates
|
||||
pub enum VariantAlternates {
|
||||
/// Enables display of stylistic alternates
|
||||
|
@ -1005,10 +1098,10 @@ pub enum VariantAlternates {
|
|||
Stylistic(CustomIdent),
|
||||
/// Enables display with stylistic sets
|
||||
#[css(comma, function)]
|
||||
Styleset(#[css(iterable)] Box<[CustomIdent]>),
|
||||
Styleset(#[css(iterable)] crate::OwnedSlice<CustomIdent>),
|
||||
/// Enables display of specific character variants
|
||||
#[css(comma, function)]
|
||||
CharacterVariant(#[css(iterable)] Box<[CustomIdent]>),
|
||||
CharacterVariant(#[css(iterable)] crate::OwnedSlice<CustomIdent>),
|
||||
/// Enables display of swash glyphs
|
||||
#[css(function)]
|
||||
Swash(CustomIdent),
|
||||
|
@ -1023,11 +1116,20 @@ pub enum VariantAlternates {
|
|||
}
|
||||
|
||||
#[derive(
|
||||
Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToResolvedValue, ToShmem,
|
||||
Clone,
|
||||
Debug,
|
||||
Default,
|
||||
MallocSizeOf,
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToCss,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[repr(transparent)]
|
||||
/// List of Variant Alternates
|
||||
pub struct VariantAlternatesList(
|
||||
#[css(if_empty = "normal", iterable)] pub Box<[VariantAlternates]>,
|
||||
#[css(if_empty = "normal", iterable)] crate::OwnedSlice<VariantAlternates>,
|
||||
);
|
||||
|
||||
impl VariantAlternatesList {
|
||||
|
@ -1059,7 +1161,7 @@ impl FontVariantAlternates {
|
|||
#[inline]
|
||||
/// Get initial specified value with VariantAlternatesList
|
||||
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);
|
||||
|
@ -1093,16 +1195,14 @@ impl Parse for FontVariantAlternates {
|
|||
_: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<FontVariantAlternates, ParseError<'i>> {
|
||||
let mut alternates = Vec::new();
|
||||
if input
|
||||
.try(|input| input.expect_ident_matching("normal"))
|
||||
.is_ok()
|
||||
{
|
||||
return Ok(FontVariantAlternates::Value(VariantAlternatesList(
|
||||
alternates.into_boxed_slice(),
|
||||
)));
|
||||
return Ok(FontVariantAlternates::Value(Default::default()));
|
||||
}
|
||||
|
||||
let mut alternates = Vec::new();
|
||||
let mut parsed_alternates = VariantAlternatesParsingFlags::empty();
|
||||
macro_rules! check_if_parsed(
|
||||
($input:expr, $flag:path) => (
|
||||
|
@ -1156,7 +1256,7 @@ impl Parse for FontVariantAlternates {
|
|||
let location = i.current_source_location();
|
||||
CustomIdent::from_ident(location, i.expect_ident()?, &[])
|
||||
})?;
|
||||
alternates.push(VariantAlternates::Styleset(idents.into_boxed_slice()));
|
||||
alternates.push(VariantAlternates::Styleset(idents.into()));
|
||||
Ok(())
|
||||
},
|
||||
"character-variant" => {
|
||||
|
@ -1165,7 +1265,7 @@ impl Parse for FontVariantAlternates {
|
|||
let location = i.current_source_location();
|
||||
CustomIdent::from_ident(location, i.expect_ident()?, &[])
|
||||
})?;
|
||||
alternates.push(VariantAlternates::CharacterVariant(idents.into_boxed_slice()));
|
||||
alternates.push(VariantAlternates::CharacterVariant(idents.into()));
|
||||
Ok(())
|
||||
},
|
||||
_ => return Err(i.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
|
||||
|
@ -1179,7 +1279,7 @@ impl Parse for FontVariantAlternates {
|
|||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||
}
|
||||
Ok(FontVariantAlternates::Value(VariantAlternatesList(
|
||||
alternates.into_boxed_slice(),
|
||||
alternates.into(),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
use crate::parser::{Parse, ParserContext};
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::values::generics::CounterStyleOrNone;
|
||||
use crate::values::generics::CounterStyle;
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::values::CustomIdent;
|
||||
use cssparser::{Parser, Token};
|
||||
|
@ -27,8 +27,10 @@ use style_traits::{ParseError, StyleParseErrorKind};
|
|||
ToShmem,
|
||||
)]
|
||||
pub enum ListStyleType {
|
||||
/// <counter-style> | none
|
||||
CounterStyle(CounterStyleOrNone),
|
||||
/// `none`
|
||||
None,
|
||||
/// <counter-style>
|
||||
CounterStyle(CounterStyle),
|
||||
/// <string>
|
||||
String(String),
|
||||
}
|
||||
|
@ -38,7 +40,7 @@ impl ListStyleType {
|
|||
/// Initial specified value for `list-style-type`.
|
||||
#[inline]
|
||||
pub fn disc() -> Self {
|
||||
ListStyleType::CounterStyle(CounterStyleOrNone::disc())
|
||||
ListStyleType::CounterStyle(CounterStyle::disc())
|
||||
}
|
||||
|
||||
/// Convert from gecko keyword to list-style-type.
|
||||
|
@ -50,10 +52,10 @@ impl ListStyleType {
|
|||
use crate::gecko_bindings::structs;
|
||||
|
||||
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_CIRCLE => atom!("circle"),
|
||||
structs::NS_STYLE_LIST_STYLE_SQUARE => atom!("square"),
|
||||
|
@ -73,10 +75,12 @@ impl Parse for ListStyleType {
|
|||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> 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));
|
||||
}
|
||||
|
||||
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(ListStyleType::None);
|
||||
}
|
||||
Ok(ListStyleType::String(
|
||||
input.expect_string()?.as_ref().to_owned(),
|
||||
))
|
||||
|
@ -126,8 +130,6 @@ pub struct QuoteList(
|
|||
|
||||
/// Specified and computed `quotes` property: `auto`, `none`, or a list
|
||||
/// of characters.
|
||||
///
|
||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
||||
#[derive(
|
||||
Clone,
|
||||
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::transform::IsParallelTo;
|
||||
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::parser::{Parse, ParserContext};
|
||||
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::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
|
||||
pub use self::svg_path::SVGPathData;
|
||||
pub use self::table::XSpan;
|
||||
pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight, TextAlign};
|
||||
pub use self::text::{OverflowWrap, TextEmphasisPosition, TextEmphasisStyle, WordBreak};
|
||||
pub use self::text::{TextAlignKeyword, TextDecorationLine, TextOverflow, WordSpacing};
|
||||
|
@ -122,7 +121,6 @@ pub mod resolution;
|
|||
pub mod source_size_list;
|
||||
pub mod svg;
|
||||
pub mod svg_path;
|
||||
pub mod table;
|
||||
pub mod text;
|
||||
pub mod time;
|
||||
pub mod transform;
|
||||
|
@ -641,7 +639,7 @@ pub type GridLine = GenericGridLine<Integer>;
|
|||
pub type GridTemplateComponent = GenericGridTemplateComponent<LengthPercentage, Integer>;
|
||||
|
||||
/// rect(...)
|
||||
pub type ClipRect = generics::ClipRect<LengthOrAuto>;
|
||||
pub type ClipRect = generics::GenericClipRect<LengthOrAuto>;
|
||||
|
||||
impl Parse for ClipRect {
|
||||
fn parse<'i, 't>(
|
||||
|
@ -654,7 +652,7 @@ impl Parse for ClipRect {
|
|||
|
||||
impl ClipRect {
|
||||
/// Parses a rect(<top>, <left>, <bottom>, <right>), allowing quirks.
|
||||
pub fn parse_quirky<'i, 't>(
|
||||
fn parse_quirky<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks,
|
||||
|
@ -698,7 +696,7 @@ impl ClipRect {
|
|||
}
|
||||
|
||||
/// rect(...) | auto
|
||||
pub type ClipRectOrAuto = Either<ClipRect, Auto>;
|
||||
pub type ClipRectOrAuto = generics::GenericClipRectOrAuto<ClipRect>;
|
||||
|
||||
impl ClipRectOrAuto {
|
||||
/// Parses a ClipRect or Auto, allowing quirks.
|
||||
|
@ -708,10 +706,10 @@ impl ClipRectOrAuto {
|
|||
allow_quirks: AllowQuirks,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
if let Ok(v) = input.try(|i| ClipRect::parse_quirky(context, i, allow_quirks)) {
|
||||
Ok(Either::First(v))
|
||||
} else {
|
||||
Auto::parse(context, input).map(Either::Second)
|
||||
return Ok(generics::GenericClipRectOrAuto::Rect(v));
|
||||
}
|
||||
input.expect_ident_matching("auto")?;
|
||||
Ok(generics::GenericClipRectOrAuto::Auto)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ use style_traits::{ParseError, StyleParseErrorKind};
|
|||
/// The offset-path value.
|
||||
///
|
||||
/// https://drafts.fxtf.org/motion-1/#offset-path-property
|
||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
||||
#[derive(
|
||||
Animate,
|
||||
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
|
||||
/// of the grid, making the overall layout of the grid container easier to
|
||||
/// understand.
|
||||
///
|
||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
||||
#[repr(C, u8)]
|
||||
#[derive(
|
||||
Clone,
|
||||
|
|
|
@ -106,13 +106,13 @@ pub enum PaintOrder {
|
|||
}
|
||||
|
||||
/// Number of non-normal components
|
||||
const PAINT_ORDER_COUNT: u8 = 3;
|
||||
pub const PAINT_ORDER_COUNT: u8 = 3;
|
||||
|
||||
/// Number of bits for each component
|
||||
const PAINT_ORDER_SHIFT: u8 = 2;
|
||||
pub const PAINT_ORDER_SHIFT: u8 = 2;
|
||||
|
||||
/// 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
|
||||
/// bitfields below, as a six-bit field, of 3 two-bit pairs
|
||||
|
@ -135,6 +135,7 @@ const PAINT_ORDER_MASK: u8 = 0b11;
|
|||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[repr(transparent)]
|
||||
pub struct SVGPaintOrder(pub u8);
|
||||
|
||||
impl SVGPaintOrder {
|
||||
|
@ -146,7 +147,7 @@ impl SVGPaintOrder {
|
|||
/// Get variant of `paint-order`
|
||||
pub fn order_at(&self, pos: u8) -> PaintOrder {
|
||||
// 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) => {
|
||||
let result = match non_negative_lp.0 {
|
||||
LengthPercentage::Length(NoCalcLength::Absolute(ref abs)) => {
|
||||
context
|
||||
.maybe_zoom_text(abs.to_computed_value(context).into())
|
||||
.0
|
||||
context.maybe_zoom_text(abs.to_computed_value(context))
|
||||
},
|
||||
LengthPercentage::Length(ref length) => length.to_computed_value(context),
|
||||
LengthPercentage::Percentage(ref p) => FontRelativeLength::Em(p.0)
|
||||
|
@ -133,7 +131,6 @@ impl ToComputedValue for LineHeight {
|
|||
}
|
||||
|
||||
/// A generic value for the `text-overflow` property.
|
||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
||||
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
|
||||
#[repr(C, u8)]
|
||||
pub enum TextOverflowSide {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue