Bug 1496008 - Serialize a bunch of image properties with Servo. r=heycam

I had to fix the conversion for BackgroundSize too, hopefully we can
simplify all this using cbindgen in the future instead of CalcValue.

Differential Revision: https://phabricator.services.mozilla.com/D7580

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Emilio Cobos Álvarez 2018-10-05 20:08:55 +00:00
parent 26da3328fb
commit e929975273
13 changed files with 105 additions and 633 deletions

View File

@ -2061,6 +2061,13 @@ Gecko_GetComputedURLSpec(const URLValueData* aURL, nsCString* aOut)
aOut->Assign(aURL->GetString());
return;
}
Gecko_GetComputedImageURLSpec(aURL, aOut);
}
void
Gecko_GetComputedImageURLSpec(const URLValueData* aURL, nsCString* aOut)
{
// Image URIs don't serialize local refs as local.
if (nsIURI* uri = aURL->GetURI()) {
nsresult rv = uri->GetSpec(*aOut);
if (NS_SUCCEEDED(rv)) {

View File

@ -550,6 +550,7 @@ void Gecko_nsStyleSVG_CopyContextProperties(nsStyleSVG* dst, const nsStyleSVG* s
mozilla::css::URLValue* Gecko_NewURLValue(ServoBundledURI uri);
size_t Gecko_URLValue_SizeOfIncludingThis(mozilla::css::URLValue* url);
void Gecko_GetComputedURLSpec(const mozilla::css::URLValueData* url, nsCString* spec);
void Gecko_GetComputedImageURLSpec(const mozilla::css::URLValueData* url, nsCString* spec);
void Gecko_nsIURI_Debug(nsIURI*, nsCString* spec);
NS_DECL_THREADSAFE_FFI_REFCOUNTING(mozilla::css::URLValue, CSSURLValue);

View File

@ -67,6 +67,8 @@ def method(prop):
# but other non-trivial dependence like scrollbar colors.
SERIALIZED_PREDEFINED_TYPES = [
"Appearance",
"BackgroundRepeat",
"BackgroundSize",
"Clear",
"ClipRectOrAuto",
"Color",
@ -90,6 +92,7 @@ SERIALIZED_PREDEFINED_TYPES = [
"FontVariationSettings",
"FontWeight",
"Integer",
"ImageLayer",
"Length",
"LengthOrPercentage",
"NonNegativeLength",
@ -98,8 +101,12 @@ SERIALIZED_PREDEFINED_TYPES = [
"OffsetPath",
"Opacity",
"Resize",
"TransformStyle",
"background::BackgroundSize",
"basic_shape::ClippingShape",
"basic_shape::FloatAreaShape",
"position::HorizontalPosition",
"position::VerticalPosition",
"url::ImageUrlOrNone",
]

View File

@ -190,22 +190,6 @@ nsCSSProps::GetStringValue(nsCSSCounterDesc aCounterDesc)
/***************************************************************************/
const KTableEntry nsCSSProps::kTransformStyleKTable[] = {
{ eCSSKeyword_flat, NS_STYLE_TRANSFORM_STYLE_FLAT },
{ eCSSKeyword_preserve_3d, NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D },
{ eCSSKeyword_UNKNOWN, -1 }
};
const KTableEntry nsCSSProps::kImageLayerRepeatKTable[] = {
{ eCSSKeyword_no_repeat, StyleImageLayerRepeat::NoRepeat },
{ eCSSKeyword_repeat, StyleImageLayerRepeat::Repeat },
{ eCSSKeyword_repeat_x, StyleImageLayerRepeat::RepeatX },
{ eCSSKeyword_repeat_y, StyleImageLayerRepeat::RepeatY },
{ eCSSKeyword_round, StyleImageLayerRepeat::Round},
{ eCSSKeyword_space, StyleImageLayerRepeat::Space},
{ eCSSKeyword_UNKNOWN, -1 }
};
const KTableEntry nsCSSProps::kBorderImageRepeatKTable[] = {
{ eCSSKeyword_stretch, StyleBorderImageRepeat::Stretch },
{ eCSSKeyword_repeat, StyleBorderImageRepeat::Repeat },
@ -566,14 +550,6 @@ const KTableEntry nsCSSProps::kOverflowSubKTable[] = {
{ eCSSKeyword_UNKNOWN, -1 }
};
const KTableEntry nsCSSProps::kRadialGradientSizeKTable[] = {
{ eCSSKeyword_closest_side, NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE },
{ eCSSKeyword_closest_corner, NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER },
{ eCSSKeyword_farthest_side, NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE },
{ eCSSKeyword_farthest_corner, NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER },
{ eCSSKeyword_UNKNOWN, -1 }
};
const KTableEntry nsCSSProps::kOverscrollBehaviorKTable[] = {
{ eCSSKeyword_auto, StyleOverscrollBehavior::Auto },
{ eCSSKeyword_contain, StyleOverscrollBehavior::Contain },

View File

@ -307,8 +307,6 @@ public:
if (nsCSSProps::IsEnabled(*it_, (mozilla::CSSEnabledState) es_))
// Keyword/Enum value tables
static const KTableEntry kTransformStyleKTable[];
static const KTableEntry kImageLayerRepeatKTable[];
// Not const because we modify its entries when the pref
// "layout.css.background-clip.text" changes:
static const KTableEntry kBorderImageRepeatKTable[];
@ -345,7 +343,6 @@ public:
static const KTableEntry kOverflowKTable[];
static const KTableEntry kOverflowSubKTable[];
static const KTableEntry kOverflowClipBoxKTable[];
static const KTableEntry kRadialGradientSizeKTable[];
static const KTableEntry kOverscrollBehaviorKTable[];
static const KTableEntry kScrollSnapTypeKTable[];
// Not const because we modify its entries when the pref

View File

@ -1293,16 +1293,6 @@ nsComputedDOMStyle::DoGetPerspective()
return val.forget();
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetTransformStyle()
{
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetIdent(
nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mTransformStyle,
nsCSSProps::kTransformStyleKTable));
return val.forget();
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetTransform()
{
@ -1654,312 +1644,6 @@ SetValueToCalc(const nsStyleCoord::CalcValue* aCalc,
aValue->SetString(result); // not really SetString
}
static void
AppendCSSGradientLength(const nsStyleCoord& aValue,
nsROCSSPrimitiveValue* aPrimitive,
nsAString& aString)
{
nsAutoString tokenString;
if (aValue.IsCalcUnit())
SetValueToCalc(aValue.GetCalcValue(), aPrimitive);
else if (aValue.GetUnit() == eStyleUnit_Coord)
aPrimitive->SetAppUnits(aValue.GetCoordValue());
else
aPrimitive->SetPercent(aValue.GetPercentValue());
aPrimitive->GetCssText(tokenString);
aString.Append(tokenString);
}
static void
AppendCSSGradientToBoxPosition(const nsStyleGradient* aGradient,
nsAString& aString,
bool& aNeedSep)
{
// This function only supports box position keywords. Make sure we're not
// calling it with inputs that would have coordinates that aren't
// representable with box-position keywords.
MOZ_ASSERT(aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR &&
!(aGradient->mLegacySyntax && aGradient->mMozLegacySyntax),
"Only call me for linear-gradient and -webkit-linear-gradient");
float xValue = aGradient->mBgPosX.GetPercentValue();
float yValue = aGradient->mBgPosY.GetPercentValue();
if (xValue == 0.5f &&
yValue == (aGradient->mLegacySyntax ? 0.0f : 1.0f)) {
// omit "to bottom" in modern syntax, "top" in legacy syntax
return;
}
NS_ASSERTION(yValue != 0.5f || xValue != 0.5f, "invalid box position");
if (!aGradient->mLegacySyntax) {
// Modern syntax explicitly includes the word "to". Old syntax does not
// (and is implicitly "from" the given position instead).
aString.AppendLiteral("to ");
}
if (xValue == 0.0f) {
aString.AppendLiteral("left");
} else if (xValue == 1.0f) {
aString.AppendLiteral("right");
} else if (xValue != 0.5f) { // do not write "center" keyword
MOZ_ASSERT_UNREACHABLE("invalid box position");
}
if (xValue != 0.5f && yValue != 0.5f) {
// We're appending both an x-keyword and a y-keyword.
// Add a space between them here.
aString.AppendLiteral(" ");
}
if (yValue == 0.0f) {
aString.AppendLiteral("top");
} else if (yValue == 1.0f) {
aString.AppendLiteral("bottom");
} else if (yValue != 0.5f) { // do not write "center" keyword
MOZ_ASSERT_UNREACHABLE("invalid box position");
}
aNeedSep = true;
}
void
nsComputedDOMStyle::GetCSSGradientString(const nsStyleGradient* aGradient,
nsAString& aString)
{
if (!aGradient->mLegacySyntax) {
aString.Truncate();
} else {
if (aGradient->mMozLegacySyntax) {
aString.AssignLiteral("-moz-");
} else {
aString.AssignLiteral("-webkit-");
}
}
if (aGradient->mRepeating) {
aString.AppendLiteral("repeating-");
}
bool isRadial = aGradient->mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR;
if (isRadial) {
aString.AppendLiteral("radial-gradient(");
} else {
aString.AppendLiteral("linear-gradient(");
}
bool needSep = false;
nsAutoString tokenString;
RefPtr<nsROCSSPrimitiveValue> tmpVal = new nsROCSSPrimitiveValue;
if (isRadial && !aGradient->mLegacySyntax) {
if (aGradient->mSize != NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE) {
if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_CIRCULAR) {
aString.AppendLiteral("circle");
needSep = true;
}
if (aGradient->mSize != NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER) {
if (needSep) {
aString.Append(' ');
}
AppendASCIItoUTF16(nsCSSProps::
ValueToKeyword(aGradient->mSize,
nsCSSProps::kRadialGradientSizeKTable),
aString);
needSep = true;
}
} else {
AppendCSSGradientLength(aGradient->mRadiusX, tmpVal, aString);
if (aGradient->mShape != NS_STYLE_GRADIENT_SHAPE_CIRCULAR) {
aString.Append(' ');
AppendCSSGradientLength(aGradient->mRadiusY, tmpVal, aString);
}
needSep = true;
}
}
if (aGradient->mBgPosX.GetUnit() != eStyleUnit_None) {
MOZ_ASSERT(aGradient->mBgPosY.GetUnit() != eStyleUnit_None);
if (!isRadial &&
!(aGradient->mLegacySyntax && aGradient->mMozLegacySyntax)) {
// linear-gradient() or -webkit-linear-gradient()
AppendCSSGradientToBoxPosition(aGradient, aString, needSep);
} else if (aGradient->mBgPosX.GetUnit() != eStyleUnit_Percent ||
aGradient->mBgPosX.GetPercentValue() != 0.5f ||
aGradient->mBgPosY.GetUnit() != eStyleUnit_Percent ||
aGradient->mBgPosY.GetPercentValue() != (isRadial ? 0.5f : 0.0f)) {
// [-vendor-]radial-gradient or -moz-linear-gradient, with
// non-default box position, which we output here.
if (isRadial && !aGradient->mLegacySyntax) {
if (needSep) {
aString.Append(' ');
}
aString.AppendLiteral("at ");
needSep = false;
}
AppendCSSGradientLength(aGradient->mBgPosX, tmpVal, aString);
if (aGradient->mBgPosY.GetUnit() != eStyleUnit_None) {
aString.Append(' ');
AppendCSSGradientLength(aGradient->mBgPosY, tmpVal, aString);
}
needSep = true;
}
}
if (aGradient->mAngle.GetUnit() != eStyleUnit_None) {
MOZ_ASSERT(!isRadial || aGradient->mLegacySyntax);
if (needSep) {
aString.Append(' ');
}
nsStyleUtil::AppendAngleValue(aGradient->mAngle, aString);
needSep = true;
}
if (isRadial && aGradient->mLegacySyntax &&
(aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_CIRCULAR ||
aGradient->mSize != NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER)) {
MOZ_ASSERT(aGradient->mSize != NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE);
if (needSep) {
aString.AppendLiteral(", ");
needSep = false;
}
if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_CIRCULAR) {
aString.AppendLiteral("circle");
needSep = true;
}
if (aGradient->mSize != NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER) {
if (needSep) {
aString.Append(' ');
}
AppendASCIItoUTF16(nsCSSProps::
ValueToKeyword(aGradient->mSize,
nsCSSProps::kRadialGradientSizeKTable),
aString);
}
needSep = true;
}
// color stops
for (uint32_t i = 0; i < aGradient->mStops.Length(); ++i) {
if (needSep) {
aString.AppendLiteral(", ");
}
const auto& stop = aGradient->mStops[i];
if (!stop.mIsInterpolationHint) {
SetValueFromComplexColor(tmpVal, stop.mColor);
tmpVal->GetCssText(tokenString);
aString.Append(tokenString);
}
if (stop.mLocation.GetUnit() != eStyleUnit_None) {
if (!stop.mIsInterpolationHint) {
aString.Append(' ');
}
AppendCSSGradientLength(stop.mLocation, tmpVal, aString);
}
needSep = true;
}
aString.Append(')');
}
// -moz-image-rect(<uri>, <top>, <right>, <bottom>, <left>)
void
nsComputedDOMStyle::GetImageRectString(nsIURI* aURI,
const nsStyleSides& aCropRect,
nsString& aString)
{
RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
// <uri>
RefPtr<nsROCSSPrimitiveValue> valURI = new nsROCSSPrimitiveValue;
valURI->SetURI(aURI);
valueList->AppendCSSValue(valURI.forget());
// <top>, <right>, <bottom>, <left>
NS_FOR_CSS_SIDES(side) {
RefPtr<nsROCSSPrimitiveValue> valSide = new nsROCSSPrimitiveValue;
SetValueToCoord(valSide, aCropRect.Get(side), false);
valueList->AppendCSSValue(valSide.forget());
}
nsAutoString argumentString;
valueList->GetCssText(argumentString);
aString = NS_LITERAL_STRING("-moz-image-rect(") +
argumentString +
NS_LITERAL_STRING(")");
}
void
nsComputedDOMStyle::SetValueToStyleImage(const nsStyleImage& aStyleImage,
nsROCSSPrimitiveValue* aValue)
{
switch (aStyleImage.GetType()) {
case eStyleImageType_Image:
{
nsCOMPtr<nsIURI> uri = aStyleImage.GetImageURI();
if (!uri) {
aValue->SetIdent(eCSSKeyword_none);
break;
}
const UniquePtr<nsStyleSides>& cropRect = aStyleImage.GetCropRect();
if (cropRect) {
nsAutoString imageRectString;
GetImageRectString(uri, *cropRect, imageRectString);
aValue->SetString(imageRectString);
} else {
aValue->SetURI(uri);
}
break;
}
case eStyleImageType_Gradient:
{
nsAutoString gradientString;
GetCSSGradientString(aStyleImage.GetGradientData(),
gradientString);
aValue->SetString(gradientString);
break;
}
case eStyleImageType_Element:
{
nsAutoString elementId;
nsStyleUtil::AppendEscapedCSSIdent(
nsDependentAtomString(aStyleImage.GetElementId()),
elementId);
nsAutoString elementString = NS_LITERAL_STRING("-moz-element(#") +
elementId +
NS_LITERAL_STRING(")");
aValue->SetString(elementString);
break;
}
case eStyleImageType_Null:
aValue->SetIdent(eCSSKeyword_none);
break;
case eStyleImageType_URL:
SetValueToURLValue(aStyleImage.GetURLValue(), aValue);
break;
default:
MOZ_ASSERT_UNREACHABLE("unexpected image type");
break;
}
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetImageLayerImage(const nsStyleImageLayers& aLayers)
{
RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
for (uint32_t i = 0, i_end = aLayers.mImageCount; i < i_end; ++i) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
SetValueToStyleImage(aLayers.mLayers[i].mImage, val);
valueList->AppendCSSValue(val.forget());
}
return valueList.forget();
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetImageLayerPosition(const nsStyleImageLayers& aLayers)
{
@ -1980,166 +1664,6 @@ nsComputedDOMStyle::DoGetImageLayerPosition(const nsStyleImageLayers& aLayers)
return valueList.forget();
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetImageLayerPositionX(const nsStyleImageLayers& aLayers)
{
RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
for (uint32_t i = 0, i_end = aLayers.mPositionXCount; i < i_end; ++i) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
SetValueToPositionCoord(aLayers.mLayers[i].mPosition.mXPosition, val);
valueList->AppendCSSValue(val.forget());
}
return valueList.forget();
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetImageLayerPositionY(const nsStyleImageLayers& aLayers)
{
RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
for (uint32_t i = 0, i_end = aLayers.mPositionYCount; i < i_end; ++i) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
SetValueToPositionCoord(aLayers.mLayers[i].mPosition.mYPosition, val);
valueList->AppendCSSValue(val.forget());
}
return valueList.forget();
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetImageLayerRepeat(const nsStyleImageLayers& aLayers)
{
RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
for (uint32_t i = 0, i_end = aLayers.mRepeatCount; i < i_end; ++i) {
RefPtr<nsDOMCSSValueList> itemList = GetROCSSValueList(false);
RefPtr<nsROCSSPrimitiveValue> valX = new nsROCSSPrimitiveValue;
const StyleImageLayerRepeat xRepeat = aLayers.mLayers[i].mRepeat.mXRepeat;
const StyleImageLayerRepeat yRepeat = aLayers.mLayers[i].mRepeat.mYRepeat;
bool hasContraction = true;
unsigned contraction;
if (xRepeat == yRepeat) {
contraction = uint8_t(xRepeat);
} else if (xRepeat == StyleImageLayerRepeat::Repeat &&
yRepeat == StyleImageLayerRepeat::NoRepeat) {
contraction = uint8_t(StyleImageLayerRepeat::RepeatX);
} else if (xRepeat == StyleImageLayerRepeat::NoRepeat &&
yRepeat == StyleImageLayerRepeat::Repeat) {
contraction = uint8_t(StyleImageLayerRepeat::RepeatY);
} else {
hasContraction = false;
}
RefPtr<nsROCSSPrimitiveValue> valY;
if (hasContraction) {
valX->SetIdent(nsCSSProps::ValueToKeywordEnum(contraction,
nsCSSProps::kImageLayerRepeatKTable));
} else {
valY = new nsROCSSPrimitiveValue;
valX->SetIdent(nsCSSProps::ValueToKeywordEnum(xRepeat,
nsCSSProps::kImageLayerRepeatKTable));
valY->SetIdent(nsCSSProps::ValueToKeywordEnum(yRepeat,
nsCSSProps::kImageLayerRepeatKTable));
}
itemList->AppendCSSValue(valX.forget());
if (valY) {
itemList->AppendCSSValue(valY.forget());
}
valueList->AppendCSSValue(itemList.forget());
}
return valueList.forget();
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetImageLayerSize(const nsStyleImageLayers& aLayers)
{
RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
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
: eCSSKeyword_cover;
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetIdent(keyword);
valueList->AppendCSSValue(val.forget());
break;
}
default: {
RefPtr<nsDOMCSSValueList> itemList = GetROCSSValueList(false);
RefPtr<nsROCSSPrimitiveValue> valX = new nsROCSSPrimitiveValue;
RefPtr<nsROCSSPrimitiveValue> valY = new nsROCSSPrimitiveValue;
if (size.mWidthType == nsStyleImageLayers::Size::eAuto) {
valX->SetIdent(eCSSKeyword_auto);
} else {
MOZ_ASSERT(size.mWidthType ==
nsStyleImageLayers::Size::eLengthPercentage,
"bad mWidthType");
if (!size.mWidth.mHasPercent &&
// negative values must have come from calc()
size.mWidth.mLength >= 0) {
MOZ_ASSERT(size.mWidth.mPercent == 0.0f,
"Shouldn't have mPercent");
valX->SetAppUnits(size.mWidth.mLength);
} else if (size.mWidth.mLength == 0 &&
// negative values must have come from calc()
size.mWidth.mPercent >= 0.0f) {
valX->SetPercent(size.mWidth.mPercent);
} else {
SetValueToCalc(&size.mWidth, valX);
}
}
if (size.mHeightType == nsStyleImageLayers::Size::eAuto) {
valY->SetIdent(eCSSKeyword_auto);
} else {
MOZ_ASSERT(size.mHeightType ==
nsStyleImageLayers::Size::eLengthPercentage,
"bad mHeightType");
if (!size.mHeight.mHasPercent &&
// negative values must have come from calc()
size.mHeight.mLength >= 0) {
MOZ_ASSERT(size.mHeight.mPercent == 0.0f,
"Shouldn't have mPercent");
valY->SetAppUnits(size.mHeight.mLength);
} else if (size.mHeight.mLength == 0 &&
// negative values must have come from calc()
size.mHeight.mPercent >= 0.0f) {
valY->SetPercent(size.mHeight.mPercent);
} else {
SetValueToCalc(&size.mHeight, valY);
}
}
itemList->AppendCSSValue(valX.forget());
itemList->AppendCSSValue(valY.forget());
valueList->AppendCSSValue(itemList.forget());
break;
}
}
}
return valueList.forget();
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetBackgroundImage()
{
const nsStyleImageLayers& layers = StyleBackground()->mImage;
return DoGetImageLayerImage(layers);
}
void
nsComputedDOMStyle::SetValueToPositionCoord(
const Position::Coord& aCoord,
@ -2207,34 +1731,6 @@ nsComputedDOMStyle::DoGetBackgroundPosition()
return DoGetImageLayerPosition(layers);
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetBackgroundPositionX()
{
const nsStyleImageLayers& layers = StyleBackground()->mImage;
return DoGetImageLayerPositionX(layers);
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetBackgroundPositionY()
{
const nsStyleImageLayers& layers = StyleBackground()->mImage;
return DoGetImageLayerPositionY(layers);
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetBackgroundRepeat()
{
const nsStyleImageLayers& layers = StyleBackground()->mImage;
return DoGetImageLayerRepeat(layers);
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetBackgroundSize()
{
const nsStyleImageLayers& layers = StyleBackground()->mImage;
return DoGetImageLayerSize(layers);
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetGridTemplateAreas()
{
@ -3502,18 +2998,6 @@ nsComputedDOMStyle::DoGetBoxFlex()
/* Border image properties */
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetBorderImageSource()
{
const nsStyleBorder* border = StyleBorder();
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
const nsStyleImage& image = border->mBorderImageSource;
SetValueToStyleImage(image, val);
return val.forget();
}
void
nsComputedDOMStyle::AppendFourSideCoordValues(nsDOMCSSValueList* aList,
const nsStyleSides& aValues)
@ -5054,13 +4538,6 @@ nsComputedDOMStyle::DoGetMask()
return val.forget();
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetMaskImage()
{
const nsStyleImageLayers& layers = StyleSVGReset()->mMask;
return DoGetImageLayerImage(layers);
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetMaskPosition()
{
@ -5068,34 +4545,6 @@ nsComputedDOMStyle::DoGetMaskPosition()
return DoGetImageLayerPosition(layers);
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetMaskPositionX()
{
const nsStyleImageLayers& layers = StyleSVGReset()->mMask;
return DoGetImageLayerPositionX(layers);
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetMaskPositionY()
{
const nsStyleImageLayers& layers = StyleSVGReset()->mMask;
return DoGetImageLayerPositionY(layers);
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetMaskRepeat()
{
const nsStyleImageLayers& layers = StyleSVGReset()->mMask;
return DoGetImageLayerRepeat(layers);
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetMaskSize()
{
const nsStyleImageLayers& layers = StyleSVGReset()->mMask;
return DoGetImageLayerSize(layers);
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetPaintOrder()
{

View File

@ -281,29 +281,14 @@ private:
already_AddRefed<CSSValue> DoGetGridRowEnd();
/* StyleImageLayer properties */
already_AddRefed<CSSValue> DoGetImageLayerImage(const nsStyleImageLayers& aLayers);
already_AddRefed<CSSValue> DoGetImageLayerPosition(const nsStyleImageLayers& aLayers);
already_AddRefed<CSSValue> DoGetImageLayerPositionX(const nsStyleImageLayers& aLayers);
already_AddRefed<CSSValue> DoGetImageLayerPositionY(const nsStyleImageLayers& aLayers);
already_AddRefed<CSSValue> DoGetImageLayerRepeat(const nsStyleImageLayers& aLayers);
already_AddRefed<CSSValue> DoGetImageLayerSize(const nsStyleImageLayers& aLayers);
/* Background properties */
already_AddRefed<CSSValue> DoGetBackgroundImage();
already_AddRefed<CSSValue> DoGetBackgroundPosition();
already_AddRefed<CSSValue> DoGetBackgroundPositionX();
already_AddRefed<CSSValue> DoGetBackgroundPositionY();
already_AddRefed<CSSValue> DoGetBackgroundRepeat();
already_AddRefed<CSSValue> DoGetBackgroundSize();
/* Mask properties */
already_AddRefed<CSSValue> DoGetMask();
already_AddRefed<CSSValue> DoGetMaskImage();
already_AddRefed<CSSValue> DoGetMaskPosition();
already_AddRefed<CSSValue> DoGetMaskPositionX();
already_AddRefed<CSSValue> DoGetMaskPositionY();
already_AddRefed<CSSValue> DoGetMaskRepeat();
already_AddRefed<CSSValue> DoGetMaskSize();
/* Padding properties */
already_AddRefed<CSSValue> DoGetPaddingTop();
@ -330,7 +315,6 @@ private:
already_AddRefed<CSSValue> DoGetBorderTopRightRadius();
/* Border Image */
already_AddRefed<CSSValue> DoGetBorderImageSource();
already_AddRefed<CSSValue> DoGetBorderImageSlice();
already_AddRefed<CSSValue> DoGetBorderImageWidth();
already_AddRefed<CSSValue> DoGetBorderImageOutset();
@ -399,7 +383,6 @@ private:
already_AddRefed<CSSValue> DoGetTransformOrigin();
already_AddRefed<CSSValue> DoGetPerspective();
already_AddRefed<CSSValue> DoGetPerspectiveOrigin();
already_AddRefed<CSSValue> DoGetTransformStyle();
already_AddRefed<CSSValue> DoGetOverscrollBehaviorX();
already_AddRefed<CSSValue> DoGetOverscrollBehaviorY();
already_AddRefed<CSSValue> DoGetScrollSnapTypeX();
@ -483,8 +466,6 @@ private:
void SetValueForWidgetColor(nsROCSSPrimitiveValue* aValue,
const mozilla::StyleComplexColor& aColor,
mozilla::StyleAppearance aWidgetType);
void SetValueToStyleImage(const nsStyleImage& aStyleImage,
nsROCSSPrimitiveValue* aValue);
void SetValueToPositionCoord(const mozilla::Position::Coord& aCoord,
nsROCSSPrimitiveValue* aValue);
void SetValueToPosition(const mozilla::Position& aPosition,

View File

@ -178,9 +178,9 @@ var noframe_container = document.getElementById("content");
[ "0 calc(3px - 3px)", "0px 0px", "computed 0 calc with units vertical" ],
[ "calc(0%) 0", "0% 0px", "0% calc horizontal"],
[ "0 calc(0%)", "0px 0%", "0% calc vertical"],
[ "calc(3px + 2% - 2%) 0", "calc(3px + 0%) 0px",
[ "calc(3px + 2% - 2%) 0", "calc(0% + 3px) 0px",
"computed 0% calc horizontal"],
[ "0 calc(3px + 2% - 2%)", "0px calc(3px + 0%)",
[ "0 calc(3px + 2% - 2%)", "0px calc(0% + 3px)",
"computed 0% calc vertical"],
[ "calc(3px - 5px) calc(6px - 9px)",
"calc(-2px) calc(-3px)", "negative pixel width" ],
@ -207,10 +207,10 @@ var noframe_container = document.getElementById("content");
"radial-gradient(at 10% 100%, rgb(255, 255, 255), rgb(0, 0, 0))",
"radial gradient 1" ],
[ "radial-gradient(#ffffff, black)",
"radial-gradient(rgb(255, 255, 255), rgb(0, 0, 0))",
"radial-gradient(at 50% 50%, rgb(255, 255, 255), rgb(0, 0, 0))",
"radial gradient 2" ],
[ "radial-gradient(farthest-corner, #ffffff, black)",
"radial-gradient(rgb(255, 255, 255), rgb(0, 0, 0))",
"radial-gradient(at 50% 50%, rgb(255, 255, 255), rgb(0, 0, 0))",
"radial gradient 3" ],
[ "linear-gradient(red, blue)",
"linear-gradient(rgb(255, 0, 0), rgb(0, 0, 255))",
@ -629,7 +629,7 @@ var noframe_container = document.getElementById("content");
// Radial gradients (should be serialized using modern unprefixed style):
[ "-webkit-radial-gradient(contain, red, blue)",
"radial-gradient(closest-side, rgb(255, 0, 0), rgb(0, 0, 255))",
"radial-gradient(closest-side at 50% 50%, rgb(255, 0, 0), rgb(0, 0, 255))",
"-webkit-radial-gradient with legacy 'contain' keyword" ],
];

View File

@ -2526,11 +2526,11 @@ function test_background_position_coord_transition(prop) {
// values.
div.style.setProperty("transition-property", "none", "");
div.style.setProperty(prop, `${endEdge} 20px`, "");
is(cs.getPropertyValue(prop), "calc(-20px + 100%)",
is(cs.getPropertyValue(prop), "calc(100% - 20px)",
"property " + prop + ": computed value before transition");
div.style.setProperty("transition-property", prop, "");
div.style.setProperty(prop, "calc(40px + 20%)", "");
is(cs.getPropertyValue(prop), "calc(-5px + 80%)",
is(cs.getPropertyValue(prop), "calc(80% - 5px)",
"property " + prop + ": interpolation of edge keywords w/ offsets & calc");
check_distance(prop, `${endEdge} 20px`,
"calc(-5px + 80%)",
@ -2566,7 +2566,7 @@ function test_background_position_coord_transition(prop) {
"property " + prop + ": computed value before transition");
div.style.setProperty("transition-property", prop, "");
div.style.setProperty(prop, "12px, 40%", "");
is(cs.getPropertyValue(prop), "calc(3px + 15%), calc(6px + 10%)",
is(cs.getPropertyValue(prop), "calc(15% + 3px), calc(10% + 6px)",
"property " + prop + ": interpolation that computes to calc()");
check_distance(prop, "20%, 8px",
"calc(3px + 15%), calc(6px + 10%)",
@ -2574,11 +2574,11 @@ function test_background_position_coord_transition(prop) {
div.style.setProperty("transition-property", "none", "");
div.style.setProperty(prop, "calc(20% + 40px), 8px, calc(20px + 12%)", "");
is(cs.getPropertyValue(prop), "calc(40px + 20%), 8px, calc(20px + 12%)",
is(cs.getPropertyValue(prop), "calc(20% + 40px), 8px, calc(12% + 20px)",
"property " + prop + ": computed value before transition");
div.style.setProperty("transition-property", prop, "");
div.style.setProperty(prop, "12px, calc(20%), calc(8px + 20%)", "");
is(cs.getPropertyValue(prop), "calc(33px + 15%), calc(6px + 5%), calc(17px + 14%)",
is(cs.getPropertyValue(prop), "calc(15% + 33px), calc(5% + 6px), calc(14% + 17px)",
"property " + prop + ": interpolation that computes to calc()");
check_distance(prop, "calc(20% + 40px), 8px, calc(20px + 12%)",
"calc(33px + 15%), calc(6px + 5%), calc(17px + 14%)",
@ -2634,6 +2634,8 @@ function test_background_position_size_common(prop, doesPropTakeListValues,
check_distance(prop, "10px 40px", "20px 30px", "50px 0");
}
const serializesCalcAccordingToTheSpec = prop == "mask-size" || prop == "background-size";
// Test interpolation that computes to to calc() (transition from % to px)
div.style.setProperty("transition-property", "none", "");
div.style.setProperty(prop, "20% 40%", "");
@ -2641,7 +2643,8 @@ function test_background_position_size_common(prop, doesPropTakeListValues,
"property " + prop + ": computed value before transition");
div.style.setProperty("transition-property", prop, "");
div.style.setProperty(prop, "12px 20px", "");
is(cs.getPropertyValue(prop), "calc(3px + 15%) calc(5px + 30%)",
is(cs.getPropertyValue(prop),
serializesCalcAccordingToTheSpec ? "calc(15% + 3px) calc(30% + 5px)" : "calc(3px + 15%) calc(5px + 30%)",
"property " + prop + ": interpolation that computes to calc()");
if (doesPropHaveDistanceComputation) {
check_distance(prop, "20% 40%",
@ -2656,7 +2659,8 @@ function test_background_position_size_common(prop, doesPropTakeListValues,
"property " + prop + ": computed value before transition");
div.style.setProperty("transition-property", prop, "");
div.style.setProperty(prop, "20% 40%", "");
is(cs.getPropertyValue(prop), "calc(9px + 5%) calc(15px + 10%)",
is(cs.getPropertyValue(prop),
serializesCalcAccordingToTheSpec ? "calc(5% + 9px) calc(10% + 15px)" : "calc(9px + 5%) calc(15px + 10%)",
"property " + prop + ": interpolation that computes to calc()");
if (doesPropHaveDistanceComputation) {
check_distance(prop, "12px 20px",
@ -2667,11 +2671,11 @@ function test_background_position_size_common(prop, doesPropTakeListValues,
// Test interpolation between calc() and non-calc()
div.style.setProperty("transition-property", "none", "");
div.style.setProperty(prop, "calc(40px + 10%) 16px", "");
is(cs.getPropertyValue(prop), "calc(40px + 10%) 16px",
is(cs.getPropertyValue(prop), serializesCalcAccordingToTheSpec ? "calc(10% + 40px) 16px" : "calc(40px + 10%) 16px",
"property " + prop + ": computed value before transition");
div.style.setProperty("transition-property", prop, "");
div.style.setProperty(prop, "30% calc(8px + 60%)", "");
is(cs.getPropertyValue(prop), "calc(30px + 15%) calc(14px + 15%)",
is(cs.getPropertyValue(prop), serializesCalcAccordingToTheSpec ? "calc(15% + 30px) calc(15% + 14px)" : "calc(30px + 15%) calc(14px + 15%)",
"property " + prop + ": interpolation between calc() and non-calc()");
if (doesPropHaveDistanceComputation) {
check_distance(prop, "calc(40px + 10%) 16px",
@ -2713,7 +2717,9 @@ function test_background_position_size_common(prop, doesPropTakeListValues,
"property " + prop + ": computed value before transition");
div.style.setProperty("transition-property", prop, "");
div.style.setProperty(prop, "12px 20px, 40% 16%", "");
is(cs.getPropertyValue(prop), "calc(3px + 15%) calc(5px + 30%), calc(6px + 10%) calc(9px + 4%)",
is(cs.getPropertyValue(prop), serializesCalcAccordingToTheSpec
? "calc(15% + 3px) calc(30% + 5px), calc(10% + 6px) calc(4% + 9px)"
: "calc(3px + 15%) calc(5px + 30%), calc(6px + 10%) calc(9px + 4%)",
"property " + prop + ": interpolation that computes to calc()");
if (doesPropHaveDistanceComputation) {
check_distance(prop, "20% 40%, 8px 12px",
@ -2722,11 +2728,15 @@ function test_background_position_size_common(prop, doesPropTakeListValues,
}
div.style.setProperty("transition-property", "none", "");
div.style.setProperty(prop, "calc(20% + 40px) calc(40px + 40%), 8px 12%, calc(20px + 12%) calc(24px + 8%)", "");
is(cs.getPropertyValue(prop), "calc(40px + 20%) calc(40px + 40%), 8px 12%, calc(20px + 12%) calc(24px + 8%)",
is(cs.getPropertyValue(prop), serializesCalcAccordingToTheSpec
? "calc(20% + 40px) calc(40% + 40px), 8px 12%, calc(12% + 20px) calc(8% + 24px)"
: "calc(40px + 20%) calc(40px + 40%), 8px 12%, calc(20px + 12%) calc(24px + 8%)",
"property " + prop + ": computed value before transition");
div.style.setProperty("transition-property", prop, "");
div.style.setProperty(prop, "12px 20%, calc(20%) calc(16px + 60%), calc(8px + 20%) calc(40px + 16%)", "");
is(cs.getPropertyValue(prop), "calc(33px + 15%) calc(30px + 35%), calc(6px + 5%) calc(4px + 24%), calc(17px + 14%) calc(28px + 10%)",
is(cs.getPropertyValue(prop), serializesCalcAccordingToTheSpec
? "calc(15% + 33px) calc(35% + 30px), calc(5% + 6px) calc(24% + 4px), calc(14% + 17px) calc(10% + 28px)"
: "calc(33px + 15%) calc(30px + 35%), calc(6px + 5%) calc(4px + 24%), calc(17px + 14%) calc(28px + 10%)",
"property " + prop + ": interpolation that computes to calc()");
if (doesPropHaveDistanceComputation) {
check_distance(prop, "calc(20% + 40px) calc(40px + 40%), 8px 12%, calc(20px + 12%) calc(24px + 8%)",

View File

@ -17,7 +17,7 @@ use gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataVa
use std::f32::consts::PI;
use stylesheets::{Origin, RulesMutateError};
use values::computed::{Angle, CalcLengthOrPercentage, Gradient, Image};
use values::computed::{Integer, LengthOrPercentage, LengthOrPercentageOrAuto};
use values::computed::{Integer, LengthOrPercentage, LengthOrPercentageOrAuto, NonNegativeLengthOrPercentageOrAuto};
use values::computed::{Percentage, TextAlign};
use values::computed::image::LineDirection;
use values::computed::url::ComputedImageUrl;
@ -106,6 +106,26 @@ impl From<nsStyleCoord_CalcValue> for LengthOrPercentageOrAuto {
}
}
// FIXME(emilio): A lot of these impl From should probably become explicit or
// disappear as we move more stuff to cbindgen.
impl From<nsStyleCoord_CalcValue> for NonNegativeLengthOrPercentageOrAuto {
fn from(other: nsStyleCoord_CalcValue) -> Self {
use values::generics::NonNegative;
use style_traits::values::specified::AllowedNumericType;
NonNegative(if other.mLength < 0 || other.mPercent < 0. {
LengthOrPercentageOrAuto::Calc(
CalcLengthOrPercentage::with_clamping_mode(
Au(other.mLength).into(),
if other.mHasPercent { Some(Percentage(other.mPercent)) } else { None },
AllowedNumericType::NonNegative,
)
)
} else {
other.into()
})
}
}
impl From<Angle> for CoordDataValue {
fn from(reference: Angle) -> Self {
match reference {

View File

@ -273,14 +273,18 @@ impl ToComputedValue for SpecifiedImageUrl {
}
}
fn serialize_computed_url<W>(url_value_data: &URLValueData, dest: &mut CssWriter<W>) -> fmt::Result
fn serialize_computed_url<W>(
url_value_data: &URLValueData,
dest: &mut CssWriter<W>,
get_url: unsafe extern "C" fn(*const URLValueData, *mut nsCString) -> (),
) -> fmt::Result
where
W: Write,
{
dest.write_str("url(")?;
unsafe {
let mut string = nsCString::new();
bindings::Gecko_GetComputedURLSpec(url_value_data, &mut string);
get_url(url_value_data, &mut string);
string.as_str_unchecked().to_css(dest)?;
}
dest.write_char(')')
@ -298,7 +302,11 @@ impl ToCss for ComputedUrl {
where
W: Write,
{
serialize_computed_url(&self.0.url_value._base, dest)
serialize_computed_url(
&self.0.url_value._base,
dest,
bindings::Gecko_GetComputedURLSpec,
)
}
}
@ -319,7 +327,11 @@ impl ToCss for ComputedImageUrl {
where
W: Write,
{
serialize_computed_url(&self.0.image_value._base, dest)
serialize_computed_url(
&self.0.image_value._base,
dest,
bindings::Gecko_GetComputedImageURLSpec,
)
}
}

View File

@ -4005,7 +4005,6 @@ fn static_assert() {
pub fn clone_${shorthand}_size(&self) -> longhands::${shorthand}_size::computed_value::T {
use gecko_bindings::structs::nsStyleCoord_CalcValue as CalcValue;
use gecko_bindings::structs::nsStyleImageLayers_Size_DimensionType as DimensionType;
use values::generics::NonNegative;
use values::computed::NonNegativeLengthOrPercentageOrAuto;
use values::generics::background::BackgroundSize;
@ -4014,7 +4013,7 @@ fn static_assert() {
NonNegativeLengthOrPercentageOrAuto::auto()
} else {
debug_assert_eq!(ty, DimensionType::eLengthPercentage as u8);
NonNegative(value.into())
value.into()
}
}

View File

@ -202,21 +202,34 @@ impl ToCss for CalcLengthOrPercentage {
{
use num_traits::Zero;
let (length, percentage) = match (self.length, self.percentage) {
(l, None) => return l.to_css(dest),
(l, Some(p)) if l.px() == 0. => return p.to_css(dest),
(l, Some(p)) => (l, p),
};
let length = self.unclamped_length();
match self.percentage {
Some(p) => {
if length.px() == 0. && self.clamping_mode.clamp(p.0) == p.0 {
return p.to_css(dest);
}
}
None => {
if self.clamping_mode.clamp(length.px()) == length.px() {
return length.to_css(dest);
}
}
}
dest.write_str("calc(")?;
percentage.to_css(dest)?;
dest.write_str(if length.px() < Zero::zero() {
" - "
if let Some(percentage) = self.percentage {
percentage.to_css(dest)?;
if length.px() != 0. {
dest.write_str(if length.px() < Zero::zero() {
" - "
} else {
" + "
})?;
length.abs().to_css(dest)?;
}
} else {
" + "
})?;
length.abs().to_css(dest)?;
length.to_css(dest)?;
}
dest.write_str(")")
}