diff --git a/dom/interfaces/css/nsIDOMCSS2Properties.idl b/dom/interfaces/css/nsIDOMCSS2Properties.idl index 76d39df320de..874579636779 100644 --- a/dom/interfaces/css/nsIDOMCSS2Properties.idl +++ b/dom/interfaces/css/nsIDOMCSS2Properties.idl @@ -51,7 +51,7 @@ * http://www.w3.org/TR/DOM-Level-2-Style */ -[scriptable, uuid(1ca298f0-4eaf-4483-8aa2-587f392f84bb)] +[scriptable, uuid(63a0afd0-b322-11e0-aff2-0800200c9a66)] interface nsIDOMCSS2Properties : nsISupports { attribute DOMString background; @@ -684,6 +684,9 @@ interface nsIDOMCSS2Properties : nsISupports attribute DOMString MozPerspective; // raises(DOMException) on setting + attribute DOMString MozBackfaceVisibility; + // raises(DOMException) on setting + attribute DOMString MozWindowShadow; // raises(DOMException) on setting diff --git a/gfx/thebes/gfx3DMatrix.cpp b/gfx/thebes/gfx3DMatrix.cpp index f45d983ea8d5..d03a7d2b522a 100644 --- a/gfx/thebes/gfx3DMatrix.cpp +++ b/gfx/thebes/gfx3DMatrix.cpp @@ -392,3 +392,17 @@ gfxRect gfx3DMatrix::ProjectRectBounds(const gfxRect& aRect) const return gfxRect(min_x, min_y, max_x - min_x, max_y - min_y); } +gfxPoint3D gfx3DMatrix::GetNormalVector() const +{ + // Define a plane in transformed space as the transformations + // of 3 points on the z=0 screen plane. + gfxPoint3D a = Transform3D(gfxPoint3D(0, 0, 0)); + gfxPoint3D b = Transform3D(gfxPoint3D(0, 1, 0)); + gfxPoint3D c = Transform3D(gfxPoint3D(1, 0, 0)); + + // Convert to two vectors on the surface of the plane. + gfxPoint3D ab = b - a; + gfxPoint3D ac = c - a; + + return ac.CrossProduct(ab); +} diff --git a/gfx/thebes/gfx3DMatrix.h b/gfx/thebes/gfx3DMatrix.h index 5fc680095234..f1d594a5d7b5 100644 --- a/gfx/thebes/gfx3DMatrix.h +++ b/gfx/thebes/gfx3DMatrix.h @@ -134,6 +134,12 @@ public: return temp; } + /** + * Returns a unit vector that is perpendicular to the plane formed + * by transform the screen plane (z=0) by this matrix. + */ + gfxPoint3D GetNormalVector() const; + /** * Check if matrix is singular (no inverse exists). */ diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 3aebe7dbe03b..3cb51fdd3c6a 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -2418,8 +2418,12 @@ already_AddRefed nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu { const gfx3DMatrix& newTransformMatrix = GetTransform(mFrame->PresContext()->AppUnitsPerDevPixel()); - if (newTransformMatrix.IsSingular()) + + if (newTransformMatrix.IsSingular() || + (mFrame->GetStyleDisplay()->mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN && + newTransformMatrix.GetNormalVector().z <= 0.0)) { return nsnull; + } return aBuilder->LayerBuilder()-> BuildContainerLayerFor(aBuilder, aManager, mFrame, this, *mStoredList.GetList(), @@ -2487,8 +2491,12 @@ void nsDisplayTransform::HitTest(nsDisplayListBuilder *aBuilder, float factor = nsPresContext::AppUnitsPerCSSPixel(); gfx3DMatrix matrix = GetTransform(factor); - if (matrix.IsSingular()) - return; + /* If the matrix is singular, or a hidden backface is shown, we didn't hit anything. */ + if (matrix.IsSingular() || + (mFrame->GetStyleDisplay()->mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN && + matrix.GetNormalVector().z <= 0.0)) { + return; + } /* We want to go from transformed-space to regular space. * Thus we have to invert the matrix, which normally does diff --git a/layout/base/nsStyleConsts.h b/layout/base/nsStyleConsts.h index ed32bdf74198..0c716208a637 100644 --- a/layout/base/nsStyleConsts.h +++ b/layout/base/nsStyleConsts.h @@ -858,6 +858,10 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) { #define NS_STYLE_COLOR_INTERPOLATION_SRGB 1 #define NS_STYLE_COLOR_INTERPOLATION_LINEARRGB 2 +// 3d Transforms - Backface visibility +#define NS_STYLE_BACKFACE_VISIBILITY_VISIBLE 1 +#define NS_STYLE_BACKFACE_VISIBILITY_HIDDEN 0 + /***************************************************************************** * Constants for media features. * *****************************************************************************/ diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index c6c71fe4c12d..c7271df7874e 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -2267,6 +2267,15 @@ CSS_PROP_DISPLAY( nsnull, offsetof(nsStyleDisplay, mChildPerspective), eStyleAnimType_Coord) +CSS_PROP_DISPLAY( + -moz-backface-visibility, + backface_visibility, + CSS_PROP_DOMPROP_PREFIXED(BackfaceVisibility), + CSS_PROPERTY_PARSE_VALUE, + VARIANT_HK, + kBackfaceVisibilityKTable, + offsetof(nsStyleDisplay, mBackfaceVisibility), + eStyleAnimType_None) CSS_PROP_POSITION( top, top, diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp index 633def4d7c93..2116bf2479ad 100644 --- a/layout/style/nsCSSProps.cpp +++ b/layout/style/nsCSSProps.cpp @@ -581,6 +581,11 @@ const PRInt32 nsCSSProps::kAppearanceKTable[] = { eCSSKeyword_UNKNOWN,-1 }; +const PRInt32 nsCSSProps::kBackfaceVisibilityKTable[] = { + eCSSKeyword_visible, NS_STYLE_BACKFACE_VISIBILITY_VISIBLE, + eCSSKeyword_hidden, NS_STYLE_BACKFACE_VISIBILITY_HIDDEN +}; + const PRInt32 nsCSSProps::kBackgroundAttachmentKTable[] = { eCSSKeyword_fixed, NS_STYLE_BG_ATTACHMENT_FIXED, eCSSKeyword_scroll, NS_STYLE_BG_ATTACHMENT_SCROLL, diff --git a/layout/style/nsCSSProps.h b/layout/style/nsCSSProps.h index 504f81ecc60b..866112148d13 100644 --- a/layout/style/nsCSSProps.h +++ b/layout/style/nsCSSProps.h @@ -333,6 +333,7 @@ public: static const PRInt32 kAnimationTimingFunctionKTable[]; static const PRInt32 kAppearanceKTable[]; static const PRInt32 kAzimuthKTable[]; + static const PRInt32 kBackfaceVisibilityKTable[]; static const PRInt32 kBackgroundAttachmentKTable[]; static const PRInt32 kBackgroundInlinePolicyKTable[]; static const PRInt32 kBackgroundOriginKTable[]; diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index a7bc3bab4dc6..e240b283fa4e 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -954,6 +954,16 @@ nsComputedDOMStyle::DoGetMozPerspective() return val; } +nsIDOMCSSValue* +nsComputedDOMStyle::DoGetMozBackfaceVisibility() +{ + nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue(); + val->SetIdent( + nsCSSProps::ValueToKeywordEnum(GetStyleDisplay()->mBackfaceVisibility, + nsCSSProps::kBackfaceVisibilityKTable)); + return val; +} + /* If the property is "none", hand back "none" wrapped in a value. * Otherwise, compute the aggregate transform matrix and hands it back in a * "matrix" wrapper. @@ -4378,6 +4388,7 @@ nsComputedDOMStyle::GetQueryablePropertyMap(PRUint32* aLength) COMPUTED_STYLE_MAP_ENTRY(animation_play_state, AnimationPlayState), COMPUTED_STYLE_MAP_ENTRY(animation_timing_function, AnimationTimingFunction), COMPUTED_STYLE_MAP_ENTRY(appearance, Appearance), + COMPUTED_STYLE_MAP_ENTRY(backface_visibility, MozBackfaceVisibility), COMPUTED_STYLE_MAP_ENTRY(_moz_background_inline_policy, BackgroundInlinePolicy), COMPUTED_STYLE_MAP_ENTRY(binding, Binding), COMPUTED_STYLE_MAP_ENTRY(border_bottom_colors, BorderBottomColors), diff --git a/layout/style/nsComputedDOMStyle.h b/layout/style/nsComputedDOMStyle.h index e32d7e568f1e..73650109e15f 100644 --- a/layout/style/nsComputedDOMStyle.h +++ b/layout/style/nsComputedDOMStyle.h @@ -348,6 +348,7 @@ private: nsIDOMCSSValue* DoGetMozTransform(); nsIDOMCSSValue* DoGetMozTransformOrigin(); nsIDOMCSSValue* DoGetMozPerspective(); + nsIDOMCSSValue* DoGetMozBackfaceVisibility(); nsIDOMCSSValue* DoGetOrient(); /* User interface properties */ diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 6c6bdefc9589..0badd01875b4 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -4489,6 +4489,11 @@ nsRuleNode::ComputeDisplayData(void* aStartStruct, SETCOORD_LAH | SETCOORD_INITIAL_ZERO | SETCOORD_NONE, aContext, mPresContext, canStoreInRuleTree); + SetDiscrete(*aRuleData->ValueForBackfaceVisibility(), + display->mBackfaceVisibility, canStoreInRuleTree, + SETDSC_ENUMERATED, parentDisplay->mBackfaceVisibility, + NS_STYLE_BACKFACE_VISIBILITY_VISIBLE, 0, 0, 0, 0); + // orient: enum, inherit, initial SetDiscrete(*aRuleData->ValueForOrient(), display->mOrient, canStoreInRuleTree, diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index a481de8b9882..309f2d361988 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -2034,6 +2034,7 @@ nsStyleDisplay::nsStyleDisplay() mTransformOrigin[0].SetPercentValue(0.5f); // Transform is centered on origin mTransformOrigin[1].SetPercentValue(0.5f); mChildPerspective.SetCoordValue(0); + mBackfaceVisibility = NS_STYLE_BACKFACE_VISIBILITY_VISIBLE; mOrient = NS_STYLE_ORIENT_HORIZONTAL; mTransitions.AppendElement(); @@ -2100,6 +2101,7 @@ nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource) mTransformOrigin[0] = aSource.mTransformOrigin[0]; mTransformOrigin[1] = aSource.mTransformOrigin[1]; mChildPerspective = aSource.mChildPerspective; + mBackfaceVisibility = aSource.mBackfaceVisibility; } nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const @@ -2165,6 +2167,9 @@ nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const if (mChildPerspective != aOther.mChildPerspective) NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_ReflowFrame, nsChangeHint_RepaintFrame)); + + if (mBackfaceVisibility != aOther.mBackfaceVisibility) + NS_UpdateHint(hint, nsChangeHint_RepaintFrame); } // Note: Our current behavior for handling changes to the diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index ea747caeca6d..40b0ae74a6a9 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -1516,6 +1516,7 @@ struct nsStyleDisplay { const nsCSSValueList *mSpecifiedTransform; // [reset] nsStyleCoord mTransformOrigin[2]; // [reset] percent, coord, calc nsStyleCoord mChildPerspective; // [reset] coord + PRUint8 mBackfaceVisibility; nsAutoTArray mTransitions; // [reset] // The number of elements in mTransitions that are not from repeating diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index 7e1bd95e453a..fa57e3c69622 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -975,6 +975,14 @@ var gCSSProperties = { other_values: [ "1000px", "500.2px", "-100px", "-27.2em" ], invalid_values: [ "pants", "200" ] }, + "-moz-backface-visibility": { + domProp: "MozBackfaceVisibility", + inherited: false, + type: CSS_TYPE_LONGHAND, + initial_values: [ "visible" ], + other_values: [ "hidden" ], + invalid_values: [ "collapse" ] + }, "-moz-user-focus": { domProp: "MozUserFocus", inherited: true,