--- a/dom/base/DOMIntersectionObserver.cpp
+++ b/dom/base/DOMIntersectionObserver.cpp
@@ -5,17 +5,17 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "DOMIntersectionObserver.h"
#include "nsCSSParser.h"
#include "nsCSSPropertyID.h"
#include "nsIFrame.h"
#include "nsContentUtils.h"
#include "nsLayoutUtils.h"
-#include "mozilla/ServoCSSParser.h"
+#include "mozilla/ServoBindings.h"
namespace mozilla {
namespace dom {
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMIntersectionObserverEntry)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
@@ -111,24 +111,24 @@ DOMIntersectionObserver::Constructor(con
}
return observer.forget();
}
bool
DOMIntersectionObserver::SetRootMargin(const nsAString& aString)
{
- return ServoCSSParser::ParseIntersectionObserverRootMargin(aString,
- &mRootMargin);
+ return Servo_IntersectionObserverRootMargin_Parse(&aString, &mRootMargin);
}
void
DOMIntersectionObserver::GetRootMargin(mozilla::dom::DOMString& aRetVal)
{
- mRootMargin.AppendToString(eCSSProperty_DOM, aRetVal);
+ nsString& retVal = aRetVal;
+ Servo_IntersectionObserverRootMargin_ToString(&mRootMargin, &retVal);
}
void
DOMIntersectionObserver::GetThresholds(nsTArray<double>& aRetVal)
{
aRetVal = mThresholds;
}
@@ -301,25 +301,17 @@ DOMIntersectionObserver::Update(nsIDocum
}
}
}
nsMargin rootMargin;
NS_FOR_CSS_SIDES(side) {
nscoord basis = side == eSideTop || side == eSideBottom ?
rootRect.Height() : rootRect.Width();
- nsCSSValue value = mRootMargin.*nsCSSRect::sides[side];
- nsStyleCoord coord;
- if (value.IsPixelLengthUnit()) {
- coord.SetCoordValue(value.GetPixelLength());
- } else if (value.IsPercentLengthUnit()) {
- coord.SetPercentValue(value.GetPercentValue());
- } else {
- MOZ_ASSERT_UNREACHABLE("invalid length unit");
- }
+ nsStyleCoord coord = mRootMargin.Get(side);
rootMargin.Side(side) = nsLayoutUtils::ComputeCBDependentValue(basis, coord);
}
for (size_t i = 0; i < mObservationTargets.Length(); ++i) {
Element* target = mObservationTargets.ElementAt(i);
nsIFrame* targetFrame = target->GetPrimaryFrame();
nsRect targetRect;
Maybe<nsRect> intersectionRect;
--- a/dom/base/DOMIntersectionObserver.h
+++ b/dom/base/DOMIntersectionObserver.h
@@ -3,17 +3,17 @@
/* 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 http://mozilla.org/MPL/2.0/. */
#ifndef DOMIntersectionObserver_h
#define DOMIntersectionObserver_h
#include "mozilla/dom/IntersectionObserverBinding.h"
-#include "nsCSSValue.h"
+#include "nsStyleCoord.h"
#include "nsTArray.h"
using mozilla::dom::DOMRect;
using mozilla::dom::Element;
namespace mozilla {
namespace dom {
@@ -172,17 +172,17 @@ protected:
const nsRect& aTargetRect,
const Maybe<nsRect>& aIntersectionRect,
double aIntersectionRatio);
nsCOMPtr<nsPIDOMWindowInner> mOwner;
RefPtr<nsIDocument> mDocument;
RefPtr<mozilla::dom::IntersectionCallback> mCallback;
RefPtr<Element> mRoot;
- nsCSSRect mRootMargin;
+ nsStyleSides mRootMargin;
nsTArray<double> mThresholds;
// Holds raw pointers which are explicitly cleared by UnlinkTarget().
nsTArray<Element*> mObservationTargets;
nsTArray<RefPtr<DOMIntersectionObserverEntry>> mQueuedEntries;
bool mConnected;
};
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -831,19 +831,20 @@ SERVO_BINDING_FUNC(Servo_CloneArcStringD
SERVO_BINDING_FUNC(Servo_IsValidCSSColor, bool, const nsAString* value);
SERVO_BINDING_FUNC(Servo_ComputeColor, bool,
RawServoStyleSetBorrowedOrNull set,
nscolor current_color,
const nsAString* value,
nscolor* result_color,
bool* was_current_color,
mozilla::css::Loader* loader)
-SERVO_BINDING_FUNC(Servo_ParseIntersectionObserverRootMargin, bool,
- const nsAString* value,
- nsCSSRect* result);
+SERVO_BINDING_FUNC(Servo_IntersectionObserverRootMargin_Parse, bool,
+ const nsAString* value, nsStyleSides* result)
+SERVO_BINDING_FUNC(Servo_IntersectionObserverRootMargin_ToString, void,
+ const nsStyleSides* rect, nsAString* result)
// Returning false means the parsed transform contains relative lengths or
// percentage value, so we cannot compute the matrix. In this case, we keep
// |result| and |contains_3d_transform| as-is.
SERVO_BINDING_FUNC(Servo_ParseTransformIntoMatrix, bool,
const nsAString* value,
bool* contains_3d_transform,
RawGeckoGfxMatrix4x4* result);
SERVO_BINDING_FUNC(Servo_ParseFontShorthandForMatching, bool,
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -277,18 +277,16 @@ whitelist-types = [
"nscolor",
"nsChangeHint",
"nsCSSCounterDesc",
"nsCSSFontDesc",
"nsCSSKeyword",
"nsCSSPropertyID",
"nsCSSPropertyIDSet",
"nsCSSProps",
- "nsCSSRect",
- "nsCSSRect_heap",
"nsCSSShadowArray",
"nsCSSValue",
"nsCSSValueFloatColor",
"nsCSSValueGradient",
"nsCSSValueGradientStop",
"nsCSSValueList",
"nsCSSValueList_heap",
"nsCSSValuePair_heap",
@@ -329,16 +327,17 @@ whitelist-types = [
"nsStyleGridTemplate",
"nsStyleImage",
"nsStyleImageLayers",
"nsStyleList",
"nsStyleMargin",
"nsStyleOutline",
"nsStylePadding",
"nsStylePosition",
+ "nsStyleSides",
"nsStyleSVG",
"nsStyleSVGOpacitySource",
"nsStyleSVGPaint",
"nsStyleSVGReset",
"nsStyleTable",
"nsStyleTableBorder",
"nsStyleText",
"nsStyleTextReset",
@@ -529,17 +528,16 @@ structs-types = [
"StyleShapeSource",
"StyleTransition",
"gfxFontFeatureValueSet",
"nsCSSCounterDesc",
"nsCSSFontDesc",
"nsCSSKeyword",
"nsCSSPropertyID",
"nsCSSPropertyIDSet",
- "nsCSSRect",
"nsCSSShadowArray",
"nsCSSUnit",
"nsCSSValue",
"nsCSSValueSharedList",
"nsChangeHint",
"nsCursorImage",
"nsFont",
"nsAtom",
@@ -575,16 +573,17 @@ structs-types = [
"nsStyleOutline",
"nsStylePadding",
"nsStylePosition",
"nsStyleQuoteValues",
"nsStyleSVG",
"nsStyleSVGOpacitySource",
"nsStyleSVGPaint",
"nsStyleSVGReset",
+ "nsStyleSides",
"nsStyleTable",
"nsStyleTableBorder",
"nsStyleText",
"nsStyleTextReset",
"nsStyleUIReset",
"nsStyleUnion",
"nsStyleUnit",
"nsStyleUserInterface",
--- a/layout/style/ServoCSSParser.cpp
+++ b/layout/style/ServoCSSParser.cpp
@@ -28,23 +28,16 @@ ServoCSSParser::ComputeColor(ServoStyleS
bool* aWasCurrentColor,
css::Loader* aLoader)
{
return Servo_ComputeColor(aStyleSet ? aStyleSet->RawSet() : nullptr,
aCurrentColor, &aValue, aResultColor,
aWasCurrentColor, aLoader);
}
-/* static */ bool
-ServoCSSParser::ParseIntersectionObserverRootMargin(const nsAString& aValue,
- nsCSSRect* aResult)
-{
- return Servo_ParseIntersectionObserverRootMargin(&aValue, aResult);
-}
-
/* static */ already_AddRefed<RawServoDeclarationBlock>
ServoCSSParser::ParseProperty(nsCSSPropertyID aProperty,
const nsAString& aValue,
const ParsingEnvironment& aParsingEnvironment,
ParsingMode aParsingMode)
{
NS_ConvertUTF16toUTF8 value(aValue);
return Servo_ParseProperty(aProperty,
--- a/layout/style/ServoCSSParser.h
+++ b/layout/style/ServoCSSParser.h
@@ -68,27 +68,16 @@ public:
static bool ComputeColor(ServoStyleSet* aStyleSet,
nscolor aCurrentColor,
const nsAString& aValue,
nscolor* aResultColor,
bool* aWasCurrentColor = nullptr,
css::Loader* aLoader = nullptr);
/**
- * Parses a IntersectionObserver's initialization dictionary's rootMargin
- * property.
- *
- * @param aValue The rootMargin value.
- * @param aResult The nsCSSRect object to write the result into.
- * @return Whether the value was successfully parsed.
- */
- static bool ParseIntersectionObserverRootMargin(const nsAString& aValue,
- nsCSSRect* aResult);
-
- /**
* Parse a string representing a CSS property value into a
* RawServoDeclarationBlock.
*
* @param aProperty The property to be parsed.
* @param aValue The specified value.
* @param aParsingEnvironment All the parsing environment data we need.
* @param aParsingMode The paring mode we apply.
* @return The parsed value as a RawServoDeclarationBlock. We put the value
--- a/servo/components/style/values/specified/gecko.rs
+++ b/servo/components/style/values/specified/gecko.rs
@@ -1,24 +1,26 @@
/* 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 http://mozilla.org/MPL/2.0/. */
//! Specified types for legacy Gecko-only properties.
use cssparser::{Parser, Token};
-use gecko_bindings::structs;
-use gecko_bindings::sugar::ns_css_value::ToNsCssValue;
+use gecko::values::GeckoStyleCoordConvertible;
+use gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut};
use parser::{Parse, ParserContext};
-use style_traits::{ParseError, StyleParseErrorKind};
-use values::CSSFloat;
+use std::fmt;
+use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
+use style_traits::values::SequenceWriter;
use values::computed;
use values::generics::gecko::ScrollSnapPoint as GenericScrollSnapPoint;
use values::generics::rect::Rect;
use values::specified::length::LengthOrPercentage;
+use values::computed::length::CSSPixelLength;
/// A specified type for scroll snap points.
pub type ScrollSnapPoint = GenericScrollSnapPoint<LengthOrPercentage>;
impl Parse for ScrollSnapPoint {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
return Ok(GenericScrollSnapPoint::None);
@@ -27,62 +29,67 @@ impl Parse for ScrollSnapPoint {
let length = input.parse_nested_block(|i| {
LengthOrPercentage::parse_non_negative(context, i)
})?;
Ok(GenericScrollSnapPoint::Repeat(length))
}
}
/// A component of an IntersectionObserverRootMargin.
-#[derive(Clone, Copy, Debug, PartialEq)]
+#[derive(Clone, Copy, Debug, PartialEq, ToCss)]
pub enum PixelOrPercentage {
/// An absolute length in pixels (px)
- Px(CSSFloat),
+ Pixel(CSSPixelLength),
/// A percentage (%)
Percentage(computed::Percentage),
}
impl Parse for PixelOrPercentage {
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>
) -> Result<Self, ParseError<'i>> {
let location = input.current_source_location();
let token = input.next()?;
let value = match *token {
Token::Dimension { value, ref unit, .. } => {
match_ignore_ascii_case! { unit,
- "px" => Ok(PixelOrPercentage::Px(value)),
+ "px" => Ok(PixelOrPercentage::Pixel(CSSPixelLength::new(value))),
_ => Err(()),
}
}
Token::Percentage { unit_value, .. } => {
Ok(PixelOrPercentage::Percentage(
computed::Percentage(unit_value)
))
}
_ => Err(()),
};
value.map_err(|()| {
location.new_custom_error(StyleParseErrorKind::UnspecifiedError)
})
}
}
-impl ToNsCssValue for PixelOrPercentage {
- fn convert(self, nscssvalue: &mut structs::nsCSSValue) {
- match self {
- PixelOrPercentage::Px(px) => {
- unsafe { nscssvalue.set_px(px); }
- }
- PixelOrPercentage::Percentage(pc) => {
- unsafe { nscssvalue.set_percentage(pc.0); }
- }
+impl GeckoStyleCoordConvertible for PixelOrPercentage {
+ fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
+ match *self {
+ PixelOrPercentage::Pixel(ref l) => l.to_gecko_style_coord(coord),
+ PixelOrPercentage::Percentage(ref pc) => pc.to_gecko_style_coord(coord),
}
}
+
+ fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
+ CSSPixelLength::from_gecko_style_coord(coord)
+ .map(PixelOrPercentage::Pixel)
+ .or_else(|| {
+ computed::Percentage::from_gecko_style_coord(coord)
+ .map(PixelOrPercentage::Percentage)
+ })
+ }
}
/// The value of an IntersectionObserver's rootMargin property.
///
/// Only bare px or percentage values are allowed. Other length units and
/// calc() values are not allowed.
///
/// <https://w3c.github.io/IntersectionObserver/#parse-a-root-margin>
@@ -92,8 +99,25 @@ impl Parse for IntersectionObserverRootM
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let rect = Rect::parse_with(context, input, PixelOrPercentage::parse)?;
Ok(IntersectionObserverRootMargin(rect))
}
}
+
+// Strictly speaking this is not ToCss. It's serializing for DOM. But
+// we can just reuse the infrastructure of this.
+//
+// <https://w3c.github.io/IntersectionObserver/#dom-intersectionobserver-rootmargin>
+impl ToCss for IntersectionObserverRootMargin {
+ fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
+ // We cannot use the ToCss impl of Rect, because that would
+ // merge items when they are equal. We want to list them all.
+ let mut writer = SequenceWriter::new(dest, " ");
+ let rect = &self.0;
+ writer.item(&rect.0)?;
+ writer.item(&rect.1)?;
+ writer.item(&rect.2)?;
+ writer.item(&rect.3)
+ }
+}
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -152,18 +152,19 @@ use style::thread_state;
use style::timer::Timer;
use style::traversal::DomTraversal;
use style::traversal::resolve_style;
use style::traversal_flags::{self, TraversalFlags};
use style::values::{CustomIdent, KeyframesName};
use style::values::animated::{Animate, Procedure, ToAnimatedZero};
use style::values::computed::{Context, ToComputedValue};
use style::values::distance::ComputeSquaredDistance;
+use style::values::generics::rect::Rect;
use style::values::specified;
-use style::values::specified::gecko::IntersectionObserverRootMargin;
+use style::values::specified::gecko::{IntersectionObserverRootMargin, PixelOrPercentage};
use style::values::specified::source_size_list::SourceSizeList;
use style_traits::{CssWriter, ParsingMode, StyleParseErrorKind, ToCss};
use super::error_reporter::ErrorReporter;
use super::stylesheet_loader::StylesheetLoader;
/*
* For Gecko->Servo function calls, we need to redeclare the same signature that was declared in
* the C header in Gecko. In order to catch accidental mismatches, we run rust-bindgen against
@@ -5199,52 +5200,60 @@ pub extern "C" fn Servo_ComputeColor(
None => false,
}
}
Err(_) => false,
}
}
#[no_mangle]
-pub extern "C" fn Servo_ParseIntersectionObserverRootMargin(
+pub unsafe extern "C" fn Servo_IntersectionObserverRootMargin_Parse(
value: *const nsAString,
- result: *mut structs::nsCSSRect,
+ result: *mut structs::nsStyleSides,
) -> bool {
- let value = unsafe { value.as_ref().unwrap().to_string() };
- let result = unsafe { result.as_mut().unwrap() };
+ let value = value.as_ref().unwrap().to_string();
+ let result = result.as_mut().unwrap();
let mut input = ParserInput::new(&value);
let mut parser = Parser::new(&mut input);
- let url_data = unsafe { dummy_url_data() };
+ let url_data = dummy_url_data();
let context = ParserContext::new(
Origin::Author,
url_data,
Some(CssRuleType::Style),
ParsingMode::DEFAULT,
QuirksMode::NoQuirks,
);
let margin = parser.parse_entirely(|p| {
IntersectionObserverRootMargin::parse(&context, p)
});
match margin {
Ok(margin) => {
- let rect = margin.0;
- result.mTop.set_from(rect.0);
- result.mRight.set_from(rect.1);
- result.mBottom.set_from(rect.2);
- result.mLeft.set_from(rect.3);
+ margin.0.to_gecko_rect(result);
true
}
Err(..) => false,
}
}
#[no_mangle]
+pub unsafe extern "C" fn Servo_IntersectionObserverRootMargin_ToString(
+ rect: *mut structs::nsStyleSides,
+ result: *mut nsAString,
+) {
+ let rect = Rect::<PixelOrPercentage>::
+ from_gecko_rect(rect.as_ref().unwrap()).unwrap();
+ let root_margin = IntersectionObserverRootMargin(rect);
+ let mut writer = CssWriter::new(result.as_mut().unwrap());
+ root_margin.to_css(&mut writer).unwrap();
+}
+
+#[no_mangle]
pub extern "C" fn Servo_ParseTransformIntoMatrix(
value: *const nsAString,
contain_3d: *mut bool,
result: *mut RawGeckoGfxMatrix4x4
) -> bool {
use style::properties::longhands::transform;
let string = unsafe { (*value).to_string() };