--- a/layout/style/Declaration.cpp
+++ b/layout/style/Declaration.cpp
@@ -197,16 +197,196 @@ Declaration::GetValue(nsCSSProperty aPro
void
Declaration::GetAuthoredValue(nsCSSProperty aProperty, nsAString& aValue) const
{
GetValue(aProperty, aValue, nsCSSValue::eAuthorSpecified);
}
void
+Declaration::GetImageLayerValue(
+ nsCSSCompressedDataBlock *data,
+ nsAString& aValue,
+ nsCSSValue::Serialization aSerialization,
+ const nsCSSProperty aTable[]) const
+{
+ // We know from above that all subproperties were specified.
+ // However, we still can't represent that in the shorthand unless
+ // they're all lists of the same length. So if they're different
+ // lengths, we need to bail out.
+ // We also need to bail out if an item has background-clip and
+ // background-origin that are different and not the default
+ // values. (We omit them if they're both default.)
+
+ // Common CSS properties for both background & mask layer.
+ const nsCSSValueList *image =
+ data->ValueFor(aTable[nsStyleImageLayers::image])->GetListValue();
+ const nsCSSValuePairList *repeat =
+ data->ValueFor(aTable[nsStyleImageLayers::repeat])->GetPairListValue();
+ const nsCSSValueList *position =
+ data->ValueFor(aTable[nsStyleImageLayers::position])->GetListValue();
+ const nsCSSValueList *clip =
+ data->ValueFor(aTable[nsStyleImageLayers::clip])->GetListValue();
+ const nsCSSValueList *origin =
+ data->ValueFor(aTable[nsStyleImageLayers::origin])->GetListValue();
+ const nsCSSValuePairList *size =
+ data->ValueFor(aTable[nsStyleImageLayers::size])->GetPairListValue();
+
+ // Background layer property.
+ const nsCSSValueList *attachment =
+ (aTable[nsStyleImageLayers::attachment] == eCSSProperty_UNKNOWN)?
+ nullptr :
+ data->ValueFor(aTable[nsStyleImageLayers::attachment])->GetListValue();
+
+ // Mask layer properties.
+ const nsCSSValueList *composite =
+ (aTable[nsStyleImageLayers::composite] == eCSSProperty_UNKNOWN)?
+ nullptr :
+ data->ValueFor(aTable[nsStyleImageLayers::composite])->GetListValue();
+ const nsCSSValueList *mode =
+ (aTable[nsStyleImageLayers::maskMode] == eCSSProperty_UNKNOWN)?
+ nullptr :
+ data->ValueFor(aTable[nsStyleImageLayers::maskMode])->GetListValue();
+
+ for (;;) {
+ // Serialize background-color at the beginning of the last item.
+ if (!image->mNext) {
+ if (aTable[nsStyleImageLayers::color] != eCSSProperty_UNKNOWN) {
+ AppendValueToString(aTable[nsStyleImageLayers::color], aValue,
+ aSerialization);
+ aValue.Append(char16_t(' '));
+ }
+ }
+
+ image->mValue.AppendToString(aTable[nsStyleImageLayers::image], aValue,
+ aSerialization);
+
+ aValue.Append(char16_t(' '));
+ repeat->mXValue.AppendToString(aTable[nsStyleImageLayers::repeat], aValue,
+ aSerialization);
+ if (repeat->mYValue.GetUnit() != eCSSUnit_Null) {
+ repeat->mYValue.AppendToString(aTable[nsStyleImageLayers::repeat], aValue,
+ aSerialization);
+ }
+
+ if (attachment) {
+ aValue.Append(char16_t(' '));
+ attachment->mValue.AppendToString(aTable[nsStyleImageLayers::attachment],
+ aValue, aSerialization);
+ }
+
+ aValue.Append(char16_t(' '));
+ position->mValue.AppendToString(aTable[nsStyleImageLayers::position],
+ aValue, aSerialization);
+
+ if (size->mXValue.GetUnit() != eCSSUnit_Auto ||
+ size->mYValue.GetUnit() != eCSSUnit_Auto) {
+ aValue.Append(char16_t(' '));
+ aValue.Append(char16_t('/'));
+ aValue.Append(char16_t(' '));
+ size->mXValue.AppendToString(aTable[nsStyleImageLayers::size], aValue,
+ aSerialization);
+ aValue.Append(char16_t(' '));
+ size->mYValue.AppendToString(aTable[nsStyleImageLayers::size], aValue,
+ aSerialization);
+ }
+
+ MOZ_ASSERT(clip->mValue.GetUnit() == eCSSUnit_Enumerated &&
+ origin->mValue.GetUnit() == eCSSUnit_Enumerated,
+ "should not have inherit/initial within list");
+
+ if (clip->mValue.GetIntValue() != NS_STYLE_IMAGELAYER_CLIP_BORDER ||
+ origin->mValue.GetIntValue() != NS_STYLE_IMAGELAYER_ORIGIN_PADDING) {
+ MOZ_ASSERT(nsCSSProps::kKeywordTableTable[
+ aTable[nsStyleImageLayers::origin]] ==
+ nsCSSProps::kImageLayerOriginKTable);
+ MOZ_ASSERT(nsCSSProps::kKeywordTableTable[
+ aTable[nsStyleImageLayers::clip]] ==
+ nsCSSProps::kImageLayerOriginKTable);
+ static_assert(NS_STYLE_IMAGELAYER_CLIP_BORDER ==
+ NS_STYLE_IMAGELAYER_ORIGIN_BORDER &&
+ NS_STYLE_IMAGELAYER_CLIP_PADDING ==
+ NS_STYLE_IMAGELAYER_ORIGIN_PADDING &&
+ NS_STYLE_IMAGELAYER_CLIP_CONTENT ==
+ NS_STYLE_IMAGELAYER_ORIGIN_CONTENT,
+ "mask-clip and mask-origin style constants must agree");
+ aValue.Append(char16_t(' '));
+ origin->mValue.AppendToString(aTable[nsStyleImageLayers::origin], aValue,
+ aSerialization);
+
+ if (clip->mValue != origin->mValue) {
+ aValue.Append(char16_t(' '));
+ clip->mValue.AppendToString(aTable[nsStyleImageLayers::clip], aValue,
+ aSerialization);
+ }
+ }
+
+ if (composite) {
+ aValue.Append(char16_t(' '));
+ composite->mValue.AppendToString(aTable[nsStyleImageLayers::composite],
+ aValue, aSerialization);
+ }
+
+ if (mode) {
+ aValue.Append(char16_t(' '));
+ mode->mValue.AppendToString(aTable[nsStyleImageLayers::maskMode],
+ aValue, aSerialization);
+ }
+
+ image = image->mNext;
+ repeat = repeat->mNext;
+ position = position->mNext;
+ clip = clip->mNext;
+ origin = origin->mNext;
+ size = size->mNext;
+ attachment = attachment ? attachment->mNext : nullptr;
+ composite = composite ? composite->mNext : nullptr;
+ mode = mode ? mode->mNext : nullptr;
+
+ if (!image) {
+ // This layer is an background layer
+ if (aTable == nsStyleImageLayers::kBackgroundLayerTable) {
+ if (repeat || position || clip || origin || size || attachment) {
+ // Uneven length lists, so can't be serialized as shorthand.
+ aValue.Truncate();
+ return;
+ }
+ // This layer is an mask layer
+ } else {
+ if (repeat || position || clip || origin || size || composite || mode) {
+ // Uneven length lists, so can't be serialized as shorthand.
+ aValue.Truncate();
+ return;
+ }
+ }
+ break;
+ }
+
+ // This layer is an background layer
+ if (aTable == nsStyleImageLayers::kBackgroundLayerTable) {
+ if (!repeat || !position || !clip || !origin || !size || !attachment) {
+ // Uneven length lists, so can't be serialized as shorthand.
+ aValue.Truncate();
+ return;
+ }
+ // This layer is an mask layer
+ } else {
+ if (!repeat || !position || !clip || !origin || !size ||
+ !composite || !mode) {
+ // Uneven length lists, so can't be serialized as shorthand.
+ aValue.Truncate();
+ return;
+ }
+ }
+ aValue.Append(char16_t(','));
+ aValue.Append(char16_t(' '));
+ }
+}
+
+void
Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue,
nsCSSValue::Serialization aSerialization) const
{
aValue.Truncate(0);
// simple properties are easy.
if (!nsCSSProps::IsShorthand(aProperty)) {
AppendValueToString(aProperty, aValue, aSerialization);
@@ -311,20 +491,20 @@ Declaration::GetValue(nsCSSProperty aPro
} else {
// In all other cases, serialize to the empty string.
}
return;
}
nsCSSCompressedDataBlock *data = importantCount ? mImportantData : mData;
switch (aProperty) {
- case eCSSProperty_margin:
- case eCSSProperty_padding:
- case eCSSProperty_border_color:
- case eCSSProperty_border_style:
+ case eCSSProperty_margin:
+ case eCSSProperty_padding:
+ case eCSSProperty_border_color:
+ case eCSSProperty_border_style:
case eCSSProperty_border_width: {
const nsCSSProperty* subprops =
nsCSSProps::SubpropertyEntryFor(aProperty);
MOZ_ASSERT(nsCSSProps::GetStringValue(subprops[0]).Find("-top") !=
kNotFound, "first subprop must be top");
MOZ_ASSERT(nsCSSProps::GetStringValue(subprops[1]).Find("-right") !=
kNotFound, "second subprop must be right");
MOZ_ASSERT(nsCSSProps::GetStringValue(subprops[2]).Find("-bottom") !=
@@ -465,134 +645,23 @@ Declaration::GetValue(nsCSSProperty aPro
!(isMozUseTextColor ||
(aValue.Append(char16_t(' ')),
AppendValueToString(subprops[2], aValue, aSerialization)))) {
aValue.Truncate();
}
break;
}
case eCSSProperty_background: {
- // We know from above that all subproperties were specified.
- // However, we still can't represent that in the shorthand unless
- // they're all lists of the same length. So if they're different
- // lengths, we need to bail out.
- // We also need to bail out if an item has background-clip and
- // background-origin that are different and not the default
- // values. (We omit them if they're both default.)
- const nsCSSValueList *image =
- data->ValueFor(eCSSProperty_background_image)->
- GetListValue();
- const nsCSSValuePairList *repeat =
- data->ValueFor(eCSSProperty_background_repeat)->
- GetPairListValue();
- const nsCSSValueList *attachment =
- data->ValueFor(eCSSProperty_background_attachment)->
- GetListValue();
- const nsCSSValueList *position =
- data->ValueFor(eCSSProperty_background_position)->
- GetListValue();
- const nsCSSValueList *clip =
- data->ValueFor(eCSSProperty_background_clip)->
- GetListValue();
- const nsCSSValueList *origin =
- data->ValueFor(eCSSProperty_background_origin)->
- GetListValue();
- const nsCSSValuePairList *size =
- data->ValueFor(eCSSProperty_background_size)->
- GetPairListValue();
- for (;;) {
- // Serialize background-color at the beginning of the last item.
- if (!image->mNext) {
- AppendValueToString(eCSSProperty_background_color, aValue,
- aSerialization);
- aValue.Append(char16_t(' '));
- }
-
- image->mValue.AppendToString(eCSSProperty_background_image, aValue,
- aSerialization);
- aValue.Append(char16_t(' '));
- repeat->mXValue.AppendToString(eCSSProperty_background_repeat, aValue,
- aSerialization);
- if (repeat->mYValue.GetUnit() != eCSSUnit_Null) {
- repeat->mYValue.AppendToString(eCSSProperty_background_repeat, aValue,
- aSerialization);
- }
- aValue.Append(char16_t(' '));
- attachment->mValue.AppendToString(eCSSProperty_background_attachment,
- aValue, aSerialization);
- aValue.Append(char16_t(' '));
- position->mValue.AppendToString(eCSSProperty_background_position,
- aValue, aSerialization);
-
- if (size->mXValue.GetUnit() != eCSSUnit_Auto ||
- size->mYValue.GetUnit() != eCSSUnit_Auto) {
- aValue.Append(char16_t(' '));
- aValue.Append(char16_t('/'));
- aValue.Append(char16_t(' '));
- size->mXValue.AppendToString(eCSSProperty_background_size, aValue,
- aSerialization);
- aValue.Append(char16_t(' '));
- size->mYValue.AppendToString(eCSSProperty_background_size, aValue,
- aSerialization);
- }
-
- MOZ_ASSERT(clip->mValue.GetUnit() == eCSSUnit_Enumerated &&
- origin->mValue.GetUnit() == eCSSUnit_Enumerated,
- "should not have inherit/initial within list");
-
- if (clip->mValue.GetIntValue() != NS_STYLE_IMAGELAYER_CLIP_BORDER ||
- origin->mValue.GetIntValue() != NS_STYLE_IMAGELAYER_ORIGIN_PADDING) {
- MOZ_ASSERT(nsCSSProps::kKeywordTableTable[
- eCSSProperty_background_origin] ==
- nsCSSProps::kImageLayerOriginKTable);
- MOZ_ASSERT(nsCSSProps::kKeywordTableTable[
- eCSSProperty_background_clip] ==
- nsCSSProps::kImageLayerOriginKTable);
- static_assert(NS_STYLE_IMAGELAYER_CLIP_BORDER ==
- NS_STYLE_IMAGELAYER_ORIGIN_BORDER &&
- NS_STYLE_IMAGELAYER_CLIP_PADDING ==
- NS_STYLE_IMAGELAYER_ORIGIN_PADDING &&
- NS_STYLE_IMAGELAYER_CLIP_CONTENT ==
- NS_STYLE_IMAGELAYER_ORIGIN_CONTENT,
- "bg-clip and bg-origin style constants must agree");
- aValue.Append(char16_t(' '));
- origin->mValue.AppendToString(eCSSProperty_background_origin, aValue,
- aSerialization);
-
- if (clip->mValue != origin->mValue) {
- aValue.Append(char16_t(' '));
- clip->mValue.AppendToString(eCSSProperty_background_clip, aValue,
- aSerialization);
- }
- }
-
- image = image->mNext;
- repeat = repeat->mNext;
- attachment = attachment->mNext;
- position = position->mNext;
- clip = clip->mNext;
- origin = origin->mNext;
- size = size->mNext;
-
- if (!image) {
- if (repeat || attachment || position || clip || origin || size) {
- // Uneven length lists, so can't be serialized as shorthand.
- aValue.Truncate();
- return;
- }
- break;
- }
- if (!repeat || !attachment || !position || !clip || !origin || !size) {
- // Uneven length lists, so can't be serialized as shorthand.
- aValue.Truncate();
- return;
- }
- aValue.Append(char16_t(','));
- aValue.Append(char16_t(' '));
- }
+ GetImageLayerValue(data, aValue, aSerialization,
+ nsStyleImageLayers::kBackgroundLayerTable);
+ break;
+ }
+ case eCSSProperty_mask: {
+ GetImageLayerValue(data, aValue, aSerialization,
+ nsStyleImageLayers::kMaskLayerTable);
break;
}
case eCSSProperty_font: {
// systemFont might not be present; other values are guaranteed to be
// available based on the shorthand check at the beginning of the
// function, as long as the prop is enabled
const nsCSSValue *systemFont =
data->ValueFor(eCSSProperty__x_system_font);
--- a/layout/style/Declaration.h
+++ b/layout/style/Declaration.h
@@ -373,16 +373,21 @@ private:
void AppendPropertyAndValueToString(nsCSSProperty aProperty,
nsAutoString& aValue,
nsAString& aResult) const;
// helper for ToString that serializes a custom property declaration for
// a variable with the specified name
void AppendVariableAndValueToString(const nsAString& aName,
nsAString& aResult) const;
+ void GetImageLayerValue(nsCSSCompressedDataBlock *data,
+ nsAString& aValue,
+ nsCSSValue::Serialization aSerialization,
+ const nsCSSProperty aTable[]) const;
+
public:
/**
* Returns the property at the given index in the ordered list of
* declarations. For custom properties, eCSSPropertyExtra_variable
* is returned.
*/
nsCSSProperty GetPropertyAt(uint32_t aIndex) const {
uint32_t value = mOrder[aIndex];
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -833,43 +833,44 @@ protected:
};
PriorityParsingStatus ParsePriority();
#ifdef MOZ_XUL
bool ParseTreePseudoElement(nsAtomList **aPseudoElementArgs);
#endif
// Property specific parsing routines
- bool ParseBackground();
+ bool ParseImageLayers(const nsCSSProperty aTable[]);
struct ImageLayersShorthandParseState {
nsCSSValue& mColor;
nsCSSValueList* mImage;
nsCSSValuePairList* mRepeat;
- nsCSSValueList* mAttachment;
+ nsCSSValueList* mAttachment; // A property for background layer only
nsCSSValueList* mClip;
nsCSSValueList* mOrigin;
nsCSSValueList* mPosition;
nsCSSValuePairList* mSize;
- nsCSSValueList* mComposite;
- nsCSSValueList* mMode;
+ nsCSSValueList* mComposite; // A property for mask layer only
+ nsCSSValueList* mMode; // A property for mask layer only
ImageLayersShorthandParseState(
nsCSSValue& aColor, nsCSSValueList* aImage, nsCSSValuePairList* aRepeat,
nsCSSValueList* aAttachment, nsCSSValueList* aClip,
nsCSSValueList* aOrigin, nsCSSValueList* aPosition,
nsCSSValuePairList* aSize, nsCSSValueList* aComposite,
nsCSSValueList* aMode) :
mColor(aColor), mImage(aImage), mRepeat(aRepeat),
mAttachment(aAttachment), mClip(aClip), mOrigin(aOrigin),
mPosition(aPosition), mSize(aSize), mComposite(aComposite),
mMode(aMode) {};
};
bool IsFunctionTokenValidForImageLayerImage(const nsCSSToken& aToken) const;
- bool ParseBackgroundItem(ImageLayersShorthandParseState& aState);
+ bool ParseImageLayersItem(ImageLayersShorthandParseState& aState,
+ const nsCSSProperty aTable[]);
bool ParseValueList(nsCSSProperty aPropID); // a single value prop-id
bool ParseImageLayerRepeat(nsCSSProperty aPropID);
bool ParseImageLayerRepeatValues(nsCSSValuePair& aValue);
bool ParseImageLayerPosition(nsCSSProperty aPropID);
// ParseBoxPositionValues parses the CSS 2.1 background-position syntax,
// which is still used by some properties. See ParsePositionValue
@@ -11076,17 +11077,17 @@ CSSParserImpl::ParseProperty(nsCSSProper
return result;
}
bool
CSSParserImpl::ParsePropertyByFunction(nsCSSProperty aPropID)
{
switch (aPropID) { // handle shorthand or multiple properties
case eCSSProperty_background:
- return ParseBackground();
+ return ParseImageLayers(nsStyleImageLayers::kBackgroundLayerTable);
case eCSSProperty_background_repeat:
return ParseImageLayerRepeat(eCSSProperty_background_repeat);
case eCSSProperty_background_position:
return ParseImageLayerPosition(eCSSProperty_background_position);
case eCSSProperty_background_size:
return ParseImageLayerSize(eCSSProperty_background_size);
case eCSSProperty_border:
return ParseBorderSide(kBorderTopIDs, true);
@@ -11256,16 +11257,24 @@ CSSParserImpl::ParsePropertyByFunction(n
case eCSSProperty_marker:
return ParseMarker();
case eCSSProperty_paint_order:
return ParsePaintOrder();
case eCSSProperty_clip_path:
return ParseClipPath();
case eCSSProperty_scroll_snap_type:
return ParseScrollSnapType();
+ case eCSSProperty_mask:
+ return ParseImageLayers(nsStyleImageLayers::kMaskLayerTable);
+ case eCSSProperty_mask_repeat:
+ return ParseImageLayerRepeat(eCSSProperty_mask_repeat);
+ case eCSSProperty_mask_position:
+ return ParseImageLayerPosition(eCSSProperty_mask_position);
+ case eCSSProperty_mask_size:
+ return ParseImageLayerSize(eCSSProperty_mask_size);
case eCSSProperty_all:
return ParseAll();
default:
MOZ_ASSERT(false, "should not be called");
return false;
}
}
@@ -11509,88 +11518,115 @@ BoxPositionMaskToCSSValue(int32_t aMask,
val = NS_STYLE_IMAGELAYER_POSITION_BOTTOM;
}
}
return nsCSSValue(val, eCSSUnit_Enumerated);
}
bool
-CSSParserImpl::ParseBackground()
+CSSParserImpl::ParseImageLayers(const nsCSSProperty aTable[])
{
nsAutoParseCompoundProperty compound(this);
// background-color can only be set once, so it's not a list.
nsCSSValue color;
// Check first for inherit/initial/unset.
if (ParseSingleTokenVariant(color, VARIANT_INHERIT, nullptr)) {
// must be alone
for (const nsCSSProperty* subprops =
- nsCSSProps::SubpropertyEntryFor(eCSSProperty_background);
+ nsCSSProps::SubpropertyEntryFor(aTable[nsStyleImageLayers::shorthand]);
*subprops != eCSSProperty_UNKNOWN; ++subprops) {
AppendValue(*subprops, color);
}
return true;
}
- nsCSSValue image, repeat, attachment, clip, origin, position, size, composite, mode;
+ nsCSSValue image, repeat, attachment, clip, origin, position, size,
+ composite, maskMode;
ImageLayersShorthandParseState state(color, image.SetListValue(),
repeat.SetPairListValue(),
attachment.SetListValue(), clip.SetListValue(),
origin.SetListValue(), position.SetListValue(),
size.SetPairListValue(), composite.SetListValue(),
- mode.SetListValue());
+ maskMode.SetListValue());
for (;;) {
- if (!ParseBackgroundItem(state)) {
- return false;
- }
+ if (!ParseImageLayersItem(state, aTable)) {
+ return false;
+ }
+
// If we saw a color, this must be the last item.
if (color.GetUnit() != eCSSUnit_Null) {
- break;
- }
+ MOZ_ASSERT(aTable[nsStyleImageLayers::color] != eCSSProperty_UNKNOWN);
+ break;
+ }
+
// If there's a comma, expect another item.
if (!ExpectSymbol(',', true)) {
break;
}
+
+#define APPENDNEXT(propID_, propMember_, propType_) \
+ if (aTable[propID_] != eCSSProperty_UNKNOWN) { \
+ propMember_->mNext = new propType_; \
+ propMember_ = propMember_->mNext; \
+ }
// Chain another entry on all the lists.
- state.mImage->mNext = new nsCSSValueList;
- state.mImage = state.mImage->mNext;
- state.mRepeat->mNext = new nsCSSValuePairList;
- state.mRepeat = state.mRepeat->mNext;
- state.mAttachment->mNext = new nsCSSValueList;
- state.mAttachment = state.mAttachment->mNext;
- state.mClip->mNext = new nsCSSValueList;
- state.mClip = state.mClip->mNext;
- state.mOrigin->mNext = new nsCSSValueList;
- state.mOrigin = state.mOrigin->mNext;
- state.mPosition->mNext = new nsCSSValueList;
- state.mPosition = state.mPosition->mNext;
- state.mSize->mNext = new nsCSSValuePairList;
- state.mSize = state.mSize->mNext;
+ APPENDNEXT(nsStyleImageLayers::image, state.mImage,
+ nsCSSValueList);
+ APPENDNEXT(nsStyleImageLayers::repeat, state.mRepeat,
+ nsCSSValuePairList);
+ APPENDNEXT(nsStyleImageLayers::clip, state.mClip,
+ nsCSSValueList);
+ APPENDNEXT(nsStyleImageLayers::origin, state.mOrigin,
+ nsCSSValueList);
+ APPENDNEXT(nsStyleImageLayers::position, state.mPosition,
+ nsCSSValueList);
+ APPENDNEXT(nsStyleImageLayers::size, state.mSize,
+ nsCSSValuePairList);
+ APPENDNEXT(nsStyleImageLayers::attachment, state.mAttachment,
+ nsCSSValueList);
+ APPENDNEXT(nsStyleImageLayers::maskMode, state.mMode,
+ nsCSSValueList);
+ APPENDNEXT(nsStyleImageLayers::composite, state.mComposite,
+ nsCSSValueList);
+#undef APPENDNEXT
}
// If we get to this point without seeing a color, provide a default.
- if (color.GetUnit() == eCSSUnit_Null) {
- color.SetIntegerColorValue(NS_RGBA(0,0,0,0), eCSSUnit_RGBAColor);
- }
-
- AppendValue(eCSSProperty_background_image, image);
- AppendValue(eCSSProperty_background_repeat, repeat);
- AppendValue(eCSSProperty_background_attachment, attachment);
- AppendValue(eCSSProperty_background_clip, clip);
- AppendValue(eCSSProperty_background_origin, origin);
- AppendValue(eCSSProperty_background_position, position);
- AppendValue(eCSSProperty_background_size, size);
- AppendValue(eCSSProperty_background_color, color);
- return true;
-}
-
-// Helper for ParseBackgroundItem. Returns true if the passed-in nsCSSToken is
+ if (aTable[nsStyleImageLayers::color] != eCSSProperty_UNKNOWN) {
+ if (color.GetUnit() == eCSSUnit_Null) {
+ color.SetIntegerColorValue(NS_RGBA(0,0,0,0), eCSSUnit_RGBAColor);
+ }
+ }
+
+#define APPENDVALUE(propID_, propValue_) \
+ if (aTable[propID_] != eCSSProperty_UNKNOWN) { \
+ AppendValue(aTable[propID_], propValue_); \
+ }
+
+ APPENDVALUE(nsStyleImageLayers::image, image);
+ APPENDVALUE(nsStyleImageLayers::repeat, repeat);
+ APPENDVALUE(nsStyleImageLayers::clip, clip);
+ APPENDVALUE(nsStyleImageLayers::origin, origin);
+ APPENDVALUE(nsStyleImageLayers::position, position);
+ APPENDVALUE(nsStyleImageLayers::size, size);
+ APPENDVALUE(nsStyleImageLayers::color, color);
+ APPENDVALUE(nsStyleImageLayers::attachment, attachment);
+ APPENDVALUE(nsStyleImageLayers::maskMode, maskMode);
+ APPENDVALUE(nsStyleImageLayers::composite, composite);
+
+#undef APPENDVALUE
+
+ return true;
+}
+
+// Helper for ParseImageLayersItem. Returns true if the passed-in nsCSSToken is
// a function which is accepted for background-image.
bool
CSSParserImpl::IsFunctionTokenValidForImageLayerImage(
const nsCSSToken& aToken) const
{
MOZ_ASSERT(aToken.mType == eCSSToken_Function,
"Should only be called for function-typed tokens");
@@ -11611,18 +11647,19 @@ CSSParserImpl::IsFunctionTokenValidForIm
funcName.LowerCaseEqualsLiteral("-webkit-linear-gradient") ||
funcName.LowerCaseEqualsLiteral("-webkit-radial-gradient") ||
funcName.LowerCaseEqualsLiteral("-webkit-repeating-linear-gradient") ||
funcName.LowerCaseEqualsLiteral("-webkit-repeating-radial-gradient")));
}
// Parse one item of the background shorthand property.
bool
-CSSParserImpl::ParseBackgroundItem(CSSParserImpl::ImageLayersShorthandParseState& aState)
-
+CSSParserImpl::ParseImageLayersItem(
+ CSSParserImpl::ImageLayersShorthandParseState& aState,
+ const nsCSSProperty aTable[])
{
// Fill in the values that the shorthand will set if we don't find
// other values.
aState.mImage->mValue.SetNoneValue();
aState.mRepeat->mXValue.SetIntValue(NS_STYLE_IMAGELAYER_REPEAT_REPEAT,
eCSSUnit_Enumerated);
aState.mRepeat->mYValue.Reset();
aState.mAttachment->mValue.SetIntValue(NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL,
@@ -11632,23 +11669,28 @@ CSSParserImpl::ParseBackgroundItem(CSSPa
aState.mOrigin->mValue.SetIntValue(NS_STYLE_IMAGELAYER_ORIGIN_PADDING,
eCSSUnit_Enumerated);
RefPtr<nsCSSValue::Array> positionArr = nsCSSValue::Array::Create(4);
aState.mPosition->mValue.SetArrayValue(positionArr, eCSSUnit_Array);
positionArr->Item(1).SetPercentValue(0.0f);
positionArr->Item(3).SetPercentValue(0.0f);
aState.mSize->mXValue.SetAutoValue();
aState.mSize->mYValue.SetAutoValue();
-
+ aState.mComposite->mValue.SetIntValue(NS_STYLE_COMPOSITE_MODE_ADD,
+ eCSSUnit_Enumerated);
+ aState.mMode->mValue.SetIntValue(NS_STYLE_MASK_MODE_AUTO,
+ eCSSUnit_Enumerated);
bool haveColor = false,
haveImage = false,
haveRepeat = false,
haveAttach = false,
havePositionAndSize = false,
haveOrigin = false,
+ haveComposite = false,
+ haveMode = false,
haveSomething = false;
while (GetToken(true)) {
nsCSSTokenType tt = mToken.mType;
UngetToken(); // ...but we'll still cheat and use mToken
if (tt == eCSSToken_Symbol) {
// ExpectEndProperty only looks for symbols, and nothing else will
// show up as one.
@@ -11662,28 +11704,30 @@ CSSParserImpl::ParseBackgroundItem(CSSPa
keyword == eCSSKeyword_initial ||
keyword == eCSSKeyword_unset) {
return false;
} else if (keyword == eCSSKeyword_none) {
if (haveImage)
return false;
haveImage = true;
if (ParseSingleValueProperty(aState.mImage->mValue,
- eCSSProperty_background_image) !=
+ aTable[nsStyleImageLayers::image]) !=
CSSParseResult::Ok) {
NS_NOTREACHED("should be able to parse");
return false;
}
- } else if (nsCSSProps::FindKeyword(keyword,
+ } else if (aTable[nsStyleImageLayers::attachment] !=
+ eCSSProperty_UNKNOWN &&
+ nsCSSProps::FindKeyword(keyword,
nsCSSProps::kImageLayerAttachmentKTable, dummy)) {
if (haveAttach)
return false;
haveAttach = true;
if (ParseSingleValueProperty(aState.mAttachment->mValue,
- eCSSProperty_background_attachment) !=
+ aTable[nsStyleImageLayers::attachment]) !=
CSSParseResult::Ok) {
NS_NOTREACHED("should be able to parse");
return false;
}
} else if (nsCSSProps::FindKeyword(keyword,
nsCSSProps::kImageLayerRepeatKTable, dummy)) {
if (haveRepeat)
return false;
@@ -11712,70 +11756,98 @@ CSSParserImpl::ParseBackgroundItem(CSSPa
aState.mSize->mYValue = scratch.mYValue;
}
} else if (nsCSSProps::FindKeyword(keyword,
nsCSSProps::kImageLayerOriginKTable, dummy)) {
if (haveOrigin)
return false;
haveOrigin = true;
if (ParseSingleValueProperty(aState.mOrigin->mValue,
- eCSSProperty_background_origin) !=
+ aTable[nsStyleImageLayers::origin]) !=
CSSParseResult::Ok) {
NS_NOTREACHED("should be able to parse");
return false;
}
// The spec allows a second box value (for background-clip),
// immediately following the first one (for background-origin).
// 'background-clip' and 'background-origin' use the same keyword table
MOZ_ASSERT(nsCSSProps::kKeywordTableTable[
- eCSSProperty_background_origin] ==
+ aTable[nsStyleImageLayers::origin]] ==
nsCSSProps::kImageLayerOriginKTable);
MOZ_ASSERT(nsCSSProps::kKeywordTableTable[
- eCSSProperty_background_clip] ==
+ aTable[nsStyleImageLayers::clip]] ==
nsCSSProps::kImageLayerOriginKTable);
static_assert(NS_STYLE_IMAGELAYER_CLIP_BORDER ==
NS_STYLE_IMAGELAYER_ORIGIN_BORDER &&
NS_STYLE_IMAGELAYER_CLIP_PADDING ==
NS_STYLE_IMAGELAYER_ORIGIN_PADDING &&
NS_STYLE_IMAGELAYER_CLIP_CONTENT ==
NS_STYLE_IMAGELAYER_ORIGIN_CONTENT,
"bg-clip and bg-origin style constants must agree");
CSSParseResult result =
ParseSingleValueProperty(aState.mClip->mValue,
- eCSSProperty_background_clip);
+ aTable[nsStyleImageLayers::clip]);
MOZ_ASSERT(result != CSSParseResult::Error,
"how can failing to parse a single background-clip value "
"consume tokens?");
if (result == CSSParseResult::NotFound) {
// When exactly one <box> value is set, it is used for both
// 'background-origin' and 'background-clip'.
// See assertions above showing these values are compatible.
aState.mClip->mValue = aState.mOrigin->mValue;
}
- } else {
- if (haveColor)
+ } else if (aTable[nsStyleImageLayers::composite] != eCSSProperty_UNKNOWN &&
+ nsCSSProps::FindKeyword(keyword,
+ nsCSSProps::kImageLayerCompositeKTable, dummy)) {
+ if (haveComposite)
+ return false;
+ haveComposite = true;
+ if (ParseSingleValueProperty(aState.mComposite->mValue,
+ aTable[nsStyleImageLayers::composite]) !=
+ CSSParseResult::Ok) {
+ NS_NOTREACHED("should be able to parse");
+ return false;
+ }
+ } else if (aTable[nsStyleImageLayers::maskMode] != eCSSProperty_UNKNOWN &&
+ nsCSSProps::FindKeyword(keyword,
+ nsCSSProps::kImageLayerModeKTable, dummy)) {
+ if (haveMode)
return false;
- haveColor = true;
- if (ParseSingleValueProperty(aState.mColor,
- eCSSProperty_background_color) !=
+ haveMode = true;
+ if (ParseSingleValueProperty(aState.mMode->mValue,
+ aTable[nsStyleImageLayers::maskMode]) !=
CSSParseResult::Ok) {
+ NS_NOTREACHED("should be able to parse");
+ return false;
+ }
+ } else {
+ if (aTable[nsStyleImageLayers::color] != eCSSProperty_UNKNOWN) {
+ if (haveColor)
+ return false;
+ haveColor = true;
+ if (ParseSingleValueProperty(aState.mColor,
+ aTable[nsStyleImageLayers::color]) !=
+ CSSParseResult::Ok) {
+ return false;
+ }
+ } else {
return false;
}
}
} else if (tt == eCSSToken_URL ||
(tt == eCSSToken_Function &&
IsFunctionTokenValidForImageLayerImage(mToken))) {
if (haveImage)
return false;
haveImage = true;
if (ParseSingleValueProperty(aState.mImage->mValue,
- eCSSProperty_background_image) !=
+ aTable[nsStyleImageLayers::image]) !=
CSSParseResult::Ok) {
return false;
}
} else if (tt == eCSSToken_Dimension ||
tt == eCSSToken_Number ||
tt == eCSSToken_Percentage ||
(tt == eCSSToken_Function &&
(mToken.mIdent.LowerCaseEqualsLiteral("calc") ||
@@ -11790,35 +11862,42 @@ CSSParserImpl::ParseBackgroundItem(CSSPa
nsCSSValuePair scratch;
if (!ParseImageLayerSizeValues(scratch)) {
return false;
}
aState.mSize->mXValue = scratch.mXValue;
aState.mSize->mYValue = scratch.mYValue;
}
} else {
- if (haveColor)
- return false;
- haveColor = true;
- // Note: This parses 'inherit', 'initial' and 'unset', but
- // we've already checked for them, so it's ok.
- if (ParseSingleValueProperty(aState.mColor,
- eCSSProperty_background_color) !=
- CSSParseResult::Ok) {
- return false;
- }
- }
+ if (aTable[nsStyleImageLayers::color] != eCSSProperty_UNKNOWN) {
+ if (haveColor)
+ return false;
+ haveColor = true;
+ // Note: This parses 'inherit', 'initial' and 'unset', but
+ // we've already checked for them, so it's ok.
+ if (aTable[nsStyleImageLayers::color] != eCSSProperty_UNKNOWN) {
+ if (ParseSingleValueProperty(aState.mColor,
+ aTable[nsStyleImageLayers::color]) !=
+ CSSParseResult::Ok) {
+ return false;
+ }
+ }
+ } else {
+ return false;
+ }
+ }
+
haveSomething = true;
}
return haveSomething;
}
// This function is very similar to ParseScrollSnapCoordinate,
-// ParseImageLayerPosition, and ParseBackgroundSize.
+// ParseImageLayerPosition, and ParseImageLayersSize.
bool
CSSParserImpl::ParseValueList(nsCSSProperty aPropID)
{
// aPropID is a single value prop-id
nsCSSValue value;
// 'initial', 'inherit' and 'unset' stand alone, no list permitted.
if (!ParseSingleTokenVariant(value, VARIANT_INHERIT, nullptr)) {
nsCSSValueList* item = value.SetListValue();
@@ -11885,17 +11964,17 @@ CSSParserImpl::ParseImageLayerRepeatValu
}
return true;
}
return false;
}
// This function is very similar to ParseScrollSnapCoordinate,
-// ParseBackgroundList, and ParseBackgroundSize.
+// ParseImageLayers, ParseImageLayerSize.
bool
CSSParserImpl::ParseImageLayerPosition(nsCSSProperty aPropID)
{
nsCSSValue value;
// 'initial', 'inherit' and 'unset' stand alone, no list permitted.
if (!ParseSingleTokenVariant(value, VARIANT_INHERIT, nullptr)) {
nsCSSValue itemValue;
if (!ParsePositionValue(itemValue)) {
@@ -12203,17 +12282,17 @@ CSSParserImpl::ParsePositionValue(nsCSSV
yEdge = swapEdge;
yOffset = swapOffset;
}
return true;
}
// This function is very similar to ParseScrollSnapCoordinate,
-// ParseBackgroundList, and ParseBackgroundPosition.
+// ParseImageLayers, and ParseImageLayerPosition.
bool
CSSParserImpl::ParseImageLayerSize(nsCSSProperty aPropID)
{
nsCSSValue value;
// 'initial', 'inherit' and 'unset' stand alone, no list permitted.
if (!ParseSingleTokenVariant(value, VARIANT_INHERIT, nullptr)) {
nsCSSValuePair valuePair;
if (!ParseImageLayerSizeValues(valuePair)) {
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -2115,114 +2115,60 @@ nsComputedDOMStyle::SetValueToStyleImage
break;
default:
NS_NOTREACHED("unexpected image type");
break;
}
}
CSSValue*
-nsComputedDOMStyle::DoGetBackgroundImage()
-{
- const nsStyleBackground* bg = StyleBackground();
-
+nsComputedDOMStyle::DoGetImageLayerImage(const nsStyleImageLayers& aLayers)
+{
nsDOMCSSValueList *valueList = GetROCSSValueList(true);
- for (uint32_t i = 0, i_end = bg->mLayers.mImageCount; i < i_end; ++i) {
+ for (uint32_t i = 0, i_end = aLayers.mImageCount; i < i_end; ++i) {
nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
valueList->AppendCSSValue(val);
- const nsStyleImage& image = bg->mLayers.mLayers[i].mImage;
+ const nsStyleImage& image = aLayers.mLayers[i].mImage;
SetValueToStyleImage(image, val);
}
return valueList;
}
CSSValue*
-nsComputedDOMStyle::DoGetBackgroundBlendMode()
-{
- return GetBackgroundList(&nsStyleImageLayers::Layer::mBlendMode,
- &nsStyleImageLayers::mBlendModeCount,
- StyleBackground()->mLayers,
- nsCSSProps::kBlendModeKTable);
-}
-
-CSSValue*
-nsComputedDOMStyle::DoGetBackgroundOrigin()
-{
- return GetBackgroundList(&nsStyleImageLayers::Layer::mOrigin,
- &nsStyleImageLayers::mOriginCount,
- StyleBackground()->mLayers,
- nsCSSProps::kImageLayerOriginKTable);
-}
-
-void
-nsComputedDOMStyle::SetValueToPositionCoord(
- const nsStyleImageLayers::Position::PositionCoord& aCoord,
- nsROCSSPrimitiveValue* aValue)
-{
- if (!aCoord.mHasPercent) {
- MOZ_ASSERT(aCoord.mPercent == 0.0f,
- "Shouldn't have mPercent!");
- aValue->SetAppUnits(aCoord.mLength);
- } else if (aCoord.mLength == 0) {
- aValue->SetPercent(aCoord.mPercent);
- } else {
- SetValueToCalc(&aCoord, aValue);
- }
-}
-
-void
-nsComputedDOMStyle::SetValueToPosition(
- const nsStyleImageLayers::Position& aPosition,
- nsDOMCSSValueList* aValueList)
-{
- nsROCSSPrimitiveValue* valX = new nsROCSSPrimitiveValue;
- aValueList->AppendCSSValue(valX);
- SetValueToPositionCoord(aPosition.mXPosition, valX);
-
- nsROCSSPrimitiveValue* valY = new nsROCSSPrimitiveValue;
- aValueList->AppendCSSValue(valY);
- SetValueToPositionCoord(aPosition.mYPosition, valY);
-}
-
-CSSValue*
-nsComputedDOMStyle::DoGetBackgroundPosition()
-{
- const nsStyleBackground* bg = StyleBackground();
-
+nsComputedDOMStyle::DoGetImageLayerPosition(const nsStyleImageLayers& aLayers)
+{
nsDOMCSSValueList *valueList = GetROCSSValueList(true);
- for (uint32_t i = 0, i_end = bg->mLayers.mPositionCount; i < i_end; ++i) {
+ for (uint32_t i = 0, i_end = aLayers.mPositionCount; i < i_end; ++i) {
nsDOMCSSValueList *itemList = GetROCSSValueList(false);
valueList->AppendCSSValue(itemList);
- SetValueToPosition(bg->mLayers.mLayers[i].mPosition, itemList);
+ SetValueToPosition(aLayers.mLayers[i].mPosition, itemList);
}
return valueList;
}
CSSValue*
-nsComputedDOMStyle::DoGetBackgroundRepeat()
-{
- const nsStyleBackground* bg = StyleBackground();
-
+nsComputedDOMStyle::DoGetImageLayerRepeat(const nsStyleImageLayers& aLayers)
+{
nsDOMCSSValueList *valueList = GetROCSSValueList(true);
- for (uint32_t i = 0, i_end = bg->mLayers.mRepeatCount; i < i_end; ++i) {
+ for (uint32_t i = 0, i_end = aLayers.mRepeatCount; i < i_end; ++i) {
nsDOMCSSValueList *itemList = GetROCSSValueList(false);
valueList->AppendCSSValue(itemList);
nsROCSSPrimitiveValue *valX = new nsROCSSPrimitiveValue;
itemList->AppendCSSValue(valX);
- const uint8_t& xRepeat = bg->mLayers.mLayers[i].mRepeat.mXRepeat;
- const uint8_t& yRepeat = bg->mLayers.mLayers[i].mRepeat.mYRepeat;
+ const uint8_t& xRepeat = aLayers.mLayers[i].mRepeat.mXRepeat;
+ const uint8_t& yRepeat = aLayers.mLayers[i].mRepeat.mYRepeat;
bool hasContraction = true;
unsigned contraction;
if (xRepeat == yRepeat) {
contraction = xRepeat;
} else if (xRepeat == NS_STYLE_IMAGELAYER_REPEAT_REPEAT &&
yRepeat == NS_STYLE_IMAGELAYER_REPEAT_NO_REPEAT) {
contraction = NS_STYLE_IMAGELAYER_REPEAT_REPEAT_X;
@@ -2234,37 +2180,34 @@ nsComputedDOMStyle::DoGetBackgroundRepea
}
if (hasContraction) {
valX->SetIdent(nsCSSProps::ValueToKeywordEnum(contraction,
nsCSSProps::kImageLayerRepeatKTable));
} else {
nsROCSSPrimitiveValue *valY = new nsROCSSPrimitiveValue;
itemList->AppendCSSValue(valY);
-
+
valX->SetIdent(nsCSSProps::ValueToKeywordEnum(xRepeat,
nsCSSProps::kImageLayerRepeatKTable));
valY->SetIdent(nsCSSProps::ValueToKeywordEnum(yRepeat,
nsCSSProps::kImageLayerRepeatKTable));
}
}
return valueList;
}
-
-CSSValue*
-nsComputedDOMStyle::DoGetBackgroundSize()
-{
- const nsStyleBackground* bg = StyleBackground();
-
+CSSValue*
+nsComputedDOMStyle::DoGetImageLayerSize(const nsStyleImageLayers& aLayers)
+{
nsDOMCSSValueList *valueList = GetROCSSValueList(true);
- for (uint32_t i = 0, i_end = bg->mLayers.mSizeCount; i < i_end; ++i) {
- const nsStyleImageLayers::Size &size = bg->mLayers.mLayers[i].mSize;
+ for (uint32_t i = 0, i_end = aLayers.mSizeCount; i < i_end; ++i) {
+ const nsStyleImageLayers::Size &size = aLayers.mLayers[i].mSize;
switch (size.mWidthType) {
case nsStyleImageLayers::Size::eContain:
case nsStyleImageLayers::Size::eCover: {
MOZ_ASSERT(size.mWidthType == size.mHeightType,
"unsynced types");
nsCSSKeyword keyword = size.mWidthType == nsStyleImageLayers::Size::eContain
? eCSSKeyword_contain
@@ -2328,16 +2271,92 @@ nsComputedDOMStyle::DoGetBackgroundSize(
}
}
}
return valueList;
}
CSSValue*
+nsComputedDOMStyle::DoGetBackgroundImage()
+{
+ const nsStyleImageLayers& layers = StyleBackground()->mLayers;
+ return DoGetImageLayerImage(layers);
+}
+
+CSSValue*
+nsComputedDOMStyle::DoGetBackgroundBlendMode()
+{
+ return GetBackgroundList(&nsStyleImageLayers::Layer::mBlendMode,
+ &nsStyleImageLayers::mBlendModeCount,
+ StyleBackground()->mLayers,
+ nsCSSProps::kBlendModeKTable);
+}
+
+CSSValue*
+nsComputedDOMStyle::DoGetBackgroundOrigin()
+{
+ return GetBackgroundList(&nsStyleImageLayers::Layer::mOrigin,
+ &nsStyleImageLayers::mOriginCount,
+ StyleBackground()->mLayers,
+ nsCSSProps::kImageLayerOriginKTable);
+}
+
+void
+nsComputedDOMStyle::SetValueToPositionCoord(
+ const nsStyleImageLayers::Position::PositionCoord& aCoord,
+ nsROCSSPrimitiveValue* aValue)
+{
+ if (!aCoord.mHasPercent) {
+ MOZ_ASSERT(aCoord.mPercent == 0.0f,
+ "Shouldn't have mPercent!");
+ aValue->SetAppUnits(aCoord.mLength);
+ } else if (aCoord.mLength == 0) {
+ aValue->SetPercent(aCoord.mPercent);
+ } else {
+ SetValueToCalc(&aCoord, aValue);
+ }
+}
+
+void
+nsComputedDOMStyle::SetValueToPosition(
+ const nsStyleImageLayers::Position& aPosition,
+ nsDOMCSSValueList* aValueList)
+{
+ nsROCSSPrimitiveValue* valX = new nsROCSSPrimitiveValue;
+ aValueList->AppendCSSValue(valX);
+ SetValueToPositionCoord(aPosition.mXPosition, valX);
+
+ nsROCSSPrimitiveValue* valY = new nsROCSSPrimitiveValue;
+ aValueList->AppendCSSValue(valY);
+ SetValueToPositionCoord(aPosition.mYPosition, valY);
+}
+
+CSSValue*
+nsComputedDOMStyle::DoGetBackgroundPosition()
+{
+ const nsStyleImageLayers& layers = StyleBackground()->mLayers;
+ return DoGetImageLayerPosition(layers);
+}
+
+CSSValue*
+nsComputedDOMStyle::DoGetBackgroundRepeat()
+{
+ const nsStyleImageLayers& layers = StyleBackground()->mLayers;
+ return DoGetImageLayerRepeat(layers);
+}
+
+CSSValue*
+nsComputedDOMStyle::DoGetBackgroundSize()
+{
+ const nsStyleImageLayers& layers = StyleBackground()->mLayers;
+ return DoGetImageLayerSize(layers);
+}
+
+CSSValue*
nsComputedDOMStyle::DoGetGridTemplateAreas()
{
const css::GridTemplateAreasValue* areas =
StylePosition()->mGridTemplateAreas;
if (!areas) {
nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
val->SetIdent(eCSSKeyword_none);
return val;
@@ -5812,29 +5831,105 @@ nsComputedDOMStyle::DoGetFilter()
valueList->AppendCSSValue(value);
}
return valueList;
}
CSSValue*
nsComputedDOMStyle::DoGetMask()
{
+ const nsStyleSVGReset* svg = StyleSVGReset();
+ const nsStyleImageLayers::Layer& firstLayer = svg->mLayers.mLayers[0];
+
+ if (svg->mLayers.mImageCount > 1 ||
+ firstLayer.mClip != NS_STYLE_IMAGELAYER_CLIP_BORDER ||
+ firstLayer.mOrigin != NS_STYLE_IMAGELAYER_ORIGIN_PADDING ||
+ firstLayer.mAttachment != NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL ||
+ firstLayer.mBlendMode != NS_STYLE_BLEND_NORMAL ||
+ firstLayer.mComposite != NS_STYLE_COMPOSITE_MODE_ADD ||
+ firstLayer.mMaskMode != NS_STYLE_MASK_MODE_AUTO ||
+ !nsStyleImageLayers::Position::IsInitialValue(firstLayer.mPosition) ||
+ !nsStyleImageLayers::Repeat::IsInitialValue(firstLayer.mRepeat) ||
+ !nsStyleImageLayers::Size::IsInitialValue(firstLayer.mSize)){
+ return nullptr;
+ }
+
nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
- const nsStyleSVGReset* svg = StyleSVGReset();
-
if (svg->mMask)
val->SetURI(svg->mMask);
else
val->SetIdent(eCSSKeyword_none);
return val;
}
CSSValue*
+nsComputedDOMStyle::DoGetMaskClip()
+{
+ return GetBackgroundList(&nsStyleImageLayers::Layer::mClip,
+ &nsStyleImageLayers::mClipCount,
+ StyleSVGReset()->mLayers,
+ nsCSSProps::kImageLayerOriginKTable);
+}
+
+CSSValue*
+nsComputedDOMStyle::DoGetMaskComposite()
+{
+ return GetBackgroundList(&nsStyleImageLayers::Layer::mComposite,
+ &nsStyleImageLayers::mCompositeCount,
+ StyleSVGReset()->mLayers,
+ nsCSSProps::kImageLayerCompositeKTable);
+}
+
+CSSValue*
+nsComputedDOMStyle::DoGetMaskImage()
+{
+ const nsStyleImageLayers& layers = StyleSVGReset()->mLayers;
+ return DoGetImageLayerImage(layers);
+}
+
+CSSValue*
+nsComputedDOMStyle::DoGetMaskMode()
+{
+ return GetBackgroundList(&nsStyleImageLayers::Layer::mMaskMode,
+ &nsStyleImageLayers::mMaskModeCount,
+ StyleSVGReset()->mLayers,
+ nsCSSProps::kImageLayerModeKTable);
+}
+
+CSSValue*
+nsComputedDOMStyle::DoGetMaskOrigin()
+{
+ return GetBackgroundList(&nsStyleImageLayers::Layer::mOrigin,
+ &nsStyleImageLayers::mOriginCount,
+ StyleSVGReset()->mLayers,
+ nsCSSProps::kImageLayerOriginKTable);
+}
+
+CSSValue*
+nsComputedDOMStyle::DoGetMaskPosition()
+{
+ const nsStyleImageLayers& layers = StyleSVGReset()->mLayers;
+ return DoGetImageLayerPosition(layers);
+}
+CSSValue*
+nsComputedDOMStyle::DoGetMaskRepeat()
+{
+ const nsStyleImageLayers& layers = StyleSVGReset()->mLayers;
+ return DoGetImageLayerRepeat(layers);
+}
+
+CSSValue*
+nsComputedDOMStyle::DoGetMaskSize()
+{
+ const nsStyleImageLayers& layers = StyleSVGReset()->mLayers;
+ return DoGetImageLayerSize(layers);
+}
+CSSValue*
nsComputedDOMStyle::DoGetMaskType()
{
nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
val->SetIdent(
nsCSSProps::ValueToKeywordEnum(StyleSVGReset()->mMaskType,
nsCSSProps::kMaskTypeKTable));
return val;
}
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -265,27 +265,44 @@ private:
mozilla::dom::CSSValue* DoGetGridTemplateRows();
mozilla::dom::CSSValue* DoGetGridColumnStart();
mozilla::dom::CSSValue* DoGetGridColumnEnd();
mozilla::dom::CSSValue* DoGetGridRowStart();
mozilla::dom::CSSValue* DoGetGridRowEnd();
mozilla::dom::CSSValue* DoGetGridColumnGap();
mozilla::dom::CSSValue* DoGetGridRowGap();
+ /* StyleImageLayer properties */
+ mozilla::dom::CSSValue* DoGetImageLayerImage(const nsStyleImageLayers& aLayers);
+ mozilla::dom::CSSValue* DoGetImageLayerPosition(const nsStyleImageLayers& aLayers);
+ mozilla::dom::CSSValue* DoGetImageLayerRepeat(const nsStyleImageLayers& aLayers);
+ mozilla::dom::CSSValue* DoGetImageLayerSize(const nsStyleImageLayers& aLayers);
+
/* Background properties */
mozilla::dom::CSSValue* DoGetBackgroundAttachment();
mozilla::dom::CSSValue* DoGetBackgroundColor();
mozilla::dom::CSSValue* DoGetBackgroundImage();
mozilla::dom::CSSValue* DoGetBackgroundPosition();
mozilla::dom::CSSValue* DoGetBackgroundRepeat();
mozilla::dom::CSSValue* DoGetBackgroundClip();
mozilla::dom::CSSValue* DoGetBackgroundBlendMode();
mozilla::dom::CSSValue* DoGetBackgroundOrigin();
mozilla::dom::CSSValue* DoGetBackgroundSize();
+ /* Mask properties */
+ mozilla::dom::CSSValue* DoGetMask();
+ mozilla::dom::CSSValue* DoGetMaskImage();
+ mozilla::dom::CSSValue* DoGetMaskPosition();
+ mozilla::dom::CSSValue* DoGetMaskRepeat();
+ mozilla::dom::CSSValue* DoGetMaskClip();
+ mozilla::dom::CSSValue* DoGetMaskOrigin();
+ mozilla::dom::CSSValue* DoGetMaskSize();
+ mozilla::dom::CSSValue* DoGetMaskMode();
+ mozilla::dom::CSSValue* DoGetMaskComposite();
+
/* Padding properties */
mozilla::dom::CSSValue* DoGetPaddingTop();
mozilla::dom::CSSValue* DoGetPaddingBottom();
mozilla::dom::CSSValue* DoGetPaddingLeft();
mozilla::dom::CSSValue* DoGetPaddingRight();
/* Table Properties */
mozilla::dom::CSSValue* DoGetBorderCollapse();
@@ -524,17 +541,16 @@ private:
mozilla::dom::CSSValue* DoGetTextRendering();
mozilla::dom::CSSValue* DoGetFloodColor();
mozilla::dom::CSSValue* DoGetLightingColor();
mozilla::dom::CSSValue* DoGetStopColor();
mozilla::dom::CSSValue* DoGetClipPath();
mozilla::dom::CSSValue* DoGetFilter();
- mozilla::dom::CSSValue* DoGetMask();
mozilla::dom::CSSValue* DoGetMaskType();
mozilla::dom::CSSValue* DoGetPaintOrder();
/* Custom properties */
mozilla::dom::CSSValue* DoGetCustomProperty(const nsAString& aPropertyName);
nsDOMCSSValueList* GetROCSSValueList(bool aCommaDelimited);
--- a/layout/style/nsComputedDOMStylePropertyList.h
+++ b/layout/style/nsComputedDOMStylePropertyList.h
@@ -313,16 +313,24 @@ COMPUTED_STYLE_PROP(filter,
COMPUTED_STYLE_PROP(flood_color, FloodColor)
COMPUTED_STYLE_PROP(flood_opacity, FloodOpacity)
COMPUTED_STYLE_PROP(image_rendering, ImageRendering)
COMPUTED_STYLE_PROP(lighting_color, LightingColor)
COMPUTED_STYLE_PROP(marker_end, MarkerEnd)
COMPUTED_STYLE_PROP(marker_mid, MarkerMid)
COMPUTED_STYLE_PROP(marker_start, MarkerStart)
COMPUTED_STYLE_PROP(mask, Mask)
+COMPUTED_STYLE_PROP(mask_clip, MaskClip)
+COMPUTED_STYLE_PROP(mask_composite, MaskComposite)
+COMPUTED_STYLE_PROP(mask_image, MaskImage)
+COMPUTED_STYLE_PROP(mask_mode, MaskMode)
+COMPUTED_STYLE_PROP(mask_origin, MaskOrigin)
+COMPUTED_STYLE_PROP(mask_position, MaskPosition)
+COMPUTED_STYLE_PROP(mask_repeat, MaskRepeat)
+COMPUTED_STYLE_PROP(mask_size, MaskSize)
COMPUTED_STYLE_PROP(mask_type, MaskType)
COMPUTED_STYLE_PROP(paint_order, PaintOrder)
COMPUTED_STYLE_PROP(shape_rendering, ShapeRendering)
COMPUTED_STYLE_PROP(stop_color, StopColor)
COMPUTED_STYLE_PROP(stop_opacity, StopOpacity)
COMPUTED_STYLE_PROP(stroke, Stroke)
COMPUTED_STYLE_PROP(stroke_dasharray, StrokeDasharray)
COMPUTED_STYLE_PROP(stroke_dashoffset, StrokeDashoffset)
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -6800,103 +6800,122 @@ nsRuleNode::ComputeBackgroundData(void*
uint32_t maxItemCount = 1;
bool rebuild = false;
// background-image: url (stored as image), none, inherit [list]
nsStyleImage initialImage;
SetImageLayerList(aContext, *aRuleData->ValueForBackgroundImage(),
bg->mLayers.mLayers,
- parentBG->mLayers.mLayers, &nsStyleImageLayers::Layer::mImage,
- initialImage, parentBG->mLayers.mImageCount, bg->mLayers.mImageCount,
+ parentBG->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mImage,
+ initialImage, parentBG->mLayers.mImageCount,
+ bg->mLayers.mImageCount,
maxItemCount, rebuild, conditions);
// background-repeat: enum, inherit, initial [pair list]
nsStyleImageLayers::Repeat initialRepeat;
initialRepeat.SetInitialValues();
SetImageLayerPairList(aContext, *aRuleData->ValueForBackgroundRepeat(),
bg->mLayers.mLayers,
- parentBG->mLayers.mLayers, &nsStyleImageLayers::Layer::mRepeat,
+ parentBG->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mRepeat,
initialRepeat, parentBG->mLayers.mRepeatCount,
bg->mLayers.mRepeatCount, maxItemCount, rebuild,
conditions);
// background-attachment: enum, inherit, initial [list]
SetImageLayerList(aContext, *aRuleData->ValueForBackgroundAttachment(),
bg->mLayers.mLayers, parentBG->mLayers.mLayers,
&nsStyleImageLayers::Layer::mAttachment,
uint8_t(NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL),
parentBG->mLayers.mAttachmentCount,
bg->mLayers.mAttachmentCount, maxItemCount, rebuild,
conditions);
// background-clip: enum, inherit, initial [list]
SetImageLayerList(aContext, *aRuleData->ValueForBackgroundClip(),
bg->mLayers.mLayers,
- parentBG->mLayers.mLayers, &nsStyleImageLayers::Layer::mClip,
- uint8_t(NS_STYLE_IMAGELAYER_CLIP_BORDER), parentBG->mLayers.mClipCount,
+ parentBG->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mClip,
+ uint8_t(NS_STYLE_IMAGELAYER_CLIP_BORDER),
+ parentBG->mLayers.mClipCount,
bg->mLayers.mClipCount, maxItemCount, rebuild, conditions);
// background-blend-mode: enum, inherit, initial [list]
SetImageLayerList(aContext, *aRuleData->ValueForBackgroundBlendMode(),
bg->mLayers.mLayers,
- parentBG->mLayers.mLayers, &nsStyleImageLayers::Layer::mBlendMode,
- uint8_t(NS_STYLE_BLEND_NORMAL), parentBG->mLayers.mBlendModeCount,
+ parentBG->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mBlendMode,
+ uint8_t(NS_STYLE_BLEND_NORMAL),
+ parentBG->mLayers.mBlendModeCount,
bg->mLayers.mBlendModeCount, maxItemCount, rebuild,
conditions);
// background-origin: enum, inherit, initial [list]
SetImageLayerList(aContext, *aRuleData->ValueForBackgroundOrigin(),
bg->mLayers.mLayers,
- parentBG->mLayers.mLayers, &nsStyleImageLayers::Layer::mOrigin,
- uint8_t(NS_STYLE_IMAGELAYER_ORIGIN_PADDING), parentBG->mLayers.mOriginCount,
+ parentBG->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mOrigin,
+ uint8_t(NS_STYLE_IMAGELAYER_ORIGIN_PADDING),
+ parentBG->mLayers.mOriginCount,
bg->mLayers.mOriginCount, maxItemCount, rebuild,
conditions);
// background-position: enum, length, percent (flags), inherit [pair list]
nsStyleImageLayers::Position initialPosition;
initialPosition.SetInitialPercentValues(0.0f);
SetImageLayerList(aContext, *aRuleData->ValueForBackgroundPosition(),
bg->mLayers.mLayers,
- parentBG->mLayers.mLayers, &nsStyleImageLayers::Layer::mPosition,
+ parentBG->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mPosition,
initialPosition, parentBG->mLayers.mPositionCount,
bg->mLayers.mPositionCount, maxItemCount, rebuild,
conditions);
// background-size: enum, length, auto, inherit, initial [pair list]
nsStyleImageLayers::Size initialSize;
initialSize.SetInitialValues();
SetImageLayerPairList(aContext, *aRuleData->ValueForBackgroundSize(),
bg->mLayers.mLayers,
- parentBG->mLayers.mLayers, &nsStyleImageLayers::Layer::mSize,
+ parentBG->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mSize,
initialSize, parentBG->mLayers.mSizeCount,
bg->mLayers.mSizeCount, maxItemCount, rebuild,
conditions);
if (rebuild) {
// Delete any extra items. We need to keep layers in which any
// property was specified.
bg->mLayers.mLayers.TruncateLength(maxItemCount);
uint32_t fillCount = bg->mLayers.mImageCount;
- FillBackgroundList(bg->mLayers.mLayers, &nsStyleImageLayers::Layer::mImage,
+ FillBackgroundList(bg->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mImage,
bg->mLayers.mImageCount, fillCount);
- FillBackgroundList(bg->mLayers.mLayers, &nsStyleImageLayers::Layer::mRepeat,
+ FillBackgroundList(bg->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mRepeat,
bg->mLayers.mRepeatCount, fillCount);
- FillBackgroundList(bg->mLayers.mLayers, &nsStyleImageLayers::Layer::mAttachment,
+ FillBackgroundList(bg->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mAttachment,
bg->mLayers.mAttachmentCount, fillCount);
- FillBackgroundList(bg->mLayers.mLayers, &nsStyleImageLayers::Layer::mClip,
+ FillBackgroundList(bg->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mClip,
bg->mLayers.mClipCount, fillCount);
- FillBackgroundList(bg->mLayers.mLayers, &nsStyleImageLayers::Layer::mBlendMode,
+ FillBackgroundList(bg->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mBlendMode,
bg->mLayers.mBlendModeCount, fillCount);
- FillBackgroundList(bg->mLayers.mLayers, &nsStyleImageLayers::Layer::mOrigin,
+ FillBackgroundList(bg->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mOrigin,
bg->mLayers.mOriginCount, fillCount);
- FillBackgroundList(bg->mLayers.mLayers, &nsStyleImageLayers::Layer::mPosition,
+ FillBackgroundList(bg->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mPosition,
bg->mLayers.mPositionCount, fillCount);
- FillBackgroundList(bg->mLayers.mLayers, &nsStyleImageLayers::Layer::mSize,
+ FillBackgroundList(bg->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mSize,
bg->mLayers.mSizeCount, fillCount);
}
// Now that the dust has settled, register the images with the document
bg->mLayers.TrackImages(aContext->PresContext());
COMPUTE_END_RESET(Background, bg)
}
@@ -9666,16 +9685,135 @@ nsRuleNode::ComputeSVGResetData(void* aS
// mask-type: enum, inherit, initial
SetDiscrete(*aRuleData->ValueForMaskType(),
svgReset->mMaskType,
conditions,
SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL,
parentSVGReset->mMaskType,
NS_STYLE_MASK_TYPE_LUMINANCE, 0, 0, 0, 0);
+ uint32_t maxItemCount = 1;
+ bool rebuild = false;
+
+ // mask-image: none | <url> | <image-list> | <element-reference> | <gradient>
+ nsStyleImage initialImage;
+ SetImageLayerList(aContext, *aRuleData->ValueForMaskImage(),
+ svgReset->mLayers.mLayers,
+ parentSVGReset->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mImage,
+ initialImage, parentSVGReset->mLayers.mImageCount,
+ svgReset->mLayers.mImageCount,
+ maxItemCount, rebuild, conditions);
+
+ // mask-repeat: enum, inherit, initial [pair list]
+ nsStyleImageLayers::Repeat initialRepeat;
+ initialRepeat.SetInitialValues();
+ SetImageLayerPairList(aContext, *aRuleData->ValueForMaskRepeat(),
+ svgReset->mLayers.mLayers,
+ parentSVGReset->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mRepeat,
+ initialRepeat, parentSVGReset->mLayers.mRepeatCount,
+ svgReset->mLayers.mRepeatCount, maxItemCount, rebuild,
+ conditions);
+
+ // mask-clip: enum, inherit, initial [list]
+ SetImageLayerList(aContext, *aRuleData->ValueForMaskClip(),
+ svgReset->mLayers.mLayers,
+ parentSVGReset->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mClip,
+ uint8_t(NS_STYLE_IMAGELAYER_CLIP_BORDER),
+ parentSVGReset->mLayers.mClipCount,
+ svgReset->mLayers.mClipCount, maxItemCount, rebuild,
+ conditions);
+
+ // mask-origin: enum, inherit, initial [list]
+ SetImageLayerList(aContext, *aRuleData->ValueForMaskOrigin(),
+ svgReset->mLayers.mLayers,
+ parentSVGReset->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mOrigin,
+ uint8_t(NS_STYLE_IMAGELAYER_ORIGIN_PADDING),
+ parentSVGReset->mLayers.mOriginCount,
+ svgReset->mLayers.mOriginCount, maxItemCount, rebuild,
+ conditions);
+
+ // mask-position: enum, length, percent (flags), inherit [pair list]
+ nsStyleImageLayers::Position initialPosition;
+ initialPosition.SetInitialPercentValues(0.0f);
+ SetImageLayerList(aContext, *aRuleData->ValueForMaskPosition(),
+ svgReset->mLayers.mLayers,
+ parentSVGReset->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mPosition,
+ initialPosition, parentSVGReset->mLayers.mPositionCount,
+ svgReset->mLayers.mPositionCount, maxItemCount, rebuild,
+ conditions);
+
+ // mask-size: enum, length, auto, inherit, initial [pair list]
+ nsStyleImageLayers::Size initialSize;
+ initialSize.SetInitialValues();
+ SetImageLayerPairList(aContext, *aRuleData->ValueForMaskSize(),
+ svgReset->mLayers.mLayers,
+ parentSVGReset->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mSize,
+ initialSize, parentSVGReset->mLayers.mSizeCount,
+ svgReset->mLayers.mSizeCount, maxItemCount, rebuild,
+ conditions);
+
+ // mask-mode: enum, inherit, initial [list]
+ SetImageLayerList(aContext, *aRuleData->ValueForMaskMode(),
+ svgReset->mLayers.mLayers,
+ parentSVGReset->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mMaskMode,
+ uint8_t(NS_STYLE_MASK_MODE_AUTO),
+ parentSVGReset->mLayers.mMaskModeCount,
+ svgReset->mLayers.mMaskModeCount, maxItemCount, rebuild, conditions);
+
+ // mask-composite: enum, inherit, initial [list]
+ SetImageLayerList(aContext, *aRuleData->ValueForMaskComposite(),
+ svgReset->mLayers.mLayers,
+ parentSVGReset->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mComposite,
+ uint8_t(NS_STYLE_COMPOSITE_MODE_ADD),
+ parentSVGReset->mLayers.mCompositeCount,
+ svgReset->mLayers.mCompositeCount, maxItemCount, rebuild, conditions);
+
+ if (rebuild) {
+ // Delete any extra items. We need to keep layers in which any
+ // property was specified.
+ svgReset->mLayers.mLayers.TruncateLength(maxItemCount);
+
+ uint32_t fillCount = svgReset->mLayers.mImageCount;
+
+ FillBackgroundList(svgReset->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mImage,
+ svgReset->mLayers.mImageCount, fillCount);
+ FillBackgroundList(svgReset->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mRepeat,
+ svgReset->mLayers.mRepeatCount, fillCount);
+ FillBackgroundList(svgReset->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mClip,
+ svgReset->mLayers.mClipCount, fillCount);
+ FillBackgroundList(svgReset->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mOrigin,
+ svgReset->mLayers.mOriginCount, fillCount);
+ FillBackgroundList(svgReset->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mPosition,
+ svgReset->mLayers.mPositionCount, fillCount);
+ FillBackgroundList(svgReset->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mSize,
+ svgReset->mLayers.mSizeCount, fillCount);
+ FillBackgroundList(svgReset->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mMaskMode,
+ svgReset->mLayers.mMaskModeCount, fillCount);
+ FillBackgroundList(svgReset->mLayers.mLayers,
+ &nsStyleImageLayers::Layer::mComposite,
+ svgReset->mLayers.mCompositeCount, fillCount);
+ }
+
+ svgReset->mLayers.TrackImages(aContext->PresContext());
+
COMPUTE_END_RESET(SVGReset, svgReset)
}
const void*
nsRuleNode::ComputeVariablesData(void* aStartStruct,
const nsRuleData* aRuleData,
nsStyleContext* aContext,
nsRuleNode* aHighestNode,