mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1074528 - Implement parsing/computing of inset(). r=dbaron
This commit is contained in:
parent
ace0826205
commit
88dd1c0c4c
@ -114,38 +114,6 @@ Declaration::AppendValueToString(nsCSSProperty aProperty,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Helper to append |aString| with the shorthand sides notation used in e.g.
|
||||
// 'padding'. |aProperties| and |aValues| are expected to have 4 elements.
|
||||
static void
|
||||
AppendSidesShorthandToString(const nsCSSProperty aProperties[],
|
||||
const nsCSSValue* aValues[],
|
||||
nsAString& aString,
|
||||
nsCSSValue::Serialization aSerialization)
|
||||
{
|
||||
const nsCSSValue& value1 = *aValues[0];
|
||||
const nsCSSValue& value2 = *aValues[1];
|
||||
const nsCSSValue& value3 = *aValues[2];
|
||||
const nsCSSValue& value4 = *aValues[3];
|
||||
|
||||
NS_ABORT_IF_FALSE(value1.GetUnit() != eCSSUnit_Null, "null value 1");
|
||||
value1.AppendToString(aProperties[0], aString, aSerialization);
|
||||
if (value1 != value2 || value1 != value3 || value1 != value4) {
|
||||
aString.Append(char16_t(' '));
|
||||
NS_ABORT_IF_FALSE(value2.GetUnit() != eCSSUnit_Null, "null value 2");
|
||||
value2.AppendToString(aProperties[1], aString, aSerialization);
|
||||
if (value1 != value3 || value2 != value4) {
|
||||
aString.Append(char16_t(' '));
|
||||
NS_ABORT_IF_FALSE(value3.GetUnit() != eCSSUnit_Null, "null value 3");
|
||||
value3.AppendToString(aProperties[2], aString, aSerialization);
|
||||
if (value2 != value4) {
|
||||
aString.Append(char16_t(' '));
|
||||
NS_ABORT_IF_FALSE(value4.GetUnit() != eCSSUnit_Null, "null value 4");
|
||||
value4.AppendToString(aProperties[3], aString, aSerialization);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
|
||||
{
|
||||
@ -294,7 +262,8 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue,
|
||||
data->ValueFor(subprops[2]),
|
||||
data->ValueFor(subprops[3])
|
||||
};
|
||||
AppendSidesShorthandToString(subprops, vals, aValue, aSerialization);
|
||||
nsCSSValue::AppendSidesShorthandToString(subprops, vals, aValue,
|
||||
aSerialization);
|
||||
break;
|
||||
}
|
||||
case eCSSProperty_border_radius:
|
||||
@ -307,27 +276,8 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue,
|
||||
data->ValueFor(subprops[2]),
|
||||
data->ValueFor(subprops[3])
|
||||
};
|
||||
|
||||
// For compatibility, only write a slash and the y-values
|
||||
// if they're not identical to the x-values.
|
||||
bool needY = false;
|
||||
const nsCSSValue* xVals[4];
|
||||
const nsCSSValue* yVals[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (vals[i]->GetUnit() == eCSSUnit_Pair) {
|
||||
needY = true;
|
||||
xVals[i] = &vals[i]->GetPairValue().mXValue;
|
||||
yVals[i] = &vals[i]->GetPairValue().mYValue;
|
||||
} else {
|
||||
xVals[i] = yVals[i] = vals[i];
|
||||
}
|
||||
}
|
||||
|
||||
AppendSidesShorthandToString(subprops, xVals, aValue, aSerialization);
|
||||
if (needY) {
|
||||
aValue.AppendLiteral(" / ");
|
||||
AppendSidesShorthandToString(subprops, yVals, aValue, aSerialization);
|
||||
}
|
||||
nsCSSValue::AppendBasicShapeRadiusToString(subprops, vals, aValue,
|
||||
aSerialization);
|
||||
break;
|
||||
}
|
||||
case eCSSProperty_border_image: {
|
||||
|
@ -889,7 +889,9 @@ protected:
|
||||
bool ParseDirectionalBoxProperty(nsCSSProperty aProperty,
|
||||
int32_t aSourceType);
|
||||
bool ParseBoxCornerRadius(const nsCSSProperty aPropID);
|
||||
bool ParseBoxCornerRadiiInternals(nsCSSValue array[]);
|
||||
bool ParseBoxCornerRadii(const nsCSSProperty aPropIDs[]);
|
||||
|
||||
int32_t ParseChoice(nsCSSValue aValues[],
|
||||
const nsCSSProperty aPropIDs[], int32_t aNumIDs);
|
||||
bool ParseColor(nsCSSValue& aValue);
|
||||
@ -966,6 +968,7 @@ protected:
|
||||
bool ParseBasicShape(nsCSSValue& aValue, bool* aConsumedTokens);
|
||||
bool ParsePolygonFunction(nsCSSValue& aValue);
|
||||
bool ParseCircleOrEllipseFunction(nsCSSKeyword, nsCSSValue& aValue);
|
||||
bool ParseInsetFunction(nsCSSValue& aValue);
|
||||
|
||||
/* Functions for transform Parsing */
|
||||
bool ParseSingleTransform(bool aIsPrefixed, nsCSSValue& aValue);
|
||||
@ -9383,7 +9386,7 @@ CSSParserImpl::ParseBoxCornerRadius(nsCSSProperty aPropID)
|
||||
}
|
||||
|
||||
bool
|
||||
CSSParserImpl::ParseBoxCornerRadii(const nsCSSProperty aPropIDs[])
|
||||
CSSParserImpl::ParseBoxCornerRadiiInternals(nsCSSValue array[])
|
||||
{
|
||||
// Rectangles are used as scratch storage.
|
||||
// top => top-left, right => top-right,
|
||||
@ -9446,16 +9449,30 @@ CSSParserImpl::ParseBoxCornerRadii(const nsCSSProperty aPropIDs[])
|
||||
nsCSSValue& y = dimenY.*nsCSSRect::sides[side];
|
||||
|
||||
if (x == y) {
|
||||
AppendValue(aPropIDs[side], x);
|
||||
array[side] = x;
|
||||
} else {
|
||||
nsCSSValue pair;
|
||||
pair.SetPairValue(x, y);
|
||||
AppendValue(aPropIDs[side], pair);
|
||||
array[side] = pair;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CSSParserImpl::ParseBoxCornerRadii(const nsCSSProperty aPropIDs[])
|
||||
{
|
||||
nsCSSValue value[4];
|
||||
if (!ParseBoxCornerRadiiInternals(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_FOR_CSS_SIDES(side) {
|
||||
AppendValue(aPropIDs[side], value[side]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// These must be in CSS order (top,right,bottom,left) for indexing to work
|
||||
static const nsCSSProperty kBorderStyleIDs[] = {
|
||||
eCSSProperty_border_top_style,
|
||||
@ -13887,6 +13904,49 @@ CSSParserImpl::ParseCircleOrEllipseFunction(nsCSSKeyword aKeyword,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CSSParserImpl::ParseInsetFunction(nsCSSValue& aValue)
|
||||
{
|
||||
nsRefPtr<nsCSSValue::Array> functionArray =
|
||||
aValue.InitFunction(eCSSKeyword_inset, 5);
|
||||
|
||||
if (ParseVariant(functionArray->Item(1), VARIANT_LPCALC, nullptr)) {
|
||||
// Consume up to 4, but only require one.
|
||||
ParseVariant(functionArray->Item(2), VARIANT_LPCALC, nullptr) &&
|
||||
ParseVariant(functionArray->Item(3), VARIANT_LPCALC, nullptr) &&
|
||||
ParseVariant(functionArray->Item(4), VARIANT_LPCALC, nullptr);
|
||||
} else {
|
||||
REPORT_UNEXPECTED_TOKEN(PEExpectedShapeArg);
|
||||
SkipUntil(')');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ExpectSymbol(')', true)) {
|
||||
if (!GetToken(true)) {
|
||||
NS_NOTREACHED("ExpectSymbol should have returned true");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsRefPtr<nsCSSValue::Array> radiusArray = nsCSSValue::Array::Create(4);
|
||||
functionArray->Item(5).SetArrayValue(radiusArray, eCSSUnit_Array);
|
||||
if (mToken.mType != eCSSToken_Ident ||
|
||||
!mToken.mIdent.LowerCaseEqualsLiteral("round") ||
|
||||
!ParseBoxCornerRadiiInternals(radiusArray->ItemStorage())) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEExpectedRadius);
|
||||
SkipUntil(')');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ExpectSymbol(')', true)) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEExpectedCloseParen);
|
||||
SkipUntil(')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CSSParserImpl::ParseBasicShape(nsCSSValue& aValue, bool* aConsumedTokens)
|
||||
{
|
||||
@ -13908,6 +13968,8 @@ CSSParserImpl::ParseBasicShape(nsCSSValue& aValue, bool* aConsumedTokens)
|
||||
case eCSSKeyword_circle:
|
||||
case eCSSKeyword_ellipse:
|
||||
return ParseCircleOrEllipseFunction(keyword, aValue);
|
||||
case eCSSKeyword_inset:
|
||||
return ParseInsetFunction(aValue);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -904,6 +904,108 @@ nsCSSValue::AppendCircleOrEllipseToString(nsCSSKeyword aFunctionId,
|
||||
aResult, aSerialization);
|
||||
}
|
||||
|
||||
// Helper to append |aString| with the shorthand sides notation used in e.g.
|
||||
// 'padding'. |aProperties| and |aValues| are expected to have 4 elements.
|
||||
/*static*/ void
|
||||
nsCSSValue::AppendSidesShorthandToString(const nsCSSProperty aProperties[],
|
||||
const nsCSSValue* aValues[],
|
||||
nsAString& aString,
|
||||
nsCSSValue::Serialization
|
||||
aSerialization)
|
||||
{
|
||||
const nsCSSValue& value1 = *aValues[0];
|
||||
const nsCSSValue& value2 = *aValues[1];
|
||||
const nsCSSValue& value3 = *aValues[2];
|
||||
const nsCSSValue& value4 = *aValues[3];
|
||||
|
||||
NS_ABORT_IF_FALSE(value1.GetUnit() != eCSSUnit_Null, "null value 1");
|
||||
value1.AppendToString(aProperties[0], aString, aSerialization);
|
||||
if (value1 != value2 || value1 != value3 || value1 != value4) {
|
||||
aString.Append(char16_t(' '));
|
||||
NS_ABORT_IF_FALSE(value2.GetUnit() != eCSSUnit_Null, "null value 2");
|
||||
value2.AppendToString(aProperties[1], aString, aSerialization);
|
||||
if (value1 != value3 || value2 != value4) {
|
||||
aString.Append(char16_t(' '));
|
||||
NS_ABORT_IF_FALSE(value3.GetUnit() != eCSSUnit_Null, "null value 3");
|
||||
value3.AppendToString(aProperties[2], aString, aSerialization);
|
||||
if (value2 != value4) {
|
||||
aString.Append(char16_t(' '));
|
||||
NS_ABORT_IF_FALSE(value4.GetUnit() != eCSSUnit_Null, "null value 4");
|
||||
value4.AppendToString(aProperties[3], aString, aSerialization);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
nsCSSValue::AppendBasicShapeRadiusToString(const nsCSSProperty aProperties[],
|
||||
const nsCSSValue* aValues[],
|
||||
nsAString& aResult,
|
||||
Serialization aSerialization)
|
||||
{
|
||||
bool needY = false;
|
||||
const nsCSSValue* xVals[4];
|
||||
const nsCSSValue* yVals[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (aValues[i]->GetUnit() == eCSSUnit_Pair) {
|
||||
needY = true;
|
||||
xVals[i] = &aValues[i]->GetPairValue().mXValue;
|
||||
yVals[i] = &aValues[i]->GetPairValue().mYValue;
|
||||
} else {
|
||||
xVals[i] = yVals[i] = aValues[i];
|
||||
}
|
||||
}
|
||||
|
||||
AppendSidesShorthandToString(aProperties, xVals, aResult, aSerialization);
|
||||
if (needY) {
|
||||
aResult.AppendLiteral(" / ");
|
||||
AppendSidesShorthandToString(aProperties, yVals, aResult, aSerialization);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsCSSValue::AppendInsetToString(nsCSSProperty aProperty, nsAString& aResult,
|
||||
Serialization aSerialization) const
|
||||
{
|
||||
const nsCSSValue::Array* array = GetArrayValue();
|
||||
NS_ABORT_IF_FALSE(array->Count() == 6,
|
||||
"inset function has wrong number of arguments");
|
||||
if (array->Item(1).GetUnit() != eCSSUnit_Null) {
|
||||
array->Item(1).AppendToString(aProperty, aResult, aSerialization);
|
||||
if (array->Item(2).GetUnit() != eCSSUnit_Null) {
|
||||
aResult.Append(' ');
|
||||
array->Item(2).AppendToString(aProperty, aResult, aSerialization);
|
||||
if (array->Item(3).GetUnit() != eCSSUnit_Null) {
|
||||
aResult.Append(' ');
|
||||
array->Item(3).AppendToString(aProperty, aResult, aSerialization);
|
||||
if (array->Item(4).GetUnit() != eCSSUnit_Null) {
|
||||
aResult.Append(' ');
|
||||
array->Item(4).AppendToString(aProperty, aResult, aSerialization);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (array->Item(5).GetUnit() == eCSSUnit_Array) {
|
||||
const nsCSSProperty* subprops =
|
||||
nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_radius);
|
||||
const nsCSSValue::Array* radius = array->Item(5).GetArrayValue();
|
||||
NS_ABORT_IF_FALSE(radius->Count() == 4, "expected 4 radii values");
|
||||
const nsCSSValue* vals[4] = {
|
||||
&(radius->Item(0)),
|
||||
&(radius->Item(1)),
|
||||
&(radius->Item(2)),
|
||||
&(radius->Item(3))
|
||||
};
|
||||
aResult.AppendLiteral(" round ");
|
||||
AppendBasicShapeRadiusToString(subprops, vals, aResult,
|
||||
aSerialization);
|
||||
} else {
|
||||
NS_ABORT_IF_FALSE(array->Item(5).GetUnit() == eCSSUnit_Null,
|
||||
"unexpected value");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult,
|
||||
Serialization aSerialization) const
|
||||
@ -1049,6 +1151,10 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult,
|
||||
aSerialization);
|
||||
break;
|
||||
|
||||
case eCSSKeyword_inset:
|
||||
AppendInsetToString(aProperty, aResult, aSerialization);
|
||||
break;
|
||||
|
||||
default: {
|
||||
// Now, step through the function contents, writing each of
|
||||
// them as we go.
|
||||
|
@ -714,6 +714,16 @@ public:
|
||||
|
||||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
static void
|
||||
AppendSidesShorthandToString(const nsCSSProperty aProperties[],
|
||||
const nsCSSValue* aValues[],
|
||||
nsAString& aString,
|
||||
Serialization aSerialization);
|
||||
static void
|
||||
AppendBasicShapeRadiusToString(const nsCSSProperty aProperties[],
|
||||
const nsCSSValue* aValues[],
|
||||
nsAString& aResult,
|
||||
Serialization aValueSerialization);
|
||||
private:
|
||||
static const char16_t* GetBufferValue(nsStringBuffer* aBuffer) {
|
||||
return static_cast<char16_t*>(aBuffer->Data());
|
||||
@ -729,6 +739,8 @@ private:
|
||||
nsCSSKeyword aFunctionId,
|
||||
nsCSSProperty aProperty, nsAString& aResult,
|
||||
Serialization aValueSerialization) const;
|
||||
void AppendInsetToString(nsCSSProperty aProperty, nsAString& aResult,
|
||||
Serialization aValueSerialization) const;
|
||||
protected:
|
||||
nsCSSUnit mUnit;
|
||||
union {
|
||||
@ -779,6 +791,11 @@ struct nsCSSValue::Array MOZ_FINAL {
|
||||
|
||||
size_t Count() const { return mCount; }
|
||||
|
||||
// callers depend on the items being contiguous
|
||||
nsCSSValue* ItemStorage() {
|
||||
return this->First();
|
||||
}
|
||||
|
||||
bool operator==(const Array& aOther) const
|
||||
{
|
||||
if (mCount != aOther.mCount)
|
||||
|
@ -5199,13 +5199,67 @@ inline void AppendBasicShapeTypeToString(nsStyleBasicShape::Type aType,
|
||||
case nsStyleBasicShape::Type::eEllipse:
|
||||
functionName = eCSSKeyword_ellipse;
|
||||
break;
|
||||
case nsStyleBasicShape::Type::eInset:
|
||||
functionName = eCSSKeyword_inset;
|
||||
break;
|
||||
default:
|
||||
functionName = eCSSKeyword_UNKNOWN;
|
||||
NS_NOTREACHED("unexpected type");
|
||||
}
|
||||
AppendASCIItoUTF16(nsCSSKeywords::GetStringValue(functionName),
|
||||
aString);
|
||||
}
|
||||
|
||||
void
|
||||
nsComputedDOMStyle::BoxValuesToString(nsAString& aString,
|
||||
const nsTArray<nsStyleCoord>& aBoxValues)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aBoxValues.Length() == 4, "wrong number of box values");
|
||||
nsAutoString value1, value2, value3, value4;
|
||||
SetCssTextToCoord(value1, aBoxValues[0]);
|
||||
SetCssTextToCoord(value2, aBoxValues[1]);
|
||||
SetCssTextToCoord(value3, aBoxValues[2]);
|
||||
SetCssTextToCoord(value4, aBoxValues[3]);
|
||||
|
||||
// nsROCSSPrimitiveValue do not have binary comparison operators.
|
||||
// Compare string results instead.
|
||||
aString.Append(value1);
|
||||
if (value1 != value2 || value1 != value3 || value1 != value4) {
|
||||
aString.Append(' ');
|
||||
aString.Append(value2);
|
||||
if (value1 != value3 || value2 != value4) {
|
||||
aString.Append(' ');
|
||||
aString.Append(value3);
|
||||
if (value2 != value4) {
|
||||
aString.Append(' ');
|
||||
aString.Append(value4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsComputedDOMStyle::BasicShapeRadiiToString(nsAString& aCssText,
|
||||
const nsStyleCorners& aCorners)
|
||||
{
|
||||
nsTArray<nsStyleCoord> horizontal, vertical;
|
||||
nsAutoString horizontalString, verticalString;
|
||||
NS_FOR_CSS_FULL_CORNERS(corner) {
|
||||
horizontal.AppendElement(
|
||||
aCorners.Get(NS_FULL_TO_HALF_CORNER(corner, false)));
|
||||
vertical.AppendElement(
|
||||
aCorners.Get(NS_FULL_TO_HALF_CORNER(corner, true)));
|
||||
}
|
||||
BoxValuesToString(horizontalString, horizontal);
|
||||
BoxValuesToString(verticalString, vertical);
|
||||
aCssText.Append(horizontalString);
|
||||
if (horizontalString == verticalString) {
|
||||
return;
|
||||
}
|
||||
aCssText.AppendLiteral(" / ");
|
||||
aCssText.Append(verticalString);
|
||||
}
|
||||
|
||||
CSSValue*
|
||||
nsComputedDOMStyle::CreatePrimitiveValueForClipPath(
|
||||
const nsStyleBasicShape* aStyleBasicShape, uint8_t aSizingBox)
|
||||
@ -5265,6 +5319,16 @@ nsComputedDOMStyle::CreatePrimitiveValueForClipPath(
|
||||
shapeFunctionString.Append(positionString);
|
||||
break;
|
||||
}
|
||||
case nsStyleBasicShape::Type::eInset: {
|
||||
BoxValuesToString(shapeFunctionString, aStyleBasicShape->Coordinates());
|
||||
if (aStyleBasicShape->HasRadius()) {
|
||||
shapeFunctionString.AppendLiteral(" round ");
|
||||
nsAutoString radiiString;
|
||||
BasicShapeRadiiToString(radiiString, aStyleBasicShape->GetRadius());
|
||||
shapeFunctionString.Append(radiiString);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NS_NOTREACHED("unexpected type");
|
||||
}
|
||||
|
@ -591,6 +591,11 @@ private:
|
||||
// Helper function for computing basic shape styles.
|
||||
mozilla::dom::CSSValue* CreatePrimitiveValueForClipPath(
|
||||
const nsStyleBasicShape* aStyleBasicShape, uint8_t aSizingBox);
|
||||
void BoxValuesToString(nsAString& aString,
|
||||
const nsTArray<nsStyleCoord>& aBoxValues);
|
||||
void BasicShapeRadiiToString(nsAString& aCssText,
|
||||
const nsStyleCorners& aCorners);
|
||||
|
||||
|
||||
static nsComputedStyleMap* GetComputedStyleMap();
|
||||
|
||||
|
@ -8851,8 +8851,8 @@ nsRuleNode::SetStyleClipPathToCSSValue(nsStyleClipPath* aStyleClipPath,
|
||||
basicShape->SetFillRule(shapeFunction->Item(j).GetIntValue());
|
||||
++j;
|
||||
}
|
||||
int32_t mask = SETCOORD_PERCENT | SETCOORD_LENGTH |
|
||||
SETCOORD_STORE_CALC;
|
||||
const int32_t mask = SETCOORD_PERCENT | SETCOORD_LENGTH |
|
||||
SETCOORD_STORE_CALC;
|
||||
const nsCSSValuePairList* curPair =
|
||||
shapeFunction->Item(j).GetPairListValue();
|
||||
nsTArray<nsStyleCoord>& coordinates = basicShape->Coordinates();
|
||||
@ -8879,8 +8879,8 @@ nsRuleNode::SetStyleClipPathToCSSValue(nsStyleClipPath* aStyleClipPath,
|
||||
nsStyleBasicShape::eEllipse;
|
||||
NS_ABORT_IF_FALSE(!basicShape, "did not expect value");
|
||||
basicShape = new nsStyleBasicShape(type);
|
||||
int32_t mask = SETCOORD_PERCENT | SETCOORD_LENGTH |
|
||||
SETCOORD_STORE_CALC | SETCOORD_ENUMERATED;
|
||||
const int32_t mask = SETCOORD_PERCENT | SETCOORD_LENGTH |
|
||||
SETCOORD_STORE_CALC | SETCOORD_ENUMERATED;
|
||||
size_t count = type == nsStyleBasicShape::eCircle ? 2 : 3;
|
||||
NS_ABORT_IF_FALSE(shapeFunction->Count() == count + 1,
|
||||
"unexpected arguments count");
|
||||
@ -8912,8 +8912,66 @@ nsRuleNode::SetStyleClipPathToCSSValue(nsStyleClipPath* aStyleClipPath,
|
||||
NS_ABORT_IF_FALSE(positionVal.GetUnit() == eCSSUnit_Null,
|
||||
"expected no value");
|
||||
}
|
||||
} else if (functionName == eCSSKeyword_inset) {
|
||||
NS_ABORT_IF_FALSE(!basicShape, "did not expect value");
|
||||
basicShape = new nsStyleBasicShape(nsStyleBasicShape::eInset);
|
||||
NS_ABORT_IF_FALSE(shapeFunction->Count() == 6,
|
||||
"inset function has wrong number of arguments");
|
||||
NS_ABORT_IF_FALSE(shapeFunction->Item(1).GetUnit() != eCSSUnit_Null,
|
||||
"no shape arguments defined");
|
||||
const int32_t mask = SETCOORD_PERCENT | SETCOORD_LENGTH |
|
||||
SETCOORD_STORE_CALC;
|
||||
nsTArray<nsStyleCoord>& coords = basicShape->Coordinates();
|
||||
for (size_t j = 1; j <= 4; ++j) {
|
||||
const nsCSSValue& val = shapeFunction->Item(j);
|
||||
nsStyleCoord inset;
|
||||
// Fill missing values to get 4 at the end.
|
||||
if (val.GetUnit() == eCSSUnit_Null) {
|
||||
if (j == 4) {
|
||||
inset = coords[1];
|
||||
} else {
|
||||
NS_ABORT_IF_FALSE(j != 1, "first argument not specified");
|
||||
inset = coords[0];
|
||||
}
|
||||
} else {
|
||||
DebugOnly<bool> didSetInset = SetCoord(val, inset,
|
||||
nsStyleCoord(), mask,
|
||||
aStyleContext, aPresContext,
|
||||
aCanStoreInRuleTree);
|
||||
NS_ABORT_IF_FALSE(didSetInset, "unexpected inset unit");
|
||||
}
|
||||
coords.AppendElement(inset);
|
||||
}
|
||||
|
||||
nsStyleCorners& insetRadius = basicShape->GetRadius();
|
||||
if (shapeFunction->Item(5).GetUnit() == eCSSUnit_Array) {
|
||||
nsCSSValue::Array* radiiArray = shapeFunction->Item(5).GetArrayValue();
|
||||
NS_FOR_CSS_FULL_CORNERS(corner) {
|
||||
int cx = NS_FULL_TO_HALF_CORNER(corner, false);
|
||||
int cy = NS_FULL_TO_HALF_CORNER(corner, true);
|
||||
const nsCSSValue& radius = radiiArray->Item(corner);
|
||||
nsStyleCoord coordX, coordY;
|
||||
DebugOnly<bool> didSetRadii = SetPairCoords(radius, coordX, coordY,
|
||||
nsStyleCoord(),
|
||||
nsStyleCoord(), mask,
|
||||
aStyleContext,
|
||||
aPresContext,
|
||||
aCanStoreInRuleTree);
|
||||
NS_ABORT_IF_FALSE(didSetRadii, "unexpected radius unit");
|
||||
insetRadius.Set(cx, coordX);
|
||||
insetRadius.Set(cy, coordY);
|
||||
}
|
||||
} else {
|
||||
NS_ABORT_IF_FALSE(shapeFunction->Item(5).GetUnit() ==
|
||||
eCSSUnit_Null, "unexpected value");
|
||||
// Initialize border-radius
|
||||
nsStyleCoord zero;
|
||||
zero.SetCoordValue(0);
|
||||
NS_FOR_CSS_HALF_CORNERS(j) {
|
||||
insetRadius.Set(j, zero);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// XXX Handle more basic shape functions later.
|
||||
NS_NOTREACHED("unexpected basic shape function");
|
||||
return;
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) {
|
||||
#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
|
||||
#define NS_STYLE_BASIC_SHAPE_INSET 3
|
||||
|
||||
// box-shadow
|
||||
#define NS_STYLE_BOX_SHADOW_INSET 0
|
||||
|
@ -2838,14 +2838,15 @@ struct nsStyleSVG {
|
||||
class nsStyleBasicShape MOZ_FINAL {
|
||||
public:
|
||||
enum Type {
|
||||
// eInset,
|
||||
eInset,
|
||||
eCircle,
|
||||
eEllipse,
|
||||
ePolygon
|
||||
};
|
||||
|
||||
explicit nsStyleBasicShape(Type type)
|
||||
: mType(type)
|
||||
: mType(type),
|
||||
mFillRule(NS_STYLE_FILL_RULE_NONZERO)
|
||||
{
|
||||
mPosition.SetInitialPercentValues(0.5f);
|
||||
}
|
||||
@ -2871,19 +2872,35 @@ public:
|
||||
return mPosition;
|
||||
}
|
||||
|
||||
bool HasRadius() const {
|
||||
NS_ASSERTION(mType == eInset, "expected inset");
|
||||
nsStyleCoord zero;
|
||||
zero.SetCoordValue(0);
|
||||
NS_FOR_CSS_HALF_CORNERS(corner) {
|
||||
if (mRadius.Get(corner) != zero) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
nsStyleCorners& GetRadius() {
|
||||
NS_ASSERTION(mType == eInset, "expected circle or ellipse");
|
||||
return mRadius;
|
||||
}
|
||||
const nsStyleCorners& GetRadius() const {
|
||||
NS_ASSERTION(mType == eInset, "expected circle or ellipse");
|
||||
return mRadius;
|
||||
}
|
||||
|
||||
// mCoordinates has coordinates for polygon or radii for
|
||||
// ellipse and circle.
|
||||
nsTArray<nsStyleCoord>& Coordinates()
|
||||
{
|
||||
NS_ASSERTION(mType == ePolygon || mType == eCircle || mType == eEllipse,
|
||||
"expected polygon, circle or ellipse");
|
||||
return mCoordinates;
|
||||
}
|
||||
|
||||
const nsTArray<nsStyleCoord>& Coordinates() const
|
||||
{
|
||||
NS_ASSERTION(mType == ePolygon || mType == eCircle || mType == eEllipse,
|
||||
"expected polygon, circle or ellipse");
|
||||
return mCoordinates;
|
||||
}
|
||||
|
||||
@ -2892,7 +2909,8 @@ public:
|
||||
return mType == aOther.mType &&
|
||||
mFillRule == aOther.mFillRule &&
|
||||
mCoordinates == aOther.mCoordinates &&
|
||||
mPosition == aOther.mPosition;
|
||||
mPosition == aOther.mPosition &&
|
||||
mRadius == aOther.mRadius;
|
||||
}
|
||||
bool operator!=(const nsStyleBasicShape& aOther) const {
|
||||
return !(*this == aOther);
|
||||
@ -2905,10 +2923,12 @@ private:
|
||||
|
||||
Type mType;
|
||||
int32_t mFillRule;
|
||||
|
||||
// mCoordinates has coordinates for polygon or radii for
|
||||
// ellipse and circle.
|
||||
nsTArray<nsStyleCoord> mCoordinates;
|
||||
Position mPosition;
|
||||
nsStyleCorners mRadius;
|
||||
};
|
||||
|
||||
struct nsStyleClipPath
|
||||
|
@ -4633,7 +4633,7 @@ if (SpecialPowers.getBoolPref("svg.paint-order.enabled")) {
|
||||
|
||||
if (SpecialPowers.getBoolPref("layout.css.clip-path-shapes.enabled")) {
|
||||
gCSSProperties["clip-path"] = {
|
||||
domProp: "clip-path",
|
||||
domProp: "clipPath",
|
||||
inherited: false,
|
||||
type: CSS_TYPE_LONGHAND,
|
||||
initial_values: [ "none" ],
|
||||
@ -4702,6 +4702,15 @@ if (SpecialPowers.getBoolPref("layout.css.clip-path-shapes.enabled")) {
|
||||
"ellipse(20px 50% at top right)",
|
||||
"ellipse(closest-side 40% at 50% 100%)",
|
||||
"ellipse(calc(20% + 20%) calc(20px + 20cm) at right bottom)",
|
||||
|
||||
"inset(1px)",
|
||||
"inset(20% -20px)",
|
||||
"inset(20em 4rem calc(20% + 20px))",
|
||||
"inset(20vh 20vw 20pt 3%)",
|
||||
"inset(5px round 3px)",
|
||||
"inset(1px 2px round 3px / 3px)",
|
||||
"inset(1px 2px 3px round 3px 2em / 20%)",
|
||||
"inset(1px 2px 3px 4px round 3px 2vw 20% / 20px 3em 2vh 20%)",
|
||||
],
|
||||
invalid_values: [
|
||||
"url(#test) url(#tes2)",
|
||||
@ -4767,6 +4776,18 @@ if (SpecialPowers.getBoolPref("layout.css.clip-path-shapes.enabled")) {
|
||||
"polygon(at center top closest-side closest-side)",
|
||||
"polygon(40% at 50% 100%)",
|
||||
"polygon(40% farthest-side 20px at 50% 100%)",
|
||||
|
||||
"inset()",
|
||||
"inset(round)",
|
||||
"inset(round 3px)",
|
||||
"inset(1px round 1px 2px 3px 4px 5px)",
|
||||
"inset(1px 2px 3px 4px 5px)",
|
||||
"inset(1px, round 3px)",
|
||||
"inset(1px, 2px)",
|
||||
"inset(1px 2px, 3px)",
|
||||
"inset(1px at 3px)",
|
||||
"inset(1px round 1px // 2px)",
|
||||
"inset(1px round)",
|
||||
],
|
||||
unbalanced_values: [
|
||||
"polygon(30% 30%",
|
||||
@ -4777,6 +4798,13 @@ if (SpecialPowers.getBoolPref("layout.css.clip-path-shapes.enabled")) {
|
||||
"circle(40% at 50% 100%",
|
||||
"ellipse(",
|
||||
"ellipse(40% at 50% 100%",
|
||||
|
||||
"inset(1px",
|
||||
"inset(1px 2px",
|
||||
"inset(1px 2px 3px",
|
||||
"inset(1px 2px 3px 4px",
|
||||
"inset(1px 2px 3px 4px round 5px",
|
||||
"inset(1px 2px 3px 4px round 5px / 6px",
|
||||
]
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user