Bug 793617 - Implement mask-type property. r=dbaron,longsonr

This commit is contained in:
Cameron McCormack 2012-12-21 11:15:22 +11:00
parent 70b21266cb
commit 3a091090a1
24 changed files with 180 additions and 12 deletions

View File

@ -1296,6 +1296,7 @@ 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")

View File

@ -228,6 +228,7 @@ nsSMILCSSProperty::IsPropertyAnimatable(nsCSSProperty aPropID)
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:

View File

@ -1011,6 +1011,13 @@ nsSVGElement::sLightingEffectsMap[] = {
{ nullptr }
};
// PresentationAttributes-mask
/* static */ const Element::MappedAttributeEntry
nsSVGElement::sMaskMap[] = {
{ &nsGkAtoms::mask_type },
{ nullptr }
};
//----------------------------------------------------------------------
// nsIDOMNode methods

View File

@ -103,6 +103,7 @@ public:
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,

View File

@ -141,6 +141,7 @@ nsSVGMaskElement::IsAttributeMapped(const nsIAtom* name) const
sGradientStopMap,
sGraphicsMap,
sMarkersMap,
sMaskMap,
sTextContentElementsMap,
sViewportsMap
};

View File

@ -859,6 +859,10 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) {
#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

View File

@ -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>

After

Width:  |  Height:  |  Size: 382 B

View File

@ -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>

After

Width:  |  Height:  |  Size: 534 B

View File

@ -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>

After

Width:  |  Height:  |  Size: 560 B

View File

@ -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>

After

Width:  |  Height:  |  Size: 750 B

View File

@ -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>

After

Width:  |  Height:  |  Size: 588 B

View File

@ -177,6 +177,10 @@ fuzzy-if(Android,9,980) == gradient-live-01d.svg gradient-live-01-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

View File

@ -164,6 +164,7 @@ 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)
@ -316,6 +317,7 @@ 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)

View File

@ -3294,6 +3294,16 @@ CSS_PROP_SVGRESET(
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,

View File

@ -1586,6 +1586,12 @@ const int32_t nsCSSProps::kImageRenderingKTable[] = {
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,

View File

@ -406,6 +406,7 @@ public:
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[];

View File

@ -4362,6 +4362,16 @@ nsComputedDOMStyle::DoGetMask()
return val;
}
CSSValue*
nsComputedDOMStyle::DoGetMaskType()
{
nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
val->SetIdent(
nsCSSProps::ValueToKeywordEnum(GetStyleSVGReset()->mMaskType,
nsCSSProps::kMaskTypeKTable));
return val;
}
CSSValue*
nsComputedDOMStyle::DoGetTransitionDelay()
{
@ -4929,6 +4939,7 @@ nsComputedDOMStyle::GetQueryablePropertyMap(uint32_t* aLength)
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),

View File

@ -421,6 +421,7 @@ private:
mozilla::dom::CSSValue* DoGetClipPath();
mozilla::dom::CSSValue* DoGetFilter();
mozilla::dom::CSSValue* DoGetMask();
mozilla::dom::CSSValue* DoGetMaskType();
nsROCSSPrimitiveValue* GetROCSSPrimitiveValue();
nsDOMCSSValueList* GetROCSSValueList(bool aCommaDelimited);

View File

@ -7617,6 +7617,13 @@ nsRuleNode::ComputeSVGResetData(void* aStartStruct,
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)
}

View File

@ -970,6 +970,7 @@ nsStyleSVGReset::nsStyleSVGReset()
mFloodOpacity = 1.0f;
mDominantBaseline = NS_STYLE_DOMINANT_BASELINE_AUTO;
mVectorEffect = NS_STYLE_VECTOR_EFFECT_NONE;
mMaskType = NS_STYLE_MASK_TYPE_LUMINANCE;
}
nsStyleSVGReset::~nsStyleSVGReset()
@ -990,6 +991,7 @@ nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset& aSource)
mFloodOpacity = aSource.mFloodOpacity;
mDominantBaseline = aSource.mDominantBaseline;
mVectorEffect = aSource.mVectorEffect;
mMaskType = aSource.mMaskType;
}
nsChangeHint nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aOther) const
@ -1010,7 +1012,8 @@ nsChangeHint nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aOther) cons
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;

View File

@ -2278,6 +2278,7 @@ struct nsStyleSVGReset {
uint8_t mDominantBaseline; // [reset] see nsStyleConsts.h
uint8_t mVectorEffect; // [reset] see nsStyleConsts.h
uint8_t mMaskType; // [reset] see nsStyleConsts.h
};
#endif /* nsStyleStruct_h___ */

View File

@ -3578,6 +3578,14 @@ var gCSSProperties = {
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,

View File

@ -119,20 +119,31 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsRenderingContext *aContext,
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);

View File

@ -1638,6 +1638,13 @@ pref("layout.css.dpi", -1);
// 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);