--- a/devtools/shared/css/generated/properties-db.js
+++ b/devtools/shared/css/generated/properties-db.js
@@ -1510,16 +1510,48 @@ exports.CSS_PROPERTIES = {
7
],
"values": [
"inherit",
"initial",
"unset"
]
},
+ "-moz-window-transform": {
+ "isInherited": false,
+ "subproperties": [
+ "-moz-window-transform"
+ ],
+ "supports": [],
+ "values": [
+ "inherit",
+ "initial",
+ "unset"
+ ]
+ },
+ "-moz-window-transform-origin": {
+ "isInherited": false,
+ "subproperties": [
+ "-moz-window-transform-origin"
+ ],
+ "supports": [
+ 6,
+ 8
+ ],
+ "values": [
+ "bottom",
+ "center",
+ "inherit",
+ "initial",
+ "left",
+ "right",
+ "top",
+ "unset"
+ ]
+ },
"-webkit-align-content": {
"isInherited": false,
"subproperties": [
"align-content"
],
"supports": [],
"values": [
"baseline",
@@ -3160,16 +3192,18 @@ exports.CSS_PROPERTIES = {
"vertical-align",
"visibility",
"white-space",
"width",
"will-change",
"-moz-window-dragging",
"-moz-window-shadow",
"-moz-window-opacity",
+ "-moz-window-transform",
+ "-moz-window-transform-origin",
"word-break",
"word-spacing",
"overflow-wrap",
"writing-mode",
"z-index"
],
"supports": [
1,
--- a/layout/inspector/inDOMUtils.cpp
+++ b/layout/inspector/inDOMUtils.cpp
@@ -781,16 +781,17 @@ PropertySupportsVariant(nsCSSPropertyID
case eCSSProperty_scroll_snap_coordinate:
case eCSSProperty_scroll_snap_destination:
case eCSSProperty_transform_origin:
case eCSSProperty_perspective_origin:
case eCSSProperty__moz_outline_radius_topleft:
case eCSSProperty__moz_outline_radius_topright:
case eCSSProperty__moz_outline_radius_bottomleft:
case eCSSProperty__moz_outline_radius_bottomright:
+ case eCSSProperty__moz_window_transform_origin:
supported = VARIANT_LP;
break;
case eCSSProperty__moz_border_bottom_colors:
case eCSSProperty__moz_border_left_colors:
case eCSSProperty__moz_border_right_colors:
case eCSSProperty__moz_border_top_colors:
supported = VARIANT_COLOR;
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -4312,16 +4312,31 @@ StyleAnimationValue::ExtractComputedValu
pair->mYValue)) {
return false;
}
aComputedValue.SetAndAdoptCSSValuePairValue(pair.forget(),
eUnit_CSSValuePair);
break;
}
+ case eCSSProperty__moz_window_transform_origin: {
+ const nsStyleUIReset *styleUIReset =
+ static_cast<const nsStyleUIReset*>(styleStruct);
+ nsAutoPtr<nsCSSValuePair> pair(new nsCSSValuePair);
+ if (!StyleCoordToCSSValue(styleUIReset->mWindowTransformOrigin[0],
+ pair->mXValue) ||
+ !StyleCoordToCSSValue(styleUIReset->mWindowTransformOrigin[1],
+ pair->mYValue)) {
+ return false;
+ }
+ aComputedValue.SetAndAdoptCSSValuePairValue(pair.forget(),
+ eUnit_CSSValuePair);
+ break;
+ }
+
case eCSSProperty_stroke_dasharray: {
const nsStyleSVG *svg = static_cast<const nsStyleSVG*>(styleStruct);
if (!svg->mStrokeDasharray.IsEmpty()) {
nsAutoPtr<nsCSSValueList> result;
nsCSSValueList **resultTail = getter_Transfers(result);
for (uint32_t i = 0, i_end = svg->mStrokeDasharray.Length();
i != i_end; ++i) {
nsCSSValueList *item = new nsCSSValueList;
@@ -4589,16 +4604,41 @@ StyleAnimationValue::ExtractComputedValu
result->mValue.SetNoneValue();
}
aComputedValue.SetTransformValue(
new nsCSSValueSharedList(result.forget()));
break;
}
+ case eCSSProperty__moz_window_transform: {
+ const nsStyleUIReset *uiReset =
+ static_cast<const nsStyleUIReset*>(styleStruct);
+ nsAutoPtr<nsCSSValueList> result;
+ if (uiReset->mSpecifiedWindowTransform) {
+ // Clone, and convert all lengths (not percents) to pixels.
+ nsCSSValueList **resultTail = getter_Transfers(result);
+ for (const nsCSSValueList *l = uiReset->mSpecifiedWindowTransform->mHead;
+ l; l = l->mNext) {
+ nsCSSValueList *clone = new nsCSSValueList;
+ *resultTail = clone;
+ resultTail = &clone->mNext;
+
+ SubstitutePixelValues(aStyleContext, l->mValue, clone->mValue);
+ }
+ } else {
+ result = new nsCSSValueList();
+ result->mValue.SetNoneValue();
+ }
+
+ aComputedValue.SetTransformValue(
+ new nsCSSValueSharedList(result.forget()));
+ break;
+ }
+
case eCSSProperty_font_variation_settings: {
auto font = static_cast<const nsStyleFont*>(styleStruct);
UniquePtr<nsCSSValuePairList> result;
if (!font->mFont.fontVariationSettings.IsEmpty()) {
// Make a new list that clones the current settings
nsCSSValuePairList* tail = nullptr;
for (auto v : font->mFont.fontVariationSettings) {
auto clone = MakeUnique<nsCSSValuePairList>();
--- a/layout/style/generate-stylestructlist.py
+++ b/layout/style/generate-stylestructlist.py
@@ -34,17 +34,17 @@ STYLE_STRUCTS = [("INHERITED",) + x for
("Variables", "CheckVariablesCallback",[]),
]] + [("RESET",) + x for x in [
# Reset style structs.
("Background", "nullptr", NORMAL_DEP + LENGTH_DEP + COLOR_DEP),
("Position", "nullptr", NORMAL_DEP + LENGTH_DEP),
("TextReset", "nullptr", NORMAL_DEP + LENGTH_DEP + COLOR_DEP),
("Display", "nullptr", NORMAL_DEP + LENGTH_DEP),
("Content", "nullptr", NORMAL_DEP + LENGTH_DEP),
- ("UIReset", "nullptr", NORMAL_DEP),
+ ("UIReset", "nullptr", NORMAL_DEP + LENGTH_DEP),
("Table", "nullptr", NORMAL_DEP),
("Margin", "nullptr", NORMAL_DEP + LENGTH_DEP),
("Padding", "nullptr", NORMAL_DEP + LENGTH_DEP),
("Border", "nullptr", NORMAL_DEP + LENGTH_DEP + COLOR_DEP),
("Outline", "nullptr", NORMAL_DEP + LENGTH_DEP + COLOR_DEP),
("XUL", "nullptr", NORMAL_DEP),
("SVGReset", "nullptr", NORMAL_DEP + LENGTH_DEP + COLOR_DEP),
("Column", "nullptr", NORMAL_DEP + LENGTH_DEP + COLOR_DEP),
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -1037,17 +1037,18 @@ protected:
bool ParseFontVariationSettings(nsCSSValue& aValue);
bool ParseFontSrc(nsCSSValue& aValue);
bool ParseFontSrcFormat(InfallibleTArray<nsCSSValue>& values);
bool ParseFontRanges(nsCSSValue& aValue);
bool ParseListStyle();
bool ParseListStyleType(nsCSSValue& aValue);
bool ParseMargin();
bool ParseClipPath(nsCSSValue& aValue);
- bool ParseTransform(bool aIsPrefixed, bool aDisallowRelativeValues = false);
+ bool ParseTransform(bool aIsPrefixed, nsCSSPropertyID aProperty,
+ bool aDisallowRelativeValues = false);
bool ParseObjectPosition();
bool ParseOutline();
bool ParseOverflow();
bool ParsePadding();
bool ParseQuotes();
bool ParseTextAlign(nsCSSValue& aValue,
const KTableEntry aTable[]);
bool ParseTextAlign(nsCSSValue& aValue);
@@ -1380,17 +1381,17 @@ protected:
uint16_t aMaxElems, nsCSSValue &aValue);
bool ParseFunctionInternals(const uint32_t aVariantMask[],
uint32_t aVariantMaskAll,
uint16_t aMinElems,
uint16_t aMaxElems,
InfallibleTArray<nsCSSValue>& aOutput);
/* Functions for transform-origin/perspective-origin Parsing */
- bool ParseTransformOrigin(bool aPerspective);
+ bool ParseTransformOrigin(nsCSSPropertyID aProperty);
/* Functions for filter parsing */
bool ParseFilter();
bool ParseSingleFilter(nsCSSValue* aValue);
bool ParseDropShadow(nsCSSValue* aValue);
/* Find and return the namespace ID associated with aPrefix.
If aPrefix has not been declared in an @namespace rule, returns
@@ -1941,17 +1942,18 @@ CSSParserImpl::ParseTransformProperty(co
mData.AssertInitialState();
mTempData.AssertInitialState();
nsCSSScanner scanner(aPropValue, 0);
css::ErrorReporter reporter(scanner, mSheet, mChildLoader, nullptr);
InitScanner(scanner, reporter, nullptr, nullptr, nullptr);
- bool parsedOK = ParseTransform(false, aDisallowRelativeValues);
+ bool parsedOK = ParseTransform(false, eCSSProperty_transform,
+ aDisallowRelativeValues);
// We should now be at EOF
if (parsedOK && GetToken(true)) {
parsedOK = false;
}
bool changed = false;
if (parsedOK) {
declaration->ExpandTo(&mData);
@@ -11862,23 +11864,24 @@ CSSParserImpl::ParsePropertyByFunction(n
return ParseQuotes();
case eCSSProperty_text_decoration:
return ParseTextDecoration();
case eCSSProperty_text_emphasis:
return ParseTextEmphasis();
case eCSSProperty_will_change:
return ParseWillChange();
case eCSSProperty_transform:
- return ParseTransform(false);
+ case eCSSProperty__moz_window_transform:
+ return ParseTransform(false, aPropID);
case eCSSProperty__moz_transform:
- return ParseTransform(true);
+ return ParseTransform(true, eCSSProperty_transform);
case eCSSProperty_transform_origin:
- return ParseTransformOrigin(false);
case eCSSProperty_perspective_origin:
- return ParseTransformOrigin(true);
+ case eCSSProperty__moz_window_transform_origin:
+ return ParseTransformOrigin(aPropID);
case eCSSProperty_transition:
return ParseTransition();
case eCSSProperty_animation:
return ParseAnimation();
case eCSSProperty_transition_property:
return ParseTransitionProperty();
case eCSSProperty_fill:
case eCSSProperty_stroke:
@@ -16227,19 +16230,25 @@ CSSParserImpl::ParseSingleTransform(bool
variantMask))
return false;
return ParseFunction(keyword, variantMask, 0, minElems, maxElems, aValue);
}
/* Parses a transform property list by continuously reading in properties
* and constructing a matrix from it.
+ * aProperty can be transform or -moz-window-transform.
+ * FIXME: For -moz-window-transform, it would be nice to reject non-2d
+ * transforms at parse time, because the implementation only supports 2d
+ * transforms. Instead, at the moment, non-2d transforms are treated as the
+ * identity transform very late in the pipeline.
*/
bool
-CSSParserImpl::ParseTransform(bool aIsPrefixed, bool aDisallowRelativeValues)
+CSSParserImpl::ParseTransform(bool aIsPrefixed, nsCSSPropertyID aProperty,
+ bool aDisallowRelativeValues)
{
nsCSSValue value;
// 'inherit', 'initial', 'unset' and 'none' must be alone
if (!ParseSingleTokenVariant(value, VARIANT_INHERIT | VARIANT_NONE,
nullptr)) {
nsCSSValueSharedList* list = new nsCSSValueSharedList;
value.SetSharedListValue(list);
list->mHead = new nsCSSValueList;
@@ -16251,17 +16260,17 @@ CSSParserImpl::ParseTransform(bool aIsPr
}
if (CheckEndProperty()) {
break;
}
cur->mNext = new nsCSSValueList;
cur = cur->mNext;
}
}
- AppendValue(eCSSProperty_transform, value);
+ AppendValue(aProperty, value);
return true;
}
/* Reads a polygon function's argument list.
*/
bool
CSSParserImpl::ParsePolygonFunction(nsCSSValue& aValue)
{
@@ -16526,53 +16535,48 @@ CSSParserImpl::ParseShapeOutside(nsCSSVa
// 'inherit', 'initial', 'unset', 'none', and <image> url must be alone.
return true;
}
return ParseReferenceBoxAndBasicShape(
aValue, nsCSSProps::kShapeOutsideShapeBoxKTable);
}
-bool CSSParserImpl::ParseTransformOrigin(bool aPerspective)
+bool CSSParserImpl::ParseTransformOrigin(nsCSSPropertyID aProperty)
{
nsCSSValuePair position;
if (!ParseBoxPositionValues(position, true))
return false;
- nsCSSPropertyID prop = eCSSProperty_transform_origin;
- if (aPerspective) {
- prop = eCSSProperty_perspective_origin;
- }
-
// Unlike many other uses of pairs, this position should always be stored
// as a pair, even if the values are the same, so it always serializes as
// a pair, and to keep the computation code simple.
if (position.mXValue.GetUnit() == eCSSUnit_Inherit ||
position.mXValue.GetUnit() == eCSSUnit_Initial ||
position.mXValue.GetUnit() == eCSSUnit_Unset) {
MOZ_ASSERT(position.mXValue == position.mYValue,
"inherit/initial/unset only half?");
- AppendValue(prop, position.mXValue);
+ AppendValue(aProperty, position.mXValue);
} else {
nsCSSValue value;
- if (aPerspective) {
+ if (aProperty != eCSSProperty_transform_origin) {
value.SetPairValue(position.mXValue, position.mYValue);
} else {
nsCSSValue depth;
CSSParseResult result =
ParseVariant(depth, VARIANT_LENGTH | VARIANT_CALC, nullptr);
if (result == CSSParseResult::Error) {
return false;
} else if (result == CSSParseResult::NotFound) {
depth.SetFloatValue(0.0f, eCSSUnit_Pixel);
}
value.SetTripletValue(position.mXValue, position.mYValue, depth);
}
- AppendValue(prop, value);
+ AppendValue(aProperty, value);
}
return true;
}
/**
* Reads a drop-shadow value. At the moment the Filter Effects specification
* just expects one shadow item. Should this ever change to a list of shadow
* items, use ParseShadowList instead.
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -4499,16 +4499,41 @@ CSS_PROP_UIRESET(
_moz_window_opacity,
CSS_PROP_DOMPROP_PREFIXED(WindowOpacity),
CSS_PROPERTY_INTERNAL | CSS_PROPERTY_PARSE_VALUE,
"",
VARIANT_HN,
nullptr,
offsetof(nsStyleUIReset, mWindowOpacity),
eStyleAnimType_float)
+CSS_PROP_UIRESET(
+ -moz-window-transform,
+ _moz_window_transform,
+ CSS_PROP_DOMPROP_PREFIXED(WindowTransform),
+ CSS_PROPERTY_INTERNAL |
+ CSS_PROPERTY_PARSE_FUNCTION |
+ CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH,
+ "",
+ 0,
+ nullptr,
+ offsetof(nsStyleUIReset, mSpecifiedWindowTransform),
+ eStyleAnimType_Custom)
+CSS_PROP_UIRESET(
+ -moz-window-transform-origin,
+ _moz_window_transform_origin,
+ CSS_PROP_DOMPROP_PREFIXED(WindowTransformOrigin),
+ CSS_PROPERTY_INTERNAL |
+ CSS_PROPERTY_PARSE_FUNCTION |
+ CSS_PROPERTY_STORES_CALC |
+ CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH,
+ "",
+ 0,
+ kImageLayerPositionKTable,
+ CSS_PROP_NO_OFFSET,
+ eStyleAnimType_Custom)
#endif // CSS_PROP_LIST_EXCLUDE_INTERNAL
CSS_PROP_TEXT(
word-break,
word_break,
WordBreak,
CSS_PROPERTY_PARSE_VALUE,
"",
VARIANT_HK,
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -1531,67 +1531,21 @@ nsComputedDOMStyle::DoGetTransformStyle(
{
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetIdent(
nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mTransformStyle,
nsCSSProps::kTransformStyleKTable));
return val.forget();
}
-/* If the property is "none", hand back "none" wrapped in a value.
- * Otherwise, compute the aggregate transform matrix and hands it back in a
- * "matrix" wrapper.
- */
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetTransform()
{
- /* First, get the display data. We'll need it. */
const nsStyleDisplay* display = StyleDisplay();
-
- /* If there are no transforms, then we should construct a single-element
- * entry and hand it back.
- */
- if (!display->mSpecifiedTransform) {
- RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-
- /* Set it to "none." */
- val->SetIdent(eCSSKeyword_none);
- return val.forget();
- }
-
- /* Otherwise, we need to compute the current value of the transform matrix,
- * store it in a string, and hand it back to the caller.
- */
-
- /* Use the inner frame for the reference box. If we don't have an inner
- * frame we use empty dimensions to allow us to continue (and percentage
- * values in the transform will simply give broken results).
- * TODO: There is no good way for us to represent the case where there's no
- * frame, which is problematic. The reason is that when we have percentage
- * transforms, there are a total of four stored matrix entries that influence
- * the transform based on the size of the element. However, this poses a
- * problem, because only two of these values can be explicitly referenced
- * using the named transforms. Until a real solution is found, we'll just
- * use this approach.
- */
- nsStyleTransformMatrix::TransformReferenceBox refBox(mInnerFrame,
- nsSize(0, 0));
-
- RuleNodeCacheConditions dummy;
- bool dummyBool;
- gfx::Matrix4x4 matrix =
- nsStyleTransformMatrix::ReadTransforms(display->mSpecifiedTransform->mHead,
- mStyleContext,
- mStyleContext->PresContext(),
- dummy,
- refBox,
- float(mozilla::AppUnitsPerCSSPixel()),
- &dummyBool);
-
- return MatrixToCSSValue(matrix);
+ return GetTransformValue(display->mSpecifiedTransform);
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetTransformBox()
{
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetIdent(
nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mTransformBox,
@@ -4230,16 +4184,43 @@ already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetWindowOpacity()
{
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetNumber(StyleUIReset()->mWindowOpacity);
return val.forget();
}
already_AddRefed<CSSValue>
+nsComputedDOMStyle::DoGetWindowTransform()
+{
+ const nsStyleUIReset* uiReset = StyleUIReset();
+ return GetTransformValue(uiReset->mSpecifiedWindowTransform);
+}
+
+already_AddRefed<CSSValue>
+nsComputedDOMStyle::DoGetWindowTransformOrigin()
+{
+ RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
+
+ const nsStyleUIReset* uiReset = StyleUIReset();
+
+ RefPtr<nsROCSSPrimitiveValue> originX = new nsROCSSPrimitiveValue;
+ SetValueToCoord(originX, uiReset->mWindowTransformOrigin[0], false,
+ &nsComputedDOMStyle::GetFrameBoundsWidthForTransform);
+ valueList->AppendCSSValue(originX.forget());
+
+ RefPtr<nsROCSSPrimitiveValue> originY = new nsROCSSPrimitiveValue;
+ SetValueToCoord(originY, uiReset->mWindowTransformOrigin[1], false,
+ &nsComputedDOMStyle::GetFrameBoundsHeightForTransform);
+ valueList->AppendCSSValue(originY.forget());
+
+ return valueList.forget();
+}
+
+already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetWordBreak()
{
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetIdent(
nsCSSProps::ValueToKeywordEnum(StyleText()->mWordBreak,
nsCSSProps::kWordBreakKTable));
return val.forget();
}
@@ -5866,16 +5847,66 @@ nsComputedDOMStyle::GetSVGPaintFor(bool
}
break;
}
}
return val.forget();
}
+/* If the property is "none", hand back "none" wrapped in a value.
+ * Otherwise, compute the aggregate transform matrix and hands it back in a
+ * "matrix" wrapper.
+ */
+already_AddRefed<CSSValue>
+nsComputedDOMStyle::GetTransformValue(nsCSSValueSharedList* aSpecifiedTransform)
+{
+ /* If there are no transforms, then we should construct a single-element
+ * entry and hand it back.
+ */
+ if (!aSpecifiedTransform) {
+ RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
+
+ /* Set it to "none." */
+ val->SetIdent(eCSSKeyword_none);
+ return val.forget();
+ }
+
+ /* Otherwise, we need to compute the current value of the transform matrix,
+ * store it in a string, and hand it back to the caller.
+ */
+
+ /* Use the inner frame for the reference box. If we don't have an inner
+ * frame we use empty dimensions to allow us to continue (and percentage
+ * values in the transform will simply give broken results).
+ * TODO: There is no good way for us to represent the case where there's no
+ * frame, which is problematic. The reason is that when we have percentage
+ * transforms, there are a total of four stored matrix entries that influence
+ * the transform based on the size of the element. However, this poses a
+ * problem, because only two of these values can be explicitly referenced
+ * using the named transforms. Until a real solution is found, we'll just
+ * use this approach.
+ */
+ nsStyleTransformMatrix::TransformReferenceBox refBox(mInnerFrame,
+ nsSize(0, 0));
+
+ RuleNodeCacheConditions dummy;
+ bool dummyBool;
+ gfx::Matrix4x4 matrix =
+ nsStyleTransformMatrix::ReadTransforms(aSpecifiedTransform->mHead,
+ mStyleContext,
+ mStyleContext->PresContext(),
+ dummy,
+ refBox,
+ float(mozilla::AppUnitsPerCSSPixel()),
+ &dummyBool);
+
+ return MatrixToCSSValue(matrix);
+}
+
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetFill()
{
return GetSVGPaintFor(true);
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetStroke()
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -209,16 +209,18 @@ private:
already_AddRefed<CSSValue> GetBorderColorFor(mozilla::Side aSide);
already_AddRefed<CSSValue> GetMarginWidthFor(mozilla::Side aSide);
already_AddRefed<CSSValue> GetFallbackValue(const nsStyleSVGPaint* aPaint);
already_AddRefed<CSSValue> GetSVGPaintFor(bool aFill);
+ already_AddRefed<CSSValue> GetTransformValue(nsCSSValueSharedList* aSpecifiedTransform);
+
// Appends all aLineNames (may be empty) space-separated to aResult.
void AppendGridLineNames(nsString& aResult,
const nsTArray<nsString>& aLineNames);
// Appends aLineNames as a CSSValue* to aValueList. If aLineNames is empty
// a value ("[]") is only appended if aSuppressEmptyList is false.
void AppendGridLineNames(nsDOMCSSValueList* aValueList,
const nsTArray<nsString>& aLineNames,
bool aSuppressEmptyList = true);
@@ -524,16 +526,18 @@ private:
already_AddRefed<CSSValue> DoGetForceBrokenImageIcon();
already_AddRefed<CSSValue> DoGetIMEMode();
already_AddRefed<CSSValue> DoGetUserFocus();
already_AddRefed<CSSValue> DoGetUserInput();
already_AddRefed<CSSValue> DoGetUserModify();
already_AddRefed<CSSValue> DoGetUserSelect();
already_AddRefed<CSSValue> DoGetWindowDragging();
already_AddRefed<CSSValue> DoGetWindowOpacity();
+ already_AddRefed<CSSValue> DoGetWindowTransform();
+ already_AddRefed<CSSValue> DoGetWindowTransformOrigin();
/* Column properties */
already_AddRefed<CSSValue> DoGetColumnCount();
already_AddRefed<CSSValue> DoGetColumnFill();
already_AddRefed<CSSValue> DoGetColumnSpan();
already_AddRefed<CSSValue> DoGetColumnWidth();
already_AddRefed<CSSValue> DoGetColumnGap();
already_AddRefed<CSSValue> DoGetColumnRuleWidth();
--- a/layout/style/nsComputedDOMStylePropertyList.h
+++ b/layout/style/nsComputedDOMStylePropertyList.h
@@ -301,16 +301,18 @@ COMPUTED_STYLE_PROP(_moz_tab_size,
COMPUTED_STYLE_PROP(_moz_text_size_adjust, TextSizeAdjust)
COMPUTED_STYLE_PROP(_moz_user_focus, UserFocus)
COMPUTED_STYLE_PROP(_moz_user_input, UserInput)
COMPUTED_STYLE_PROP(_moz_user_modify, UserModify)
COMPUTED_STYLE_PROP(_moz_user_select, UserSelect)
COMPUTED_STYLE_PROP(_moz_window_dragging, WindowDragging)
COMPUTED_STYLE_PROP(_moz_window_shadow, WindowShadow)
COMPUTED_STYLE_PROP(_moz_window_opacity, WindowOpacity)
+COMPUTED_STYLE_PROP(_moz_window_transform, WindowTransform)
+COMPUTED_STYLE_PROP(_moz_window_transform_origin, WindowTransformOrigin)
/* ********************************** *\
* Implementations of -webkit- styles *
\* ********************************** */
COMPUTED_STYLE_PROP(_webkit_text_fill_color, WebkitTextFillColor)
//// COMPUTED_STYLE_PROP(webkit-text-stroke, WebkitTextStroke)
COMPUTED_STYLE_PROP(_webkit_text_stroke_color, WebkitTextStrokeColor)
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -1735,16 +1735,57 @@ SetFactor(const nsCSSValue& aValue, floa
default:
break;
}
NS_NOTREACHED("SetFactor: inappropriate unit");
}
+static void
+SetTransformValue(const nsCSSValue& aValue,
+ RefPtr<nsCSSValueSharedList>& aField,
+ RuleNodeCacheConditions& aConditions,
+ nsCSSValueSharedList* const aParentValue)
+{
+ /* Convert the nsCSSValueList into an nsTArray<nsTransformFunction *>. */
+ switch (aValue.GetUnit()) {
+ case eCSSUnit_Null:
+ break;
+
+ case eCSSUnit_Initial:
+ case eCSSUnit_Unset:
+ case eCSSUnit_None:
+ aField = nullptr;
+ break;
+
+ case eCSSUnit_Inherit:
+ aField = aParentValue;
+ aConditions.SetUncacheable();
+ break;
+
+ case eCSSUnit_SharedList: {
+ nsCSSValueSharedList* list = aValue.GetSharedListValue();
+ nsCSSValueList* head = list->mHead;
+ MOZ_ASSERT(head, "transform list must have at least one item");
+ // can get a _None in here from transform animation
+ if (head->mValue.GetUnit() == eCSSUnit_None) {
+ MOZ_ASSERT(head->mNext == nullptr, "none must be alone");
+ aField = nullptr;
+ } else {
+ aField = list;
+ }
+ break;
+ }
+
+ default:
+ MOZ_ASSERT(false, "unrecognized transform unit");
+ }
+}
+
void*
nsRuleNode::operator new(size_t sz, nsPresContext* aPresContext)
{
// Check the recycle list first.
return aPresContext->PresShell()->AllocateByObjectID(eArenaObjectID_nsRuleNode, sz);
}
// Overridden to prevent the global delete from being called, since the memory
@@ -5276,16 +5317,38 @@ nsRuleNode::ComputeUIResetData(void* aSt
NS_STYLE_WINDOW_SHADOW_DEFAULT);
// -moz-window-opacity: factor, inherit, initial
SetFactor(*aRuleData->ValueForWindowOpacity(),
ui->mWindowOpacity, conditions,
parentUI->mWindowOpacity, 1.0f,
SETFCT_OPACITY | SETFCT_UNSET_INITIAL);
+ // -moz-window-transform
+ SetTransformValue(*aRuleData->ValueForWindowTransform(),
+ ui->mSpecifiedWindowTransform, conditions,
+ parentUI->mSpecifiedWindowTransform);
+
+ // -moz-window-transform-origin
+ const nsCSSValue* windowTransformOriginValue =
+ aRuleData->ValueForWindowTransformOrigin();
+ if (windowTransformOriginValue->GetUnit() != eCSSUnit_Null) {
+ mozilla::DebugOnly<bool> result =
+ SetPairCoords(*windowTransformOriginValue,
+ ui->mWindowTransformOrigin[0],
+ ui->mWindowTransformOrigin[1],
+ parentUI->mWindowTransformOrigin[0],
+ parentUI->mWindowTransformOrigin[1],
+ SETCOORD_LPH | SETCOORD_INITIAL_HALF |
+ SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC |
+ SETCOORD_UNSET_INITIAL,
+ aContext, mPresContext, conditions);
+ NS_ASSERTION(result, "Malformed -moz-window-transform-origin parse!");
+ }
+
COMPUTE_END_RESET(UIReset, ui)
}
// Information about each transition or animation property that is
// constant.
struct TransitionPropInfo {
nsCSSPropertyID property;
// Location of the count of the property's computed value.
@@ -6343,50 +6406,19 @@ nsRuleNode::ComputeDisplayData(void* aSt
// It's okay to cache this change in the rule tree for the same
// reasons as floats in the previous condition.
if (display->mDisplay == StyleDisplay::Inline) {
display->mDisplay = StyleDisplay::InlineBlock;
}
}
}
- /* Convert the nsCSSValueList into an nsTArray<nsTransformFunction *>. */
- const nsCSSValue* transformValue = aRuleData->ValueForTransform();
- switch (transformValue->GetUnit()) {
- case eCSSUnit_Null:
- break;
-
- case eCSSUnit_Initial:
- case eCSSUnit_Unset:
- case eCSSUnit_None:
- display->mSpecifiedTransform = nullptr;
- break;
-
- case eCSSUnit_Inherit:
- display->mSpecifiedTransform = parentDisplay->mSpecifiedTransform;
- conditions.SetUncacheable();
- break;
-
- case eCSSUnit_SharedList: {
- nsCSSValueSharedList* list = transformValue->GetSharedListValue();
- nsCSSValueList* head = list->mHead;
- MOZ_ASSERT(head, "transform list must have at least one item");
- // can get a _None in here from transform animation
- if (head->mValue.GetUnit() == eCSSUnit_None) {
- MOZ_ASSERT(head->mNext == nullptr, "none must be alone");
- display->mSpecifiedTransform = nullptr;
- } else {
- display->mSpecifiedTransform = list;
- }
- break;
- }
-
- default:
- MOZ_ASSERT(false, "unrecognized transform unit");
- }
+ SetTransformValue(*aRuleData->ValueForTransform(),
+ display->mSpecifiedTransform, conditions,
+ parentDisplay->mSpecifiedTransform);
/* Convert the nsCSSValueList into a will-change bitfield for fast lookup */
const nsCSSValue* willChangeValue = aRuleData->ValueForWillChange();
switch (willChangeValue->GetUnit()) {
case eCSSUnit_Null:
break;
case eCSSUnit_List:
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -4322,34 +4322,51 @@ nsStyleUserInterface::CalcDifference(con
nsStyleUIReset::nsStyleUIReset(const nsPresContext* aContext)
: mUserSelect(StyleUserSelect::Auto)
, mForceBrokenImageIcon(0)
, mIMEMode(NS_STYLE_IME_MODE_AUTO)
, mWindowDragging(StyleWindowDragging::Default)
, mWindowShadow(NS_STYLE_WINDOW_SHADOW_DEFAULT)
, mWindowOpacity(1.0)
+ , mSpecifiedWindowTransform(nullptr)
+ , mWindowTransformOrigin{ {0.5f, eStyleUnit_Percent}, // Transform is centered on origin
+ {0.5f, eStyleUnit_Percent} }
{
MOZ_COUNT_CTOR(nsStyleUIReset);
}
nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset& aSource)
: mUserSelect(aSource.mUserSelect)
, mForceBrokenImageIcon(aSource.mForceBrokenImageIcon)
, mIMEMode(aSource.mIMEMode)
, mWindowDragging(aSource.mWindowDragging)
, mWindowShadow(aSource.mWindowShadow)
, mWindowOpacity(aSource.mWindowOpacity)
+ , mSpecifiedWindowTransform(aSource.mSpecifiedWindowTransform)
+ , mWindowTransformOrigin{ aSource.mWindowTransformOrigin[0],
+ aSource.mWindowTransformOrigin[1] }
{
MOZ_COUNT_CTOR(nsStyleUIReset);
}
nsStyleUIReset::~nsStyleUIReset()
{
MOZ_COUNT_DTOR(nsStyleUIReset);
+
+ // See the nsStyleDisplay destructor for why we're doing this.
+ if (mSpecifiedWindowTransform && ServoStyleSet::IsInServoTraversal()) {
+ bool alwaysProxy =
+#ifdef DEBUG
+ true;
+#else
+ false;
+#endif
+ NS_ReleaseOnMainThread(mSpecifiedWindowTransform.forget(), alwaysProxy);
+ }
}
nsChangeHint
nsStyleUIReset::CalcDifference(const nsStyleUIReset& aNewData) const
{
nsChangeHint hint = nsChangeHint(0);
if (mForceBrokenImageIcon != aNewData.mForceBrokenImageIcon) {
@@ -4364,18 +4381,29 @@ nsStyleUIReset::CalcDifference(const nsS
if (mUserSelect != aNewData.mUserSelect) {
hint |= NS_STYLE_HINT_VISUAL;
}
if (mWindowDragging != aNewData.mWindowDragging) {
hint |= nsChangeHint_SchedulePaint;
}
- if (mWindowOpacity != aNewData.mWindowOpacity) {
+ if (mWindowOpacity != aNewData.mWindowOpacity ||
+ !mSpecifiedWindowTransform != !aNewData.mSpecifiedWindowTransform ||
+ (mSpecifiedWindowTransform &&
+ *mSpecifiedWindowTransform != *aNewData.mSpecifiedWindowTransform)) {
hint |= nsChangeHint_UpdateWidgetProperties;
+ } else {
+ for (uint8_t index = 0; index < 2; ++index) {
+ if (mWindowTransformOrigin[index] !=
+ aNewData.mWindowTransformOrigin[index]) {
+ hint |= nsChangeHint_UpdateWidgetProperties;
+ break;
+ }
+ }
}
if (!hint &&
mIMEMode != aNewData.mIMEMode) {
hint |= nsChangeHint_NeutralChange;
}
return hint;
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -3224,16 +3224,18 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
nsChangeHint CalcDifference(const nsStyleUIReset& aNewData) const;
mozilla::StyleUserSelect mUserSelect; // [reset](selection-style)
uint8_t mForceBrokenImageIcon; // [reset] (0 if not forcing, otherwise forcing)
uint8_t mIMEMode; // [reset]
mozilla::StyleWindowDragging mWindowDragging; // [reset]
uint8_t mWindowShadow; // [reset]
float mWindowOpacity; // [reset]
+ RefPtr<nsCSSValueSharedList> mSpecifiedWindowTransform; // [reset]
+ nsStyleCoord mWindowTransformOrigin[2]; // [reset] percent, coord, calc
};
struct nsCursorImage
{
bool mHaveHotspot;
float mHotspotX, mHotspotY;
RefPtr<nsStyleImageRequest> mImage;
--- a/layout/style/test/ListCSSProperties.cpp
+++ b/layout/style/test/ListCSSProperties.cpp
@@ -111,16 +111,18 @@ const char *gInaccessibleProperties[] =
"-moz-script-level", // parsed by UA sheets only
"-moz-script-size-multiplier",
"-moz-script-min-size",
"-moz-math-variant",
"-moz-math-display", // parsed by UA sheets only
"-moz-top-layer", // parsed by UA sheets only
"-moz-min-font-size-ratio", // parsed by UA sheets only
"-moz-window-opacity", // chrome-only internal properties
+ "-moz-window-transform", // chrome-only internal properties
+ "-moz-window-transform-origin", // chrome-only internal properties
"-moz-window-shadow" // chrome-only internal properties
};
inline int
is_inaccessible(const char* aPropName)
{
for (unsigned j = 0; j < MOZ_ARRAY_LENGTH(gInaccessibleProperties); ++j) {
if (strcmp(aPropName, gInaccessibleProperties[j]) == 0)
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -7909,16 +7909,112 @@ if (false) {
// domProp: "MozWindowOpacity",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "1", "17", "397.376", "3e1", "3e+1", "3e0", "3e+0", "3e-0" ],
other_values: [ "0", "0.4", "0.0000", "-3", "3e-1" ],
invalid_values: [ "0px", "1px", "20%", "default", "auto" ]
};
+ gCSSProperties["-moz-window-transform"] = {
+ // domProp: "MozWindowTransform",
+ inherited: false,
+ type: CSS_TYPE_LONGHAND,
+ prerequisites: { "width": "300px", "height": "50px" },
+ initial_values: [ "none" ],
+ other_values: [ "translatex(1px)", "translatex(4em)",
+ "translatex(-4px)", "translatex(3px)",
+ "translatex(0px) translatex(1px) translatex(2px) translatex(3px) translatex(4px)",
+ "translatey(4em)", "translate(3px)", "translate(10px, -3px)",
+ "rotate(45deg)", "rotate(45grad)", "rotate(45rad)",
+ "rotate(0.25turn)", "rotate(0)", "scalex(10)", "scaley(10)",
+ "scale(10)", "scale(10, 20)", "skewx(30deg)", "skewx(0)",
+ "skewy(0)", "skewx(30grad)", "skewx(30rad)", "skewx(0.08turn)",
+ "skewy(30deg)", "skewy(30grad)", "skewy(30rad)", "skewy(0.08turn)",
+ "rotate(45deg) scale(2, 1)", "skewx(45deg) skewx(-50grad)",
+ "translate(0, 0) scale(1, 1) skewx(0) skewy(0) matrix(1, 0, 0, 1, 0, 0)",
+ "translatex(50%)", "translatey(50%)", "translate(50%)",
+ "translate(3%, 5px)", "translate(5px, 3%)",
+ "matrix(1, 2, 3, 4, 5, 6)",
+ /* valid calc() values */
+ "translatex(calc(5px + 10%))",
+ "translatey(calc(0.25 * 5px + 10% / 3))",
+ "translate(calc(5px - 10% * 3))",
+ "translate(calc(5px - 3 * 10%), 50px)",
+ "translate(-50px, calc(5px - 10% * 3))",
+ "translatez(1px)", "translatez(4em)", "translatez(-4px)",
+ "translatez(0px)", "translatez(2px) translatez(5px)",
+ "translate3d(3px, 4px, 5px)", "translate3d(2em, 3px, 1em)",
+ "translatex(2px) translate3d(4px, 5px, 6px) translatey(1px)",
+ "scale3d(4, 4, 4)", "scale3d(-2, 3, -7)", "scalez(4)",
+ "scalez(-6)", "rotate3d(2, 3, 4, 45deg)",
+ "rotate3d(-3, 7, 0, 12rad)", "rotatex(15deg)", "rotatey(-12grad)",
+ "rotatez(72rad)", "rotatex(0.125turn)",
+ "perspective(0px)", "perspective(1000px)",
+ "matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)",
+ ],
+ invalid_values: ["1px", "#0000ff", "red", "auto",
+ "translatex(1)", "translatey(1)", "translate(2)",
+ "translate(-3, -4)",
+ "translatex(1px 1px)", "translatex(translatex(1px))",
+ "translatex(#0000ff)", "translatex(red)", "translatey()",
+ "matrix(1px, 2px, 3px, 4px, 5px, 6px)", "scale(150%)",
+ "skewx(red)", "matrix(1%, 0, 0, 0, 0px, 0px)",
+ "matrix(0, 1%, 2, 3, 4px,5px)", "matrix(0, 1, 2%, 3, 4px, 5px)",
+ "matrix(0, 1, 2, 3%, 4%, 5%)", "matrix(1, 2, 3, 4, 5px, 6%)",
+ "matrix(1, 2, 3, 4, 5%, 6px)", "matrix(1, 2, 3, 4, 5%, 6%)",
+ "matrix(1, 2, 3, 4, 5px, 6em)",
+ /* invalid calc() values */
+ "translatey(-moz-min(5px,10%))",
+ "translatex(-moz-max(5px,10%))",
+ "translate(10px, calc(min(5px,10%)))",
+ "translate(calc(max(5px,10%)), 10%)",
+ "matrix(1, 0, 0, 1, max(5px * 3), calc(10% - 3px))",
+ "perspective(-10px)", "matrix3d(dinosaur)",
+ "matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)",
+ "matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)",
+ "matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15%, 16)",
+ "matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16px)",
+ "rotatey(words)", "rotatex(7)", "translate3d(3px, 4px, 1px, 7px)",
+ "matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13px, 14em, 15px, 16)",
+ "matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 20%, 10%, 15, 16)"
+ ],
+ };
+
+ gCSSProperties["-moz-window-transform-origin"] = {
+ // domProp: "MozWindowTransformOrigin",
+ inherited: false,
+ type: CSS_TYPE_LONGHAND,
+ /* no subproperties */
+ prerequisites: { "width": "10px", "height": "10px", "display": "block"},
+ initial_values: [ "50% 50%", "center", "center center" ],
+ other_values: [ "25% 25%", "6px 5px", "20% 3em", "0 0", "0in 1in",
+ "top", "bottom","top left", "top right",
+ "top center", "center left", "center right",
+ "bottom left", "bottom right", "bottom center",
+ "20% center", "6px center", "13in bottom",
+ "left 50px", "right 13%", "center 40px",
+ "calc(20px)",
+ "calc(20px) 10px",
+ "10px calc(20px)",
+ "calc(20px) 25%",
+ "25% calc(20px)",
+ "calc(20px) calc(20px)",
+ "calc(20px + 1em) calc(20px / 2)",
+ "calc(20px + 50%) calc(50% - 10px)",
+ "calc(-20px) calc(-50%)",
+ "calc(-20%) calc(-50%)"
+ ],
+ invalid_values: ["red", "auto", "none", "0.5 0.5", "40px #0000ff",
+ "border", "center red", "right diagonal",
+ "#00ffff bottom", "0px calc(0px + rubbish)",
+ "0px 0px calc(0px + rubbish)", "6px 5px 5px",
+ "top center 10px"]
+ };
+
gCSSProperties["-moz-context-properties"] = {
//domProp: "MozContextProperties",
inherited: true,
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
other_values: [ "fill", "stroke", "fill, stroke", "fill, stroke, fill", "fill, foo", "foo" ],
invalid_values: [ "default", "fill, auto", "all, stroke", "none, fill", "fill, none", "fill, default", "2px" ]
};