mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Bug 1072894 - Implement polygon() parsing for clip-path. r=heycam
This commit is contained in:
parent
b86ae28eb1
commit
a028173cff
@ -56,6 +56,7 @@ PECounterExtendsNotIdent=Expected identifier for extends system but found '%1$S'
|
||||
PECounterASWeight=Each weight in the additive-symbols descriptor must be smaller than the previous weight.
|
||||
PEClassSelEOF=class name
|
||||
PEClassSelNotIdent=Expected identifier for class selector but found '%1$S'.
|
||||
PECoordinatePair=Expected coordinate pair but found '%1$S'.
|
||||
PETypeSelEOF=element type
|
||||
PETypeSelNotType=Expected element name or '*' but found '%1$S'.
|
||||
PEUnknownNamespacePrefix=Unknown namespace prefix '%1$S'.
|
||||
@ -106,6 +107,7 @@ PEColorLightnessEOF=lightness
|
||||
PEColorOpacityEOF=opacity in color value
|
||||
PEExpectedNumber=Expected a number but found '%1$S'.
|
||||
PEExpectedCloseParen=Expected ')' but found '%1$S'.
|
||||
PEClipPathEOF=<basic-shape> or reference box
|
||||
PEDeclEndEOF=';' or '}' to end declaration
|
||||
PEParseDeclarationNoColon=Expected ':' but found '%1$S'.
|
||||
PEParseDeclarationDeclExpected=Expected declaration but found '%1$S'.
|
||||
|
@ -607,6 +607,22 @@ nsLayoutUtils::CSSFiltersEnabled()
|
||||
return sCSSFiltersEnabled;
|
||||
}
|
||||
|
||||
bool
|
||||
nsLayoutUtils::CSSClipPathShapesEnabled()
|
||||
{
|
||||
static bool sCSSClipPathShapesEnabled;
|
||||
static bool sCSSClipPathShapesPrefCached = false;
|
||||
|
||||
if (!sCSSClipPathShapesPrefCached) {
|
||||
sCSSClipPathShapesPrefCached = true;
|
||||
Preferences::AddBoolVarCache(&sCSSClipPathShapesEnabled,
|
||||
"layout.css.clip-path-shapes.enabled",
|
||||
false);
|
||||
}
|
||||
|
||||
return sCSSClipPathShapesEnabled;
|
||||
}
|
||||
|
||||
bool
|
||||
nsLayoutUtils::UnsetValueEnabled()
|
||||
{
|
||||
|
@ -1929,6 +1929,11 @@ public:
|
||||
*/
|
||||
static bool CSSFiltersEnabled();
|
||||
|
||||
/**
|
||||
* Checks if we should enable parsing for CSS clip-path basic shapes.
|
||||
*/
|
||||
static bool CSSClipPathShapesEnabled();
|
||||
|
||||
/**
|
||||
* Checks whether support for the CSS-wide "unset" value is enabled.
|
||||
*/
|
||||
|
@ -257,6 +257,7 @@ CSS_KEY(fantasy, fantasy)
|
||||
CSS_KEY(farthest-side, farthest_side)
|
||||
CSS_KEY(farthest-corner, farthest_corner)
|
||||
CSS_KEY(fill, fill)
|
||||
CSS_KEY(fill-box, fill_box)
|
||||
CSS_KEY(fixed, fixed)
|
||||
CSS_KEY(flat, flat)
|
||||
CSS_KEY(flex, flex)
|
||||
@ -404,6 +405,7 @@ CSS_KEY(perspective, perspective)
|
||||
CSS_KEY(petite-caps, petite_caps)
|
||||
CSS_KEY(physical, physical)
|
||||
CSS_KEY(pointer, pointer)
|
||||
CSS_KEY(polygon, polygon)
|
||||
CSS_KEY(portrait, portrait)
|
||||
CSS_KEY(pre, pre)
|
||||
CSS_KEY(pre-wrap, pre_wrap)
|
||||
@ -503,6 +505,7 @@ CSS_KEY(stretch, stretch)
|
||||
CSS_KEY(stretch-to-fit, stretch_to_fit)
|
||||
CSS_KEY(stretched, stretched)
|
||||
CSS_KEY(stroke, stroke)
|
||||
CSS_KEY(stroke-box, stroke_box)
|
||||
CSS_KEY(style, style)
|
||||
CSS_KEY(styleset, styleset)
|
||||
CSS_KEY(stylistic, stylistic)
|
||||
@ -558,6 +561,7 @@ CSS_KEY(vertical, vertical)
|
||||
CSS_KEY(vertical-lr, vertical_lr)
|
||||
CSS_KEY(vertical-rl, vertical_rl)
|
||||
CSS_KEY(vertical-text, vertical_text)
|
||||
CSS_KEY(view-box, view_box)
|
||||
CSS_KEY(visible, visible)
|
||||
CSS_KEY(visiblefill, visiblefill)
|
||||
CSS_KEY(visiblepainted, visiblepainted)
|
||||
|
@ -788,6 +788,7 @@ protected:
|
||||
bool ParseListStyleType(nsCSSValue& aValue);
|
||||
bool ParseMargin();
|
||||
bool ParseMarks(nsCSSValue& aValue);
|
||||
bool ParseClipPath();
|
||||
bool ParseTransform(bool aIsPrefixed);
|
||||
bool ParseObjectPosition();
|
||||
bool ParseOutline();
|
||||
@ -961,6 +962,10 @@ protected:
|
||||
return mParsingCompoundProperty;
|
||||
}
|
||||
|
||||
/* Functions for basic shapes */
|
||||
bool ParseBasicShape(nsCSSValue& aValue);
|
||||
bool ParsePolygonFunction(nsCSSValue& aValue);
|
||||
|
||||
/* Functions for transform Parsing */
|
||||
bool ParseSingleTransform(bool aIsPrefixed, nsCSSValue& aValue);
|
||||
bool ParseFunction(nsCSSKeyword aFunction, const int32_t aAllowedTypes[],
|
||||
@ -9917,6 +9922,8 @@ CSSParserImpl::ParsePropertyByFunction(nsCSSProperty aPropID)
|
||||
return ParseMarker();
|
||||
case eCSSProperty_paint_order:
|
||||
return ParsePaintOrder();
|
||||
case eCSSProperty_clip_path:
|
||||
return ParseClipPath();
|
||||
case eCSSProperty_all:
|
||||
return ParseAll();
|
||||
default:
|
||||
@ -13780,6 +13787,125 @@ bool CSSParserImpl::ParseTransform(bool aIsPrefixed)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Reads a polygon function's argument list.
|
||||
*/
|
||||
bool
|
||||
CSSParserImpl::ParsePolygonFunction(nsCSSValue& aValue)
|
||||
{
|
||||
uint16_t numArgs = 1;
|
||||
|
||||
nsCSSValue fillRuleValue;
|
||||
if (ParseEnum(fillRuleValue, nsCSSProps::kFillRuleKTable)) {
|
||||
numArgs++;
|
||||
|
||||
// The fill-rule must be comma separated from the polygon points.
|
||||
if (!ExpectSymbol(',', true)) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEExpectedComma);
|
||||
SkipUntil(')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
nsCSSValue coordinates;
|
||||
nsCSSValuePairList* item = coordinates.SetPairListValue();
|
||||
for (;;) {
|
||||
nsCSSValue xValue, yValue;
|
||||
if (!ParseVariant(xValue, VARIANT_LPCALC, nullptr) ||
|
||||
!ParseVariant(yValue, VARIANT_LPCALC, nullptr)) {
|
||||
REPORT_UNEXPECTED_TOKEN(PECoordinatePair);
|
||||
SkipUntil(')');
|
||||
return false;
|
||||
}
|
||||
item->mXValue = xValue;
|
||||
item->mYValue = yValue;
|
||||
|
||||
// See whether to continue or whether to look for end of function.
|
||||
if (!ExpectSymbol(',', true)) {
|
||||
// We need to read the closing parenthesis.
|
||||
if (!ExpectSymbol(')', true)) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEExpectedCloseParen);
|
||||
SkipUntil(')');
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
item->mNext = new nsCSSValuePairList;
|
||||
item = item->mNext;
|
||||
}
|
||||
|
||||
nsRefPtr<nsCSSValue::Array> functionArray =
|
||||
aValue.InitFunction(eCSSKeyword_polygon, numArgs);
|
||||
functionArray->Item(numArgs) = coordinates;
|
||||
if (numArgs > 1) {
|
||||
functionArray->Item(1) = fillRuleValue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CSSParserImpl::ParseBasicShape(nsCSSValue& aValue)
|
||||
{
|
||||
if (!GetToken(true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mToken.mType != eCSSToken_Function) {
|
||||
UngetToken();
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent);
|
||||
switch (keyword) {
|
||||
case eCSSKeyword_polygon:
|
||||
return ParsePolygonFunction(aValue);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse a clip-path url to a <clipPath> element or a basic shape. */
|
||||
bool CSSParserImpl::ParseClipPath()
|
||||
{
|
||||
nsCSSValue value;
|
||||
if (!ParseVariant(value, VARIANT_HUO, nullptr)) {
|
||||
if (!nsLayoutUtils::CSSClipPathShapesEnabled()) {
|
||||
// With CSS Clip Path Shapes disabled, we should only accept
|
||||
// SVG clipPath reference and none.
|
||||
REPORT_UNEXPECTED_TOKEN(PEExpectedNoneOrURL);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool shape = false, box = false;
|
||||
nsCSSValueList* cur = value.SetListValue();
|
||||
bool eof = false;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (ParseBasicShape(cur->mValue) && !shape) {
|
||||
shape = true;
|
||||
} else if (ParseEnum(cur->mValue, nsCSSProps::kClipShapeSizingKTable) &&
|
||||
!box) {
|
||||
box = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (!GetToken(true)) {
|
||||
eof = true;
|
||||
break;
|
||||
}
|
||||
UngetToken();
|
||||
cur->mNext = new nsCSSValueList;
|
||||
cur = cur->mNext;
|
||||
}
|
||||
if (!shape && !box && !eof) {
|
||||
REPORT_UNEXPECTED_EOF(PEClipPathEOF);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
AppendValue(eCSSProperty_clip_path, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSSParserImpl::ParseTransformOrigin(bool aPerspective)
|
||||
{
|
||||
nsCSSValuePair position;
|
||||
|
@ -3612,10 +3612,10 @@ CSS_PROP_SVGRESET(
|
||||
clip-path,
|
||||
clip_path,
|
||||
ClipPath,
|
||||
CSS_PROPERTY_PARSE_VALUE |
|
||||
CSS_PROPERTY_PARSE_FUNCTION |
|
||||
CSS_PROPERTY_CREATES_STACKING_CONTEXT,
|
||||
"",
|
||||
VARIANT_HUO,
|
||||
0,
|
||||
nullptr,
|
||||
CSS_PROP_NO_OFFSET,
|
||||
eStyleAnimType_None)
|
||||
|
@ -1880,6 +1880,17 @@ const KTableValue nsCSSProps::kFillRuleKTable[] = {
|
||||
eCSSKeyword_UNKNOWN, -1
|
||||
};
|
||||
|
||||
const KTableValue nsCSSProps::kClipShapeSizingKTable[] = {
|
||||
eCSSKeyword_content_box, NS_STYLE_CLIP_SHAPE_SIZING_CONTENT,
|
||||
eCSSKeyword_padding_box, NS_STYLE_CLIP_SHAPE_SIZING_PADDING,
|
||||
eCSSKeyword_border_box, NS_STYLE_CLIP_SHAPE_SIZING_BORDER,
|
||||
eCSSKeyword_margin_box, NS_STYLE_CLIP_SHAPE_SIZING_MARGIN,
|
||||
eCSSKeyword_fill_box, NS_STYLE_CLIP_SHAPE_SIZING_FILL,
|
||||
eCSSKeyword_stroke_box, NS_STYLE_CLIP_SHAPE_SIZING_STROKE,
|
||||
eCSSKeyword_view_box, NS_STYLE_CLIP_SHAPE_SIZING_VIEW,
|
||||
eCSSKeyword_UNKNOWN,-1
|
||||
};
|
||||
|
||||
const KTableValue nsCSSProps::kFilterFunctionKTable[] = {
|
||||
eCSSKeyword_blur, NS_STYLE_FILTER_BLUR,
|
||||
eCSSKeyword_brightness, NS_STYLE_FILTER_BRIGHTNESS,
|
||||
|
@ -535,6 +535,7 @@ public:
|
||||
static const KTableValue kBoxDirectionKTable[];
|
||||
static const KTableValue kBoxOrientKTable[];
|
||||
static const KTableValue kBoxPackKTable[];
|
||||
static const KTableValue kClipShapeSizingKTable[];
|
||||
static const KTableValue kDominantBaselineKTable[];
|
||||
static const KTableValue kFillRuleKTable[];
|
||||
static const KTableValue kFilterFunctionKTable[];
|
||||
|
@ -826,6 +826,32 @@ private:
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void
|
||||
nsCSSValue::AppendPolygonToString(nsCSSProperty aProperty, nsAString& aResult,
|
||||
Serialization aSerialization) const
|
||||
{
|
||||
const nsCSSValue::Array* array = GetArrayValue();
|
||||
NS_ABORT_IF_FALSE(array->Count() > 1 && array->Count() <= 3,
|
||||
"Polygons must have name and at least one more value.");
|
||||
// When the array has 2 elements, the item on index 1 is the coordinate
|
||||
// pair list.
|
||||
// When the array has 3 elements, the item on index 1 is a fill-rule
|
||||
// and item on index 2 is the coordinate pair list.
|
||||
size_t index = 1;
|
||||
if (array->Count() == 3) {
|
||||
const nsCSSValue& fillRuleValue = array->Item(index);
|
||||
NS_ABORT_IF_FALSE(fillRuleValue.GetUnit() == eCSSUnit_Enumerated,
|
||||
"Expected polygon fill rule.");
|
||||
int32_t fillRule = fillRuleValue.GetIntValue();
|
||||
AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(fillRule,
|
||||
nsCSSProps::kFillRuleKTable),
|
||||
aResult);
|
||||
aResult.AppendLiteral(", ");
|
||||
++index;
|
||||
}
|
||||
array->Item(index).AppendToString(aProperty, aResult, aSerialization);
|
||||
}
|
||||
|
||||
void
|
||||
nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult,
|
||||
Serialization aSerialization) const
|
||||
@ -922,53 +948,61 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult,
|
||||
NS_ABORT_IF_FALSE(array->Count() >= 1,
|
||||
"Functions must have at least one element for the name.");
|
||||
|
||||
/* Append the function name. */
|
||||
const nsCSSValue& functionName = array->Item(0);
|
||||
if (functionName.GetUnit() == eCSSUnit_Enumerated) {
|
||||
// We assume that the first argument is always of nsCSSKeyword type.
|
||||
const nsCSSKeyword functionId = functionName.GetKeywordValue();
|
||||
NS_ConvertASCIItoUTF16 ident(nsCSSKeywords::GetStringValue(functionId));
|
||||
// Bug 721136: Normalize the identifier to lowercase, except that things
|
||||
// like scaleX should have the last character capitalized. This matches
|
||||
// what other browsers do.
|
||||
switch (functionId) {
|
||||
case eCSSKeyword_rotatex:
|
||||
case eCSSKeyword_scalex:
|
||||
case eCSSKeyword_skewx:
|
||||
case eCSSKeyword_translatex:
|
||||
ident.Replace(ident.Length() - 1, 1, char16_t('X'));
|
||||
break;
|
||||
NS_ABORT_IF_FALSE(functionName.GetUnit() == eCSSUnit_Enumerated,
|
||||
"Functions must have an enumerated name.");
|
||||
|
||||
case eCSSKeyword_rotatey:
|
||||
case eCSSKeyword_scaley:
|
||||
case eCSSKeyword_skewy:
|
||||
case eCSSKeyword_translatey:
|
||||
ident.Replace(ident.Length() - 1, 1, char16_t('Y'));
|
||||
break;
|
||||
/* Append the function name. */
|
||||
// The first argument is always of nsCSSKeyword type.
|
||||
const nsCSSKeyword functionId = functionName.GetKeywordValue();
|
||||
NS_ConvertASCIItoUTF16 ident(nsCSSKeywords::GetStringValue(functionId));
|
||||
// Bug 721136: Normalize the identifier to lowercase, except that things
|
||||
// like scaleX should have the last character capitalized. This matches
|
||||
// what other browsers do.
|
||||
switch (functionId) {
|
||||
case eCSSKeyword_rotatex:
|
||||
case eCSSKeyword_scalex:
|
||||
case eCSSKeyword_skewx:
|
||||
case eCSSKeyword_translatex:
|
||||
ident.Replace(ident.Length() - 1, 1, char16_t('X'));
|
||||
break;
|
||||
|
||||
case eCSSKeyword_rotatez:
|
||||
case eCSSKeyword_scalez:
|
||||
case eCSSKeyword_translatez:
|
||||
ident.Replace(ident.Length() - 1, 1, char16_t('Z'));
|
||||
break;
|
||||
case eCSSKeyword_rotatey:
|
||||
case eCSSKeyword_scaley:
|
||||
case eCSSKeyword_skewy:
|
||||
case eCSSKeyword_translatey:
|
||||
ident.Replace(ident.Length() - 1, 1, char16_t('Y'));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
nsStyleUtil::AppendEscapedCSSIdent(ident, aResult);
|
||||
} else {
|
||||
MOZ_ASSERT(false, "should no longer have non-enumerated functions");
|
||||
case eCSSKeyword_rotatez:
|
||||
case eCSSKeyword_scalez:
|
||||
case eCSSKeyword_translatez:
|
||||
ident.Replace(ident.Length() - 1, 1, char16_t('Z'));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
nsStyleUtil::AppendEscapedCSSIdent(ident, aResult);
|
||||
aResult.Append('(');
|
||||
|
||||
/* Now, step through the function contents, writing each of them as we go. */
|
||||
for (size_t index = 1; index < array->Count(); ++index) {
|
||||
array->Item(index).AppendToString(aProperty, aResult,
|
||||
aSerialization);
|
||||
switch (functionId) {
|
||||
case eCSSKeyword_polygon:
|
||||
AppendPolygonToString(aProperty, aResult, aSerialization);
|
||||
break;
|
||||
|
||||
/* If we're not at the final element, append a comma. */
|
||||
if (index + 1 != array->Count())
|
||||
aResult.AppendLiteral(", ");
|
||||
default: {
|
||||
// Now, step through the function contents, writing each of
|
||||
// them as we go.
|
||||
for (size_t index = 1; index < array->Count(); ++index) {
|
||||
array->Item(index).AppendToString(aProperty, aResult,
|
||||
aSerialization);
|
||||
|
||||
/* If we're not at the final element, append a comma. */
|
||||
if (index + 1 != array->Count())
|
||||
aResult.AppendLiteral(", ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, append the closing parenthesis. */
|
||||
@ -1086,6 +1120,12 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult,
|
||||
aResult);
|
||||
break;
|
||||
|
||||
case eCSSProperty_clip_path:
|
||||
AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
|
||||
nsCSSProps::kClipShapeSizingKTable),
|
||||
aResult);
|
||||
break;
|
||||
|
||||
default:
|
||||
const nsAFlatCString& name = nsCSSProps::LookupPropertyValue(aProperty, intValue);
|
||||
AppendASCIItoUTF16(name, aResult);
|
||||
@ -2045,7 +2085,8 @@ nsCSSValuePairList::AppendToString(nsCSSProperty aProperty,
|
||||
break;
|
||||
|
||||
if (nsCSSProps::PropHasFlags(aProperty,
|
||||
CSS_PROPERTY_VALUE_LIST_USES_COMMAS))
|
||||
CSS_PROPERTY_VALUE_LIST_USES_COMMAS) ||
|
||||
aProperty == eCSSProperty_clip_path)
|
||||
aResult.Append(char16_t(','));
|
||||
aResult.Append(char16_t(' '));
|
||||
}
|
||||
|
@ -719,6 +719,9 @@ private:
|
||||
return static_cast<char16_t*>(aBuffer->Data());
|
||||
}
|
||||
|
||||
void AppendPolygonToString(nsCSSProperty aProperty, nsAString& aResult,
|
||||
Serialization aValueSerialization) const;
|
||||
|
||||
protected:
|
||||
nsCSSUnit mUnit;
|
||||
union {
|
||||
|
@ -5176,18 +5176,84 @@ nsComputedDOMStyle::DoGetStopColor()
|
||||
}
|
||||
|
||||
CSSValue*
|
||||
nsComputedDOMStyle::DoGetClipPath()
|
||||
nsComputedDOMStyle::CreatePrimitiveValueForClipPath(
|
||||
const nsStyleBasicShape* aStyleBasicShape, uint8_t aSizingBox)
|
||||
{
|
||||
nsDOMCSSValueList* valueList = GetROCSSValueList(false);
|
||||
|
||||
if (aStyleBasicShape &&
|
||||
aStyleBasicShape->GetShapeType() == nsStyleBasicShape::Type::ePolygon) {
|
||||
nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
|
||||
|
||||
// Shape function name and opening parenthesis.
|
||||
nsAutoString shapeFunctionString;
|
||||
AppendASCIItoUTF16(nsCSSKeywords::GetStringValue(eCSSKeyword_polygon),
|
||||
shapeFunctionString);
|
||||
shapeFunctionString.Append('(');
|
||||
uint8_t fillRule = aStyleBasicShape->GetFillRule();
|
||||
if (fillRule == NS_STYLE_FILL_RULE_EVENODD) {
|
||||
shapeFunctionString.AppendLiteral("evenodd");
|
||||
}
|
||||
for (size_t i = 0; i < aStyleBasicShape->Coordinates().Length(); i += 2) {
|
||||
nsAutoString coordString;
|
||||
if (i > 0 || fillRule) {
|
||||
shapeFunctionString.AppendLiteral(", ");
|
||||
}
|
||||
SetCssTextToCoord(coordString,
|
||||
aStyleBasicShape->Coordinates()[i]);
|
||||
shapeFunctionString.Append(coordString);
|
||||
shapeFunctionString.Append(' ');
|
||||
SetCssTextToCoord(coordString,
|
||||
aStyleBasicShape->Coordinates()[i + 1]);
|
||||
shapeFunctionString.Append(coordString);
|
||||
}
|
||||
shapeFunctionString.Append(')');
|
||||
val->SetString(shapeFunctionString);
|
||||
valueList->AppendCSSValue(val);
|
||||
}
|
||||
|
||||
nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
|
||||
|
||||
if (aSizingBox == NS_STYLE_CLIP_SHAPE_SIZING_NOBOX) {
|
||||
return valueList;
|
||||
}
|
||||
|
||||
nsAutoString boxString;
|
||||
AppendASCIItoUTF16(
|
||||
nsCSSProps::ValueToKeyword(aSizingBox,
|
||||
nsCSSProps::kClipShapeSizingKTable),
|
||||
boxString);
|
||||
val->SetString(boxString);
|
||||
valueList->AppendCSSValue(val);
|
||||
|
||||
return valueList;
|
||||
}
|
||||
|
||||
CSSValue*
|
||||
nsComputedDOMStyle::DoGetClipPath()
|
||||
{
|
||||
const nsStyleSVGReset* svg = StyleSVGReset();
|
||||
|
||||
if (svg->mClipPath)
|
||||
val->SetURI(svg->mClipPath);
|
||||
else
|
||||
val->SetIdent(eCSSKeyword_none);
|
||||
|
||||
return val;
|
||||
switch (svg->mClipPath.GetType()) {
|
||||
case NS_STYLE_CLIP_PATH_SHAPE:
|
||||
return CreatePrimitiveValueForClipPath(svg->mClipPath.GetBasicShape(),
|
||||
svg->mClipPath.GetSizingBox());
|
||||
case NS_STYLE_CLIP_PATH_BOX:
|
||||
return CreatePrimitiveValueForClipPath(nullptr,
|
||||
svg->mClipPath.GetSizingBox());
|
||||
case NS_STYLE_CLIP_PATH_URL: {
|
||||
nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
|
||||
val->SetURI(svg->mClipPath.GetURL());
|
||||
return val;
|
||||
}
|
||||
case NS_STYLE_CLIP_PATH_NONE: {
|
||||
nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
|
||||
val->SetIdent(eCSSKeyword_none);
|
||||
return val;
|
||||
}
|
||||
default:
|
||||
NS_NOTREACHED("unexpected type");
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -586,6 +586,10 @@ private:
|
||||
mozilla::dom::CSSValue* CreatePrimitiveValueForStyleFilter(
|
||||
const nsStyleFilter& aStyleFilter);
|
||||
|
||||
// Helper function for computing basic shape styles.
|
||||
mozilla::dom::CSSValue* CreatePrimitiveValueForClipPath(
|
||||
const nsStyleBasicShape* aStyleBasicShape, uint8_t aSizingBox);
|
||||
|
||||
static nsComputedStyleMap* GetComputedStyleMap();
|
||||
|
||||
// We don't really have a good immutable representation of "presentation".
|
||||
|
@ -8758,6 +8758,86 @@ nsRuleNode::ComputeSVGData(void* aStartStruct,
|
||||
COMPUTE_END_INHERITED(SVG, svg)
|
||||
}
|
||||
|
||||
void
|
||||
nsRuleNode::SetStyleClipPathToCSSValue(nsStyleClipPath* aStyleClipPath,
|
||||
const nsCSSValue* aValue,
|
||||
nsStyleContext* aStyleContext,
|
||||
nsPresContext* aPresContext,
|
||||
bool& aCanStoreInRuleTree)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aValue->GetUnit() != eCSSUnit_ListDep ||
|
||||
aValue->GetUnit() != eCSSUnit_List,
|
||||
"expected a basic shape or reference box");
|
||||
|
||||
const nsCSSValueList* cur = aValue->GetListValue();
|
||||
|
||||
uint8_t sizingBox = NS_STYLE_CLIP_SHAPE_SIZING_NOBOX;
|
||||
nsStyleBasicShape* basicShape = nullptr;
|
||||
for (unsigned i = 0; i < 2; ++i) {
|
||||
if (!cur) {
|
||||
break;
|
||||
}
|
||||
if (cur->mValue.GetUnit() == eCSSUnit_Function) {
|
||||
nsCSSValue::Array* shapeFunction = cur->mValue.GetArrayValue();
|
||||
nsCSSKeyword functionName =
|
||||
(nsCSSKeyword)shapeFunction->Item(0).GetIntValue();
|
||||
if (functionName == eCSSKeyword_polygon) {
|
||||
basicShape = new nsStyleBasicShape(nsStyleBasicShape::ePolygon);
|
||||
NS_ABORT_IF_FALSE(shapeFunction->Count() > 1,
|
||||
"polygon has wrong number of arguments");
|
||||
size_t j = 1;
|
||||
if (shapeFunction->Item(j).GetUnit() == eCSSUnit_Enumerated) {
|
||||
basicShape->SetFillRule(shapeFunction->Item(j).GetIntValue());
|
||||
++j;
|
||||
}
|
||||
int32_t mask = SETCOORD_PERCENT | SETCOORD_LENGTH |
|
||||
SETCOORD_STORE_CALC;
|
||||
const nsCSSValuePairList* curPair =
|
||||
shapeFunction->Item(j).GetPairListValue();
|
||||
nsTArray<nsStyleCoord>& coordinates = basicShape->Coordinates();
|
||||
while (curPair) {
|
||||
nsStyleCoord xCoord, yCoord;
|
||||
DebugOnly<bool> didSetCoordX = SetCoord(curPair->mXValue, xCoord,
|
||||
nsStyleCoord(), mask,
|
||||
aStyleContext, aPresContext,
|
||||
aCanStoreInRuleTree);
|
||||
coordinates.AppendElement(xCoord);
|
||||
NS_ABORT_IF_FALSE(didSetCoordX, "unexpected x coordinate unit");
|
||||
DebugOnly<bool> didSetCoordY = SetCoord(curPair->mYValue, yCoord,
|
||||
nsStyleCoord(), mask,
|
||||
aStyleContext, aPresContext,
|
||||
aCanStoreInRuleTree);
|
||||
coordinates.AppendElement(yCoord);
|
||||
NS_ABORT_IF_FALSE(didSetCoordY, "unexpected y coordinate unit");
|
||||
curPair = curPair->mNext;
|
||||
}
|
||||
} else {
|
||||
// XXX Handle more basic shape functions later.
|
||||
NS_NOTREACHED("unexpected basic shape function");
|
||||
return;
|
||||
}
|
||||
} else if (cur->mValue.GetUnit() == eCSSUnit_Enumerated) {
|
||||
int32_t type = cur->mValue.GetIntValue();
|
||||
if (type > NS_STYLE_CLIP_SHAPE_SIZING_VIEW ||
|
||||
type < NS_STYLE_CLIP_SHAPE_SIZING_NOBOX) {
|
||||
NS_NOTREACHED("unexpected reference box");
|
||||
return;
|
||||
}
|
||||
sizingBox = (uint8_t)type;
|
||||
} else {
|
||||
NS_NOTREACHED("unexpected value");
|
||||
return;
|
||||
}
|
||||
cur = cur->mNext;
|
||||
}
|
||||
|
||||
if (basicShape) {
|
||||
aStyleClipPath->SetBasicShape(basicShape, sizingBox);
|
||||
} else {
|
||||
aStyleClipPath->SetSizingBox(sizingBox);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the nsStyleFilter was successfully set using the nsCSSValue.
|
||||
bool
|
||||
nsRuleNode::SetStyleFilterToCSSValue(nsStyleFilter* aStyleFilter,
|
||||
@ -8862,17 +8942,37 @@ nsRuleNode::ComputeSVGResetData(void* aStartStruct,
|
||||
canStoreInRuleTree);
|
||||
}
|
||||
|
||||
// clip-path: url, none, inherit
|
||||
// clip-path: url, <basic-shape> || <geometry-box>, none, inherit
|
||||
const nsCSSValue* clipPathValue = aRuleData->ValueForClipPath();
|
||||
if (eCSSUnit_URL == clipPathValue->GetUnit()) {
|
||||
svgReset->mClipPath = clipPathValue->GetURLValue();
|
||||
} else if (eCSSUnit_None == clipPathValue->GetUnit() ||
|
||||
eCSSUnit_Initial == clipPathValue->GetUnit() ||
|
||||
eCSSUnit_Unset == clipPathValue->GetUnit()) {
|
||||
svgReset->mClipPath = nullptr;
|
||||
} else if (eCSSUnit_Inherit == clipPathValue->GetUnit()) {
|
||||
canStoreInRuleTree = false;
|
||||
svgReset->mClipPath = parentSVGReset->mClipPath;
|
||||
switch (clipPathValue->GetUnit()) {
|
||||
case eCSSUnit_Null:
|
||||
break;
|
||||
case eCSSUnit_None:
|
||||
case eCSSUnit_Initial:
|
||||
case eCSSUnit_Unset:
|
||||
svgReset->mClipPath = nsStyleClipPath();
|
||||
break;
|
||||
case eCSSUnit_Inherit:
|
||||
canStoreInRuleTree = false;
|
||||
svgReset->mClipPath = parentSVGReset->mClipPath;
|
||||
break;
|
||||
case eCSSUnit_URL: {
|
||||
svgReset->mClipPath = nsStyleClipPath();
|
||||
nsIURI* url = clipPathValue->GetURLValue();
|
||||
if (url) {
|
||||
svgReset->mClipPath.SetURL(url);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case eCSSUnit_List:
|
||||
case eCSSUnit_ListDep: {
|
||||
svgReset->mClipPath = nsStyleClipPath();
|
||||
SetStyleClipPathToCSSValue(&svgReset->mClipPath, clipPathValue, aContext,
|
||||
mPresContext, canStoreInRuleTree);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NS_NOTREACHED("unexpected unit");
|
||||
}
|
||||
|
||||
// stop-opacity:
|
||||
|
@ -665,6 +665,11 @@ protected:
|
||||
nsStyleContext* aStyleContext,
|
||||
nsPresContext* aPresContext,
|
||||
bool& aCanStoreInRuleTree);
|
||||
void SetStyleClipPathToCSSValue(nsStyleClipPath* aStyleClipPath,
|
||||
const nsCSSValue* aValue,
|
||||
nsStyleContext* aStyleContext,
|
||||
nsPresContext* aPresContext,
|
||||
bool& aCanStoreInRuleTree);
|
||||
|
||||
private:
|
||||
nsRuleNode(nsPresContext* aPresContext, nsRuleNode* aParent,
|
||||
|
@ -65,6 +65,22 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) {
|
||||
#define NS_STYLE_BOX_SIZING_PADDING 1
|
||||
#define NS_STYLE_BOX_SIZING_BORDER 2
|
||||
|
||||
// clip-path sizing
|
||||
#define NS_STYLE_CLIP_SHAPE_SIZING_NOBOX 0
|
||||
#define NS_STYLE_CLIP_SHAPE_SIZING_CONTENT 1
|
||||
#define NS_STYLE_CLIP_SHAPE_SIZING_PADDING 2
|
||||
#define NS_STYLE_CLIP_SHAPE_SIZING_BORDER 3
|
||||
#define NS_STYLE_CLIP_SHAPE_SIZING_MARGIN 4
|
||||
#define NS_STYLE_CLIP_SHAPE_SIZING_FILL 5
|
||||
#define NS_STYLE_CLIP_SHAPE_SIZING_STROKE 6
|
||||
#define NS_STYLE_CLIP_SHAPE_SIZING_VIEW 7
|
||||
|
||||
// Basic Shapes
|
||||
#define NS_STYLE_BASIC_SHAPE_POLYGON 0
|
||||
//#define NS_STYLE_BASIC_SHAPE_CIRCLE 1
|
||||
//#define NS_STYLE_BASIC_SHAPE_ELLIPSE 2
|
||||
//#define NS_STYLE_BASIC_SHAPE_INSET 3
|
||||
|
||||
// box-shadow
|
||||
#define NS_STYLE_BOX_SHADOW_INSET 0
|
||||
|
||||
@ -478,6 +494,12 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) {
|
||||
#define NS_STYLE_FLOAT_LEFT 1
|
||||
#define NS_STYLE_FLOAT_RIGHT 2
|
||||
|
||||
// See nsStyleClipPath
|
||||
#define NS_STYLE_CLIP_PATH_NONE 0
|
||||
#define NS_STYLE_CLIP_PATH_URL 1
|
||||
#define NS_STYLE_CLIP_PATH_SHAPE 2
|
||||
#define NS_STYLE_CLIP_PATH_BOX 3
|
||||
|
||||
// See nsStyleFilter
|
||||
#define NS_STYLE_FILTER_NONE 0
|
||||
#define NS_STYLE_FILTER_URL 1
|
||||
|
@ -1030,6 +1030,119 @@ nsChangeHint nsStyleSVG::CalcDifference(const nsStyleSVG& aOther) const
|
||||
return hint;
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// nsStyleClipPath
|
||||
//
|
||||
nsStyleClipPath::nsStyleClipPath()
|
||||
: mType(NS_STYLE_CLIP_PATH_NONE)
|
||||
, mURL(nullptr)
|
||||
, mSizingBox(NS_STYLE_CLIP_SHAPE_SIZING_NOBOX)
|
||||
{
|
||||
}
|
||||
|
||||
nsStyleClipPath::nsStyleClipPath(const nsStyleClipPath& aSource)
|
||||
: mType(NS_STYLE_CLIP_PATH_NONE)
|
||||
, mURL(nullptr)
|
||||
, mSizingBox(NS_STYLE_CLIP_SHAPE_SIZING_NOBOX)
|
||||
{
|
||||
if (aSource.mType == NS_STYLE_CLIP_PATH_URL) {
|
||||
SetURL(aSource.mURL);
|
||||
} else if (aSource.mType == NS_STYLE_CLIP_PATH_SHAPE) {
|
||||
SetBasicShape(aSource.mBasicShape, aSource.mSizingBox);
|
||||
} else if (aSource.mType == NS_STYLE_CLIP_PATH_SHAPE) {
|
||||
SetSizingBox(aSource.mSizingBox);
|
||||
}
|
||||
}
|
||||
|
||||
nsStyleClipPath::~nsStyleClipPath()
|
||||
{
|
||||
ReleaseRef();
|
||||
}
|
||||
|
||||
nsStyleClipPath&
|
||||
nsStyleClipPath::operator=(const nsStyleClipPath& aOther)
|
||||
{
|
||||
if (this == &aOther) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
ReleaseRef();
|
||||
|
||||
if (aOther.mType == NS_STYLE_CLIP_PATH_URL) {
|
||||
SetURL(aOther.mURL);
|
||||
} else if (aOther.mType == NS_STYLE_CLIP_PATH_SHAPE) {
|
||||
SetBasicShape(aOther.mBasicShape, aOther.mSizingBox);
|
||||
} else if (aOther.mType == NS_STYLE_CLIP_PATH_BOX) {
|
||||
SetSizingBox(aOther.mSizingBox);
|
||||
} else {
|
||||
mSizingBox = NS_STYLE_CLIP_SHAPE_SIZING_NOBOX;
|
||||
mType = NS_STYLE_CLIP_PATH_NONE;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
nsStyleClipPath::operator==(const nsStyleClipPath& aOther) const
|
||||
{
|
||||
if (mType != aOther.mType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mType == NS_STYLE_CLIP_PATH_URL) {
|
||||
return EqualURIs(mURL, aOther.mURL);
|
||||
} else if (mType == NS_STYLE_CLIP_PATH_SHAPE) {
|
||||
return *mBasicShape == *aOther.mBasicShape &&
|
||||
mSizingBox == aOther.mSizingBox;
|
||||
} else if (mType == NS_STYLE_CLIP_PATH_BOX) {
|
||||
return mSizingBox == aOther.mSizingBox;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsStyleClipPath::ReleaseRef()
|
||||
{
|
||||
if (mType == NS_STYLE_CLIP_PATH_SHAPE) {
|
||||
NS_ASSERTION(mBasicShape, "expected pointer");
|
||||
mBasicShape->Release();
|
||||
} else if (mType == NS_STYLE_CLIP_PATH_URL) {
|
||||
NS_ASSERTION(mURL, "expected pointer");
|
||||
mURL->Release();
|
||||
}
|
||||
mURL = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
nsStyleClipPath::SetURL(nsIURI* aURL)
|
||||
{
|
||||
NS_ASSERTION(aURL, "expected pointer");
|
||||
ReleaseRef();
|
||||
mURL = aURL;
|
||||
mURL->AddRef();
|
||||
mType = NS_STYLE_CLIP_PATH_URL;
|
||||
}
|
||||
|
||||
void
|
||||
nsStyleClipPath::SetBasicShape(nsStyleBasicShape* aBasicShape, uint8_t aSizingBox)
|
||||
{
|
||||
NS_ASSERTION(aBasicShape, "expected pointer");
|
||||
ReleaseRef();
|
||||
mBasicShape = aBasicShape;
|
||||
mBasicShape->AddRef();
|
||||
mSizingBox = aSizingBox;
|
||||
mType = NS_STYLE_CLIP_PATH_SHAPE;
|
||||
}
|
||||
|
||||
void
|
||||
nsStyleClipPath::SetSizingBox(uint8_t aSizingBox)
|
||||
{
|
||||
ReleaseRef();
|
||||
mSizingBox = aSizingBox;
|
||||
mType = NS_STYLE_CLIP_PATH_BOX;
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// nsStyleFilter
|
||||
//
|
||||
@ -1145,7 +1258,6 @@ nsStyleSVGReset::nsStyleSVGReset()
|
||||
mStopColor = NS_RGB(0,0,0);
|
||||
mFloodColor = NS_RGB(0,0,0);
|
||||
mLightingColor = NS_RGB(255,255,255);
|
||||
mClipPath = nullptr;
|
||||
mMask = nullptr;
|
||||
mStopOpacity = 1.0f;
|
||||
mFloodOpacity = 1.0f;
|
||||
@ -1179,7 +1291,7 @@ nsChangeHint nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aOther) cons
|
||||
{
|
||||
nsChangeHint hint = nsChangeHint(0);
|
||||
|
||||
if (!EqualURIs(mClipPath, aOther.mClipPath) ||
|
||||
if (mClipPath != aOther.mClipPath ||
|
||||
!EqualURIs(mMask, aOther.mMask) ||
|
||||
mFilters != aOther.mFilters) {
|
||||
NS_UpdateHint(hint, nsChangeHint_UpdateEffects);
|
||||
|
@ -2827,6 +2827,107 @@ struct nsStyleSVG {
|
||||
}
|
||||
};
|
||||
|
||||
class nsStyleBasicShape MOZ_FINAL {
|
||||
public:
|
||||
enum Type {
|
||||
// eInset,
|
||||
// eCircle,
|
||||
// eEllipse,
|
||||
ePolygon
|
||||
};
|
||||
|
||||
nsStyleBasicShape(Type type)
|
||||
: mType(type)
|
||||
{
|
||||
}
|
||||
|
||||
Type GetShapeType() const { return mType; }
|
||||
|
||||
int32_t GetFillRule() const { return mFillRule; }
|
||||
void SetFillRule(int32_t aFillRule)
|
||||
{
|
||||
NS_ASSERTION(mType == ePolygon, "expected polygon");
|
||||
mFillRule = aFillRule;
|
||||
}
|
||||
|
||||
nsTArray<nsStyleCoord>& Coordinates()
|
||||
{
|
||||
NS_ASSERTION(mType == ePolygon, "expected polygon");
|
||||
return mCoordinates;
|
||||
}
|
||||
|
||||
const nsTArray<nsStyleCoord>& Coordinates() const
|
||||
{
|
||||
NS_ASSERTION(mType == ePolygon, "expected polygon");
|
||||
return mCoordinates;
|
||||
}
|
||||
|
||||
bool operator==(const nsStyleBasicShape& aOther) const
|
||||
{
|
||||
return mType == aOther.mType &&
|
||||
mFillRule == aOther.mFillRule &&
|
||||
mCoordinates == aOther.mCoordinates;
|
||||
}
|
||||
bool operator!=(const nsStyleBasicShape& aOther) const {
|
||||
return !(*this == aOther);
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(nsStyleBasicShape);
|
||||
|
||||
private:
|
||||
~nsStyleBasicShape() {}
|
||||
|
||||
Type mType;
|
||||
int32_t mFillRule;
|
||||
nsTArray<nsStyleCoord> mCoordinates;
|
||||
};
|
||||
|
||||
struct nsStyleClipPath
|
||||
{
|
||||
nsStyleClipPath();
|
||||
nsStyleClipPath(const nsStyleClipPath& aSource);
|
||||
~nsStyleClipPath();
|
||||
|
||||
nsStyleClipPath& operator=(const nsStyleClipPath& aOther);
|
||||
|
||||
bool operator==(const nsStyleClipPath& aOther) const;
|
||||
bool operator!=(const nsStyleClipPath& aOther) const {
|
||||
return !(*this == aOther);
|
||||
}
|
||||
|
||||
int32_t GetType() const {
|
||||
return mType;
|
||||
}
|
||||
|
||||
nsIURI* GetURL() const {
|
||||
NS_ASSERTION(mType == NS_STYLE_CLIP_PATH_URL, "wrong clip-path type");
|
||||
return mURL;
|
||||
}
|
||||
void SetURL(nsIURI* aURL);
|
||||
|
||||
nsStyleBasicShape* GetBasicShape() const {
|
||||
NS_ASSERTION(mType == NS_STYLE_CLIP_PATH_SHAPE, "wrong clip-path type");
|
||||
return mBasicShape;
|
||||
}
|
||||
|
||||
void SetBasicShape(nsStyleBasicShape* mBasicShape,
|
||||
uint8_t aSizingBox = NS_STYLE_CLIP_SHAPE_SIZING_NOBOX);
|
||||
|
||||
uint8_t GetSizingBox() const { return mSizingBox; }
|
||||
void SetSizingBox(uint8_t aSizingBox);
|
||||
|
||||
private:
|
||||
void ReleaseRef();
|
||||
void* operator new(size_t) MOZ_DELETE;
|
||||
|
||||
int32_t mType; // see NS_STYLE_CLIP_PATH_* constants in nsStyleConsts.h
|
||||
union {
|
||||
nsStyleBasicShape* mBasicShape;
|
||||
nsIURI* mURL;
|
||||
};
|
||||
uint8_t mSizingBox; // see NS_STYLE_CLIP_SHAPE_SIZING_* constants in nsStyleConsts.h
|
||||
};
|
||||
|
||||
struct nsStyleFilter {
|
||||
nsStyleFilter();
|
||||
nsStyleFilter(const nsStyleFilter& aSource);
|
||||
@ -2911,7 +3012,7 @@ struct nsStyleSVGReset {
|
||||
return mFilters.Length() > 0;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> mClipPath; // [reset]
|
||||
nsStyleClipPath mClipPath; // [reset]
|
||||
nsTArray<nsStyleFilter> mFilters; // [reset]
|
||||
nsCOMPtr<nsIURI> mMask; // [reset]
|
||||
nscolor mStopColor; // [reset]
|
||||
|
@ -4584,6 +4584,54 @@ if (SpecialPowers.getBoolPref("svg.paint-order.enabled")) {
|
||||
};
|
||||
}
|
||||
|
||||
if (SpecialPowers.getBoolPref("layout.css.clip-path-shapes.enabled")) {
|
||||
gCSSProperties["clip-path"] = {
|
||||
domProp: "clip-path",
|
||||
inherited: false,
|
||||
type: CSS_TYPE_LONGHAND,
|
||||
initial_values: [ "none" ],
|
||||
other_values: [
|
||||
// SVG reference clip-path
|
||||
"url(#my-clip-path)",
|
||||
|
||||
"polygon(20px 20px)",
|
||||
"polygon(20px 20%)",
|
||||
"polygon(20% 20%)",
|
||||
"polygon(20rem 20em)",
|
||||
"polygon(20cm 20mm)",
|
||||
"polygon(20px 20px, 30px 30px)",
|
||||
"polygon(20px 20px, 30% 30%, 30px 30px)",
|
||||
"polygon(nonzero, 20px 20px, 30% 30%, 30px 30px)",
|
||||
"polygon(evenodd, 20px 20px, 30% 30%, 30px 30px)",
|
||||
|
||||
"content-box",
|
||||
"padding-box",
|
||||
"border-box",
|
||||
"margin-box",
|
||||
"fill-box",
|
||||
"stroke-box",
|
||||
"view-box",
|
||||
|
||||
"polygon(0 0) conten-box",
|
||||
"border-box polygon(0 0)",
|
||||
"padding-box polygon( 0 20px , 30px 20% ) ",
|
||||
],
|
||||
invalid_values: [
|
||||
"url(#test) url(#tes2)",
|
||||
"polygon (0 0)",
|
||||
"polygon(20px, 40px)",
|
||||
"border-box content-box",
|
||||
"polygon(0 0) polygon(0 0)",
|
||||
"polygon(nonzero 0 0)",
|
||||
"polygon(evenodd 20px 20px)",
|
||||
"polygon(20px 20px, evenodd)",
|
||||
"polygon(20px 20px, nonzero)",
|
||||
"polygon(30% 30%",
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
if (SpecialPowers.getBoolPref("layout.css.filters.enabled")) {
|
||||
gCSSProperties["filter"] = {
|
||||
domProp: "filter",
|
||||
|
@ -551,8 +551,12 @@ nsSVGEffects::GetEffectProperties(nsIFrame *aFrame)
|
||||
EffectProperties result;
|
||||
const nsStyleSVGReset *style = aFrame->StyleSVGReset();
|
||||
result.mFilter = GetOrCreateFilterProperty(aFrame);
|
||||
result.mClipPath =
|
||||
GetPaintingProperty(style->mClipPath, aFrame, ClipPathProperty());
|
||||
if (style->mClipPath.GetType() == NS_STYLE_CLIP_PATH_URL) {
|
||||
result.mClipPath =
|
||||
GetPaintingProperty(style->mClipPath.GetURL(), aFrame, ClipPathProperty());
|
||||
} else {
|
||||
result.mClipPath = nullptr;
|
||||
}
|
||||
result.mMask =
|
||||
GetPaintingProperty(style->mMask, aFrame, MaskProperty());
|
||||
return result;
|
||||
|
@ -152,7 +152,8 @@ nsSVGIntegrationUtils::UsingEffectsForFrame(const nsIFrame* aFrame)
|
||||
// checking the SDL prefs here, since we don't know if we're being called for
|
||||
// painting or hit-testing anyway.
|
||||
const nsStyleSVGReset *style = aFrame->StyleSVGReset();
|
||||
return (style->HasFilters() || style->mClipPath || style->mMask);
|
||||
return (style->HasFilters() ||
|
||||
style->mClipPath.GetType() != NS_STYLE_CLIP_PATH_NONE || style->mMask);
|
||||
}
|
||||
|
||||
// For non-SVG frames, this gives the offset to the frame's "user space".
|
||||
|
@ -2006,6 +2006,9 @@ pref("layout.css.mix-blend-mode.enabled", true);
|
||||
// Is support for CSS Filters enabled?
|
||||
pref("layout.css.filters.enabled", false);
|
||||
|
||||
// Is support for basic shapes in clip-path enabled?
|
||||
pref("layout.css.clip-path-shapes.enabled", false);
|
||||
|
||||
// Is support for CSS sticky positioning enabled?
|
||||
pref("layout.css.sticky.enabled", true);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user