mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Use IntoIterator for nsCSSValueList.
This commit is contained in:
parent
313f7d86db
commit
8a69132de0
2 changed files with 125 additions and 68 deletions
|
@ -8,8 +8,9 @@ use app_units::Au;
|
||||||
use gecko_bindings::bindings;
|
use gecko_bindings::bindings;
|
||||||
use gecko_bindings::structs;
|
use gecko_bindings::structs;
|
||||||
use gecko_bindings::structs::{nsCSSValue, nsCSSUnit};
|
use gecko_bindings::structs::{nsCSSValue, nsCSSUnit};
|
||||||
use gecko_bindings::structs::{nsCSSValue_Array, nscolor};
|
use gecko_bindings::structs::{nsCSSValue_Array, nsCSSValueList, nscolor};
|
||||||
use gecko_string_cache::Atom;
|
use gecko_string_cache::Atom;
|
||||||
|
use std::marker::PhantomData;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
@ -225,19 +226,17 @@ impl nsCSSValue {
|
||||||
/// Set to a list value
|
/// Set to a list value
|
||||||
///
|
///
|
||||||
/// This is only supported on the main thread.
|
/// This is only supported on the main thread.
|
||||||
pub fn set_list<I>(&mut self, mut values: I) where I: ExactSizeIterator<Item=nsCSSValue> {
|
pub fn set_list<I>(&mut self, values: I) where I: ExactSizeIterator<Item=nsCSSValue> {
|
||||||
debug_assert!(values.len() > 0, "Empty list is not supported");
|
debug_assert!(values.len() > 0, "Empty list is not supported");
|
||||||
unsafe { bindings::Gecko_CSSValue_SetList(self, values.len() as u32); }
|
unsafe { bindings::Gecko_CSSValue_SetList(self, values.len() as u32); }
|
||||||
debug_assert_eq!(self.mUnit, nsCSSUnit::eCSSUnit_List);
|
debug_assert_eq!(self.mUnit, nsCSSUnit::eCSSUnit_List);
|
||||||
let mut item_ptr = &mut unsafe {
|
let list: &mut structs::nsCSSValueList = &mut unsafe {
|
||||||
self.mValue.mList.as_ref() // &*nsCSSValueList_heap
|
self.mValue.mList.as_ref() // &*nsCSSValueList_heap
|
||||||
.as_mut().expect("List pointer should be non-null")
|
.as_mut().expect("List pointer should be non-null")
|
||||||
}._base as *mut structs::nsCSSValueList;
|
}._base;
|
||||||
while let Some(item) = unsafe { item_ptr.as_mut() } {
|
for (item, new_value) in list.into_iter().zip(values) {
|
||||||
item.mValue = values.next().expect("Values shouldn't have been exhausted");
|
*item = new_value;
|
||||||
item_ptr = item.mNext;
|
|
||||||
}
|
}
|
||||||
debug_assert!(values.next().is_none(), "Values should have been exhausted");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set to a pair list value
|
/// Set to a pair list value
|
||||||
|
@ -268,6 +267,64 @@ impl Drop for nsCSSValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Iterator of nsCSSValueList.
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub struct nsCSSValueListIterator<'a> {
|
||||||
|
current: Option<&'a nsCSSValueList>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for nsCSSValueListIterator<'a> {
|
||||||
|
type Item = &'a nsCSSValue;
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
match self.current {
|
||||||
|
Some(item) => {
|
||||||
|
self.current = unsafe { item.mNext.as_ref() };
|
||||||
|
Some(&item.mValue)
|
||||||
|
},
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a nsCSSValueList {
|
||||||
|
type Item = &'a nsCSSValue;
|
||||||
|
type IntoIter = nsCSSValueListIterator<'a>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
nsCSSValueListIterator { current: Some(self) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mutable Iterator of nsCSSValueList.
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub struct nsCSSValueListMutIterator<'a> {
|
||||||
|
current: *mut nsCSSValueList,
|
||||||
|
phantom: PhantomData<&'a mut nsCSSValue>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for nsCSSValueListMutIterator<'a> {
|
||||||
|
type Item = &'a mut nsCSSValue;
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
match unsafe { self.current.as_mut() } {
|
||||||
|
Some(item) => {
|
||||||
|
self.current = item.mNext;
|
||||||
|
Some(&mut item.mValue)
|
||||||
|
},
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a mut nsCSSValueList {
|
||||||
|
type Item = &'a mut nsCSSValue;
|
||||||
|
type IntoIter = nsCSSValueListMutIterator<'a>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
nsCSSValueListMutIterator { current: self as *mut nsCSSValueList,
|
||||||
|
phantom: PhantomData }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl nsCSSValue_Array {
|
impl nsCSSValue_Array {
|
||||||
/// Return the length of this `nsCSSValue::Array`
|
/// Return the length of this `nsCSSValue::Array`
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -2307,7 +2307,7 @@ fn static_assert() {
|
||||||
bindings::Gecko_CSSValue_SetFunction(gecko_value, ${len(items) + 1});
|
bindings::Gecko_CSSValue_SetFunction(gecko_value, ${len(items) + 1});
|
||||||
bindings::Gecko_CSSValue_SetKeyword(
|
bindings::Gecko_CSSValue_SetKeyword(
|
||||||
bindings::Gecko_CSSValue_GetArrayItem(gecko_value, 0),
|
bindings::Gecko_CSSValue_GetArrayItem(gecko_value, 0),
|
||||||
eCSSKeyword_${keyword}
|
structs::nsCSSKeyword::eCSSKeyword_${keyword}
|
||||||
);
|
);
|
||||||
% for index, item in enumerate(items):
|
% for index, item in enumerate(items):
|
||||||
${css_value_setters[item] % (
|
${css_value_setters[item] % (
|
||||||
|
@ -2317,47 +2317,46 @@ fn static_assert() {
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
</%def>
|
</%def>
|
||||||
pub fn convert_transform(input: &[longhands::transform::computed_value::ComputedOperation],
|
fn set_single_transform_function(servo_value: &longhands::transform::computed_value::ComputedOperation,
|
||||||
output: &mut structs::root::RefPtr<structs::root::nsCSSValueSharedList>) {
|
gecko_value: &mut structs::nsCSSValue /* output */) {
|
||||||
use gecko_bindings::structs::nsCSSKeyword::*;
|
|
||||||
use gecko_bindings::sugar::refptr::RefPtr;
|
|
||||||
use properties::longhands::transform::computed_value::ComputedMatrix;
|
use properties::longhands::transform::computed_value::ComputedMatrix;
|
||||||
use properties::longhands::transform::computed_value::ComputedMatrixWithPercents;
|
use properties::longhands::transform::computed_value::ComputedMatrixWithPercents;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
match *servo_value {
|
||||||
|
${transform_function_arm("Matrix", "matrix3d", ["number"] * 16)}
|
||||||
|
${transform_function_arm("MatrixWithPercents", "matrix3d", ["number"] * 12 + ["lop"] * 2
|
||||||
|
+ ["length"] + ["number"])}
|
||||||
|
${transform_function_arm("Skew", "skew", ["angle"] * 2)}
|
||||||
|
${transform_function_arm("Translate", "translate3d", ["lop", "lop", "length"])}
|
||||||
|
${transform_function_arm("Scale", "scale3d", ["number"] * 3)}
|
||||||
|
${transform_function_arm("Rotate", "rotate3d", ["number"] * 3 + ["angle"])}
|
||||||
|
${transform_function_arm("Perspective", "perspective", ["length"])}
|
||||||
|
_ => {
|
||||||
|
// TODO: Convert ComputedOperation::InterpolateMatrix into
|
||||||
|
// eCSSKeyword_interpolatematrix, and convert
|
||||||
|
// ComputedOperation::AccumulateMatrix into
|
||||||
|
// eCSSKeyword_accumulatematrix in the patch series.
|
||||||
|
gecko_value.mUnit = structs::nsCSSUnit::eCSSUnit_None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn convert_transform(input: &[longhands::transform::computed_value::ComputedOperation],
|
||||||
|
output: &mut structs::root::RefPtr<structs::root::nsCSSValueSharedList>) {
|
||||||
|
use gecko_bindings::sugar::refptr::RefPtr;
|
||||||
|
|
||||||
unsafe { output.clear() };
|
unsafe { output.clear() };
|
||||||
|
|
||||||
let list = unsafe {
|
let list = unsafe {
|
||||||
RefPtr::from_addrefed(bindings::Gecko_NewCSSValueSharedList(input.len() as u32))
|
RefPtr::from_addrefed(bindings::Gecko_NewCSSValueSharedList(input.len() as u32))
|
||||||
};
|
};
|
||||||
|
let value_list = unsafe { list.mHead.as_mut() };
|
||||||
let mut cur = list.mHead;
|
if let Some(value_list) = value_list {
|
||||||
let mut iter = input.into_iter();
|
for (gecko, servo) in value_list.into_iter().zip(input.into_iter()) {
|
||||||
while !cur.is_null() {
|
Self::set_single_transform_function(servo, gecko);
|
||||||
let gecko_value = unsafe { &mut (*cur).mValue };
|
|
||||||
let servo = iter.next().expect("Gecko_NewCSSValueSharedList should create a shared \
|
|
||||||
value list of the same length as the transform vector");
|
|
||||||
unsafe {
|
|
||||||
match *servo {
|
|
||||||
${transform_function_arm("Matrix", "matrix3d", ["number"] * 16)}
|
|
||||||
${transform_function_arm("MatrixWithPercents", "matrix3d", ["number"] * 12 + ["lop"] * 2
|
|
||||||
+ ["length"] + ["number"])}
|
|
||||||
${transform_function_arm("Skew", "skew", ["angle"] * 2)}
|
|
||||||
${transform_function_arm("Translate", "translate3d", ["lop", "lop", "length"])}
|
|
||||||
${transform_function_arm("Scale", "scale3d", ["number"] * 3)}
|
|
||||||
${transform_function_arm("Rotate", "rotate3d", ["number"] * 3 + ["angle"])}
|
|
||||||
${transform_function_arm("Perspective", "perspective", ["length"])}
|
|
||||||
_ => {
|
|
||||||
// TODO: Convert ComputedOperation::InterpolateMatrix into
|
|
||||||
// eCSSKeyword_interpolatematrix, and convert
|
|
||||||
// ComputedOperation::AccumulateMatrix into
|
|
||||||
// eCSSKeyword_accumulatematrix in the patch series.
|
|
||||||
gecko_value.mUnit = structs::nsCSSUnit::eCSSUnit_None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cur = (*cur).mNext;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug_assert!(iter.next().is_none());
|
|
||||||
unsafe { output.set_move(list) };
|
unsafe { output.set_move(list) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2387,7 +2386,7 @@ fn static_assert() {
|
||||||
"number" : "bindings::Gecko_CSSValue_GetNumber(%s)",
|
"number" : "bindings::Gecko_CSSValue_GetNumber(%s)",
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
eCSSKeyword_${keyword} => {
|
structs::nsCSSKeyword::eCSSKeyword_${keyword} => {
|
||||||
ComputedOperation::${name}(
|
ComputedOperation::${name}(
|
||||||
% if keyword == "matrix3d":
|
% if keyword == "matrix3d":
|
||||||
ComputedMatrix {
|
ComputedMatrix {
|
||||||
|
@ -2406,39 +2405,40 @@ fn static_assert() {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
</%def>
|
</%def>
|
||||||
pub fn clone_transform(&self) -> longhands::transform::computed_value::T {
|
fn clone_single_transform_function(gecko_value: &structs::nsCSSValue)
|
||||||
use app_units::Au;
|
-> longhands::transform::computed_value::ComputedOperation {
|
||||||
use gecko_bindings::structs::nsCSSKeyword::*;
|
|
||||||
use properties::longhands::transform::computed_value;
|
|
||||||
use properties::longhands::transform::computed_value::ComputedMatrix;
|
use properties::longhands::transform::computed_value::ComputedMatrix;
|
||||||
use properties::longhands::transform::computed_value::ComputedOperation;
|
use properties::longhands::transform::computed_value::ComputedOperation;
|
||||||
|
|
||||||
|
let transform_function = unsafe {
|
||||||
|
bindings::Gecko_CSSValue_GetKeyword(bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, 0))
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
match transform_function {
|
||||||
|
${computed_operation_arm("Matrix", "matrix3d", ["number"] * 16)}
|
||||||
|
${computed_operation_arm("Skew", "skew", ["angle"] * 2)}
|
||||||
|
${computed_operation_arm("Translate", "translate3d", ["lop", "lop", "length"])}
|
||||||
|
${computed_operation_arm("Scale", "scale3d", ["number"] * 3)}
|
||||||
|
${computed_operation_arm("Rotate", "rotate3d", ["number"] * 3 + ["angle"])}
|
||||||
|
${computed_operation_arm("Perspective", "perspective", ["length"])}
|
||||||
|
_ => panic!("We shouldn't set any other transform function types"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn clone_transform(&self) -> longhands::transform::computed_value::T {
|
||||||
|
use properties::longhands::transform::computed_value;
|
||||||
|
|
||||||
if self.gecko.mSpecifiedTransform.mRawPtr.is_null() {
|
if self.gecko.mSpecifiedTransform.mRawPtr.is_null() {
|
||||||
return computed_value::T(None);
|
return computed_value::T(None);
|
||||||
}
|
}
|
||||||
|
let list = unsafe { (*self.gecko.mSpecifiedTransform.to_safe().get()).mHead.as_ref() };
|
||||||
let mut result = vec![];
|
let result = list.map(|list| {
|
||||||
let mut cur = unsafe { (*self.gecko.mSpecifiedTransform.to_safe().get()).mHead };
|
list.into_iter()
|
||||||
while !cur.is_null() {
|
.map(|value| Self::clone_single_transform_function(value))
|
||||||
let gecko_value = unsafe { &(*cur).mValue };
|
.collect()
|
||||||
let transform_function = unsafe {
|
});
|
||||||
bindings::Gecko_CSSValue_GetKeyword(bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, 0))
|
computed_value::T(result)
|
||||||
};
|
|
||||||
let servo = unsafe {
|
|
||||||
match transform_function {
|
|
||||||
${computed_operation_arm("Matrix", "matrix3d", ["number"] * 16)}
|
|
||||||
${computed_operation_arm("Skew", "skew", ["angle"] * 2)}
|
|
||||||
${computed_operation_arm("Translate", "translate3d", ["lop", "lop", "length"])}
|
|
||||||
${computed_operation_arm("Scale", "scale3d", ["number"] * 3)}
|
|
||||||
${computed_operation_arm("Rotate", "rotate3d", ["number"] * 3 + ["angle"])}
|
|
||||||
${computed_operation_arm("Perspective", "perspective", ["length"])}
|
|
||||||
_ => panic!("We shouldn't set any other transform function types"),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
result.push(servo);
|
|
||||||
unsafe { cur = (&*cur).mNext };
|
|
||||||
}
|
|
||||||
computed_value::T(Some(result))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
${impl_transition_time_value('delay', 'Delay')}
|
${impl_transition_time_value('delay', 'Delay')}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue