mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
style: Add bindings for box shadows, and remove nsCSSShadowArray and friends.
Differential Revision: https://phabricator.services.mozilla.com/D30547
This commit is contained in:
parent
a109fbb7c8
commit
5f6c8d9060
11 changed files with 46 additions and 220 deletions
|
@ -6,8 +6,6 @@
|
|||
|
||||
mod ns_com_ptr;
|
||||
mod ns_compatibility;
|
||||
mod ns_css_shadow_array;
|
||||
mod ns_css_shadow_item;
|
||||
pub mod ns_css_value;
|
||||
mod ns_style_auto_array;
|
||||
pub mod ns_style_coord;
|
||||
|
|
|
@ -1,78 +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/. */
|
||||
|
||||
//! Rust helpers for Gecko's `nsCSSShadowArray`.
|
||||
|
||||
use crate::gecko_bindings::bindings::Gecko_AddRefCSSShadowArrayArbitraryThread;
|
||||
use crate::gecko_bindings::bindings::Gecko_NewCSSShadowArray;
|
||||
use crate::gecko_bindings::bindings::Gecko_ReleaseCSSShadowArrayArbitraryThread;
|
||||
use crate::gecko_bindings::structs::{nsCSSShadowArray, nsCSSShadowItem, RefPtr};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::{ptr, slice};
|
||||
|
||||
impl RefPtr<nsCSSShadowArray> {
|
||||
/// Replaces the current `nsCSSShadowArray` with a new one of len `len`.
|
||||
pub fn replace_with_new(&mut self, len: u32) {
|
||||
unsafe {
|
||||
if !self.mRawPtr.is_null() {
|
||||
Gecko_ReleaseCSSShadowArrayArbitraryThread(self.mRawPtr);
|
||||
}
|
||||
|
||||
self.mRawPtr = if len == 0 {
|
||||
ptr::null_mut()
|
||||
} else {
|
||||
Gecko_NewCSSShadowArray(len)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the value to other `nsCSSShadowArray`, bumping and decreasing
|
||||
/// refcounts as needed.
|
||||
///
|
||||
/// TODO(emilio): Seems like this could move to `refptr.rs`, and be more
|
||||
/// generic.
|
||||
pub fn copy_from(&mut self, other: &Self) {
|
||||
unsafe {
|
||||
if !self.mRawPtr.is_null() {
|
||||
Gecko_ReleaseCSSShadowArrayArbitraryThread(self.mRawPtr);
|
||||
}
|
||||
if !other.mRawPtr.is_null() {
|
||||
Gecko_AddRefCSSShadowArrayArbitraryThread(other.mRawPtr);
|
||||
}
|
||||
|
||||
self.mRawPtr = other.mRawPtr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for RefPtr<nsCSSShadowArray> {
|
||||
type Target = [nsCSSShadowItem];
|
||||
fn deref(&self) -> &[nsCSSShadowItem] {
|
||||
if self.mRawPtr.is_null() {
|
||||
&[]
|
||||
} else {
|
||||
unsafe {
|
||||
slice::from_raw_parts(
|
||||
(*self.mRawPtr).mArray.as_ptr(),
|
||||
(*self.mRawPtr).mLength as usize,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for RefPtr<nsCSSShadowArray> {
|
||||
fn deref_mut(&mut self) -> &mut [nsCSSShadowItem] {
|
||||
if self.mRawPtr.is_null() {
|
||||
&mut []
|
||||
} else {
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(
|
||||
(*self.mRawPtr).mArray.as_mut_ptr(),
|
||||
(*self.mRawPtr).mLength as usize,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,59 +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/. */
|
||||
|
||||
//! Rust helpers for Gecko's `nsCSSShadowItem`.
|
||||
|
||||
use crate::gecko_bindings::structs::nsCSSShadowItem;
|
||||
use crate::values::computed::effects::{BoxShadow, SimpleShadow};
|
||||
use app_units::Au;
|
||||
|
||||
impl nsCSSShadowItem {
|
||||
/// Sets this item from the given box shadow.
|
||||
#[inline]
|
||||
pub fn set_from_box_shadow(&mut self, shadow: BoxShadow) {
|
||||
self.set_from_simple_shadow(shadow.base);
|
||||
self.mSpread = shadow.spread.to_i32_au();
|
||||
self.mInset = shadow.inset;
|
||||
}
|
||||
|
||||
/// Returns this item as a box shadow.
|
||||
#[inline]
|
||||
pub fn to_box_shadow(&self) -> BoxShadow {
|
||||
BoxShadow {
|
||||
base: self.extract_simple_shadow(),
|
||||
spread: Au(self.mSpread).into(),
|
||||
inset: self.mInset,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets this item from the given simple shadow.
|
||||
#[inline]
|
||||
pub fn set_from_simple_shadow(&mut self, shadow: SimpleShadow) {
|
||||
self.mXOffset = shadow.horizontal.to_i32_au();
|
||||
self.mYOffset = shadow.vertical.to_i32_au();
|
||||
self.mRadius = shadow.blur.0.to_i32_au();
|
||||
self.mSpread = 0;
|
||||
self.mInset = false;
|
||||
self.mColor = shadow.color.into();
|
||||
}
|
||||
|
||||
/// Gets a simple shadow from this item.
|
||||
#[inline]
|
||||
fn extract_simple_shadow(&self) -> SimpleShadow {
|
||||
SimpleShadow {
|
||||
color: self.mColor.into(),
|
||||
horizontal: Au(self.mXOffset).into(),
|
||||
vertical: Au(self.mYOffset).into(),
|
||||
blur: Au(self.mRadius).into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns this item as a simple shadow.
|
||||
#[inline]
|
||||
pub fn to_simple_shadow(&self) -> SimpleShadow {
|
||||
debug_assert_eq!(self.mSpread, 0);
|
||||
debug_assert_eq!(self.mInset, false);
|
||||
self.extract_simple_shadow()
|
||||
}
|
||||
}
|
|
@ -174,6 +174,7 @@ class Longhand(object):
|
|||
logical=False, logical_group=None, alias=None, extra_prefixes=None, boxed=False,
|
||||
flags=None, allowed_in_page_rule=False, allow_quirks=False,
|
||||
ignored_when_colors_disabled=False,
|
||||
simple_vector_bindings=False,
|
||||
vector=False, servo_restyle_damage="repaint"):
|
||||
self.name = name
|
||||
if not spec:
|
||||
|
@ -210,6 +211,7 @@ class Longhand(object):
|
|||
self.allow_quirks = allow_quirks
|
||||
self.ignored_when_colors_disabled = ignored_when_colors_disabled
|
||||
self.is_vector = vector
|
||||
self.simple_vector_bindings = simple_vector_bindings
|
||||
|
||||
# https://drafts.csswg.org/css-animations/#keyframes
|
||||
# > The <declaration-list> inside of <keyframe-block> accepts any CSS property
|
||||
|
|
|
@ -28,7 +28,6 @@ use crate::gecko_bindings::bindings::Gecko_CopyListStyleImageFrom;
|
|||
use crate::gecko_bindings::bindings::Gecko_EnsureImageLayersLength;
|
||||
use crate::gecko_bindings::bindings::Gecko_SetCursorArrayLength;
|
||||
use crate::gecko_bindings::bindings::Gecko_SetCursorImageValue;
|
||||
use crate::gecko_bindings::bindings::Gecko_NewCSSShadowArray;
|
||||
use crate::gecko_bindings::bindings::Gecko_nsStyleFont_SetLang;
|
||||
use crate::gecko_bindings::bindings::Gecko_nsStyleFont_CopyLangFrom;
|
||||
use crate::gecko_bindings::bindings::Gecko_SetListStyleImageNone;
|
||||
|
@ -56,7 +55,7 @@ use crate::values::{self, CustomIdent, Either, KeyframesName, None_};
|
|||
use crate::values::computed::{NonNegativeLength, Percentage, TransitionProperty};
|
||||
use crate::values::computed::BorderStyle;
|
||||
use crate::values::computed::font::FontSize;
|
||||
use crate::values::computed::effects::{BoxShadow, Filter, SimpleShadow};
|
||||
use crate::values::computed::effects::Filter;
|
||||
use crate::values::generics::column::ColumnCount;
|
||||
use crate::values::generics::transform::TransformStyle;
|
||||
use crate::values::generics::url::UrlOrNone;
|
||||
|
@ -3455,31 +3454,7 @@ fn static_assert() {
|
|||
</%self:impl_trait>
|
||||
|
||||
<%self:impl_trait style_struct_name="Effects"
|
||||
skip_longhands="box-shadow clip filter">
|
||||
pub fn set_box_shadow<I>(&mut self, v: I)
|
||||
where I: IntoIterator<Item = BoxShadow>,
|
||||
I::IntoIter: ExactSizeIterator
|
||||
{
|
||||
let v = v.into_iter();
|
||||
self.gecko.mBoxShadow.replace_with_new(v.len() as u32);
|
||||
for (servo, gecko_shadow) in v.zip(self.gecko.mBoxShadow.iter_mut()) {
|
||||
gecko_shadow.set_from_box_shadow(servo);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_box_shadow_from(&mut self, other: &Self) {
|
||||
self.gecko.mBoxShadow.copy_from(&other.gecko.mBoxShadow);
|
||||
}
|
||||
|
||||
pub fn reset_box_shadow(&mut self, other: &Self) {
|
||||
self.copy_box_shadow_from(other)
|
||||
}
|
||||
|
||||
pub fn clone_box_shadow(&self) -> longhands::box_shadow::computed_value::T {
|
||||
let buf = self.gecko.mBoxShadow.iter().map(|v| v.to_box_shadow()).collect();
|
||||
longhands::box_shadow::computed_value::List(buf)
|
||||
}
|
||||
|
||||
skip_longhands="clip filter">
|
||||
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;
|
||||
|
@ -3603,7 +3578,6 @@ fn static_assert() {
|
|||
I::IntoIter: ExactSizeIterator,
|
||||
{
|
||||
use crate::values::generics::effects::Filter::*;
|
||||
use crate::gecko_bindings::structs::nsCSSShadowArray;
|
||||
use crate::gecko_bindings::structs::nsStyleFilter;
|
||||
use crate::gecko_bindings::structs::NS_STYLE_FILTER_BLUR;
|
||||
use crate::gecko_bindings::structs::NS_STYLE_FILTER_BRIGHTNESS;
|
||||
|
@ -3644,19 +3618,10 @@ fn static_assert() {
|
|||
|
||||
DropShadow(shadow) => {
|
||||
gecko_filter.mType = NS_STYLE_FILTER_DROP_SHADOW;
|
||||
|
||||
fn init_shadow(filter: &mut nsStyleFilter) -> &mut nsCSSShadowArray {
|
||||
unsafe {
|
||||
let ref mut union = filter.__bindgen_anon_1;
|
||||
let shadow_array: &mut *mut nsCSSShadowArray = union.mDropShadow.as_mut();
|
||||
*shadow_array = Gecko_NewCSSShadowArray(1);
|
||||
|
||||
&mut **shadow_array
|
||||
let ref mut union = gecko_filter.__bindgen_anon_1;
|
||||
ptr::write(union.mDropShadow.as_mut(), shadow);
|
||||
}
|
||||
}
|
||||
|
||||
let gecko_shadow = init_shadow(gecko_filter);
|
||||
gecko_shadow.mArray[0].set_from_simple_shadow(shadow);
|
||||
},
|
||||
Url(ref url) => {
|
||||
unsafe {
|
||||
|
@ -3715,7 +3680,7 @@ fn static_assert() {
|
|||
},
|
||||
NS_STYLE_FILTER_DROP_SHADOW => {
|
||||
Filter::DropShadow(unsafe {
|
||||
(**filter.__bindgen_anon_1.mDropShadow.as_ref()).mArray[0].to_simple_shadow()
|
||||
(*filter.__bindgen_anon_1.mDropShadow.as_ref()).clone()
|
||||
})
|
||||
},
|
||||
NS_STYLE_FILTER_URL => {
|
||||
|
@ -3761,7 +3726,7 @@ fn static_assert() {
|
|||
|
||||
|
||||
<%self:impl_trait style_struct_name="InheritedText"
|
||||
skip_longhands="text-align text-emphasis-style text-shadow
|
||||
skip_longhands="text-align text-emphasis-style
|
||||
-webkit-text-stroke-width text-emphasis-position">
|
||||
|
||||
<% text_align_keyword = Keyword("text-align",
|
||||
|
@ -3769,32 +3734,6 @@ fn static_assert() {
|
|||
gecko_strip_moz_prefix=False) %>
|
||||
${impl_keyword('text_align', 'mTextAlign', text_align_keyword)}
|
||||
|
||||
pub fn set_text_shadow<I>(&mut self, v: I)
|
||||
where
|
||||
I: IntoIterator<Item = SimpleShadow>,
|
||||
I::IntoIter: ExactSizeIterator
|
||||
{
|
||||
let v = v.into_iter();
|
||||
self.gecko.mTextShadow.replace_with_new(v.len() as u32);
|
||||
for (servo, gecko_shadow) in v.zip(self.gecko.mTextShadow.iter_mut()) {
|
||||
gecko_shadow.set_from_simple_shadow(servo);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_text_shadow_from(&mut self, other: &Self) {
|
||||
self.gecko.mTextShadow.copy_from(&other.gecko.mTextShadow);
|
||||
}
|
||||
|
||||
pub fn reset_text_shadow(&mut self, other: &Self) {
|
||||
self.copy_text_shadow_from(other)
|
||||
}
|
||||
|
||||
// FIXME(emilio): Remove by sharing representation.
|
||||
pub fn clone_text_shadow(&self) -> longhands::text_shadow::computed_value::T {
|
||||
let iter = self.gecko.mTextShadow.iter().map(|v| v.to_simple_shadow());
|
||||
longhands::text_shadow::computed_value::List(crate::ArcSlice::from_iter(iter))
|
||||
}
|
||||
|
||||
fn clear_text_emphasis_style_if_string(&mut self) {
|
||||
if self.gecko.mTextEmphasisStyle == structs::NS_STYLE_TEXT_EMPHASIS_STYLE_STRING as u8 {
|
||||
self.gecko.mTextEmphasisStyleString.truncate();
|
||||
|
|
|
@ -90,12 +90,16 @@
|
|||
// * computed_value::List is just a convenient alias that you can use for the
|
||||
// computed value list, since this is in the computed_value module.
|
||||
//
|
||||
// If simple_vector_bindings is true, then we don't use the complex iterator
|
||||
// machinery and set_foo_from, and just compute the value like any other
|
||||
// longhand.
|
||||
<%def name="vector_longhand(name, animation_value_type=None,
|
||||
vector_animation_type=None, allow_empty=False,
|
||||
simple_vector_bindings=False,
|
||||
separator='Comma',
|
||||
**kwargs)">
|
||||
<%call expr="longhand(name, animation_value_type=animation_value_type, vector=True,
|
||||
**kwargs)">
|
||||
simple_vector_bindings=simple_vector_bindings, **kwargs)">
|
||||
#[allow(unused_imports)]
|
||||
use smallvec::SmallVec;
|
||||
|
||||
|
@ -237,6 +241,20 @@
|
|||
}
|
||||
% endif
|
||||
|
||||
% if simple_vector_bindings:
|
||||
impl From<ComputedList> for UnderlyingList<single_value::T> {
|
||||
#[inline]
|
||||
fn from(l: ComputedList) -> Self {
|
||||
l.0
|
||||
}
|
||||
}
|
||||
impl From<UnderlyingList<single_value::T>> for ComputedList {
|
||||
#[inline]
|
||||
fn from(l: UnderlyingList<single_value::T>) -> Self {
|
||||
List(l)
|
||||
}
|
||||
}
|
||||
% endif
|
||||
|
||||
% if vector_animation_type:
|
||||
% if not animation_value_type:
|
||||
|
@ -345,6 +363,7 @@
|
|||
|
||||
pub use self::single_value::SpecifiedValue as SingleSpecifiedValue;
|
||||
|
||||
% if not simple_vector_bindings:
|
||||
impl SpecifiedValue {
|
||||
fn compute_iter<'a, 'cx, 'cx_a>(
|
||||
&'a self,
|
||||
|
@ -353,6 +372,7 @@
|
|||
computed_value::Iter::new(context, &self.0)
|
||||
}
|
||||
}
|
||||
% endif
|
||||
|
||||
impl ToComputedValue for SpecifiedValue {
|
||||
type ComputedValue = computed_value::T;
|
||||
|
@ -473,7 +493,7 @@
|
|||
.set_writing_mode_dependency(context.builder.writing_mode);
|
||||
% endif
|
||||
|
||||
% if property.is_vector:
|
||||
% if property.is_vector and not property.simple_vector_bindings:
|
||||
// In the case of a vector property we want to pass down an
|
||||
// iterator so that this can be computed without allocation.
|
||||
//
|
||||
|
|
|
@ -23,6 +23,7 @@ ${helpers.predefined_type(
|
|||
"BoxShadow",
|
||||
None,
|
||||
vector=True,
|
||||
simple_vector_bindings=True,
|
||||
animation_value_type="AnimatedBoxShadowList",
|
||||
vector_animation_type="with_zero",
|
||||
extra_prefixes="webkit",
|
||||
|
|
|
@ -218,6 +218,7 @@ ${helpers.predefined_type(
|
|||
vector_animation_type="with_zero",
|
||||
animation_value_type="AnimatedTextShadowList",
|
||||
ignored_when_colors_disabled=True,
|
||||
simple_vector_bindings=True,
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-text-decor-3/#text-shadow-property",
|
||||
)}
|
||||
|
|
|
@ -3444,7 +3444,7 @@ impl<'a> StyleBuilder<'a> {
|
|||
}
|
||||
% endif
|
||||
|
||||
% if not property.is_vector:
|
||||
% if not property.is_vector or property.simple_vector_bindings:
|
||||
/// Set the `${property.ident}` to the computed value `value`.
|
||||
#[allow(non_snake_case)]
|
||||
pub fn set_${property.ident}(
|
||||
|
|
|
@ -9,22 +9,18 @@ use crate::values::computed::length::Length;
|
|||
#[cfg(feature = "gecko")]
|
||||
use crate::values::computed::url::ComputedUrl;
|
||||
use crate::values::computed::{Angle, Number};
|
||||
use crate::values::generics::effects::BoxShadow as GenericBoxShadow;
|
||||
use crate::values::generics::effects::Filter as GenericFilter;
|
||||
use crate::values::generics::effects::SimpleShadow as GenericSimpleShadow;
|
||||
#[cfg(not(feature = "gecko"))]
|
||||
use crate::values::Impossible;
|
||||
|
||||
/// An animated value for a single `box-shadow`.
|
||||
pub type BoxShadow = GenericBoxShadow<Color, Length, Length, Length>;
|
||||
/// An animated value for the `drop-shadow()` filter.
|
||||
type AnimatedSimpleShadow = GenericSimpleShadow<Color, Length, Length>;
|
||||
|
||||
/// An animated value for a single `filter`.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub type Filter = GenericFilter<Angle, Number, Length, SimpleShadow, ComputedUrl>;
|
||||
pub type Filter = GenericFilter<Angle, Number, Length, AnimatedSimpleShadow, ComputedUrl>;
|
||||
|
||||
/// An animated value for a single `filter`.
|
||||
#[cfg(not(feature = "gecko"))]
|
||||
pub type Filter = GenericFilter<Angle, Number, Length, Impossible, Impossible>;
|
||||
|
||||
/// An animated value for the `drop-shadow()` filter.
|
||||
pub type SimpleShadow = GenericSimpleShadow<Color, Length, Length>;
|
||||
|
|
|
@ -19,9 +19,10 @@
|
|||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
|
||||
#[repr(C)]
|
||||
pub struct GenericBoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
|
||||
/// The base shadow.
|
||||
pub base: SimpleShadow<Color, SizeLength, BlurShapeLength>,
|
||||
pub base: GenericSimpleShadow<Color, SizeLength, BlurShapeLength>,
|
||||
/// The spread radius.
|
||||
pub spread: ShapeLength,
|
||||
/// Whether this is an inset box shadow.
|
||||
|
@ -30,6 +31,8 @@ pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
|
|||
pub inset: bool,
|
||||
}
|
||||
|
||||
pub use self::GenericBoxShadow as BoxShadow;
|
||||
|
||||
/// A generic value for a single `filter`.
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[animation(no_bound(Url))]
|
||||
|
@ -100,7 +103,8 @@ pub enum Filter<Angle, Factor, Length, DropShadow, Url> {
|
|||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
pub struct SimpleShadow<Color, SizeLength, ShapeLength> {
|
||||
#[repr(C)]
|
||||
pub struct GenericSimpleShadow<Color, SizeLength, ShapeLength> {
|
||||
/// Color.
|
||||
pub color: Color,
|
||||
/// Horizontal radius.
|
||||
|
@ -110,3 +114,5 @@ pub struct SimpleShadow<Color, SizeLength, ShapeLength> {
|
|||
/// Blur radius.
|
||||
pub blur: ShapeLength,
|
||||
}
|
||||
|
||||
pub use self::GenericSimpleShadow as SimpleShadow;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue