mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Refactor image code and implement gecko glue for border-image-source
This commit is contained in:
parent
da27b61352
commit
132b36835b
2 changed files with 214 additions and 193 deletions
|
@ -53,6 +53,7 @@ use std::ptr;
|
|||
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::cmp;
|
||||
use values::computed::{Image, Gradient};
|
||||
|
||||
pub mod style_structs {
|
||||
% for style_struct in data.style_structs:
|
||||
|
@ -639,7 +640,7 @@ fn static_assert() {
|
|||
["border-{0}-radius".format(x.ident.replace("_", "-"))
|
||||
for x in CORNERS]) %>
|
||||
<%self:impl_trait style_struct_name="Border"
|
||||
skip_longhands="${skip_border_longhands}"
|
||||
skip_longhands="${skip_border_longhands} border-image-source"
|
||||
skip_additionals="*">
|
||||
|
||||
% for side in SIDES:
|
||||
|
@ -663,6 +664,26 @@ fn static_assert() {
|
|||
corner.y_index,
|
||||
need_clone=True) %>
|
||||
% endfor
|
||||
|
||||
pub fn set_border_image_source(&mut self, v: longhands::border_image_source::computed_value::T) {
|
||||
unsafe {
|
||||
// Prevent leaking of the last elements we did set
|
||||
Gecko_SetNullImageValue(&mut self.gecko.mBorderImageSource);
|
||||
}
|
||||
|
||||
if let Some(image) = v.0 {
|
||||
// TODO: We need to make border-image-source match with background-image
|
||||
// until then we are setting with_url to false
|
||||
set_image(image, &mut self.gecko.mBorderImageSource, false, &mut false)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_border_image_source_from(&mut self, other: &Self) {
|
||||
unsafe {
|
||||
Gecko_CopyImageValueFrom(&mut self.gecko.mBorderImageSource,
|
||||
&other.gecko.mBorderImageSource);
|
||||
}
|
||||
}
|
||||
</%self:impl_trait>
|
||||
|
||||
<% skip_margin_longhands = " ".join(["margin-%s" % x.ident for x in SIDES]) %>
|
||||
|
@ -1238,20 +1259,100 @@ fn static_assert() {
|
|||
pub fn set_${shorthand}_image(&mut self,
|
||||
images: longhands::${shorthand}_image::computed_value::T,
|
||||
cacheable: &mut bool) {
|
||||
use gecko_bindings::structs::nsStyleImage;
|
||||
use gecko_bindings::structs::nsStyleImageLayers_LayerType as LayerType;
|
||||
|
||||
unsafe {
|
||||
// Prevent leaking of the last elements we did set
|
||||
for image in &mut self.gecko.${image_layers_field}.mLayers {
|
||||
Gecko_SetNullImageValue(&mut image.mImage)
|
||||
}
|
||||
// XXXManishearth clear mSourceURI for masks
|
||||
Gecko_EnsureImageLayersLength(&mut self.gecko.${image_layers_field}, images.0.len(),
|
||||
LayerType::${shorthand.title()});
|
||||
}
|
||||
|
||||
self.gecko.${image_layers_field}.mImageCount = images.0.len() as u32;
|
||||
|
||||
for (image, geckoimage) in images.0.into_iter().zip(self.gecko.${image_layers_field}
|
||||
.mLayers.iter_mut()) {
|
||||
% if shorthand == "background":
|
||||
if let Some(image) = image.0 {
|
||||
set_image(image, &mut geckoimage.mImage, true, cacheable)
|
||||
}
|
||||
% else:
|
||||
use properties::longhands::mask_image::single_value::computed_value::T;
|
||||
match image {
|
||||
T::Image(image) => set_image(image, &mut geckoimage.mImage, false, cacheable),
|
||||
_ => () // we need to support url valeus
|
||||
}
|
||||
% endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
<%
|
||||
fill_fields = "mRepeat mClip mOrigin mPositionX mPositionY mImage"
|
||||
if shorthand == "background":
|
||||
fill_fields += " mAttachment"
|
||||
else:
|
||||
# mSourceURI uses mImageCount
|
||||
fill_fields += " mMaskMode mComposite"
|
||||
%>
|
||||
pub fn fill_arrays(&mut self) {
|
||||
use gecko_bindings::bindings::Gecko_FillAll${shorthand.title()}Lists;
|
||||
use std::cmp;
|
||||
let mut max_len = 1;
|
||||
% for member in fill_fields.split():
|
||||
max_len = cmp::max(max_len, self.gecko.${image_layers_field}.${member}Count);
|
||||
% endfor
|
||||
|
||||
// XXXManishearth Gecko does an optimization here where it only
|
||||
// fills things in if any of the properties have been set
|
||||
|
||||
unsafe {
|
||||
// While we could do this manually, we'd need to also manually
|
||||
// run all the copy constructors, so we just delegate to gecko
|
||||
Gecko_FillAll${shorthand.title()}Lists(&mut self.gecko.${image_layers_field}, max_len);
|
||||
}
|
||||
}
|
||||
</%def>
|
||||
|
||||
fn set_image(image: Image, mut geckoimage: &mut structs::nsStyleImage, with_url: bool, cacheable: &mut bool) {
|
||||
match image {
|
||||
Image::Gradient(gradient) => {
|
||||
set_gradient(gradient, &mut geckoimage)
|
||||
},
|
||||
Image::Url(ref url, ref extra_data) if with_url => {
|
||||
unsafe {
|
||||
Gecko_SetUrlImageValue(geckoimage,
|
||||
url.as_str().as_ptr(),
|
||||
url.as_str().len() as u32,
|
||||
extra_data.base.get(),
|
||||
extra_data.referrer.get(),
|
||||
extra_data.principal.get());
|
||||
}
|
||||
// We unfortunately must make any url() value uncacheable, since
|
||||
// the applicable declarations cache is not per document, but
|
||||
// global, and the imgRequestProxy objects we store in the style
|
||||
// structs don't like to be tracked by more than one document.
|
||||
*cacheable = false;
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_gradient(gradient: Gradient, geckoimage: &mut structs::nsStyleImage) {
|
||||
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SHAPE_LINEAR, NS_STYLE_GRADIENT_SHAPE_CIRCULAR};
|
||||
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL, NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER};
|
||||
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE, NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER};
|
||||
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE, NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE};
|
||||
use gecko_bindings::structs::nsStyleCoord;
|
||||
use values::computed::{Image, Gradient, GradientKind, GradientShape, LengthOrKeyword};
|
||||
use values::computed::{GradientKind, GradientShape, LengthOrKeyword};
|
||||
use values::computed::LengthOrPercentageOrKeyword;
|
||||
use values::specified::AngleOrCorner;
|
||||
use values::specified::{HorizontalDirection, SizeKeyword, VerticalDirection};
|
||||
use cssparser::Color as CSSColor;
|
||||
|
||||
fn set_gradient(gradient: Gradient, geckoimage: &mut nsStyleImage) {
|
||||
let stop_count = gradient.stops.len();
|
||||
if stop_count >= ::std::u32::MAX as usize {
|
||||
warn!("stylo: Prevented overflow due to too many gradient stops");
|
||||
|
@ -1403,87 +1504,7 @@ fn static_assert() {
|
|||
unsafe {
|
||||
Gecko_SetGradientImageValue(geckoimage, gecko_gradient);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
// Prevent leaking of the last elements we did set
|
||||
for image in &mut self.gecko.${image_layers_field}.mLayers {
|
||||
Gecko_SetNullImageValue(&mut image.mImage)
|
||||
}
|
||||
// XXXManishearth clear mSourceURI for masks
|
||||
Gecko_EnsureImageLayersLength(&mut self.gecko.${image_layers_field}, images.0.len(),
|
||||
LayerType::${shorthand.title()});
|
||||
}
|
||||
|
||||
self.gecko.${image_layers_field}.mImageCount = images.0.len() as u32;
|
||||
|
||||
for (image, geckoimage) in images.0.into_iter().zip(self.gecko.${image_layers_field}
|
||||
.mLayers.iter_mut()) {
|
||||
% if shorthand == "background":
|
||||
if let Some(image) = image.0 {
|
||||
match image {
|
||||
Image::Gradient(gradient) => {
|
||||
set_gradient(gradient, &mut geckoimage.mImage)
|
||||
},
|
||||
Image::Url(ref url, ref extra_data) => {
|
||||
unsafe {
|
||||
Gecko_SetUrlImageValue(&mut geckoimage.mImage,
|
||||
url.as_str().as_ptr(),
|
||||
url.as_str().len() as u32,
|
||||
extra_data.base.get(),
|
||||
extra_data.referrer.get(),
|
||||
extra_data.principal.get());
|
||||
}
|
||||
// We unfortunately must make any url() value uncacheable, since
|
||||
// the applicable declarations cache is not per document, but
|
||||
// global, and the imgRequestProxy objects we store in the style
|
||||
// structs don't like to be tracked by more than one document.
|
||||
*cacheable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
% else:
|
||||
use properties::longhands::mask_image::single_value::computed_value::T;
|
||||
match image {
|
||||
T::Image(image) => match image {
|
||||
Image::Gradient(gradient) => {
|
||||
set_gradient(gradient, &mut geckoimage.mImage)
|
||||
}
|
||||
_ => () // we need to support image values
|
||||
},
|
||||
_ => () // we need to support url valeus
|
||||
}
|
||||
% endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
<%
|
||||
fill_fields = "mRepeat mClip mOrigin mPositionX mPositionY mImage"
|
||||
if shorthand == "background":
|
||||
fill_fields += " mAttachment"
|
||||
else:
|
||||
# mSourceURI uses mImageCount
|
||||
fill_fields += " mMaskMode mComposite"
|
||||
%>
|
||||
pub fn fill_arrays(&mut self) {
|
||||
use gecko_bindings::bindings::Gecko_FillAll${shorthand.title()}Lists;
|
||||
use std::cmp;
|
||||
let mut max_len = 1;
|
||||
% for member in fill_fields.split():
|
||||
max_len = cmp::max(max_len, self.gecko.${image_layers_field}.${member}Count);
|
||||
% endfor
|
||||
|
||||
// XXXManishearth Gecko does an optimization here where it only
|
||||
// fills things in if any of the properties have been set
|
||||
|
||||
unsafe {
|
||||
// While we could do this manually, we'd need to also manually
|
||||
// run all the copy constructors, so we just delegate to gecko
|
||||
Gecko_FillAll${shorthand.title()}Lists(&mut self.gecko.${image_layers_field}, max_len);
|
||||
}
|
||||
}
|
||||
</%def>
|
||||
}
|
||||
|
||||
// TODO: Gecko accepts lists in most background-related properties. We just use
|
||||
// the first element (which is the common case), but at some point we want to
|
||||
|
|
|
@ -66,7 +66,7 @@ ${helpers.single_keyword("-moz-float-edge", "content-box margin-box",
|
|||
animatable=False)}
|
||||
|
||||
// https://drafts.csswg.org/css-backgrounds-3/#border-image-source
|
||||
<%helpers:longhand name="border-image-source" products="none" animatable="False">
|
||||
<%helpers:longhand name="border-image-source" products="gecko" animatable="False">
|
||||
use cssparser::ToCss;
|
||||
use std::fmt;
|
||||
use values::LocalToCss;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue