mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
stylo: Implement support for the contents property.
This commit is contained in:
parent
d85a60e366
commit
46afc56c41
3 changed files with 120 additions and 4 deletions
|
@ -1355,6 +1355,93 @@ fn static_assert() {
|
||||||
${impl_coord_copy('column_width', 'mColumnWidth')}
|
${impl_coord_copy('column_width', 'mColumnWidth')}
|
||||||
</%self:impl_trait>
|
</%self:impl_trait>
|
||||||
|
|
||||||
|
<%self:impl_trait style_struct_name="Counters"
|
||||||
|
skip_longhands="content">
|
||||||
|
pub fn set_content(&mut self, v: longhands::content::computed_value::T) {
|
||||||
|
use properties::longhands::content::computed_value::T;
|
||||||
|
use properties::longhands::content::computed_value::ContentItem;
|
||||||
|
use gecko_bindings::structs::nsStyleContentData;
|
||||||
|
use gecko_bindings::structs::nsStyleContentType::*;
|
||||||
|
use gecko_bindings::bindings::Gecko_ClearStyleContents;
|
||||||
|
|
||||||
|
// Converts a string as utf16, and returns an owned, zero-terminated raw buffer.
|
||||||
|
fn as_utf16_and_forget(s: &str) -> *mut u16 {
|
||||||
|
use std::mem;
|
||||||
|
let mut vec = s.encode_utf16().collect::<Vec<_>>();
|
||||||
|
vec.push(0u16);
|
||||||
|
let ptr = vec.as_mut_ptr();
|
||||||
|
mem::forget(vec);
|
||||||
|
ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
fn set_image_tracked(contents: &mut nsStyleContentData, val: bool) {
|
||||||
|
contents.mImageTracked = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
fn set_image_tracked(_contents: &mut nsStyleContentData, _val: bool) {}
|
||||||
|
|
||||||
|
// Ensure destructors run, otherwise we could leak.
|
||||||
|
if !self.gecko.mContents.is_empty() {
|
||||||
|
unsafe {
|
||||||
|
Gecko_ClearStyleContents(&mut self.gecko);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match v {
|
||||||
|
T::none |
|
||||||
|
T::normal => {}, // Do nothing, already cleared.
|
||||||
|
T::Content(items) => {
|
||||||
|
// NB: set_len also reserves the appropriate space.
|
||||||
|
unsafe { self.gecko.mContents.set_len(items.len() as u32) }
|
||||||
|
for (i, item) in items.into_iter().enumerate() {
|
||||||
|
// TODO: Servo lacks support for attr(), and URIs,
|
||||||
|
// We don't support images, but need to remember to
|
||||||
|
// explicitly initialize mImageTracked in debug builds.
|
||||||
|
set_image_tracked(&mut self.gecko.mContents[i], false);
|
||||||
|
// NB: Gecko compares the mString value if type is not image
|
||||||
|
// or URI independently of whatever gets there. In the quote
|
||||||
|
// cases, they set it to null, so do the same here.
|
||||||
|
unsafe {
|
||||||
|
*self.gecko.mContents[i].mContent.mString.as_mut() = ptr::null_mut();
|
||||||
|
}
|
||||||
|
match item {
|
||||||
|
ContentItem::String(value) => {
|
||||||
|
self.gecko.mContents[i].mType = eStyleContentType_String;
|
||||||
|
unsafe {
|
||||||
|
// NB: we share allocators, so doing this is fine.
|
||||||
|
*self.gecko.mContents[i].mContent.mString.as_mut() =
|
||||||
|
as_utf16_and_forget(&value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ContentItem::OpenQuote
|
||||||
|
=> self.gecko.mContents[i].mType = eStyleContentType_OpenQuote,
|
||||||
|
ContentItem::CloseQuote
|
||||||
|
=> self.gecko.mContents[i].mType = eStyleContentType_CloseQuote,
|
||||||
|
ContentItem::NoOpenQuote
|
||||||
|
=> self.gecko.mContents[i].mType = eStyleContentType_NoOpenQuote,
|
||||||
|
ContentItem::NoCloseQuote
|
||||||
|
=> self.gecko.mContents[i].mType = eStyleContentType_NoCloseQuote,
|
||||||
|
ContentItem::Counter(..) |
|
||||||
|
ContentItem::Counters(..)
|
||||||
|
=> self.gecko.mContents[i].mType = eStyleContentType_Uninitialized,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn copy_content_from(&mut self, other: &Self) {
|
||||||
|
use gecko_bindings::bindings::Gecko_CopyStyleContentsFrom;
|
||||||
|
unsafe {
|
||||||
|
Gecko_CopyStyleContentsFrom(&mut self.gecko, &other.gecko)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</%self:impl_trait>
|
||||||
|
|
||||||
<%def name="define_ffi_struct_accessor(style_struct)">
|
<%def name="define_ffi_struct_accessor(style_struct)">
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(non_snake_case, unused_variables)]
|
#[allow(non_snake_case, unused_variables)]
|
||||||
|
|
|
@ -314,6 +314,9 @@ extern "C" {
|
||||||
capacity: usize, elem_size: usize);
|
capacity: usize, elem_size: usize);
|
||||||
pub fn Gecko_ClearPODTArray(array: *mut ::std::os::raw::c_void,
|
pub fn Gecko_ClearPODTArray(array: *mut ::std::os::raw::c_void,
|
||||||
elem_size: usize, elem_align: usize);
|
elem_size: usize, elem_align: usize);
|
||||||
|
pub fn Gecko_ClearStyleContents(content: *mut nsStyleContent);
|
||||||
|
pub fn Gecko_CopyStyleContentsFrom(content: *mut nsStyleContent,
|
||||||
|
other: *const nsStyleContent);
|
||||||
pub fn Gecko_EnsureImageLayersLength(layers: *mut nsStyleImageLayers,
|
pub fn Gecko_EnsureImageLayersLength(layers: *mut nsStyleImageLayers,
|
||||||
len: usize);
|
len: usize);
|
||||||
pub fn Gecko_InitializeImageLayer(layer: *mut Layer,
|
pub fn Gecko_InitializeImageLayer(layer: *mut Layer,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use bindings::Gecko_EnsureTArrayCapacity;
|
use bindings;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
|
@ -38,6 +38,7 @@ impl<T> nsTArray<T> {
|
||||||
// unsafe, since header may be in shared static or something
|
// unsafe, since header may be in shared static or something
|
||||||
unsafe fn header_mut<'a>(&'a mut self) -> &'a mut nsTArrayHeader {
|
unsafe fn header_mut<'a>(&'a mut self) -> &'a mut nsTArrayHeader {
|
||||||
debug_assert!(!self.mBuffer.is_null());
|
debug_assert!(!self.mBuffer.is_null());
|
||||||
|
|
||||||
mem::transmute(self.mBuffer)
|
mem::transmute(self.mBuffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,12 +48,37 @@ impl<T> nsTArray<T> {
|
||||||
(self.mBuffer as *const nsTArrayHeader).offset(1) as *mut _
|
(self.mBuffer as *const nsTArrayHeader).offset(1) as *mut _
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_capacity(&mut self, cap: usize) {
|
/// Ensures the array has enough capacity at least to hold `cap` elements.
|
||||||
unsafe {
|
///
|
||||||
Gecko_EnsureTArrayCapacity(self as *mut nsTArray<T> as *mut c_void, cap, mem::size_of::<T>())
|
/// NOTE: This doesn't call the constructor on the values!
|
||||||
|
pub fn ensure_capacity(&mut self, cap: usize) {
|
||||||
|
if cap >= self.len() {
|
||||||
|
unsafe {
|
||||||
|
bindings::Gecko_EnsureTArrayCapacity(self as *mut nsTArray<T> as *mut _,
|
||||||
|
cap, mem::size_of::<T>())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clears the array storage without calling the destructor on the values.
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn clear(&mut self) {
|
||||||
|
if self.len() != 0 {
|
||||||
|
bindings::Gecko_ClearPODTArray(self as *mut nsTArray<T> as *mut _,
|
||||||
|
mem::size_of::<T>(),
|
||||||
|
mem::align_of::<T>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Clears a POD array. This is safe since copy types are memcopyable.
|
||||||
|
#[inline]
|
||||||
|
pub fn clear_pod(&mut self)
|
||||||
|
where T: Copy
|
||||||
|
{
|
||||||
|
unsafe { self.clear() }
|
||||||
|
}
|
||||||
|
|
||||||
// unsafe because the array may contain uninits
|
// unsafe because the array may contain uninits
|
||||||
// This will not call constructors, either manually
|
// This will not call constructors, either manually
|
||||||
// add bindings or run the typed ensurecapacity call
|
// add bindings or run the typed ensurecapacity call
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue