--- a/layout/inspector/inDOMUtils.cpp
+++ b/layout/inspector/inDOMUtils.cpp
@@ -818,16 +818,17 @@ PropertySupportsVariant(nsCSSProperty aP
case eCSSProperty_border_spacing:
supported = VARIANT_LENGTH;
break;
case eCSSProperty_content:
case eCSSProperty_cursor:
case eCSSProperty_clip_path:
+ case eCSSProperty_shape_outside:
supported = VARIANT_URL;
break;
case eCSSProperty_fill:
case eCSSProperty_stroke:
supported = VARIANT_COLOR | VARIANT_URL;
break;
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -1061,16 +1061,17 @@ protected:
bool ParseTextEmphasisPosition(nsCSSValue& aValue);
bool ParseTextEmphasisStyle(nsCSSValue& aValue);
bool ParseTextCombineUpright(nsCSSValue& aValue);
bool ParseTextOverflow(nsCSSValue& aValue);
bool ParseTouchAction(nsCSSValue& aValue);
bool ParseShadowItem(nsCSSValue& aValue, bool aIsBoxShadow);
bool ParseShadowList(nsCSSProperty aProperty);
+ bool ParseShapeOutside(nsCSSValue& aValue);
bool ParseTransitionProperty();
bool ParseTransitionTimingFunctionValues(nsCSSValue& aValue);
bool ParseTransitionTimingFunctionValueComponent(float& aComponent,
char aStop,
bool aIsXPoint);
bool ParseTransitionStepTimingFunctionValues(nsCSSValue& aValue);
enum ParseAnimationOrTransitionShorthandResult {
eParseAnimationOrTransitionShorthand_Values,
@@ -1319,16 +1320,18 @@ protected:
void SetParsingCompoundProperty(bool aBool) {
mParsingCompoundProperty = aBool;
}
bool IsParsingCompoundProperty(void) const {
return mParsingCompoundProperty;
}
/* Functions for basic shapes */
+ bool ParseReferenceBoxAndBasicShape(nsCSSValue& aValue,
+ const KTableEntry aBoxKeywordTable[]);
bool ParseBasicShape(nsCSSValue& aValue, bool* aConsumedTokens);
bool ParsePolygonFunction(nsCSSValue& aValue);
bool ParseCircleOrEllipseFunction(nsCSSKeyword, nsCSSValue& aValue);
bool ParseInsetFunction(nsCSSValue& aValue);
// We parse position values differently for basic-shape, by expanding defaults
// and replacing keywords with percentages
bool ParsePositionValueForBasicShape(nsCSSValue& aOut);
@@ -11754,16 +11757,18 @@ CSSParserImpl::ParseSingleValuePropertyB
case eCSSProperty_scroll_snap_points_x:
return ParseScrollSnapPoints(aValue, eCSSProperty_scroll_snap_points_x);
case eCSSProperty_scroll_snap_points_y:
return ParseScrollSnapPoints(aValue, eCSSProperty_scroll_snap_points_y);
case eCSSProperty_scroll_snap_destination:
return ParseScrollSnapDestination(aValue);
case eCSSProperty_scroll_snap_coordinate:
return ParseScrollSnapCoordinate(aValue);
+ case eCSSProperty_shape_outside:
+ return ParseShapeOutside(aValue);
case eCSSProperty_text_align:
return ParseTextAlign(aValue);
case eCSSProperty_text_align_last:
return ParseTextAlignLast(aValue);
case eCSSProperty_text_decoration_line:
return ParseTextDecorationLine(aValue);
case eCSSProperty_text_combine_upright:
return ParseTextCombineUpright(aValue);
@@ -16160,68 +16165,93 @@ CSSParserImpl::ParseBasicShape(nsCSSValu
return ParseCircleOrEllipseFunction(keyword, aValue);
case eCSSKeyword_inset:
return ParseInsetFunction(aValue);
default:
return false;
}
}
+bool
+CSSParserImpl::ParseReferenceBoxAndBasicShape(
+ nsCSSValue& aValue,
+ const KTableEntry aBoxKeywordTable[])
+{
+ nsCSSValue referenceBox;
+ bool hasBox = ParseEnum(referenceBox, aBoxKeywordTable);
+
+ const bool boxCameFirst = hasBox;
+
+ nsCSSValue basicShape;
+ bool basicShapeConsumedTokens = false;
+ bool hasShape = ParseBasicShape(basicShape, &basicShapeConsumedTokens);
+
+ // Parsing wasn't successful if ParseBasicShape consumed tokens but failed
+ // or if the token was neither a reference box nor a basic shape.
+ if ((!hasShape && basicShapeConsumedTokens) || (!hasBox && !hasShape)) {
+ return false;
+ }
+
+ // Check if the second argument is a reference box if the first wasn't.
+ if (!hasBox) {
+ hasBox = ParseEnum(referenceBox, aBoxKeywordTable);
+ }
+
+ RefPtr<nsCSSValue::Array> fullValue =
+ nsCSSValue::Array::Create((hasBox && hasShape) ? 2 : 1);
+
+ if (hasBox && hasShape) {
+ fullValue->Item(boxCameFirst ? 0 : 1) = referenceBox;
+ fullValue->Item(boxCameFirst ? 1 : 0) = basicShape;
+ } else if (hasBox) {
+ fullValue->Item(0) = referenceBox;
+ } else {
+ MOZ_ASSERT(hasShape, "should've bailed if we got neither box nor shape");
+ fullValue->Item(0) = basicShape;
+ }
+
+ aValue.SetArrayValue(fullValue, eCSSUnit_Array);
+ return true;
+}
+
/* Parse a clip-path url to a <clipPath> element or a basic shape. */
bool CSSParserImpl::ParseClipPath()
{
nsCSSValue value;
if (!ParseSingleTokenVariant(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;
}
- nsCSSValue referenceBox;
- bool hasBox = ParseEnum(referenceBox, nsCSSProps::kClipPathGeometryBoxKTable);
-
- const bool boxCameFirst = hasBox;
-
- nsCSSValue basicShape;
- bool basicShapeConsumedTokens = false;
- bool hasShape = ParseBasicShape(basicShape, &basicShapeConsumedTokens);
-
- // Parsing wasn't successful if ParseBasicShape consumed tokens but failed
- // or if the token was neither a reference box nor a basic shape.
- if ((!hasShape && basicShapeConsumedTokens) || (!hasBox && !hasShape)) {
- return false;
- }
-
- // Check if the second argument is a reference box if the first wasn't.
- if (!hasBox) {
- hasBox = ParseEnum(referenceBox, nsCSSProps::kClipPathGeometryBoxKTable);
- }
-
- RefPtr<nsCSSValue::Array> fullValue =
- nsCSSValue::Array::Create((hasBox && hasShape) ? 2 : 1);
-
- if (hasBox && hasShape) {
- fullValue->Item(boxCameFirst ? 0 : 1) = referenceBox;
- fullValue->Item(boxCameFirst ? 1 : 0) = basicShape;
- } else if (hasBox) {
- fullValue->Item(0) = referenceBox;
- } else {
- MOZ_ASSERT(hasShape, "should've bailed if we got neither box nor shape");
- fullValue->Item(0) = basicShape;
- }
-
- value.SetArrayValue(fullValue, eCSSUnit_Array);
+ if (!ParseReferenceBoxAndBasicShape(
+ value, nsCSSProps::kClipPathGeometryBoxKTable)) {
+ return false;
+ }
}
AppendValue(eCSSProperty_clip_path, value);
return true;
}
+// none | [ <basic-shape> || <shape-box> ] | <image>
+bool
+CSSParserImpl::ParseShapeOutside(nsCSSValue& aValue)
+{
+ if (ParseSingleTokenVariant(aValue, VARIANT_HUO, nullptr)) {
+ // 'inherit', 'initial', 'unset', 'none', and <image> url must be alone.
+ return true;
+ }
+
+ return ParseReferenceBoxAndBasicShape(
+ aValue, nsCSSProps::kShapeOutsideShapeBoxKTable);
+}
+
bool CSSParserImpl::ParseTransformOrigin(bool aPerspective)
{
nsCSSValuePair position;
if (!ParseBoxPositionValues(position, true))
return false;
nsCSSProperty prop = eCSSProperty_transform_origin;
if (aPerspective) {
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -3703,16 +3703,28 @@ CSS_PROP_DISPLAY(
scroll_snap_type_y,
ScrollSnapTypeY,
CSS_PROPERTY_PARSE_VALUE,
"layout.css.scroll-snap.enabled",
VARIANT_HK,
kScrollSnapTypeKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
+CSS_PROP_DISPLAY(
+ shape-outside,
+ shape_outside,
+ ShapeOutside,
+ CSS_PROPERTY_PARSE_VALUE |
+ CSS_PROPERTY_VALUE_PARSER_FUNCTION |
+ CSS_PROPERTY_APPLIES_TO_FIRST_LETTER,
+ "layout.css.shape-outside.enabled",
+ 0,
+ nullptr,
+ CSS_PROP_NO_OFFSET,
+ eStyleAnimType_None) // FIXME: Bug 1289049 for adding animation support
CSS_PROP_SVG(
shape-rendering,
shape_rendering,
ShapeRendering,
CSS_PROPERTY_PARSE_VALUE,
"",
VARIANT_HK,
kShapeRenderingKTable,
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -2336,16 +2336,24 @@ const KTableEntry nsCSSProps::kImageRend
};
const KTableEntry nsCSSProps::kMaskTypeKTable[] = {
{ eCSSKeyword_luminance, NS_STYLE_MASK_TYPE_LUMINANCE },
{ eCSSKeyword_alpha, NS_STYLE_MASK_TYPE_ALPHA },
{ eCSSKeyword_UNKNOWN, -1 }
};
+const KTableEntry nsCSSProps::kShapeOutsideShapeBoxKTable[] = {
+ { eCSSKeyword_content_box, StyleShapeOutsideShapeBox::Content },
+ { eCSSKeyword_padding_box, StyleShapeOutsideShapeBox::Padding },
+ { eCSSKeyword_border_box, StyleShapeOutsideShapeBox::Border },
+ { eCSSKeyword_margin_box, StyleShapeOutsideShapeBox::Margin },
+ { eCSSKeyword_UNKNOWN, -1 }
+};
+
const KTableEntry nsCSSProps::kShapeRenderingKTable[] = {
{ eCSSKeyword_auto, NS_STYLE_SHAPE_RENDERING_AUTO },
{ eCSSKeyword_optimizespeed, NS_STYLE_SHAPE_RENDERING_OPTIMIZESPEED },
{ eCSSKeyword_crispedges, NS_STYLE_SHAPE_RENDERING_CRISPEDGES },
{ eCSSKeyword_geometricprecision, NS_STYLE_SHAPE_RENDERING_GEOMETRICPRECISION },
{ eCSSKeyword_UNKNOWN, -1 }
};
--- a/layout/style/nsCSSProps.h
+++ b/layout/style/nsCSSProps.h
@@ -737,16 +737,17 @@ public:
static const KTableEntry kCounterSpeakAsKTable[];
static const KTableEntry kCounterSymbolsSystemKTable[];
static const KTableEntry kCounterSystemKTable[];
static const KTableEntry kDominantBaselineKTable[];
static const KTableEntry kShapeRadiusKTable[];
static const KTableEntry kFillRuleKTable[];
static const KTableEntry kFilterFunctionKTable[];
static const KTableEntry kImageRenderingKTable[];
+ static const KTableEntry kShapeOutsideShapeBoxKTable[];
static const KTableEntry kShapeRenderingKTable[];
static const KTableEntry kStrokeLinecapKTable[];
static const KTableEntry kStrokeLinejoinKTable[];
static const KTableEntry kStrokeContextValueKTable[];
static const KTableEntry kVectorEffectKTable[];
static const KTableEntry kTextAnchorKTable[];
static const KTableEntry kTextRenderingKTable[];
static const KTableEntry kColorAdjustKTable[];
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -1423,16 +1423,22 @@ nsCSSValue::AppendToString(nsCSSProperty
break;
case eCSSProperty_clip_path:
AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
nsCSSProps::kClipPathGeometryBoxKTable),
aResult);
break;
+ case eCSSProperty_shape_outside:
+ AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
+ nsCSSProps::kShapeOutsideShapeBoxKTable),
+ aResult);
+ break;
+
case eCSSProperty_contain:
if (intValue & NS_STYLE_CONTAIN_STRICT) {
NS_ASSERTION(intValue == (NS_STYLE_CONTAIN_STRICT | NS_STYLE_CONTAIN_ALL_BITS),
"contain: strict should imply contain: layout style paint");
// Only output strict.
intValue = NS_STYLE_CONTAIN_STRICT;
}
nsStyleUtil::AppendBitmaskCSSValue(aProperty,
@@ -2517,17 +2523,18 @@ nsCSSValuePairList::AppendToString(nsCSS
item->mYValue.AppendToString(aProperty, aResult, aSerialization);
}
item = item->mNext;
if (!item)
break;
if (nsCSSProps::PropHasFlags(aProperty,
CSS_PROPERTY_VALUE_LIST_USES_COMMAS) ||
- aProperty == eCSSProperty_clip_path)
+ aProperty == eCSSProperty_clip_path ||
+ aProperty == eCSSProperty_shape_outside)
aResult.Append(char16_t(','));
aResult.Append(char16_t(' '));
}
}
/* static */ bool
nsCSSValuePairList::Equal(const nsCSSValuePairList* aList1,
const nsCSSValuePairList* aList2)
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -5989,70 +5989,85 @@ nsComputedDOMStyle::CreatePrimitiveValue
NS_NOTREACHED("unexpected type");
}
shapeFunctionString.Append(')');
RefPtr<nsROCSSPrimitiveValue> functionValue = new nsROCSSPrimitiveValue;
functionValue->SetString(shapeFunctionString);
return functionValue.forget();
}
-already_AddRefed<CSSValue>
-nsComputedDOMStyle::CreatePrimitiveValueForClipPath(
+template<typename ReferenceBox>
+already_AddRefed<CSSValue>
+nsComputedDOMStyle::CreatePrimitiveValueForShapeSource(
const StyleBasicShape* aStyleBasicShape,
- StyleClipPathGeometryBox aSizingBox)
+ ReferenceBox aReferenceBox,
+ const KTableEntry aBoxKeywordTable[])
{
RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
if (aStyleBasicShape) {
valueList->AppendCSSValue(
CreatePrimitiveValueForBasicShape(aStyleBasicShape));
}
- if (aSizingBox == StyleClipPathGeometryBox::NoBox) {
+ if (aReferenceBox == ReferenceBox::NoBox) {
return valueList.forget();
}
- nsAutoString boxString;
- AppendASCIItoUTF16(
- nsCSSProps::ValueToKeyword(aSizingBox,
- nsCSSProps::kClipPathGeometryBoxKTable),
- boxString);
- RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
- val->SetString(boxString);
+ RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
+ val->SetIdent(nsCSSProps::ValueToKeywordEnum(aReferenceBox, aBoxKeywordTable));
valueList->AppendCSSValue(val.forget());
return valueList.forget();
}
-already_AddRefed<CSSValue>
-nsComputedDOMStyle::DoGetClipPath()
-{
- const nsStyleSVGReset* svg = StyleSVGReset();
- switch (svg->mClipPath.GetType()) {
+template<typename ReferenceBox>
+already_AddRefed<CSSValue>
+nsComputedDOMStyle::GetShapeSource(
+ const StyleShapeSource<ReferenceBox>& aShapeSource,
+ const KTableEntry aBoxKeywordTable[])
+{
+ switch (aShapeSource.GetType()) {
case StyleShapeSourceType::Shape:
- return CreatePrimitiveValueForClipPath(svg->mClipPath.GetBasicShape(),
- svg->mClipPath.GetReferenceBox());
+ return CreatePrimitiveValueForShapeSource(aShapeSource.GetBasicShape(),
+ aShapeSource.GetReferenceBox(),
+ aBoxKeywordTable);
case StyleShapeSourceType::Box:
- return CreatePrimitiveValueForClipPath(nullptr,
- svg->mClipPath.GetReferenceBox());
+ return CreatePrimitiveValueForShapeSource(nullptr,
+ aShapeSource.GetReferenceBox(),
+ aBoxKeywordTable);
case StyleShapeSourceType::URL: {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
- SetValueToFragmentOrURL(svg->mClipPath.GetURL(), val);
+ SetValueToFragmentOrURL(aShapeSource.GetURL(), val);
return val.forget();
}
case StyleShapeSourceType::None_: {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetIdent(eCSSKeyword_none);
return val.forget();
}
default:
NS_NOTREACHED("unexpected type");
}
return nullptr;
}
+already_AddRefed<CSSValue>
+nsComputedDOMStyle::DoGetClipPath()
+{
+ return GetShapeSource(StyleSVGReset()->mClipPath,
+ nsCSSProps::kClipPathGeometryBoxKTable);
+}
+
+already_AddRefed<CSSValue>
+nsComputedDOMStyle::DoGetShapeOutside()
+{
+ return GetShapeSource(StyleDisplay()->mShapeOutside,
+ nsCSSProps::kShapeOutsideShapeBoxKTable);
+}
+
void
nsComputedDOMStyle::SetCssTextToCoord(nsAString& aCssText,
const nsStyleCoord& aCoord)
{
RefPtr<nsROCSSPrimitiveValue> value = new nsROCSSPrimitiveValue;
bool clampNegativeCalc = true;
SetValueToCoord(value, aCoord, clampNegativeCalc);
value->GetCssText(aCssText);
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -476,16 +476,17 @@ private:
already_AddRefed<CSSValue> DoGetScrollBehavior();
already_AddRefed<CSSValue> DoGetScrollSnapType();
already_AddRefed<CSSValue> DoGetScrollSnapTypeX();
already_AddRefed<CSSValue> DoGetScrollSnapTypeY();
already_AddRefed<CSSValue> DoGetScrollSnapPointsX();
already_AddRefed<CSSValue> DoGetScrollSnapPointsY();
already_AddRefed<CSSValue> DoGetScrollSnapDestination();
already_AddRefed<CSSValue> DoGetScrollSnapCoordinate();
+ already_AddRefed<CSSValue> DoGetShapeOutside();
/* User interface properties */
already_AddRefed<CSSValue> DoGetCursor();
already_AddRefed<CSSValue> DoGetForceBrokenImageIcon();
already_AddRefed<CSSValue> DoGetIMEMode();
already_AddRefed<CSSValue> DoGetUserFocus();
already_AddRefed<CSSValue> DoGetUserInput();
already_AddRefed<CSSValue> DoGetUserModify();
@@ -640,19 +641,27 @@ private:
bool GetFrameBorderRectWidth(nscoord& aWidth);
bool GetFrameBorderRectHeight(nscoord& aHeight);
/* Helper functions for computing the filter property style. */
void SetCssTextToCoord(nsAString& aCssText, const nsStyleCoord& aCoord);
already_AddRefed<CSSValue> CreatePrimitiveValueForStyleFilter(
const nsStyleFilter& aStyleFilter);
- already_AddRefed<CSSValue> CreatePrimitiveValueForClipPath(
+ template<typename ReferenceBox>
+ already_AddRefed<CSSValue>
+ GetShapeSource(const mozilla::StyleShapeSource<ReferenceBox>& aShapeSource,
+ const KTableEntry aBoxKeywordTable[]);
+
+ template<typename ReferenceBox>
+ already_AddRefed<CSSValue>
+ CreatePrimitiveValueForShapeSource(
const mozilla::StyleBasicShape* aStyleBasicShape,
- mozilla::StyleClipPathGeometryBox aSizingBox);
+ ReferenceBox aReferenceBox,
+ const KTableEntry aBoxKeywordTable[]);
// Helper function for computing basic shape styles.
already_AddRefed<CSSValue> CreatePrimitiveValueForBasicShape(
const mozilla::StyleBasicShape* aStyleBasicShape);
void BoxValuesToString(nsAString& aString,
const nsTArray<nsStyleCoord>& aBoxValues);
void BasicShapeRadiiToString(nsAString& aCssText,
const nsStyleCorners& aCorners);
--- a/layout/style/nsComputedDOMStylePropertyList.h
+++ b/layout/style/nsComputedDOMStylePropertyList.h
@@ -212,16 +212,17 @@ COMPUTED_STYLE_PROP(ruby_align,
COMPUTED_STYLE_PROP(ruby_position, RubyPosition)
COMPUTED_STYLE_PROP(scroll_behavior, ScrollBehavior)
COMPUTED_STYLE_PROP(scroll_snap_coordinate, ScrollSnapCoordinate)
COMPUTED_STYLE_PROP(scroll_snap_destination, ScrollSnapDestination)
COMPUTED_STYLE_PROP(scroll_snap_points_x, ScrollSnapPointsX)
COMPUTED_STYLE_PROP(scroll_snap_points_y, ScrollSnapPointsY)
COMPUTED_STYLE_PROP(scroll_snap_type_x, ScrollSnapTypeX)
COMPUTED_STYLE_PROP(scroll_snap_type_y, ScrollSnapTypeY)
+COMPUTED_STYLE_PROP(shape_outside, ShapeOutside)
//// COMPUTED_STYLE_PROP(size, Size)
COMPUTED_STYLE_PROP(table_layout, TableLayout)
COMPUTED_STYLE_PROP(text_align, TextAlign)
COMPUTED_STYLE_PROP(text_align_last, TextAlignLast)
COMPUTED_STYLE_PROP(text_combine_upright, TextCombineUpright)
COMPUTED_STYLE_PROP(text_decoration, TextDecoration)
COMPUTED_STYLE_PROP(text_decoration_color, TextDecorationColor)
COMPUTED_STYLE_PROP(text_decoration_line, TextDecorationLine)
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -114,16 +114,24 @@ SetImageRequest(function<void(imgRequest
if (aPresContext->IsDynamic()) {
aCallback(req);
} else {
RefPtr<imgRequestProxy> staticReq = nsContentUtils::GetStaticRequest(req);
aCallback(staticReq);
}
}
+template<typename ReferenceBox>
+static void
+SetStyleShapeSourceToCSSValue(StyleShapeSource<ReferenceBox>* aShapeSource,
+ const nsCSSValue* aValue,
+ nsStyleContext* aStyleContext,
+ nsPresContext* aPresContext,
+ RuleNodeCacheConditions& aConditions);
+
/* Helper function to convert a CSS <position> specified value into its
* computed-style form. */
static void
ComputePositionValue(nsStyleContext* aStyleContext,
const nsCSSValue& aValue,
nsStyleImageLayers::Position& aComputedValue,
RuleNodeCacheConditions& aConditions);
@@ -6429,16 +6437,45 @@ nsRuleNode::ComputeDisplayData(void* aSt
// orient: enum, inherit, initial
SetValue(*aRuleData->ValueForOrient(),
display->mOrient, conditions,
SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
parentDisplay->mOrient,
NS_STYLE_ORIENT_INLINE);
+ // shape-outside: none | [ <basic-shape> || <shape-box> ] | <image>
+ const nsCSSValue* shapeOutsideValue = aRuleData->ValueForShapeOutside();
+ switch (shapeOutsideValue->GetUnit()) {
+ case eCSSUnit_Null:
+ break;
+ case eCSSUnit_None:
+ case eCSSUnit_Initial:
+ case eCSSUnit_Unset:
+ display->mShapeOutside = StyleShapeOutside();
+ break;
+ case eCSSUnit_Inherit:
+ conditions.SetUncacheable();
+ display->mShapeOutside = parentDisplay->mShapeOutside;
+ break;
+ case eCSSUnit_URL: {
+ display->mShapeOutside = StyleShapeOutside();
+ display->mShapeOutside.SetURL(shapeOutsideValue);
+ break;
+ }
+ case eCSSUnit_Array: {
+ display->mShapeOutside = StyleShapeOutside();
+ SetStyleShapeSourceToCSSValue(&display->mShapeOutside, shapeOutsideValue,
+ aContext, mPresContext, conditions);
+ break;
+ }
+ default:
+ MOZ_ASSERT_UNREACHABLE("Unrecognized shape-outside unit!");
+ }
+
COMPUTE_END_RESET(Display, display)
}
const void*
nsRuleNode::ComputeVisibilityData(void* aStartStruct,
const nsRuleData* aRuleData,
nsStyleContext* aContext,
nsRuleNode* aHighestNode,
@@ -9725,54 +9762,52 @@ GetStyleBasicShapeFromCSSValue(const nsC
}
} else {
NS_NOTREACHED("unexpected basic shape function");
}
return basicShape.forget();
}
+template<typename ReferenceBox>
static void
-SetStyleClipPathToCSSValue(StyleClipPath* aStyleClipPath,
- const nsCSSValue* aValue,
- nsStyleContext* aStyleContext,
- nsPresContext* aPresContext,
- RuleNodeCacheConditions& aConditions)
+SetStyleShapeSourceToCSSValue(
+ StyleShapeSource<ReferenceBox>* aShapeSource,
+ const nsCSSValue* aValue,
+ nsStyleContext* aStyleContext,
+ nsPresContext* aPresContext,
+ RuleNodeCacheConditions& aConditions)
{
MOZ_ASSERT(aValue->GetUnit() == eCSSUnit_Array,
"expected a basic shape or reference box");
const nsCSSValue::Array* array = aValue->GetArrayValue();
MOZ_ASSERT(array->Count() == 1 || array->Count() == 2,
- "Expect one or both of a shape function and geometry-box");
-
- StyleClipPathGeometryBox sizingBox = StyleClipPathGeometryBox::NoBox;
+ "Expect one or both of a shape function and a reference box");
+
+ ReferenceBox referenceBox = ReferenceBox::NoBox;
RefPtr<StyleBasicShape> basicShape;
+
for (size_t i = 0; i < array->Count(); ++i) {
- if (array->Item(i).GetUnit() == eCSSUnit_Enumerated) {
- int32_t type = array->Item(i).GetIntValue();
- if (type > uint8_t(StyleClipPathGeometryBox::View) ||
- type < uint8_t(StyleClipPathGeometryBox::NoBox)) {
- NS_NOTREACHED("unexpected reference box");
- return;
- }
- sizingBox = static_cast<StyleClipPathGeometryBox>(type);
- } else if (array->Item(i).GetUnit() == eCSSUnit_Function) {
- basicShape = GetStyleBasicShapeFromCSSValue(array->Item(i), aStyleContext,
+ const nsCSSValue& item = array->Item(i);
+ if (item.GetUnit() == eCSSUnit_Enumerated) {
+ referenceBox = static_cast<ReferenceBox>(item.GetIntValue());
+ } else if (item.GetUnit() == eCSSUnit_Function) {
+ basicShape = GetStyleBasicShapeFromCSSValue(item, aStyleContext,
aPresContext, aConditions);
} else {
- NS_NOTREACHED("unexpected value");
+ MOZ_ASSERT_UNREACHABLE("Unexpected unit!");
return;
}
}
if (basicShape) {
- aStyleClipPath->SetBasicShape(basicShape, sizingBox);
+ aShapeSource->SetBasicShape(basicShape, referenceBox);
} else {
- aStyleClipPath->SetReferenceBox(sizingBox);
+ aShapeSource->SetReferenceBox(referenceBox);
}
}
// Returns true if the nsStyleFilter was successfully set using the nsCSSValue.
static bool
SetStyleFilterToCSSValue(nsStyleFilter* aStyleFilter,
const nsCSSValue& aValue,
nsStyleContext* aStyleContext,
@@ -9887,18 +9922,18 @@ nsRuleNode::ComputeSVGResetData(void* aS
break;
case eCSSUnit_URL: {
svgReset->mClipPath = StyleClipPath();
svgReset->mClipPath.SetURL(clipPathValue);
break;
}
case eCSSUnit_Array: {
svgReset->mClipPath = StyleClipPath();
- SetStyleClipPathToCSSValue(&svgReset->mClipPath, clipPathValue, aContext,
- mPresContext, conditions);
+ SetStyleShapeSourceToCSSValue(&svgReset->mClipPath, clipPathValue, aContext,
+ mPresContext, conditions);
break;
}
default:
NS_NOTREACHED("unexpected unit");
}
// stop-opacity:
SetFactor(*aRuleData->ValueForStopOpacity(),
--- a/layout/style/nsStyleConsts.h
+++ b/layout/style/nsStyleConsts.h
@@ -86,16 +86,25 @@ enum class StyleClipPathGeometryBox : ui
};
// float-edge
enum class StyleFloatEdge : uint8_t {
ContentBox,
MarginBox,
};
+// shape-box for shape-outside
+enum class StyleShapeOutsideShapeBox : uint8_t {
+ NoBox,
+ Content,
+ Padding,
+ Border,
+ Margin
+};
+
// Shape source type
// X11 has a #define for None causing conflicts, so we use None_ here
enum class StyleShapeSourceType : uint8_t {
None_,
URL,
Shape,
Box,
};
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -3077,16 +3077,17 @@ nsStyleDisplay::nsStyleDisplay(const nsS
, mAnimationTimingFunctionCount(aSource.mAnimationTimingFunctionCount)
, mAnimationDurationCount(aSource.mAnimationDurationCount)
, mAnimationDelayCount(aSource.mAnimationDelayCount)
, mAnimationNameCount(aSource.mAnimationNameCount)
, mAnimationDirectionCount(aSource.mAnimationDirectionCount)
, mAnimationFillModeCount(aSource.mAnimationFillModeCount)
, mAnimationPlayStateCount(aSource.mAnimationPlayStateCount)
, mAnimationIterationCountCount(aSource.mAnimationIterationCountCount)
+ , mShapeOutside(aSource.mShapeOutside)
{
MOZ_COUNT_CTOR(nsStyleDisplay);
/* Copy over transform origin. */
mTransformOrigin[0] = aSource.mTransformOrigin[0];
mTransformOrigin[1] = aSource.mTransformOrigin[1];
mTransformOrigin[2] = aSource.mTransformOrigin[2];
mPerspectiveOrigin[0] = aSource.mPerspectiveOrigin[0];
@@ -3301,17 +3302,18 @@ nsStyleDisplay::CalcDifference(const nsS
mAnimationTimingFunctionCount != aNewData.mAnimationTimingFunctionCount ||
mAnimationDurationCount != aNewData.mAnimationDurationCount ||
mAnimationDelayCount != aNewData.mAnimationDelayCount ||
mAnimationNameCount != aNewData.mAnimationNameCount ||
mAnimationDirectionCount != aNewData.mAnimationDirectionCount ||
mAnimationFillModeCount != aNewData.mAnimationFillModeCount ||
mAnimationPlayStateCount != aNewData.mAnimationPlayStateCount ||
mAnimationIterationCountCount != aNewData.mAnimationIterationCountCount ||
- mScrollSnapCoordinate != aNewData.mScrollSnapCoordinate)) {
+ mScrollSnapCoordinate != aNewData.mScrollSnapCoordinate ||
+ mShapeOutside != aNewData.mShapeOutside)) {
hint |= nsChangeHint_NeutralChange;
}
return hint;
}
// --------------------
// nsStyleVisibility
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -2518,16 +2518,269 @@ private:
float mDelay;
nsString mName; // empty string for 'none'
dom::PlaybackDirection mDirection;
dom::FillMode mFillMode;
uint8_t mPlayState;
float mIterationCount; // mozilla::PositiveInfinity<float>() means infinite
};
+class StyleBasicShape final
+{
+public:
+ explicit StyleBasicShape(StyleBasicShapeType type)
+ : mType(type),
+ mFillRule(NS_STYLE_FILL_RULE_NONZERO)
+ {
+ mPosition.SetInitialPercentValues(0.5f);
+ }
+
+ StyleBasicShapeType GetShapeType() const { return mType; }
+ nsCSSKeyword GetShapeTypeName() const;
+
+ int32_t GetFillRule() const { return mFillRule; }
+ void SetFillRule(int32_t aFillRule)
+ {
+ MOZ_ASSERT(mType == StyleBasicShapeType::Polygon, "expected polygon");
+ mFillRule = aFillRule;
+ }
+
+ typedef nsStyleImageLayers::Position Position;
+ Position& GetPosition() {
+ MOZ_ASSERT(mType == StyleBasicShapeType::Circle ||
+ mType == StyleBasicShapeType::Ellipse,
+ "expected circle or ellipse");
+ return mPosition;
+ }
+ const Position& GetPosition() const {
+ MOZ_ASSERT(mType == StyleBasicShapeType::Circle ||
+ mType == StyleBasicShapeType::Ellipse,
+ "expected circle or ellipse");
+ return mPosition;
+ }
+
+ bool HasRadius() const {
+ MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
+ nsStyleCoord zero;
+ zero.SetCoordValue(0);
+ NS_FOR_CSS_HALF_CORNERS(corner) {
+ if (mRadius.Get(corner) != zero) {
+ return true;
+ }
+ }
+ return false;
+ }
+ nsStyleCorners& GetRadius() {
+ MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
+ return mRadius;
+ }
+ const nsStyleCorners& GetRadius() const {
+ MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
+ return mRadius;
+ }
+
+ // mCoordinates has coordinates for polygon or radii for
+ // ellipse and circle.
+ nsTArray<nsStyleCoord>& Coordinates()
+ {
+ return mCoordinates;
+ }
+
+ const nsTArray<nsStyleCoord>& Coordinates() const
+ {
+ return mCoordinates;
+ }
+
+ bool operator==(const StyleBasicShape& aOther) const
+ {
+ return mType == aOther.mType &&
+ mFillRule == aOther.mFillRule &&
+ mCoordinates == aOther.mCoordinates &&
+ mPosition == aOther.mPosition &&
+ mRadius == aOther.mRadius;
+ }
+ bool operator!=(const StyleBasicShape& aOther) const {
+ return !(*this == aOther);
+ }
+
+ NS_INLINE_DECL_REFCOUNTING(StyleBasicShape);
+
+private:
+ ~StyleBasicShape() {}
+
+ StyleBasicShapeType mType;
+ int32_t mFillRule;
+
+ // mCoordinates has coordinates for polygon or radii for
+ // ellipse and circle.
+ nsTArray<nsStyleCoord> mCoordinates;
+ Position mPosition;
+ nsStyleCorners mRadius;
+};
+
+template<typename ReferenceBox>
+struct StyleShapeSource
+{
+ StyleShapeSource()
+ : mURL(nullptr)
+ {}
+
+ StyleShapeSource(const StyleShapeSource& aSource)
+ : StyleShapeSource()
+ {
+ if (aSource.mType == StyleShapeSourceType::URL) {
+ CopyURL(aSource);
+ } else if (aSource.mType == StyleShapeSourceType::Shape) {
+ SetBasicShape(aSource.mBasicShape, aSource.mReferenceBox);
+ } else if (aSource.mType == StyleShapeSourceType::Box) {
+ SetReferenceBox(aSource.mReferenceBox);
+ }
+ }
+
+ ~StyleShapeSource()
+ {
+ ReleaseRef();
+ }
+
+ StyleShapeSource& operator=(const StyleShapeSource& aOther)
+ {
+ if (this == &aOther) {
+ return *this;
+ }
+
+ if (aOther.mType == StyleShapeSourceType::URL) {
+ CopyURL(aOther);
+ } else if (aOther.mType == StyleShapeSourceType::Shape) {
+ SetBasicShape(aOther.mBasicShape, aOther.mReferenceBox);
+ } else if (aOther.mType == StyleShapeSourceType::Box) {
+ SetReferenceBox(aOther.mReferenceBox);
+ } else {
+ ReleaseRef();
+ mReferenceBox = ReferenceBox::NoBox;
+ mType = StyleShapeSourceType::None_;
+ }
+ return *this;
+ }
+
+ bool operator==(const StyleShapeSource& aOther) const
+ {
+ if (mType != aOther.mType) {
+ return false;
+ }
+
+ if (mType == StyleShapeSourceType::URL) {
+ return mURL == aOther.mURL;
+ } else if (mType == StyleShapeSourceType::Shape) {
+ return *mBasicShape == *aOther.mBasicShape &&
+ mReferenceBox == aOther.mReferenceBox;
+ } else if (mType == StyleShapeSourceType::Box) {
+ return mReferenceBox == aOther.mReferenceBox;
+ }
+
+ return true;
+ }
+
+ bool operator!=(const StyleShapeSource& aOther) const
+ {
+ return !(*this == aOther);
+ }
+
+ StyleShapeSourceType GetType() const
+ {
+ return mType;
+ }
+
+ FragmentOrURL* GetURL() const
+ {
+ MOZ_ASSERT(mType == StyleShapeSourceType::URL, "Wrong shape source type!");
+ return mURL;
+ }
+
+ bool SetURL(const nsCSSValue* aValue)
+ {
+ if (!aValue->GetURLValue()) {
+ return false;
+ }
+
+ ReleaseRef();
+
+ mURL = new FragmentOrURL();
+ mURL->SetValue(aValue);
+ mType = StyleShapeSourceType::URL;
+ return true;
+ }
+
+ StyleBasicShape* GetBasicShape() const
+ {
+ MOZ_ASSERT(mType == StyleShapeSourceType::Shape, "Wrong shape source type!");
+ return mBasicShape;
+ }
+
+ void SetBasicShape(StyleBasicShape* aBasicShape,
+ ReferenceBox aReferenceBox)
+ {
+ NS_ASSERTION(aBasicShape, "expected pointer");
+ ReleaseRef();
+ mBasicShape = aBasicShape;
+ mBasicShape->AddRef();
+ mReferenceBox = aReferenceBox;
+ mType = StyleShapeSourceType::Shape;
+ }
+
+ ReferenceBox GetReferenceBox() const
+ {
+ MOZ_ASSERT(mType == StyleShapeSourceType::Box ||
+ mType == StyleShapeSourceType::Shape,
+ "Wrong shape source type!");
+ return mReferenceBox;
+ }
+
+ void SetReferenceBox(ReferenceBox aReferenceBox)
+ {
+ ReleaseRef();
+ mReferenceBox = aReferenceBox;
+ mType = StyleShapeSourceType::Box;
+ }
+
+private:
+ void ReleaseRef()
+ {
+ if (mType == StyleShapeSourceType::Shape) {
+ NS_ASSERTION(mBasicShape, "expected pointer");
+ mBasicShape->Release();
+ } else if (mType == StyleShapeSourceType::URL) {
+ NS_ASSERTION(mURL, "expected pointer");
+ delete mURL;
+ }
+ // Both mBasicShape and mURL are pointers in a union. Nulling one of them
+ // nulls both of them.
+ mURL = nullptr;
+ }
+
+ void CopyURL(const StyleShapeSource& aOther)
+ {
+ ReleaseRef();
+
+ mURL = new FragmentOrURL(*aOther.mURL);
+ mType = StyleShapeSourceType::URL;
+ }
+
+ void* operator new(size_t) = delete;
+
+ union {
+ StyleBasicShape* mBasicShape;
+ FragmentOrURL* mURL;
+ };
+ StyleShapeSourceType mType = StyleShapeSourceType::None_;
+ ReferenceBox mReferenceBox = ReferenceBox::NoBox;
+};
+
+using StyleClipPath = StyleShapeSource<StyleClipPathGeometryBox>;
+using StyleShapeOutside = StyleShapeSource<StyleShapeOutsideShapeBox>;
+
} // namespace mozilla
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay
{
explicit nsStyleDisplay(StyleStructContext aContext);
nsStyleDisplay(const nsStyleDisplay& aOther);
~nsStyleDisplay() {
MOZ_COUNT_DTOR(nsStyleDisplay);
@@ -2639,16 +2892,18 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
mAnimationDurationCount,
mAnimationDelayCount,
mAnimationNameCount,
mAnimationDirectionCount,
mAnimationFillModeCount,
mAnimationPlayStateCount,
mAnimationIterationCountCount;
+ mozilla::StyleShapeOutside mShapeOutside; // [reset]
+
bool IsBlockInsideStyle() const {
return NS_STYLE_DISPLAY_BLOCK == mDisplay ||
NS_STYLE_DISPLAY_LIST_ITEM == mDisplay ||
NS_STYLE_DISPLAY_INLINE_BLOCK == mDisplay ||
NS_STYLE_DISPLAY_TABLE_CAPTION == mDisplay;
// Should TABLE_CELL be included here? They have
// block frames nested inside of them.
// (But please audit all callers before changing.)
@@ -3431,272 +3686,16 @@ private:
STROKE_WIDTH_CONTEXT = 0x40, // stroke-width: context-value
FILL_OPACITY_SOURCE_SHIFT = 0,
STROKE_OPACITY_SOURCE_SHIFT = 2,
};
uint8_t mContextFlags; // [inherited]
};
-namespace mozilla {
-
-class StyleBasicShape final
-{
-public:
- explicit StyleBasicShape(StyleBasicShapeType type)
- : mType(type),
- mFillRule(NS_STYLE_FILL_RULE_NONZERO)
- {
- mPosition.SetInitialPercentValues(0.5f);
- }
-
- StyleBasicShapeType GetShapeType() const { return mType; }
- nsCSSKeyword GetShapeTypeName() const;
-
- int32_t GetFillRule() const { return mFillRule; }
- void SetFillRule(int32_t aFillRule)
- {
- MOZ_ASSERT(mType == StyleBasicShapeType::Polygon, "expected polygon");
- mFillRule = aFillRule;
- }
-
- typedef nsStyleImageLayers::Position Position;
- Position& GetPosition() {
- MOZ_ASSERT(mType == StyleBasicShapeType::Circle ||
- mType == StyleBasicShapeType::Ellipse,
- "expected circle or ellipse");
- return mPosition;
- }
- const Position& GetPosition() const {
- MOZ_ASSERT(mType == StyleBasicShapeType::Circle ||
- mType == StyleBasicShapeType::Ellipse,
- "expected circle or ellipse");
- return mPosition;
- }
-
- bool HasRadius() const {
- MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
- nsStyleCoord zero;
- zero.SetCoordValue(0);
- NS_FOR_CSS_HALF_CORNERS(corner) {
- if (mRadius.Get(corner) != zero) {
- return true;
- }
- }
- return false;
- }
- nsStyleCorners& GetRadius() {
- MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
- return mRadius;
- }
- const nsStyleCorners& GetRadius() const {
- MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
- return mRadius;
- }
-
- // mCoordinates has coordinates for polygon or radii for
- // ellipse and circle.
- nsTArray<nsStyleCoord>& Coordinates()
- {
- return mCoordinates;
- }
-
- const nsTArray<nsStyleCoord>& Coordinates() const
- {
- return mCoordinates;
- }
-
- bool operator==(const StyleBasicShape& aOther) const
- {
- return mType == aOther.mType &&
- mFillRule == aOther.mFillRule &&
- mCoordinates == aOther.mCoordinates &&
- mPosition == aOther.mPosition &&
- mRadius == aOther.mRadius;
- }
- bool operator!=(const StyleBasicShape& aOther) const {
- return !(*this == aOther);
- }
-
- NS_INLINE_DECL_REFCOUNTING(StyleBasicShape);
-
-private:
- ~StyleBasicShape() {}
-
- StyleBasicShapeType mType;
- int32_t mFillRule;
-
- // mCoordinates has coordinates for polygon or radii for
- // ellipse and circle.
- nsTArray<nsStyleCoord> mCoordinates;
- Position mPosition;
- nsStyleCorners mRadius;
-};
-
-template<typename ReferenceBox>
-struct StyleShapeSource
-{
- StyleShapeSource()
- : mURL(nullptr)
- {}
-
- StyleShapeSource(const StyleShapeSource& aSource)
- : StyleShapeSource()
- {
- if (aSource.mType == StyleShapeSourceType::URL) {
- CopyURL(aSource);
- } else if (aSource.mType == StyleShapeSourceType::Shape) {
- SetBasicShape(aSource.mBasicShape, aSource.mReferenceBox);
- } else if (aSource.mType == StyleShapeSourceType::Box) {
- SetReferenceBox(aSource.mReferenceBox);
- }
- }
-
- ~StyleShapeSource()
- {
- ReleaseRef();
- }
-
- StyleShapeSource& operator=(const StyleShapeSource& aOther)
- {
- if (this == &aOther) {
- return *this;
- }
-
- if (aOther.mType == StyleShapeSourceType::URL) {
- CopyURL(aOther);
- } else if (aOther.mType == StyleShapeSourceType::Shape) {
- SetBasicShape(aOther.mBasicShape, aOther.mReferenceBox);
- } else if (aOther.mType == StyleShapeSourceType::Box) {
- SetReferenceBox(aOther.mReferenceBox);
- } else {
- ReleaseRef();
- mReferenceBox = ReferenceBox::NoBox;
- mType = StyleShapeSourceType::None_;
- }
- return *this;
- }
-
- bool operator==(const StyleShapeSource& aOther) const
- {
- if (mType != aOther.mType) {
- return false;
- }
-
- if (mType == StyleShapeSourceType::URL) {
- return mURL == aOther.mURL;
- } else if (mType == StyleShapeSourceType::Shape) {
- return *mBasicShape == *aOther.mBasicShape &&
- mReferenceBox == aOther.mReferenceBox;
- } else if (mType == StyleShapeSourceType::Box) {
- return mReferenceBox == aOther.mReferenceBox;
- }
-
- return true;
- }
-
- bool operator!=(const StyleShapeSource& aOther) const
- {
- return !(*this == aOther);
- }
-
- StyleShapeSourceType GetType() const
- {
- return mType;
- }
-
- FragmentOrURL* GetURL() const
- {
- MOZ_ASSERT(mType == StyleShapeSourceType::URL, "Wrong shape source type!");
- return mURL;
- }
-
- bool SetURL(const nsCSSValue* aValue)
- {
- if (!aValue->GetURLValue()) {
- return false;
- }
-
- ReleaseRef();
-
- mURL = new FragmentOrURL();
- mURL->SetValue(aValue);
- mType = StyleShapeSourceType::URL;
- return true;
- }
-
- StyleBasicShape* GetBasicShape() const
- {
- MOZ_ASSERT(mType == StyleShapeSourceType::Shape, "Wrong shape source type!");
- return mBasicShape;
- }
-
- void SetBasicShape(StyleBasicShape* aBasicShape,
- ReferenceBox aReferenceBox)
- {
- NS_ASSERTION(aBasicShape, "expected pointer");
- ReleaseRef();
- mBasicShape = aBasicShape;
- mBasicShape->AddRef();
- mReferenceBox = aReferenceBox;
- mType = StyleShapeSourceType::Shape;
- }
-
- ReferenceBox GetReferenceBox() const
- {
- MOZ_ASSERT(mType == StyleShapeSourceType::Box ||
- mType == StyleShapeSourceType::Shape,
- "Wrong shape source type!");
- return mReferenceBox;
- }
-
- void SetReferenceBox(ReferenceBox aReferenceBox)
- {
- ReleaseRef();
- mReferenceBox = aReferenceBox;
- mType = StyleShapeSourceType::Box;
- }
-
-private:
- void ReleaseRef()
- {
- if (mType == StyleShapeSourceType::Shape) {
- NS_ASSERTION(mBasicShape, "expected pointer");
- mBasicShape->Release();
- } else if (mType == StyleShapeSourceType::URL) {
- NS_ASSERTION(mURL, "expected pointer");
- delete mURL;
- }
- // Both mBasicShape and mURL are pointers in a union. Nulling one of them
- // nulls both of them.
- mURL = nullptr;
- }
-
- void CopyURL(const StyleShapeSource& aOther)
- {
- ReleaseRef();
-
- mURL = new FragmentOrURL(*aOther.mURL);
- mType = StyleShapeSourceType::URL;
- }
-
- void* operator new(size_t) = delete;
-
- union {
- StyleBasicShape* mBasicShape;
- FragmentOrURL* mURL;
- };
- StyleShapeSourceType mType = StyleShapeSourceType::None_;
- ReferenceBox mReferenceBox = ReferenceBox::NoBox;
-};
-
-using StyleClipPath = StyleShapeSource<StyleClipPathGeometryBox>;
-
-} // namespace mozilla
-
struct nsStyleFilter
{
nsStyleFilter();
nsStyleFilter(const nsStyleFilter& aSource);
~nsStyleFilter();
nsStyleFilter& operator=(const nsStyleFilter& aOther);
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -5593,195 +5593,217 @@ if (IsCSSPropertyPrefEnabled("svg.transf
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "border-box" ],
other_values: [ "fill-box", "view-box" ],
invalid_values: []
};
}
+var basicShapeOtherValues = [
+ "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",
+
+ "polygon(0 0) content-box",
+ "border-box polygon(0 0)",
+ "padding-box polygon( 0 20px , 30px 20% ) ",
+ "polygon(evenodd, 20% 20em) content-box",
+ "polygon(evenodd, 20vh 20em) padding-box",
+ "polygon(evenodd, 20vh calc(20% + 20em)) border-box",
+ "polygon(evenodd, 20vh 20vw) margin-box",
+
+ "circle()",
+ "circle(at center)",
+ "circle(at top left 20px)",
+ "circle(at bottom right)",
+ "circle(20%)",
+ "circle(300px)",
+ "circle(calc(20px + 30px))",
+ "circle(farthest-side)",
+ "circle(closest-side)",
+ "circle(closest-side at center)",
+ "circle(farthest-side at top)",
+ "circle(20px at top right)",
+ "circle(40% at 50% 100%)",
+ "circle(calc(20% + 20%) at right bottom)",
+ "circle() padding-box",
+
+ "ellipse()",
+ "ellipse(at center)",
+ "ellipse(at top left 20px)",
+ "ellipse(at bottom right)",
+ "ellipse(20% 20%)",
+ "ellipse(300px 50%)",
+ "ellipse(calc(20px + 30px) 10%)",
+ "ellipse(farthest-side closest-side)",
+ "ellipse(closest-side farthest-side)",
+ "ellipse(farthest-side farthest-side)",
+ "ellipse(closest-side closest-side)",
+ "ellipse(closest-side closest-side at center)",
+ "ellipse(20% farthest-side at top)",
+ "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%)",
+];
+
+var basicShapeInvalidValues = [
+ "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(0 0) conten-box content-box",
+ "content-box polygon(0 0) conten-box",
+ "padding-box polygon(0 0) conten-box",
+ "polygon(0 0) polygon(0 0) content-box",
+ "polygon(0 0) content-box polygon(0 0)",
+ "polygon(0 0), content-box",
+ "polygon(0 0), polygon(0 0)",
+ "content-box polygon(0 0) polygon(0 0)",
+ "content-box polygon(0 0) none",
+ "none content-box polygon(0 0)",
+ "inherit content-box polygon(0 0)",
+ "initial polygon(0 0)",
+ "polygon(0 0) farthest-side",
+ "farthest-corner polygon(0 0)",
+ "polygon(0 0) farthest-corner",
+ "polygon(0 0) conten-box",
+ "polygon(0 0) polygon(0 0) farthest-corner",
+ "polygon(0 0) polygon(0 0) polygon(0 0)",
+ "border-box polygon(0, 0)",
+ "border-box padding-box",
+ "margin-box farthest-side",
+ "nonsense() border-box",
+ "border-box nonsense()",
+
+ "circle(at)",
+ "circle(at 20% 20% 30%)",
+ "circle(20px 2px at center)",
+ "circle(2at center)",
+ "circle(closest-corner)",
+ "circle(at center top closest-side)",
+ "circle(-20px)",
+ "circle(farthest-side closest-side)",
+ "circle(20% 20%)",
+ "circle(at farthest-side)",
+ "circle(calc(20px + rubbish))",
+
+ "ellipse(at)",
+ "ellipse(at 20% 20% 30%)",
+ "ellipse(20px at center)",
+ "ellipse(-20px 20px)",
+ "ellipse(closest-corner farthest-corner)",
+ "ellipse(20px -20px)",
+ "ellipse(-20px -20px)",
+ "ellipse(farthest-side)",
+ "ellipse(20%)",
+ "ellipse(at farthest-side farthest-side)",
+ "ellipse(at top left calc(20px + rubbish))",
+
+ "polygon(at)",
+ "polygon(at 20% 20% 30%)",
+ "polygon(20px at center)",
+ "polygon(2px 2at center)",
+ "polygon(closest-corner farthest-corner)",
+ "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)",
+ "inset(1px calc(2px + rubbish))",
+ "inset(1px round 2px calc(3px + rubbish))",
+];
+
+var basicShapeUnbalancedValues = [
+ "polygon(30% 30%",
+ "polygon(nonzero, 20% 20px",
+ "polygon(evenodd, 20px 20px",
+
+ "circle(",
+ "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",
+];
+
if (IsCSSPropertyPrefEnabled("layout.css.clip-path-shapes.enabled")) {
gCSSProperties["clip-path"] = {
domProp: "clipPath",
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) content-box",
- "border-box polygon(0 0)",
- "padding-box polygon( 0 20px , 30px 20% ) ",
- "polygon(evenodd, 20% 20em) content-box",
- "polygon(evenodd, 20vh 20em) padding-box",
- "polygon(evenodd, 20vh calc(20% + 20em)) border-box",
- "polygon(evenodd, 20vh 20vw) margin-box",
"polygon(evenodd, 20pt 20cm) fill-box",
"polygon(evenodd, 20ex 20pc) stroke-box",
"polygon(evenodd, 20rem 20in) view-box",
-
- "circle()",
- "circle(at center)",
- "circle(at top left 20px)",
- "circle(at bottom right)",
- "circle(20%)",
- "circle(300px)",
- "circle(calc(20px + 30px))",
- "circle(farthest-side)",
- "circle(closest-side)",
- "circle(closest-side at center)",
- "circle(farthest-side at top)",
- "circle(20px at top right)",
- "circle(40% at 50% 100%)",
- "circle(calc(20% + 20%) at right bottom)",
- "circle() padding-box",
-
- "ellipse()",
- "ellipse(at center)",
- "ellipse(at top left 20px)",
- "ellipse(at bottom right)",
- "ellipse(20% 20%)",
- "ellipse(300px 50%)",
- "ellipse(calc(20px + 30px) 10%)",
- "ellipse(farthest-side closest-side)",
- "ellipse(closest-side farthest-side)",
- "ellipse(farthest-side farthest-side)",
- "ellipse(closest-side closest-side)",
- "ellipse(closest-side closest-side at center)",
- "ellipse(20% farthest-side at top)",
- "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)",
- "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(0 0) conten-box content-box",
- "content-box polygon(0 0) conten-box",
- "padding-box polygon(0 0) conten-box",
- "polygon(0 0) polygon(0 0) content-box",
- "polygon(0 0) content-box polygon(0 0)",
- "polygon(0 0), content-box",
- "polygon(0 0), polygon(0 0)",
- "content-box polygon(0 0) polygon(0 0)",
- "content-box polygon(0 0) none",
- "none content-box polygon(0 0)",
- "inherit content-box polygon(0 0)",
- "initial polygon(0 0)",
- "polygon(0 0) farthest-side",
- "farthest-corner polygon(0 0)",
- "polygon(0 0) farthest-corner",
- "polygon(0 0) conten-box",
- "polygon(0 0) polygon(0 0) farthest-corner",
- "polygon(0 0) polygon(0 0) polygon(0 0)",
- "border-box polygon(0, 0)",
- "border-box padding-box",
- "margin-box farthest-side",
- "nonsense() border-box",
- "border-box nonsense()",
-
- "circle(at)",
- "circle(at 20% 20% 30%)",
- "circle(20px 2px at center)",
- "circle(2at center)",
- "circle(closest-corner)",
- "circle(at center top closest-side)",
- "circle(-20px)",
- "circle(farthest-side closest-side)",
- "circle(20% 20%)",
- "circle(at farthest-side)",
- "circle(calc(20px + rubbish))",
-
- "ellipse(at)",
- "ellipse(at 20% 20% 30%)",
- "ellipse(20px at center)",
- "ellipse(-20px 20px)",
- "ellipse(closest-corner farthest-corner)",
- "ellipse(20px -20px)",
- "ellipse(-20px -20px)",
- "ellipse(farthest-side)",
- "ellipse(20%)",
- "ellipse(at farthest-side farthest-side)",
- "ellipse(at top left calc(20px + rubbish))",
-
- "polygon(at)",
- "polygon(at 20% 20% 30%)",
- "polygon(20px at center)",
- "polygon(2px 2at center)",
- "polygon(closest-corner farthest-corner)",
- "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)",
- "inset(1px calc(2px + rubbish))",
- "inset(1px round 2px calc(3px + rubbish))",
- ],
- unbalanced_values: [
- "polygon(30% 30%",
- "polygon(nonzero, 20% 20px",
- "polygon(evenodd, 20px 20px",
-
- "circle(",
- "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",
- ]
+ ].concat(basicShapeOtherValues),
+ invalid_values: basicShapeInvalidValues,
+ unbalanced_values: basicShapeUnbalancedValues,
+ };
+}
+
+if (IsCSSPropertyPrefEnabled("layout.css.shape-outside.enabled")) {
+ gCSSProperties["shape-outside"] = {
+ domProp: "shapeOutside",
+ inherited: false,
+ type: CSS_TYPE_LONGHAND,
+ initial_values: [ "none" ],
+ other_values: [
+ "url(#my-shape-outside)",
+ ].concat(basicShapeOtherValues),
+ invalid_values: basicShapeInvalidValues,
+ unbalanced_values: basicShapeUnbalancedValues,
};
}
if (IsCSSPropertyPrefEnabled("layout.css.filters.enabled")) {
gCSSProperties["filter"] = {
domProp: "filter",
inherited: false,
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -2598,16 +2598,19 @@ pref("layout.css.scroll-behavior.spring-
// reduced speed without overshooting.
// When equal to 1.0, the system is critically-damped; it will reach the target
// at the greatest speed without overshooting.
pref("layout.css.scroll-behavior.damping-ratio", "1.0");
// Is support for scroll-snap enabled?
pref("layout.css.scroll-snap.enabled", true);
+// Is support for CSS shape-outside enabled?
+pref("layout.css.shape-outside.enabled", false);
+
// Is support for document.fonts enabled?
pref("layout.css.font-loading-api.enabled", true);
// Should stray control characters be rendered visibly?
#ifdef RELEASE_BUILD
pref("layout.css.control-characters.visible", false);
#else
pref("layout.css.control-characters.visible", true);
--- a/testing/profiles/prefs_general.js
+++ b/testing/profiles/prefs_general.js
@@ -171,16 +171,19 @@ user_pref("layout.css.initial-letter.ena
user_pref("layout.css.object-fit-and-position.enabled", true);
// Enable webkit prefixed CSS features for testing
user_pref("layout.css.prefixes.webkit", true);
// Enable -webkit-{min|max}-device-pixel-ratio media queries for testing
user_pref("layout.css.prefixes.device-pixel-ratio-webkit", true);
+// Enable CSS shape-outside for testing
+user_pref("layout.css.shape-outside.enabled", true);
+
// Disable spammy layout warnings because they pollute test logs
user_pref("layout.spammy_warnings.enabled", false);
// Enable Media Source Extensions for testing
user_pref("media.mediasource.mp4.enabled", true);
user_pref("media.mediasource.webm.enabled", true);
// Enable mozContacts