Bug 793617 - Implement mask-type property. r=dbaron,longsonr
authorCameron McCormack <cam@mcc.id.au>
Fri, 21 Dec 2012 11:15:22 +1100
changeset 116738 e043d5feb0b6
parent 116737 01f69299eba0
child 116739 f533eacd8458
push id24072
push userMs2ger@gmail.com
push date2012-12-22 13:18 +0000
treeherdermozilla-central@ea373e534245 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron, longsonr
bugs793617
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 793617 - Implement mask-type property. r=dbaron,longsonr
content/base/src/nsGkAtomList.h
content/smil/nsSMILCSSProperty.cpp
content/svg/content/src/nsSVGElement.cpp
content/svg/content/src/nsSVGElement.h
content/svg/content/src/nsSVGMaskElement.cpp
layout/base/nsStyleConsts.h
layout/reftests/svg/mask-type-01-ref.svg
layout/reftests/svg/mask-type-01.svg
layout/reftests/svg/mask-type-02.svg
layout/reftests/svg/mask-type-03.svg
layout/reftests/svg/mask-type-04.svg
layout/reftests/svg/reftest.list
layout/style/nsCSSKeywordList.h
layout/style/nsCSSPropList.h
layout/style/nsCSSProps.cpp
layout/style/nsCSSProps.h
layout/style/nsComputedDOMStyle.cpp
layout/style/nsComputedDOMStyle.h
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/style/test/property_database.js
layout/svg/nsSVGMaskFrame.cpp
modules/libpref/src/init/all.js
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1291,16 +1291,17 @@ GK_ATOM(marker, "marker")
 GK_ATOM(marker_end, "marker-end")
 GK_ATOM(marker_mid, "marker-mid")
 GK_ATOM(marker_start, "marker-start")
 GK_ATOM(markerHeight, "markerHeight")
 GK_ATOM(markerUnits, "markerUnits")
 GK_ATOM(markerWidth, "markerWidth")
 GK_ATOM(mask, "mask")
 GK_ATOM(maskContentUnits, "maskContentUnits")
+GK_ATOM(mask_type, "mask-type")
 GK_ATOM(maskUnits, "maskUnits")
 GK_ATOM(matrix, "matrix")
 GK_ATOM(metadata, "metadata")
 GK_ATOM(missingGlyph, "missing-glyph")
 GK_ATOM(mm, "mm")
 GK_ATOM(mpath, "mpath")
 GK_ATOM(noStitch, "noStitch")
 GK_ATOM(numOctaves, "numOctaves")
--- a/content/smil/nsSMILCSSProperty.cpp
+++ b/content/smil/nsSMILCSSProperty.cpp
@@ -223,16 +223,17 @@ nsSMILCSSProperty::IsPropertyAnimatable(
     case eCSSProperty_image_rendering:
     case eCSSProperty_letter_spacing:
     case eCSSProperty_lighting_color:
     case eCSSProperty_marker:
     case eCSSProperty_marker_end:
     case eCSSProperty_marker_mid:
     case eCSSProperty_marker_start:
     case eCSSProperty_mask:
+    case eCSSProperty_mask_type:
     case eCSSProperty_opacity:
     case eCSSProperty_overflow:
     case eCSSProperty_pointer_events:
     case eCSSProperty_shape_rendering:
     case eCSSProperty_stop_color:
     case eCSSProperty_stop_opacity:
     case eCSSProperty_stroke:
     case eCSSProperty_stroke_dasharray:
--- a/content/svg/content/src/nsSVGElement.cpp
+++ b/content/svg/content/src/nsSVGElement.cpp
@@ -1006,16 +1006,23 @@ nsSVGElement::sFEFloodMap[] = {
 
 // PresentationAttributes-LightingEffects
 /* static */ const Element::MappedAttributeEntry
 nsSVGElement::sLightingEffectsMap[] = {
   { &nsGkAtoms::lighting_color },
   { nullptr }
 };
 
+// PresentationAttributes-mask
+/* static */ const Element::MappedAttributeEntry
+nsSVGElement::sMaskMap[] = {
+  { &nsGkAtoms::mask_type },
+  { nullptr }
+};
+
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 NS_IMETHODIMP
 nsSVGElement::IsSupported(const nsAString& aFeature, const nsAString& aVersion, bool* aReturn)
 {
   *aReturn = Element::IsSupported(aFeature, aVersion);
   return NS_OK;
--- a/content/svg/content/src/nsSVGElement.h
+++ b/content/svg/content/src/nsSVGElement.h
@@ -98,16 +98,17 @@ public:
   static const MappedAttributeEntry sFontSpecificationMap[];
   static const MappedAttributeEntry sGradientStopMap[];
   static const MappedAttributeEntry sViewportsMap[];
   static const MappedAttributeEntry sMarkersMap[];
   static const MappedAttributeEntry sColorMap[];
   static const MappedAttributeEntry sFiltersMap[];
   static const MappedAttributeEntry sFEFloodMap[];
   static const MappedAttributeEntry sLightingEffectsMap[];
+  static const MappedAttributeEntry sMaskMap[];
 
   // nsIDOMNode
   NS_IMETHOD IsSupported(const nsAString& aFeature, const nsAString& aVersion,
                          bool* aReturn);
   
   // nsIDOMSVGElement
   NS_IMETHOD GetId(nsAString & aId);
   NS_IMETHOD SetId(const nsAString & aId);
--- a/content/svg/content/src/nsSVGMaskElement.cpp
+++ b/content/svg/content/src/nsSVGMaskElement.cpp
@@ -136,15 +136,16 @@ nsSVGMaskElement::IsAttributeMapped(cons
 {
   static const MappedAttributeEntry* const map[] = {
     sFEFloodMap,
     sFiltersMap,
     sFontSpecificationMap,
     sGradientStopMap,
     sGraphicsMap,
     sMarkersMap,
+    sMaskMap,
     sTextContentElementsMap,
     sViewportsMap
   };
 
   return FindAttributeDependence(name, map) ||
     nsSVGMaskElementBase::IsAttributeMapped(name);
 }
--- a/layout/base/nsStyleConsts.h
+++ b/layout/base/nsStyleConsts.h
@@ -854,16 +854,20 @@ static inline mozilla::css::Side operato
 #define NS_STYLE_FILL_RULE_EVENODD              1
 
 // image-rendering
 #define NS_STYLE_IMAGE_RENDERING_AUTO             0
 #define NS_STYLE_IMAGE_RENDERING_OPTIMIZESPEED    1
 #define NS_STYLE_IMAGE_RENDERING_OPTIMIZEQUALITY  2
 #define NS_STYLE_IMAGE_RENDERING_CRISPEDGES       3
 
+// mask-type
+#define NS_STYLE_MASK_TYPE_LUMINANCE            0
+#define NS_STYLE_MASK_TYPE_ALPHA                1
+
 // shape-rendering
 #define NS_STYLE_SHAPE_RENDERING_AUTO               0
 #define NS_STYLE_SHAPE_RENDERING_OPTIMIZESPEED      1
 #define NS_STYLE_SHAPE_RENDERING_CRISPEDGES         2
 #define NS_STYLE_SHAPE_RENDERING_GEOMETRICPRECISION 3
 
 // stroke-linecap
 #define NS_STYLE_STROKE_LINECAP_BUTT            0
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/mask-type-01-ref.svg
@@ -0,0 +1,12 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
+
+  <title>Reference for alpha mask</title>
+
+  <!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=793617 -->
+
+  <rect x="10" y="10" width="80" height="80" fill="blue" fill-opacity="0.5"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/mask-type-01.svg
@@ -0,0 +1,15 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
+
+  <title>Testcase for alpha mask</title>
+
+  <!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=793617 -->
+
+  <mask id="m" maskContentUnits="objectBoundingBox" style="mask-type: alpha">
+    <rect x=".1" y=".1" width=".8" height=".8" fill="black" fill-opacity="0.5"/>
+  </mask>
+  <rect width="100" height="100" fill="blue" mask="url(#m)"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/mask-type-02.svg
@@ -0,0 +1,15 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
+
+  <title>Testcase for alpha mask using the presentation attribute</title>
+
+  <!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=793617 -->
+
+  <mask id="m" maskContentUnits="objectBoundingBox" mask-type="alpha">
+    <rect x=".1" y=".1" width=".8" height=".8" fill="black" fill-opacity="0.5"/>
+  </mask>
+  <rect width="100" height="100" fill="blue" mask="url(#m)"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/mask-type-03.svg
@@ -0,0 +1,23 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"
+     class="reftest-wait" onload="run()">
+
+  <title>Testcase for alpha mask, dynamically setting mask-type</title>
+
+  <!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=793617 -->
+
+  <mask id="m" maskContentUnits="objectBoundingBox">
+    <rect x=".1" y=".1" width=".8" height=".8" fill="black" fill-opacity="0.5"/>
+  </mask>
+  <rect width="100" height="100" fill="blue" mask="url(#m)"/>
+
+  <script>
+    function run() {
+      document.getElementById("m").style.maskType = "alpha";
+      document.documentElement.removeAttribute("class");
+    }
+  </script>
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/mask-type-04.svg
@@ -0,0 +1,16 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
+
+  <title>Testcase for alpha mask, dynamically setting mask-type</title>
+
+  <!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=793617 -->
+
+  <mask id="m" maskContentUnits="objectBoundingBox">
+    <rect x=".1" y=".1" width=".8" height=".8" fill="black" fill-opacity="0.5"/>
+    <set attributeName="mask-type" to="alpha"/>
+  </mask>
+  <rect width="100" height="100" fill="blue" mask="url(#m)"/>
+</svg>
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -172,16 +172,20 @@ fuzzy-if(Android,9,980) == gradient-live
 == marker-attribute-01.svg pass.svg
 == marker-viewBox-01.svg marker-viewBox-01-ref.svg
 == marker-orientation-01.svg marker-orientation-01-ref.svg
 == mask-basic-01.svg pass.svg
 == mask-basic-02.svg mask-basic-02-ref.svg
 == mask-extref-dataURI-01.svg pass.svg
 == mask-containing-masked-content-01.svg pass.svg
 == mask-transformed-01.svg mask-transformed-01-ref.svg
+pref(layout.css.masking.enabled,true) == mask-type-01.svg mask-type-01-ref.svg
+pref(layout.css.masking.enabled,true) == mask-type-02.svg mask-type-01-ref.svg
+pref(layout.css.masking.enabled,true) == mask-type-03.svg mask-type-01-ref.svg
+pref(layout.css.masking.enabled,true) == mask-type-04.svg mask-type-01-ref.svg
 == nested-viewBox-01.svg pass.svg
 == nesting-invalid-01.svg nesting-invalid-01-ref.svg
 == non-scaling-stroke-01.svg non-scaling-stroke-01-ref.svg 
 fuzzy-if(Android,9,61) fuzzy-if(!contentSameGfxBackendAsCanvas,1,99) == non-scaling-stroke-02.svg non-scaling-stroke-02-ref.svg 
 == objectBoundingBox-and-clipPath.svg pass.svg
 # Bug 588684
 random-if(gtk2Widget) == objectBoundingBox-and-fePointLight-01.svg objectBoundingBox-and-fePointLight-01-ref.svg
 random-if(gtk2Widget) == objectBoundingBox-and-fePointLight-02.svg objectBoundingBox-and-fePointLight-02-ref.svg
--- a/layout/style/nsCSSKeywordList.h
+++ b/layout/style/nsCSSKeywordList.h
@@ -159,16 +159,17 @@ CSS_KEY(-moz-zoom-in, _moz_zoom_in)
 CSS_KEY(-moz-zoom-out, _moz_zoom_out)
 CSS_KEY(absolute, absolute)
 CSS_KEY(active, active)
 CSS_KEY(activeborder, activeborder)
 CSS_KEY(activecaption, activecaption)
 CSS_KEY(alias, alias)
 CSS_KEY(all, all)
 CSS_KEY(all-scroll, all_scroll)
+CSS_KEY(alpha, alpha)
 CSS_KEY(alternate, alternate)
 CSS_KEY(alternate-reverse, alternate_reverse)
 CSS_KEY(always, always)
 CSS_KEY(appworkspace, appworkspace)
 CSS_KEY(armenian, armenian)
 CSS_KEY(auto, auto)
 CSS_KEY(avoid, avoid)
 CSS_KEY(background, background)
@@ -311,16 +312,17 @@ CSS_KEY(linear, linear)
 CSS_KEY(list-item, list_item)
 CSS_KEY(logical, logical)
 CSS_KEY(lower-alpha, lower_alpha)
 CSS_KEY(lower-greek, lower_greek)
 CSS_KEY(lower-latin, lower_latin)
 CSS_KEY(lower-roman, lower_roman)
 CSS_KEY(lowercase, lowercase)
 CSS_KEY(ltr, ltr)
+CSS_KEY(luminance, luminance)
 CSS_KEY(manual, manual)
 CSS_KEY(margin-box, margin_box)
 CSS_KEY(matrix, matrix)
 CSS_KEY(matrix3d, matrix3d)
 CSS_KEY(medium, medium)
 CSS_KEY(menu, menu)
 CSS_KEY(menutext, menutext)
 CSS_KEY(message-box, message_box)
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -3289,16 +3289,26 @@ CSS_PROP_SVGRESET(
     mask,
     Mask,
     CSS_PROPERTY_PARSE_VALUE,
     "",
     VARIANT_HUO,
     nullptr,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
+CSS_PROP_SVGRESET(
+    mask-type,
+    mask_type,
+    MaskType,
+    CSS_PROPERTY_PARSE_VALUE,
+    "layout.css.masking.enabled",
+    VARIANT_HK,
+    kMaskTypeKTable,
+    offsetof(nsStyleSVGReset, mMaskType),
+    eStyleAnimType_EnumU8)
 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
@@ -1581,16 +1581,22 @@ const int32_t nsCSSProps::kFillRuleKTabl
 const int32_t nsCSSProps::kImageRenderingKTable[] = {
   eCSSKeyword_auto, NS_STYLE_IMAGE_RENDERING_AUTO,
   eCSSKeyword_optimizespeed, NS_STYLE_IMAGE_RENDERING_OPTIMIZESPEED,
   eCSSKeyword_optimizequality, NS_STYLE_IMAGE_RENDERING_OPTIMIZEQUALITY,
   eCSSKeyword__moz_crisp_edges, NS_STYLE_IMAGE_RENDERING_CRISPEDGES,
   eCSSKeyword_UNKNOWN, -1
 };
 
+const int32_t nsCSSProps::kMaskTypeKTable[] = {
+  eCSSKeyword_luminance, NS_STYLE_MASK_TYPE_LUMINANCE,
+  eCSSKeyword_alpha, NS_STYLE_MASK_TYPE_ALPHA,
+  eCSSKeyword_UNKNOWN, -1
+};
+
 const int32_t 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
@@ -401,16 +401,17 @@ public:
   static const int32_t kFontStretchKTable[];
   static const int32_t kFontStyleKTable[];
   static const int32_t kFontVariantKTable[];
   static const int32_t kFontWeightKTable[];
   static const int32_t kIMEModeKTable[];
   static const int32_t kLineHeightKTable[];
   static const int32_t kListStylePositionKTable[];
   static const int32_t kListStyleKTable[];
+  static const int32_t kMaskTypeKTable[];
   static const int32_t kObjectOpacityKTable[];
   static const int32_t kObjectPatternKTable[];
   static const int32_t kOrientKTable[];
   static const int32_t kOutlineStyleKTable[];
   static const int32_t kOutlineColorKTable[];
   static const int32_t kOverflowKTable[];
   static const int32_t kOverflowSubKTable[];
   static const int32_t kPageBreakKTable[];
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -4358,16 +4358,26 @@ nsComputedDOMStyle::DoGetMask()
     val->SetURI(svg->mMask);
   else
     val->SetIdent(eCSSKeyword_none);
 
   return val;
 }
 
 CSSValue*
+nsComputedDOMStyle::DoGetMaskType()
+{
+  nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
+  val->SetIdent(
+    nsCSSProps::ValueToKeywordEnum(GetStyleSVGReset()->mMaskType,
+                                   nsCSSProps::kMaskTypeKTable));
+  return val;
+}
+
+CSSValue*
 nsComputedDOMStyle::DoGetTransitionDelay()
 {
   const nsStyleDisplay* display = GetStyleDisplay();
 
   nsDOMCSSValueList *valueList = GetROCSSValueList(true);
 
   NS_ABORT_IF_FALSE(display->mTransitionDelayCount > 0,
                     "first item must be explicit");
@@ -4924,16 +4934,17 @@ nsComputedDOMStyle::GetQueryableProperty
     COMPUTED_STYLE_MAP_ENTRY(flood_color,                   FloodColor),
     COMPUTED_STYLE_MAP_ENTRY(flood_opacity,                 FloodOpacity),
     COMPUTED_STYLE_MAP_ENTRY(image_rendering,               ImageRendering),
     COMPUTED_STYLE_MAP_ENTRY(lighting_color,                LightingColor),
     COMPUTED_STYLE_MAP_ENTRY(marker_end,                    MarkerEnd),
     COMPUTED_STYLE_MAP_ENTRY(marker_mid,                    MarkerMid),
     COMPUTED_STYLE_MAP_ENTRY(marker_start,                  MarkerStart),
     COMPUTED_STYLE_MAP_ENTRY(mask,                          Mask),
+    COMPUTED_STYLE_MAP_ENTRY(mask_type,                     MaskType),
     COMPUTED_STYLE_MAP_ENTRY(shape_rendering,               ShapeRendering),
     COMPUTED_STYLE_MAP_ENTRY(stop_color,                    StopColor),
     COMPUTED_STYLE_MAP_ENTRY(stop_opacity,                  StopOpacity),
     COMPUTED_STYLE_MAP_ENTRY(stroke,                        Stroke),
     COMPUTED_STYLE_MAP_ENTRY(stroke_dasharray,              StrokeDasharray),
     COMPUTED_STYLE_MAP_ENTRY(stroke_dashoffset,             StrokeDashoffset),
     COMPUTED_STYLE_MAP_ENTRY(stroke_linecap,                StrokeLinecap),
     COMPUTED_STYLE_MAP_ENTRY(stroke_linejoin,               StrokeLinejoin),
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -416,16 +416,17 @@ private:
 
   mozilla::dom::CSSValue* DoGetFloodColor();
   mozilla::dom::CSSValue* DoGetLightingColor();
   mozilla::dom::CSSValue* DoGetStopColor();
 
   mozilla::dom::CSSValue* DoGetClipPath();
   mozilla::dom::CSSValue* DoGetFilter();
   mozilla::dom::CSSValue* DoGetMask();
+  mozilla::dom::CSSValue* DoGetMaskType();
 
   nsROCSSPrimitiveValue* GetROCSSPrimitiveValue();
   nsDOMCSSValueList* GetROCSSValueList(bool aCommaDelimited);
   void SetToRGBAColor(nsROCSSPrimitiveValue* aValue, nscolor aColor);
   void SetValueToStyleImage(const nsStyleImage& aStyleImage,
                             nsROCSSPrimitiveValue* aValue);
 
   /**
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -7612,16 +7612,23 @@ nsRuleNode::ComputeSVGResetData(void* aS
   } else if (eCSSUnit_None == maskValue->GetUnit() ||
              eCSSUnit_Initial == maskValue->GetUnit()) {
     svgReset->mMask = nullptr;
   } else if (eCSSUnit_Inherit == maskValue->GetUnit()) {
     canStoreInRuleTree = false;
     svgReset->mMask = parentSVGReset->mMask;
   }
 
+  // mask-type: enum, inherit, initial
+  SetDiscrete(*aRuleData->ValueForMaskType(),
+              svgReset->mMaskType,
+              canStoreInRuleTree, SETDSC_ENUMERATED,
+              parentSVGReset->mMaskType,
+              NS_STYLE_MASK_TYPE_LUMINANCE, 0, 0, 0, 0);
+
   COMPUTE_END_RESET(SVGReset, svgReset)
 }
 
 const void*
 nsRuleNode::GetStyleData(nsStyleStructID aSID,
                          nsStyleContext* aContext,
                          bool aComputeData)
 {
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -965,16 +965,17 @@ nsStyleSVGReset::nsStyleSVGReset()
     mLightingColor           = NS_RGB(255,255,255);
     mClipPath                = nullptr;
     mFilter                  = nullptr;
     mMask                    = nullptr;
     mStopOpacity             = 1.0f;
     mFloodOpacity            = 1.0f;
     mDominantBaseline        = NS_STYLE_DOMINANT_BASELINE_AUTO;
     mVectorEffect            = NS_STYLE_VECTOR_EFFECT_NONE;
+    mMaskType                = NS_STYLE_MASK_TYPE_LUMINANCE;
 }
 
 nsStyleSVGReset::~nsStyleSVGReset() 
 {
   MOZ_COUNT_DTOR(nsStyleSVGReset);
 }
 
 nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset& aSource)
@@ -985,16 +986,17 @@ nsStyleSVGReset::nsStyleSVGReset(const n
   mLightingColor = aSource.mLightingColor;
   mClipPath = aSource.mClipPath;
   mFilter = aSource.mFilter;
   mMask = aSource.mMask;
   mStopOpacity = aSource.mStopOpacity;
   mFloodOpacity = aSource.mFloodOpacity;
   mDominantBaseline = aSource.mDominantBaseline;
   mVectorEffect = aSource.mVectorEffect;
+  mMaskType = aSource.mMaskType;
 }
 
 nsChangeHint nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aOther) const
 {
   nsChangeHint hint = nsChangeHint(0);
 
   if (!EqualURIs(mClipPath, aOther.mClipPath) ||
       !EqualURIs(mFilter, aOther.mFilter)     ||
@@ -1005,17 +1007,18 @@ nsChangeHint nsStyleSVGReset::CalcDiffer
   } else if (mDominantBaseline != aOther.mDominantBaseline) {
     NS_UpdateHint(hint, nsChangeHint_NeedReflow);
     NS_UpdateHint(hint, nsChangeHint_NeedDirtyReflow);
   } else if (mStopColor     != aOther.mStopColor     ||
              mFloodColor    != aOther.mFloodColor    ||
              mLightingColor != aOther.mLightingColor ||
              mStopOpacity   != aOther.mStopOpacity   ||
              mFloodOpacity  != aOther.mFloodOpacity  ||
-             mVectorEffect  != aOther.mVectorEffect)
+             mVectorEffect  != aOther.mVectorEffect  ||
+             mMaskType      != aOther.mMaskType)
     NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
 
   return hint;
 }
 
 // nsStyleSVGPaint implementation
 nsStyleSVGPaint::~nsStyleSVGPaint()
 {
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -2273,11 +2273,12 @@ struct nsStyleSVGReset {
   nscolor          mFloodColor;       // [reset]
   nscolor          mLightingColor;    // [reset]
 
   float            mStopOpacity;      // [reset]
   float            mFloodOpacity;     // [reset]
 
   uint8_t          mDominantBaseline; // [reset] see nsStyleConsts.h
   uint8_t          mVectorEffect;     // [reset] see nsStyleConsts.h
+  uint8_t          mMaskType;         // [reset] see nsStyleConsts.h
 };
 
 #endif /* nsStyleStruct_h___ */
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -3573,16 +3573,24 @@ var gCSSProperties = {
 	"mask": {
 		domProp: "mask",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "none" ],
 		other_values: [ "url(#mymask)" ],
 		invalid_values: []
 	},
+	"mask-type": {
+		domProp: "maskType",
+		inherited: false,
+		type: CSS_TYPE_LONGHAND,
+		initial_values: [ "luminance" ],
+		other_values: [ "alpha" ],
+		invalid_values: []
+	},
 	"shape-rendering": {
 		domProp: "shapeRendering",
 		inherited: true,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "auto" ],
 		other_values: [ "optimizeSpeed", "crispEdges", "geometricPrecision" ],
 		invalid_values: []
 	},
--- a/layout/svg/nsSVGMaskFrame.cpp
+++ b/layout/svg/nsSVGMaskFrame.cpp
@@ -114,30 +114,41 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsRende
 
   nsIntRect rect(0, 0, surfaceSize.width, surfaceSize.height);
   nsSVGUtils::UnPremultiplyImageDataAlpha(data, stride, rect);
   if (GetStyleSVG()->mColorInterpolation ==
       NS_STYLE_COLOR_INTERPOLATION_LINEARRGB) {
     nsSVGUtils::ConvertImageDataToLinearRGB(data, stride, rect);
   }
 
-  for (int32_t y = 0; y < surfaceSize.height; y++)
-    for (int32_t x = 0; x < surfaceSize.width; x++) {
-      uint8_t *pixel = data + stride * y + 4 * x;
+  if (GetStyleSVGReset()->mMaskType == NS_STYLE_MASK_TYPE_LUMINANCE) {
+    for (int32_t y = 0; y < surfaceSize.height; y++) {
+      for (int32_t x = 0; x < surfaceSize.width; x++) {
+        uint8_t *pixel = data + stride * y + 4 * x;
+
+        /* linearRGB -> intensity */
+        uint8_t alpha =
+          static_cast<uint8_t>
+                     ((pixel[GFX_ARGB32_OFFSET_R] * 0.2125 +
+                          pixel[GFX_ARGB32_OFFSET_G] * 0.7154 +
+                          pixel[GFX_ARGB32_OFFSET_B] * 0.0721) *
+                         (pixel[GFX_ARGB32_OFFSET_A] / 255.0) * aOpacity);
 
-      /* linearRGB -> intensity */
-      uint8_t alpha =
-        static_cast<uint8_t>
-                   ((pixel[GFX_ARGB32_OFFSET_R] * 0.2125 +
-                        pixel[GFX_ARGB32_OFFSET_G] * 0.7154 +
-                        pixel[GFX_ARGB32_OFFSET_B] * 0.0721) *
-                       (pixel[GFX_ARGB32_OFFSET_A] / 255.0) * aOpacity);
-
-      memset(pixel, alpha, 4);
+        memset(pixel, alpha, 4);
+      }
     }
+  } else {
+    for (int32_t y = 0; y < surfaceSize.height; y++) {
+      for (int32_t x = 0; x < surfaceSize.width; x++) {
+        uint8_t *pixel = data + stride * y + 4 * x;
+        uint8_t alpha = pixel[GFX_ARGB32_OFFSET_A] * aOpacity;
+        memset(pixel, alpha, 4);
+      }
+    }
+  }
 
   gfxPattern *retval = new gfxPattern(image);
   retval->SetMatrix(matrix);
   NS_IF_ADDREF(retval);
   return retval;
 }
 
 /* virtual */ void
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -1633,16 +1633,23 @@ pref("layout.css.visited_links_enabled",
 pref("layout.css.dpi", -1);
 
 // Set the number of device pixels per CSS pixel. A value <= 0 means choose
 // automatically based on user settings for the platform (e.g., "UI scale factor"
 // on Mac). A positive value is used as-is. This effectively controls the size
 // of a CSS "px". This is only used for windows on the screen, not for printing.
 pref("layout.css.devPixelsPerPx", "-1.0");
 
+// Is support for CSS Masking features enabled?
+#ifdef RELEASE_BUILD
+pref("layout.css.masking.enabled", false);
+#else
+pref("layout.css.masking.enabled", true);
+#endif
+
 // Is support for the the @supports rule enabled?
 #ifdef RELEASE_BUILD
 pref("layout.css.supports-rule.enabled", false);
 #else
 pref("layout.css.supports-rule.enabled", true);
 #endif
 
 // Is support for CSS Flexbox enabled?