style: Add bindings for box shadows, and remove nsCSSShadowArray and friends.

Differential Revision: https://phabricator.services.mozilla.com/D30547
This commit is contained in:
Emilio Cobos Álvarez 2019-05-16 23:04:32 +00:00
parent a109fbb7c8
commit 5f6c8d9060
11 changed files with 46 additions and 220 deletions

View file

@ -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;

View file

@ -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,
)
}
}
}
}

View file

@ -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()
}
}

View file

@ -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

View file

@ -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();

View file

@ -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.
//

View file

@ -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",

View file

@ -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",
)}

View file

@ -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}(

View file

@ -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>;

View file

@ -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;