diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index d8c8313f9ff9..db728118faae 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -1660,6 +1660,7 @@ nsPresContext::RebuildAllStyleData(nsChangeHint aExtraHint) return; } + mUsesViewportUnits = false; RebuildUserFontSet(); AnimationManager()->KeyframesListIsDirty(); @@ -1680,12 +1681,18 @@ void nsPresContext::MediaFeatureValuesChanged(bool aCallerWillRebuildStyleData) { mPendingMediaFeatureValuesChanged = false; - if (mShell && - mShell->StyleSet()->MediumFeaturesChanged(this) && - !aCallerWillRebuildStyleData) { + + // MediumFeaturesChanged updates the applied rules, so it always gets called. + bool mediaFeaturesDidChange = mShell ? mShell->StyleSet()->MediumFeaturesChanged(this) + : false; + + if (!aCallerWillRebuildStyleData && + (mediaFeaturesDidChange || (mUsesViewportUnits && mPendingViewportChange))) { RebuildAllStyleData(nsChangeHint(0)); } + mPendingViewportChange = false; + if (!nsContentUtils::IsSafeToRunScript()) { NS_ABORT_IF_FALSE(mDocument->IsBeingUsedAsImage(), "How did we get here? Are we failing to notify " diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index cdc5cbda92fc..ba9f3e594bce 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -414,8 +414,10 @@ public: if (!r.IsEqualEdges(mVisibleArea)) { mVisibleArea = r; // Visible area does not affect media queries when paginated. - if (!IsPaginated() && HasCachedStyleData()) + if (!IsPaginated() && HasCachedStyleData()) { + mPendingViewportChange = true; PostMediaFeatureValuesChangedEvent(); + } } } @@ -943,6 +945,14 @@ public: mIsGlyph = aValue; } + bool UsesViewportUnits() const { + return mUsesViewportUnits; + } + + void SetUsesViewportUnits(bool aValue) { + mUsesViewportUnits = aValue; + } + protected: friend class nsRunnableMethod; NS_HIDDEN_(void) ThemeChangedInternal(); @@ -1195,6 +1205,12 @@ protected: // Are we currently drawing an SVG glyph? unsigned mIsGlyph : 1; + // Does the associated document use viewport units? + unsigned mUsesViewportUnits : 1; + + // Has there been a change to the viewport's dimensions? + unsigned mPendingViewportChange : 1; + // Is the current mUserFontSet valid? unsigned mUserFontSetDirty : 1; // Has GetUserFontSet() been called? diff --git a/layout/reftests/css-valuesandunits/reftest.list b/layout/reftests/css-valuesandunits/reftest.list index 1a78aa2890c9..b69f361fa1ee 100644 --- a/layout/reftests/css-valuesandunits/reftest.list +++ b/layout/reftests/css-valuesandunits/reftest.list @@ -6,3 +6,5 @@ == unit-rem-root-fontsize.html unit-rem-ref2-root-fontsize.html == unit-rem-root-width.html unit-rem-ref-root-width.html == unit-rem.svg unit-rem-ref.svg +== unit-vh-vw.html unit-vh-vw-ref.html +== unit-vh-vw-zoom.html unit-vh-vw-zoom-ref.html diff --git a/layout/reftests/css-valuesandunits/unit-vh-vw-iframe.html b/layout/reftests/css-valuesandunits/unit-vh-vw-iframe.html new file mode 100644 index 000000000000..437873782e82 --- /dev/null +++ b/layout/reftests/css-valuesandunits/unit-vh-vw-iframe.html @@ -0,0 +1,14 @@ + + + +
+
+
+
+ diff --git a/layout/reftests/css-valuesandunits/unit-vh-vw-ref-iframe.html b/layout/reftests/css-valuesandunits/unit-vh-vw-ref-iframe.html new file mode 100644 index 000000000000..ee54f5b6822a --- /dev/null +++ b/layout/reftests/css-valuesandunits/unit-vh-vw-ref-iframe.html @@ -0,0 +1,15 @@ + + + +
+
+
+
+ + diff --git a/layout/reftests/css-valuesandunits/unit-vh-vw-ref.html b/layout/reftests/css-valuesandunits/unit-vh-vw-ref.html new file mode 100644 index 000000000000..5dc30fd0e430 --- /dev/null +++ b/layout/reftests/css-valuesandunits/unit-vh-vw-ref.html @@ -0,0 +1,14 @@ + + + + + + diff --git a/layout/reftests/css-valuesandunits/unit-vh-vw-zoom-ref.html b/layout/reftests/css-valuesandunits/unit-vh-vw-zoom-ref.html new file mode 100644 index 000000000000..c477c326c395 --- /dev/null +++ b/layout/reftests/css-valuesandunits/unit-vh-vw-zoom-ref.html @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/layout/reftests/css-valuesandunits/unit-vh-vw-zoom.html b/layout/reftests/css-valuesandunits/unit-vh-vw-zoom.html new file mode 100644 index 000000000000..3272721ae2ff --- /dev/null +++ b/layout/reftests/css-valuesandunits/unit-vh-vw-zoom.html @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/layout/reftests/css-valuesandunits/unit-vh-vw.html b/layout/reftests/css-valuesandunits/unit-vh-vw.html new file mode 100644 index 000000000000..59aea944c037 --- /dev/null +++ b/layout/reftests/css-valuesandunits/unit-vh-vw.html @@ -0,0 +1,14 @@ + + + + + + diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 3fd990aa5ae7..a01b99519a1c 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -4510,6 +4510,10 @@ const UnitInfo UnitData[] = { { STR_WITH_LEN("rem"), eCSSUnit_RootEM, VARIANT_LENGTH }, { STR_WITH_LEN("mm"), eCSSUnit_Millimeter, VARIANT_LENGTH }, { STR_WITH_LEN("mozmm"), eCSSUnit_PhysicalMillimeter, VARIANT_LENGTH }, + { STR_WITH_LEN("vw"), eCSSUnit_ViewportWidth, VARIANT_LENGTH }, + { STR_WITH_LEN("vh"), eCSSUnit_ViewportHeight, VARIANT_LENGTH }, + { STR_WITH_LEN("vmin"), eCSSUnit_ViewportMin, VARIANT_LENGTH }, + { STR_WITH_LEN("vmax"), eCSSUnit_ViewportMax, VARIANT_LENGTH }, { STR_WITH_LEN("pc"), eCSSUnit_Pica, VARIANT_LENGTH }, { STR_WITH_LEN("deg"), eCSSUnit_Degree, VARIANT_ANGLE }, { STR_WITH_LEN("grad"), eCSSUnit_Grad, VARIANT_ANGLE }, diff --git a/layout/style/nsCSSValue.cpp b/layout/style/nsCSSValue.cpp index ed771c70395b..0349df15e89a 100644 --- a/layout/style/nsCSSValue.cpp +++ b/layout/style/nsCSSValue.cpp @@ -1120,6 +1120,11 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const case eCSSUnit_Point: aResult.AppendLiteral("pt"); break; case eCSSUnit_Pica: aResult.AppendLiteral("pc"); break; + case eCSSUnit_ViewportWidth: aResult.AppendLiteral("vw"); break; + case eCSSUnit_ViewportHeight: aResult.AppendLiteral("vh"); break; + case eCSSUnit_ViewportMin: aResult.AppendLiteral("vmin"); break; + case eCSSUnit_ViewportMax: aResult.AppendLiteral("vmax"); break; + case eCSSUnit_EM: aResult.AppendLiteral("em"); break; case eCSSUnit_XHeight: aResult.AppendLiteral("ex"); break; case eCSSUnit_Char: aResult.AppendLiteral("ch"); break; @@ -1248,6 +1253,10 @@ nsCSSValue::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const case eCSSUnit_Percent: case eCSSUnit_Number: case eCSSUnit_PhysicalMillimeter: + case eCSSUnit_ViewportWidth: + case eCSSUnit_ViewportHeight: + case eCSSUnit_ViewportMin: + case eCSSUnit_ViewportMax: case eCSSUnit_EM: case eCSSUnit_XHeight: case eCSSUnit_Char: diff --git a/layout/style/nsCSSValue.h b/layout/style/nsCSSValue.h index 03eac7f2152b..a4974ad466fc 100644 --- a/layout/style/nsCSSValue.h +++ b/layout/style/nsCSSValue.h @@ -209,6 +209,12 @@ enum nsCSSUnit { eCSSUnit_PhysicalMillimeter = 200, // (float) 1/25.4 inch // Length units - relative + // Viewport relative measure + eCSSUnit_ViewportWidth = 700, // (float) 1% of the width of the initial containing block + eCSSUnit_ViewportHeight = 701, // (float) 1% of the height of the initial containing block + eCSSUnit_ViewportMin = 702, // (float) smaller of ViewportWidth and ViewportHeight + eCSSUnit_ViewportMax = 703, // (float) larger of ViewportWidth and ViewportHeight + // Font relative measure eCSSUnit_EM = 800, // (float) == current font size eCSSUnit_XHeight = 801, // (float) distance from top of lower case x to baseline diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 8ac998ef58e4..e847c861f790 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -9,6 +9,8 @@ * responsible for converting the rules' information into computed style */ +#include + #include "nsRuleNode.h" #include "nscore.h" #include "nsIServiceManager.h" @@ -53,6 +55,8 @@ #include #endif +using std::max; +using std::min; using namespace mozilla; using namespace mozilla::dom; @@ -264,6 +268,24 @@ static nscoord CalcLengthWith(const nsCSSValue& aValue, aFontSize = styleFont->mFont.size; } switch (aValue.GetUnit()) { + case eCSSUnit_ViewportWidth: { + aPresContext->SetUsesViewportUnits(true); + return ScaleCoord(aValue, 0.01f * aPresContext->GetVisibleArea().width); + } + case eCSSUnit_ViewportHeight: { + aPresContext->SetUsesViewportUnits(true); + return ScaleCoord(aValue, 0.01f * aPresContext->GetVisibleArea().height); + } + case eCSSUnit_ViewportMin: { + aPresContext->SetUsesViewportUnits(true); + nsSize viewportSize = aPresContext->GetVisibleArea().Size(); + return ScaleCoord(aValue, 0.01f * min(viewportSize.width, viewportSize.height)); + } + case eCSSUnit_ViewportMax: { + aPresContext->SetUsesViewportUnits(true); + nsSize viewportSize = aPresContext->GetVisibleArea().Size(); + return ScaleCoord(aValue, 0.01f * max(viewportSize.width, viewportSize.height)); + } case eCSSUnit_RootEM: { nscoord rootFontSize;