mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
This removes nsStyleImageRequest by moving the load state to LoadData instead (where other lazy state like the resolved URL and load id lives). That way we can use cbindgen for more stuff (there's no blocker for using it for all images now), and we can undo the image tracking shenanigans that I had to do in bug 1605803 in nsImageFrame. This removes the mDocGroup member because well, there's no real upside of that now that quantum DOM is not a thing. It also removes the static clones of the image requests, and the need for each computed value instance to have its own request. These were needed because we needed the image loader for the particular document to observe the image changes. But we were also tracking the request -> loader for other purposes. Instead, Now all the images get loaded with GlobalImageObserver as a listener, which looks in the image map and forwards the notification to all the interested loaders instead dynamically. The style value is only responsible to load the image, and no longer tracks / locks it. Instead, the loader does so, via the image tracker. Differential Revision: https://phabricator.services.mozilla.com/D58519
327 lines
13 KiB
Rust
327 lines
13 KiB
Rust
/* 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/. */
|
|
|
|
//! This module contains conversion helpers between Servo and Gecko types
|
|
//! Ideally, it would be in geckolib itself, but coherence
|
|
//! forces us to keep the traits and implementations here
|
|
//!
|
|
//! FIXME(emilio): This file should generally just die.
|
|
|
|
#![allow(unsafe_code)]
|
|
|
|
use crate::gecko_bindings::bindings;
|
|
use crate::gecko_bindings::structs::{self, Matrix4x4Components};
|
|
use crate::gecko_bindings::structs::{nsStyleImage, nsresult};
|
|
use crate::stylesheets::RulesMutateError;
|
|
use crate::values::computed::transform::Matrix3D;
|
|
use crate::values::computed::{Gradient, Image, TextAlign};
|
|
use crate::values::generics::image::GenericImage;
|
|
use crate::values::generics::rect::Rect;
|
|
|
|
impl nsStyleImage {
|
|
/// Set a given Servo `Image` value into this `nsStyleImage`.
|
|
pub fn set(&mut self, image: Image) {
|
|
match image {
|
|
GenericImage::Gradient(boxed_gradient) => self.set_gradient(boxed_gradient),
|
|
GenericImage::Url(ref url) => unsafe {
|
|
bindings::Gecko_SetLayerImageImageValue(self, url);
|
|
},
|
|
GenericImage::Rect(ref image_rect) => {
|
|
unsafe {
|
|
bindings::Gecko_SetLayerImageImageValue(self, &image_rect.url);
|
|
bindings::Gecko_InitializeImageCropRect(self);
|
|
|
|
// Set CropRect
|
|
let ref mut rect = *self.mCropRect.mPtr;
|
|
*rect = Rect(
|
|
image_rect.top,
|
|
image_rect.right,
|
|
image_rect.bottom,
|
|
image_rect.left,
|
|
);
|
|
}
|
|
},
|
|
GenericImage::Element(ref element) => unsafe {
|
|
bindings::Gecko_SetImageElement(self, element.as_ptr());
|
|
},
|
|
}
|
|
}
|
|
|
|
fn set_gradient(&mut self, gradient: Box<Gradient>) {
|
|
unsafe {
|
|
bindings::Gecko_SetGradientImageValue(self, Box::into_raw(gradient));
|
|
}
|
|
}
|
|
|
|
/// Converts into Image.
|
|
pub unsafe fn into_image(self: &nsStyleImage) -> Option<Image> {
|
|
use crate::gecko_bindings::structs::nsStyleImageType;
|
|
use crate::values::computed::MozImageRect;
|
|
|
|
match self.mType {
|
|
nsStyleImageType::eStyleImageType_Null => None,
|
|
nsStyleImageType::eStyleImageType_Image => {
|
|
let url = self.__bindgen_anon_1.mImage.as_ref().clone();
|
|
if self.mCropRect.mPtr.is_null() {
|
|
Some(GenericImage::Url(url))
|
|
} else {
|
|
let rect = &*self.mCropRect.mPtr;
|
|
Some(GenericImage::Rect(Box::new(MozImageRect {
|
|
url,
|
|
top: rect.0,
|
|
right: rect.1,
|
|
bottom: rect.2,
|
|
left: rect.3,
|
|
})))
|
|
}
|
|
},
|
|
nsStyleImageType::eStyleImageType_Gradient => {
|
|
let gradient: &Gradient = &**self.__bindgen_anon_1.mGradient.as_ref();
|
|
Some(GenericImage::Gradient(Box::new(gradient.clone())))
|
|
},
|
|
nsStyleImageType::eStyleImageType_Element => {
|
|
use crate::gecko_string_cache::Atom;
|
|
let atom = bindings::Gecko_GetImageElement(self);
|
|
Some(GenericImage::Element(Atom::from_raw(atom)))
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
pub mod basic_shape {
|
|
//! Conversions from and to CSS shape representations.
|
|
use crate::gecko_bindings::structs::{
|
|
StyleGeometryBox, StyleShapeSource, StyleShapeSourceType,
|
|
};
|
|
use crate::values::computed::basic_shape::{BasicShape, ClippingShape, FloatAreaShape};
|
|
use crate::values::computed::motion::OffsetPath;
|
|
use crate::values::generics::basic_shape::{GeometryBox, Path, ShapeBox, ShapeSource};
|
|
use crate::values::specified::SVGPathData;
|
|
|
|
impl StyleShapeSource {
|
|
/// Convert StyleShapeSource to ShapeSource except URL and Image
|
|
/// types.
|
|
fn into_shape_source<ReferenceBox, ImageOrUrl>(
|
|
&self,
|
|
) -> Option<ShapeSource<BasicShape, ReferenceBox, ImageOrUrl>>
|
|
where
|
|
ReferenceBox: From<StyleGeometryBox>,
|
|
{
|
|
match self.mType {
|
|
StyleShapeSourceType::None => Some(ShapeSource::None),
|
|
StyleShapeSourceType::Box => Some(ShapeSource::Box(self.mReferenceBox.into())),
|
|
StyleShapeSourceType::Shape => {
|
|
let other_shape = unsafe { &*self.__bindgen_anon_1.mBasicShape.as_ref().mPtr };
|
|
let shape = Box::new(other_shape.clone());
|
|
let reference_box = if self.mReferenceBox == StyleGeometryBox::NoBox {
|
|
None
|
|
} else {
|
|
Some(self.mReferenceBox.into())
|
|
};
|
|
Some(ShapeSource::Shape(shape, reference_box))
|
|
},
|
|
StyleShapeSourceType::Image => None,
|
|
StyleShapeSourceType::Path => {
|
|
let path = self.to_svg_path().expect("expect an SVGPathData");
|
|
let fill = unsafe { &*self.__bindgen_anon_1.mSVGPath.as_ref().mPtr }.mFillRule;
|
|
Some(ShapeSource::Path(Path { fill, path }))
|
|
},
|
|
}
|
|
}
|
|
|
|
/// Generate a SVGPathData from StyleShapeSource if possible.
|
|
fn to_svg_path(&self) -> Option<SVGPathData> {
|
|
match self.mType {
|
|
StyleShapeSourceType::Path => {
|
|
let gecko_path = unsafe { &*self.__bindgen_anon_1.mSVGPath.as_ref().mPtr };
|
|
Some(SVGPathData(gecko_path.mPath.clone()))
|
|
},
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> From<&'a StyleShapeSource> for ClippingShape {
|
|
fn from(other: &'a StyleShapeSource) -> Self {
|
|
match other.mType {
|
|
StyleShapeSourceType::Image => unsafe {
|
|
use crate::values::generics::image::Image as GenericImage;
|
|
|
|
let shape_image = &*other.__bindgen_anon_1.mShapeImage.as_ref().mPtr;
|
|
let image = shape_image.into_image().expect("Cannot convert to Image");
|
|
match image {
|
|
GenericImage::Url(url) => ShapeSource::ImageOrUrl(url.0),
|
|
_ => panic!("ClippingShape doesn't support non-url images"),
|
|
}
|
|
},
|
|
_ => other
|
|
.into_shape_source()
|
|
.expect("Couldn't convert to StyleSource!"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> From<&'a StyleShapeSource> for FloatAreaShape {
|
|
fn from(other: &'a StyleShapeSource) -> Self {
|
|
match other.mType {
|
|
StyleShapeSourceType::Image => unsafe {
|
|
let shape_image = &*other.__bindgen_anon_1.mShapeImage.as_ref().mPtr;
|
|
let image = shape_image.into_image().expect("Cannot convert to Image");
|
|
ShapeSource::ImageOrUrl(image)
|
|
},
|
|
_ => other
|
|
.into_shape_source()
|
|
.expect("Couldn't convert to StyleSource!"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> From<&'a StyleShapeSource> for OffsetPath {
|
|
fn from(other: &'a StyleShapeSource) -> Self {
|
|
use crate::values::generics::motion::GenericOffsetPath;
|
|
match other.mType {
|
|
StyleShapeSourceType::Path => GenericOffsetPath::Path(
|
|
other.to_svg_path().expect("Cannot convert to SVGPathData"),
|
|
),
|
|
StyleShapeSourceType::None => OffsetPath::none(),
|
|
StyleShapeSourceType::Shape |
|
|
StyleShapeSourceType::Box |
|
|
StyleShapeSourceType::Image => unreachable!("Unsupported offset-path type"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<ShapeBox> for StyleGeometryBox {
|
|
fn from(reference: ShapeBox) -> Self {
|
|
use crate::gecko_bindings::structs::StyleGeometryBox::*;
|
|
match reference {
|
|
ShapeBox::ContentBox => ContentBox,
|
|
ShapeBox::PaddingBox => PaddingBox,
|
|
ShapeBox::BorderBox => BorderBox,
|
|
ShapeBox::MarginBox => MarginBox,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<GeometryBox> for StyleGeometryBox {
|
|
fn from(reference: GeometryBox) -> Self {
|
|
use crate::gecko_bindings::structs::StyleGeometryBox::*;
|
|
match reference {
|
|
GeometryBox::ShapeBox(shape_box) => From::from(shape_box),
|
|
GeometryBox::FillBox => FillBox,
|
|
GeometryBox::StrokeBox => StrokeBox,
|
|
GeometryBox::ViewBox => ViewBox,
|
|
}
|
|
}
|
|
}
|
|
|
|
// Will panic on NoBox
|
|
// Ideally these would be implemented on Option<T>,
|
|
// but coherence doesn't like that and TryFrom isn't stable
|
|
impl From<StyleGeometryBox> for GeometryBox {
|
|
fn from(reference: StyleGeometryBox) -> Self {
|
|
use crate::gecko_bindings::structs::StyleGeometryBox::*;
|
|
match reference {
|
|
ContentBox => GeometryBox::ShapeBox(ShapeBox::ContentBox),
|
|
PaddingBox => GeometryBox::ShapeBox(ShapeBox::PaddingBox),
|
|
BorderBox => GeometryBox::ShapeBox(ShapeBox::BorderBox),
|
|
MarginBox => GeometryBox::ShapeBox(ShapeBox::MarginBox),
|
|
FillBox => GeometryBox::FillBox,
|
|
StrokeBox => GeometryBox::StrokeBox,
|
|
ViewBox => GeometryBox::ViewBox,
|
|
_ => panic!("Unexpected StyleGeometryBox while converting to GeometryBox"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<StyleGeometryBox> for ShapeBox {
|
|
fn from(reference: StyleGeometryBox) -> Self {
|
|
use crate::gecko_bindings::structs::StyleGeometryBox::*;
|
|
match reference {
|
|
ContentBox => ShapeBox::ContentBox,
|
|
PaddingBox => ShapeBox::PaddingBox,
|
|
BorderBox => ShapeBox::BorderBox,
|
|
MarginBox => ShapeBox::MarginBox,
|
|
_ => panic!("Unexpected StyleGeometryBox while converting to ShapeBox"),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<RulesMutateError> for nsresult {
|
|
fn from(other: RulesMutateError) -> Self {
|
|
match other {
|
|
RulesMutateError::Syntax => nsresult::NS_ERROR_DOM_SYNTAX_ERR,
|
|
RulesMutateError::IndexSize => nsresult::NS_ERROR_DOM_INDEX_SIZE_ERR,
|
|
RulesMutateError::HierarchyRequest => nsresult::NS_ERROR_DOM_HIERARCHY_REQUEST_ERR,
|
|
RulesMutateError::InvalidState => nsresult::NS_ERROR_DOM_INVALID_STATE_ERR,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TextAlign {
|
|
/// Obtain a specified value from a Gecko keyword value
|
|
///
|
|
/// Intended for use with presentation attributes, not style structs
|
|
pub fn from_gecko_keyword(kw: u32) -> Self {
|
|
match kw {
|
|
structs::NS_STYLE_TEXT_ALIGN_LEFT => TextAlign::Left,
|
|
structs::NS_STYLE_TEXT_ALIGN_RIGHT => TextAlign::Right,
|
|
structs::NS_STYLE_TEXT_ALIGN_CENTER => TextAlign::Center,
|
|
structs::NS_STYLE_TEXT_ALIGN_JUSTIFY => TextAlign::Justify,
|
|
structs::NS_STYLE_TEXT_ALIGN_MOZ_LEFT => TextAlign::MozLeft,
|
|
structs::NS_STYLE_TEXT_ALIGN_MOZ_RIGHT => TextAlign::MozRight,
|
|
structs::NS_STYLE_TEXT_ALIGN_MOZ_CENTER => TextAlign::MozCenter,
|
|
structs::NS_STYLE_TEXT_ALIGN_CHAR => TextAlign::Char,
|
|
structs::NS_STYLE_TEXT_ALIGN_END => TextAlign::End,
|
|
_ => panic!("Found unexpected value in style struct for text-align property"),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Convert to String from given chars pointer.
|
|
pub unsafe fn string_from_chars_pointer(p: *const u16) -> String {
|
|
use std::slice;
|
|
let mut length = 0;
|
|
let mut iter = p;
|
|
while *iter != 0 {
|
|
length += 1;
|
|
iter = iter.offset(1);
|
|
}
|
|
let char_vec = slice::from_raw_parts(p, length as usize);
|
|
String::from_utf16_lossy(char_vec)
|
|
}
|
|
|
|
impl<'a> From<&'a Matrix4x4Components> for Matrix3D {
|
|
fn from(m: &'a Matrix4x4Components) -> Matrix3D {
|
|
Matrix3D {
|
|
m11: m[0],
|
|
m12: m[1],
|
|
m13: m[2],
|
|
m14: m[3],
|
|
m21: m[4],
|
|
m22: m[5],
|
|
m23: m[6],
|
|
m24: m[7],
|
|
m31: m[8],
|
|
m32: m[9],
|
|
m33: m[10],
|
|
m34: m[11],
|
|
m41: m[12],
|
|
m42: m[13],
|
|
m43: m[14],
|
|
m44: m[15],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<Matrix3D> for Matrix4x4Components {
|
|
fn from(matrix: Matrix3D) -> Self {
|
|
[
|
|
matrix.m11, matrix.m12, matrix.m13, matrix.m14, matrix.m21, matrix.m22, matrix.m23,
|
|
matrix.m24, matrix.m31, matrix.m32, matrix.m33, matrix.m34, matrix.m41, matrix.m42,
|
|
matrix.m43, matrix.m44,
|
|
]
|
|
}
|
|
}
|