From dcbe25ed4501e17de1a31d7400a8411f6c0450a0 Mon Sep 17 00:00:00 2001 From: roytam1 Date: Thu, 24 Aug 2023 10:00:58 +0800 Subject: [PATCH] import changes from `dev' branch of rmottola/Arctic-Fox: - Bug 1235979 - Remove spammy printf that got left by accident when bug 1226904 landed. r=thinker (fc6fe64f23) - Bug 1208344 part 1: Make EnsurePhysicalProperty() return the property directly, instead of using in/out-param. r=heycam (9515887dd7) - Bug 1208344 part 2: Make EnsurePhysicalProperty() (not its callers) check whether property is logical. r=heycam (defa671bab) - Bug 1208344 part 3: Rename MapSinglePropertyInto() args, to make src-vs-target distinctions clearer. r=heycam (bfd2e2c9bc) - Bug 1208344 part 4: Make MapSinglePropertyInto() take the source property as an arg (unused for the moment). r=heycam (d1278eb58a) - Bug 1208344 part 5: Add (preffed-off) support for "-webkit-box-orient" CSS property, as a writing-mode-dependent alias for "flex-direction". r=heycam (d8407990aa) - Bug 1208344 part 6: Move new CSS_PROPERTY_LOGICAL_CUSTOM flag up with other LOGICAL flags, and adjust bits accordingly. r=heycam (df27d64733) - Bug 1208344 part 7: Add mochitest to test how "-webkit-box-orient" maps to "flex-direction". r=heycam (c448070877) - Bug 686225 - Work around buggy AAT fonts for Bengali and Kannada scripts. r=jdaggett (17afddbc6c) - Bug 739117 - Avoid bidi-wrapping the text to be shaped if Core Text direction override API is available. r=jdaggett (c492390922) - Bug 1156581 - Add null check to nsSVGEffects::InvalidateRenderingObservers to prevent crashes r=dholbert (4c0460e7ac) - remove windows accents (8b0ad08f11) - Bug 1123654 - Replace use of [deprecated] GetStockObject(DEFAULT_GUI_FONT) with newer API; results in use of Tahoma in place of Microsoft Sans Serif in various contexts. r=jmathies (3a81fc1bed) - put back cleartype for winXP (1c24e5ae09) - Bug 1240180 - Optimize native theme scaling for the single-monitor case. r=emk (a5846457ab) - Bug 1242720 - Use (non-dynamic) resolution from GetDeviceCaps when dealing with native-theme code that does not handle dynamic changes to system DPI. r=emk (7c25841f0b) - More win accent removal (afd6af9fd2) - some more vista or later stuff (1d99554064) - missing bits of Bug 1243720 - Send accessibility theme state down to the content process on Windows. r=jimm (8f00b4f3ca) - Bug 1153460 - Support new Fitzpatrick emoji modifiers and regional symbol indicators in Apple Color Emoji font. r=jdaggett (6faf5f30e6) - Bug 1230497 - Ignore font fallback in Core Text shaping if it's just for a join-control character. r=jdaggett (b612806a42) - Bug 1153460 - Followup to fix warnings-as-errors build failure on a CLOSED TREE. r=bustage. (12d492772c) - bug 1243077 - make it possible to get MaiAtkObject::mAccWrap from an AtkObject* without casting to Accessible* or ProxyAccessible* r=davidb (d8f690b6cd) - Bug 1238403 - Fix inconsistent indenting in layout/style/. r=xidorn (4f24334234) - Bug 717722 - Implement WebKitCSSMatrix. r=baku (c10f90ff6e) - Bug 1241723. Update WebKitCSSMatrix.idl to match latest spec updates. r=baku (5f8c33ff14) - Bug 1241727 - Inverting non-invertible WebKitCSSMatrix should throw NotSupportedError. r=baku (c7791802b8) - Bug 1241575 - Use transform property syntax to parse WebKitCSSMatrix transform list. r=heycam (5f886e2bd9) - bug 1243077 - add AccessibleOrProxy::ChildCount() r=davidb (044537f53c) - bug 1243077 - add AccessibleOrProxy::Role() r=davidb (3f61d03c8e) - bug 1243077 - add AccessibleOrProxy::ChildAt() r=davidb (91288f269f) - bug 1243077 - add AccessibleOrProxy::FirstChild() r=davidb (ea3f984716) - bug 1243077 - add AccessibleOrProxy::LastChild() r=davidb (2181f1740b) - Bug 1237720: Put "-webkit-min-device-pixel-ratio"/"-webkit-max-device-pixel-ratio" behind its own disabled pref. r=heycam (9f75535617) - Bug 1239153: Accept unitless '0' for angle values in CSS -webkit-linear-gradient() expressions. r=heycam (c11657a6c9) - Bug 1239799 part 1: Make check for -webkit-device-pixel-ratio pref more targeted, so we can support other webkit-prefixed media queries. r=heycam (1e8a40127e) - Bug 1239799 part 2: Add support for @media(-webkit-transform-3d) media query, for web compatibility. r=heycam (f7ff08423e) - guard some code for 10.5/10.6 which didn't get run, but coulnd't natively compile (cf68e969fd) - Bug 1019856 - avoid double-buffering in BasicCompositor when window allows it. r=mattwoodrow (e94cfc3fb4) --- accessible/atk/AccessibleWrap.cpp | 11 +- accessible/atk/nsMai.h | 1 + accessible/base/AccessibleOrProxy.h | 56 + dom/base/DOMMatrix.h | 6 +- dom/base/WebKitCSSMatrix.cpp | 260 ++++ dom/base/WebKitCSSMatrix.h | 72 ++ dom/base/WindowNamedPropertiesHandler.cpp | 1 + dom/base/moz.build | 2 + dom/base/nsGkAtomList.h | 5 +- dom/base/nsXMLContentSerializer.cpp | 1 + dom/tests/mochitest/general/mochitest.ini | 1 + .../general/test_WebKitCSSMatrix.html | 326 +++++ .../mochitest/general/test_interfaces.html | 14 + dom/webidl/WebKitCSSMatrix.webidl | 39 + dom/webidl/moz.build | 1 + gfx/layers/basic/BasicCompositor.cpp | 63 +- gfx/layers/basic/BasicCompositor.h | 5 + gfx/thebes/gfxCoreTextShaper.cpp | 496 +++++--- gfx/thebes/gfxCoreTextShaper.h | 29 +- gfx/thebes/gfxGDIFontList.cpp | 20 +- layout/base/ActiveLayerTracker.cpp | 4 +- layout/base/nsDisplayList.cpp | 9 +- layout/reftests/bugs/reftest.list | 4 +- .../reftests/forms/placeholder/reftest.list | 2 +- layout/reftests/text/reftest.list | 1 + layout/style/CSSVariableImageTable.h | 190 +++ layout/style/StyleAnimationValue.cpp | 20 +- layout/style/nsCSSDataBlock.cpp | 701 ++++++----- layout/style/nsCSSDataBlock.h | 521 ++++---- layout/style/nsCSSParser.cpp | 195 ++- layout/style/nsCSSParser.h | 9 + layout/style/nsCSSPropList.h | 16 + layout/style/nsCSSPropLogicalGroupList.h | 12 + layout/style/nsCSSProperty.h | 3 + layout/style/nsCSSProps.cpp | 28 +- layout/style/nsCSSProps.h | 27 +- layout/style/nsCSSRuleProcessor.cpp | 10 - layout/style/nsCSSValue.cpp | 94 +- layout/style/nsCSSValue.h | 16 +- layout/style/nsComputedDOMStyle.cpp | 34 +- layout/style/nsMediaFeatures.cpp | 1072 +++++++++-------- layout/style/nsMediaFeatures.h | 110 +- layout/style/nsROCSSPrimitiveValue.cpp | 9 +- layout/style/nsStyleContext.cpp | 8 +- layout/style/nsStyleStruct.cpp | 94 +- layout/style/nsStyleStruct.h | 241 ++-- layout/style/nsStyleTransformMatrix.cpp | 34 +- layout/style/nsStyleTransformMatrix.h | 10 +- layout/style/test/mochitest.ini | 1 + layout/style/test/property_database.js | 45 + layout/style/test/test_media_queries.html | 2 + layout/style/test/test_webkit_box_orient.html | 54 + layout/svg/crashtests/1156581-1.svg | 12 + layout/svg/crashtests/crashtests.list | 1 + layout/svg/nsSVGEffects.cpp | 10 +- modules/libpref/init/all.js | 5 + testing/profiles/prefs_general.js | 3 + widget/cocoa/nsChildView.h | 4 +- widget/cocoa/nsChildView.mm | 6 +- widget/gtk/nsWindow.cpp | 22 +- widget/gtk/nsWindow.h | 7 +- widget/nsIWidget.h | 6 +- widget/windows/WinUtils.cpp | 16 + widget/windows/WinUtils.h | 9 + widget/windows/nsLookAndFeel.cpp | 193 +-- widget/windows/nsLookAndFeel.h | 29 +- widget/windows/nsNativeThemeWin.cpp | 18 +- 67 files changed, 3448 insertions(+), 1878 deletions(-) create mode 100644 dom/base/WebKitCSSMatrix.cpp create mode 100644 dom/base/WebKitCSSMatrix.h create mode 100644 dom/tests/mochitest/general/test_WebKitCSSMatrix.html create mode 100644 dom/webidl/WebKitCSSMatrix.webidl create mode 100644 layout/style/CSSVariableImageTable.h create mode 100644 layout/style/test/test_webkit_box_orient.html create mode 100644 layout/svg/crashtests/1156581-1.svg diff --git a/accessible/atk/AccessibleWrap.cpp b/accessible/atk/AccessibleWrap.cpp index 579c5fad2e..080e0868f3 100644 --- a/accessible/atk/AccessibleWrap.cpp +++ b/accessible/atk/AccessibleWrap.cpp @@ -1083,11 +1083,16 @@ GetAccessibleWrap(AtkObject* aAtkObj) ProxyAccessible* GetProxy(AtkObject* aObj) { - if (!aObj || !IS_MAI_OBJECT(aObj) || - !MAI_ATK_OBJECT(aObj)->accWrap.IsProxy()) + return GetInternalObj(aObj).AsProxy(); +} + +AccessibleOrProxy +GetInternalObj(AtkObject* aObj) +{ + if (!aObj || !IS_MAI_OBJECT(aObj)) return nullptr; - return MAI_ATK_OBJECT(aObj)->accWrap.AsProxy(); + return MAI_ATK_OBJECT(aObj)->accWrap; } AtkObject* diff --git a/accessible/atk/nsMai.h b/accessible/atk/nsMai.h index 2e814df7ce..76b7f260dc 100644 --- a/accessible/atk/nsMai.h +++ b/accessible/atk/nsMai.h @@ -67,6 +67,7 @@ typedef struct _MaiAtkSocketClass mozilla::a11y::AccessibleWrap* GetAccessibleWrap(AtkObject* aAtkObj); mozilla::a11y::ProxyAccessible* GetProxy(AtkObject* aAtkObj); +mozilla::a11y::AccessibleOrProxy GetInternalObj(AtkObject* aObj); AtkObject* GetWrapperFor(mozilla::a11y::ProxyAccessible* aProxy); extern int atkMajorVersion, atkMinorVersion; diff --git a/accessible/base/AccessibleOrProxy.h b/accessible/base/AccessibleOrProxy.h index 72cbeb0344..ce2b12ebf3 100644 --- a/accessible/base/AccessibleOrProxy.h +++ b/accessible/base/AccessibleOrProxy.h @@ -9,6 +9,7 @@ #include "mozilla/a11y/Accessible.h" #include "mozilla/a11y/ProxyAccessible.h" +#include "mozilla/a11y/Role.h" #include @@ -50,6 +51,61 @@ public: bool IsNull() const { return mBits == 0; } + uint32_t ChildCount() const + { + if (IsProxy()) { + return AsProxy()->ChildrenCount(); + } + + return AsAccessible()->ChildCount(); + } + + /** + * Return the child object either an accessible or a proxied accessible at + * the given index. + */ + AccessibleOrProxy ChildAt(uint32_t aIdx) + { + if (IsProxy()) { + return AsProxy()->ChildAt(aIdx); + } + + return AsAccessible()->GetChildAt(aIdx); + } + + /** + * Return the first child object. + */ + AccessibleOrProxy FirstChild() + { + if (IsProxy()) { + return AsProxy()->FirstChild(); + } + + return AsAccessible()->FirstChild(); + } + + /** + * Return the first child object. + */ + AccessibleOrProxy LastChild() + { + if (IsProxy()) { + return AsProxy()->LastChild(); + } + + return AsAccessible()->LastChild(); + } + + role Role() const + { + if (IsProxy()) { + return AsProxy()->Role(); + } + + return AsAccessible()->Role(); + } + // XXX these are implementation details that ideally would not be exposed. uintptr_t Bits() const { return mBits; } void SetBits(uintptr_t aBits) { mBits = aBits; } diff --git a/dom/base/DOMMatrix.h b/dom/base/DOMMatrix.h index f7ec1ddba7..c8e3750aab 100644 --- a/dom/base/DOMMatrix.h +++ b/dom/base/DOMMatrix.h @@ -142,7 +142,7 @@ private: DOMMatrixReadOnly& operator=(const DOMMatrixReadOnly&) = delete; }; -class DOMMatrix final : public DOMMatrixReadOnly +class DOMMatrix : public DOMMatrixReadOnly { public: explicit DOMMatrix(nsISupports* aParent) @@ -244,8 +244,10 @@ public: DOMMatrix* SkewYSelf(double aSy); DOMMatrix* InvertSelf(); DOMMatrix* SetMatrixValue(const nsAString& aTransformList, ErrorResult& aRv); -private: +protected: void Ensure3DMatrix(); + + virtual ~DOMMatrix() {} }; } // namespace dom diff --git a/dom/base/WebKitCSSMatrix.cpp b/dom/base/WebKitCSSMatrix.cpp new file mode 100644 index 0000000000..b5baf25a0a --- /dev/null +++ b/dom/base/WebKitCSSMatrix.cpp @@ -0,0 +1,260 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/WebKitCSSMatrix.h" + +#include "mozilla/dom/BindingUtils.h" +#include "mozilla/dom/WebKitCSSMatrixBinding.h" +#include "nsCSSParser.h" +#include "nsStyleTransformMatrix.h" + +namespace mozilla { +namespace dom { + +static const double sRadPerDegree = 2.0 * M_PI / 360.0; + +bool +WebKitCSSMatrix::FeatureEnabled(JSContext* aCx, JSObject* aObj) +{ + return Preferences::GetBool("layout.css.DOMMatrix.enabled", false) && + Preferences::GetBool("layout.css.prefixes.webkit", false); +} + +already_AddRefed +WebKitCSSMatrix::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv) +{ + RefPtr obj = new WebKitCSSMatrix(aGlobal.GetAsSupports()); + return obj.forget(); +} + +already_AddRefed +WebKitCSSMatrix::Constructor(const GlobalObject& aGlobal, + const nsAString& aTransformList, ErrorResult& aRv) +{ + RefPtr obj = new WebKitCSSMatrix(aGlobal.GetAsSupports()); + obj = obj->SetMatrixValue(aTransformList, aRv); + return obj.forget(); +} + +already_AddRefed +WebKitCSSMatrix::Constructor(const GlobalObject& aGlobal, + const DOMMatrixReadOnly& aOther, ErrorResult& aRv) +{ + RefPtr obj = new WebKitCSSMatrix(aGlobal.GetAsSupports(), + aOther); + return obj.forget(); +} + +JSObject* +WebKitCSSMatrix::WrapObject(JSContext* aCx, JS::Handle aGivenProto) +{ + return WebKitCSSMatrixBinding::Wrap(aCx, this, aGivenProto); +} + +WebKitCSSMatrix* +WebKitCSSMatrix::SetMatrixValue(const nsAString& aTransformList, + ErrorResult& aRv) +{ + // An empty string is a no-op. + if (aTransformList.IsEmpty()) { + return this; + } + + nsCSSValue value; + nsCSSParser parser; + bool parseSuccess = parser.ParseTransformProperty(aTransformList, + true, + value); + if (!parseSuccess) { + aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); + return nullptr; + } + + // A value of "none" results in a 2D identity matrix. + if (value.GetUnit() == eCSSUnit_None) { + mMatrix3D = nullptr; + mMatrix2D = new gfx::Matrix(); + return this; + } + + // A value other than a transform-list is a syntax error. + if (value.GetUnit() != eCSSUnit_SharedList) { + aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); + return nullptr; + } + + RuleNodeCacheConditions dummy; + nsStyleTransformMatrix::TransformReferenceBox dummyBox; + bool contains3dTransform = false; + gfx::Matrix4x4 transform = nsStyleTransformMatrix::ReadTransforms( + value.GetSharedListValue()->mHead, + nullptr, nullptr, dummy, dummyBox, + nsPresContext::AppUnitsPerCSSPixel(), + &contains3dTransform); + + if (!contains3dTransform) { + mMatrix3D = nullptr; + mMatrix2D = new gfx::Matrix(); + + SetA(transform._11); + SetB(transform._12); + SetC(transform._21); + SetD(transform._22); + SetE(transform._41); + SetF(transform._42); + } else { + mMatrix3D = new gfx::Matrix4x4(transform); + mMatrix2D = nullptr; + } + + return this; +} + +already_AddRefed +WebKitCSSMatrix::Multiply(const WebKitCSSMatrix& other) const +{ + RefPtr retval = new WebKitCSSMatrix(mParent, *this); + retval->MultiplySelf(other); + + return retval.forget(); +} + +already_AddRefed +WebKitCSSMatrix::Inverse(ErrorResult& aRv) const +{ + RefPtr retval = new WebKitCSSMatrix(mParent, *this); + retval->InvertSelfThrow(aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + return retval.forget(); +} + +WebKitCSSMatrix* +WebKitCSSMatrix::InvertSelfThrow(ErrorResult& aRv) +{ + if (mMatrix3D) { + if (!mMatrix3D->Invert()) { + aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + return nullptr; + } + } else if (!mMatrix2D->Invert()) { + aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + return nullptr; + } + + return this; +} + +already_AddRefed +WebKitCSSMatrix::Translate(double aTx, + double aTy, + double aTz) const +{ + RefPtr retval = new WebKitCSSMatrix(mParent, *this); + retval->TranslateSelf(aTx, aTy, aTz); + + return retval.forget(); +} + +already_AddRefed +WebKitCSSMatrix::Scale(double aScaleX, + const Optional& aScaleY, + double aScaleZ) const +{ + double scaleX = aScaleX; + double scaleY = aScaleY.WasPassed() ? aScaleY.Value() : scaleX; + double scaleZ = aScaleZ; + + RefPtr retval = new WebKitCSSMatrix(mParent, *this); + retval->ScaleNonUniformSelf(scaleX, scaleY, scaleZ); + + return retval.forget(); +} + +already_AddRefed +WebKitCSSMatrix::Rotate(double aRotX, + const Optional& aRotY, + const Optional& aRotZ) const +{ + double rotX = aRotX; + double rotY; + double rotZ; + + if (!aRotY.WasPassed() && !aRotZ.WasPassed()) { + rotZ = rotX; + rotX = 0; + rotY = 0; + } else { + rotY = aRotY.WasPassed() ? aRotY.Value() : 0; + rotZ = aRotZ.WasPassed() ? aRotZ.Value() : 0; + } + + RefPtr retval = new WebKitCSSMatrix(mParent, *this); + retval->Rotate3dSelf(rotX, rotY, rotZ); + + return retval.forget(); +} + +WebKitCSSMatrix* +WebKitCSSMatrix::Rotate3dSelf(double aRotX, + double aRotY, + double aRotZ) +{ + if (aRotX != 0 || aRotY != 0) { + Ensure3DMatrix(); + } + + if (mMatrix3D) { + if (fmod(aRotZ, 360) != 0) { + mMatrix3D->RotateZ(aRotZ * sRadPerDegree); + } + if (fmod(aRotY, 360) != 0) { + mMatrix3D->RotateY(aRotY * sRadPerDegree); + } + if (fmod(aRotX, 360) != 0) { + mMatrix3D->RotateX(aRotX * sRadPerDegree); + } + } else if (fmod(aRotZ, 360) != 0) { + mMatrix2D->PreRotate(aRotZ * sRadPerDegree); + } + + return this; +} + +already_AddRefed +WebKitCSSMatrix::RotateAxisAngle(double aX, + double aY, + double aZ, + double aAngle) const +{ + RefPtr retval = new WebKitCSSMatrix(mParent, *this); + retval->RotateAxisAngleSelf(aX, aY, aZ, aAngle); + + return retval.forget(); +} + +already_AddRefed +WebKitCSSMatrix::SkewX(double aSx) const +{ + RefPtr retval = new WebKitCSSMatrix(mParent, *this); + retval->SkewXSelf(aSx); + + return retval.forget(); +} + +already_AddRefed +WebKitCSSMatrix::SkewY(double aSy) const +{ + RefPtr retval = new WebKitCSSMatrix(mParent, *this); + retval->SkewYSelf(aSy); + + return retval.forget(); +} + +} // namespace dom +} // namespace mozilla diff --git a/dom/base/WebKitCSSMatrix.h b/dom/base/WebKitCSSMatrix.h new file mode 100644 index 0000000000..4b2adf9e09 --- /dev/null +++ b/dom/base/WebKitCSSMatrix.h @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_webkitcssmatrix_h__ +#define mozilla_dom_webkitcssmatrix_h__ + +#include "mozilla/dom/DOMMatrix.h" + +namespace mozilla { +namespace dom { + +class WebKitCSSMatrix final : public DOMMatrix +{ +public: + explicit WebKitCSSMatrix(nsISupports* aParent) + : DOMMatrix(aParent) + {} + + WebKitCSSMatrix(nsISupports* aParent, const DOMMatrixReadOnly& other) + : DOMMatrix(aParent, other) + {} + + static bool FeatureEnabled(JSContext* aCx, JSObject* aObj); + + static already_AddRefed + Constructor(const GlobalObject& aGlobal, ErrorResult& aRv); + static already_AddRefed + Constructor(const GlobalObject& aGlobal, + const nsAString& aTransformList, ErrorResult& aRv); + static already_AddRefed + Constructor(const GlobalObject& aGlobal, + const DOMMatrixReadOnly& aOther, ErrorResult& aRv); + + nsISupports* GetParentObject() const { return mParent; } + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle aGivenProto) override; + + WebKitCSSMatrix* SetMatrixValue(const nsAString& aTransformList, + ErrorResult& aRv); + + already_AddRefed Multiply(const WebKitCSSMatrix& aOther) const; + already_AddRefed Inverse(ErrorResult& aRv) const; + already_AddRefed Translate(double aTx, + double aTy, + double aTz) const; + already_AddRefed Scale(double aScaleX, + const Optional& aScaleY, + double aScaleZ) const; + already_AddRefed Rotate(double aRotX, + const Optional& aRotY, + const Optional& aRotZ) const; + already_AddRefed RotateAxisAngle(double aX, + double aY, + double aZ, + double aAngle) const; + already_AddRefed SkewX(double aSx) const; + already_AddRefed SkewY(double aSy) const; +protected: + WebKitCSSMatrix* Rotate3dSelf(double aRotX, + double aRotY, + double aRotZ); + + WebKitCSSMatrix* InvertSelfThrow(ErrorResult& aRv); +}; + +} // namespace dom +} // namespace mozilla + +#endif /* mozilla_dom_webkitcssmatrix_h__ */ diff --git a/dom/base/WindowNamedPropertiesHandler.cpp b/dom/base/WindowNamedPropertiesHandler.cpp index c0ef7ec7b5..1ee3a8d5b5 100644 --- a/dom/base/WindowNamedPropertiesHandler.cpp +++ b/dom/base/WindowNamedPropertiesHandler.cpp @@ -7,6 +7,7 @@ #include "WindowNamedPropertiesHandler.h" #include "mozilla/dom/EventTargetBinding.h" #include "mozilla/dom/WindowBinding.h" +#include "nsContentUtils.h" #include "nsDOMClassInfo.h" #include "nsGlobalWindow.h" #include "nsHTMLDocument.h" diff --git a/dom/base/moz.build b/dom/base/moz.build index 3c5ba1d8d7..575cfd482e 100644 --- a/dom/base/moz.build +++ b/dom/base/moz.build @@ -212,6 +212,7 @@ EXPORTS.mozilla.dom += [ 'TreeWalker.h', 'URL.h', 'URLSearchParams.h', + 'WebKitCSSMatrix.h', 'WebSocket.h', 'WindowOrientationObserver.h', ] @@ -359,6 +360,7 @@ UNIFIED_SOURCES += [ 'TreeWalker.cpp', 'URL.cpp', 'URLSearchParams.cpp', + 'WebKitCSSMatrix.cpp', 'WebSocket.cpp', 'WindowNamedPropertiesHandler.cpp', 'WindowOrientationObserver.cpp', diff --git a/dom/base/nsGkAtomList.h b/dom/base/nsGkAtomList.h index 1130d64a86..51ade79e36 100644 --- a/dom/base/nsGkAtomList.h +++ b/dom/base/nsGkAtomList.h @@ -1225,6 +1225,7 @@ GK_ATOM(tr, "tr") GK_ATOM(track, "track") GK_ATOM(trailing, "trailing") GK_ATOM(transform, "transform") +GK_ATOM(transform_3d, "transform-3d") GK_ATOM(transformiix, "transformiix") GK_ATOM(translate, "translate") GK_ATOM(transparent, "transparent") @@ -2191,8 +2192,6 @@ GK_ATOM(scrollbar_thumb_proportional, "scrollbar-thumb-proportional") GK_ATOM(images_in_menus, "images-in-menus") GK_ATOM(images_in_buttons, "images-in-buttons") GK_ATOM(overlay_scrollbars, "overlay-scrollbars") -GK_ATOM(windows_accent_color_applies, "windows-accent-color-applies") -GK_ATOM(windows_accent_color_is_dark, "windows-accent-color-is-dark") GK_ATOM(windows_default_theme, "windows-default-theme") GK_ATOM(mac_graphite_theme, "mac-graphite-theme") GK_ATOM(mac_lion_theme, "mac-lion-theme") @@ -2225,8 +2224,6 @@ GK_ATOM(_moz_scrollbar_thumb_proportional, "-moz-scrollbar-thumb-proportional") GK_ATOM(_moz_images_in_menus, "-moz-images-in-menus") GK_ATOM(_moz_images_in_buttons, "-moz-images-in-buttons") GK_ATOM(_moz_overlay_scrollbars, "-moz-overlay-scrollbars") -GK_ATOM(_moz_windows_accent_color_applies, "-moz-windows-accent-color-applies") -GK_ATOM(_moz_windows_accent_color_is_dark, "-moz-windows-accent-color-is-dark") GK_ATOM(_moz_windows_default_theme, "-moz-windows-default-theme") GK_ATOM(_moz_mac_graphite_theme, "-moz-mac-graphite-theme") GK_ATOM(_moz_mac_lion_theme, "-moz-mac-lion-theme") diff --git a/dom/base/nsXMLContentSerializer.cpp b/dom/base/nsXMLContentSerializer.cpp index 437e74d86a..887a9b78d0 100644 --- a/dom/base/nsXMLContentSerializer.cpp +++ b/dom/base/nsXMLContentSerializer.cpp @@ -19,6 +19,7 @@ #include "nsIContent.h" #include "nsIDocument.h" #include "nsIDocumentEncoder.h" +#include "nsIParserService.h" #include "nsNameSpaceManager.h" #include "nsTextFragment.h" #include "nsString.h" diff --git a/dom/tests/mochitest/general/mochitest.ini b/dom/tests/mochitest/general/mochitest.ini index 54ac94428a..14818b133b 100644 --- a/dom/tests/mochitest/general/mochitest.ini +++ b/dom/tests/mochitest/general/mochitest.ini @@ -122,3 +122,4 @@ skip-if = buildapp == 'b2g' # Bug 1184427 - no SSL certs on b2g skip-if = buildapp == 'b2g' # Bug 1184427 - no SSL certs on b2g [test_selectevents.html] skip-if = buildapp == 'b2g' || buildapp == 'mulet' # Mouse doesn't select in the same way on b2g +[test_WebKitCSSMatrix.html] diff --git a/dom/tests/mochitest/general/test_WebKitCSSMatrix.html b/dom/tests/mochitest/general/test_WebKitCSSMatrix.html new file mode 100644 index 0000000000..ca6dac4655 --- /dev/null +++ b/dom/tests/mochitest/general/test_WebKitCSSMatrix.html @@ -0,0 +1,326 @@ + + +Test for WebKitCSSMatrix + + +
+ diff --git a/dom/tests/mochitest/general/test_interfaces.html b/dom/tests/mochitest/general/test_interfaces.html index 6a6c2a2a56..dc8ea1b3d7 100644 --- a/dom/tests/mochitest/general/test_interfaces.html +++ b/dom/tests/mochitest/general/test_interfaces.html @@ -1409,18 +1409,32 @@ var interfaceNamesInGlobalScope = "WebGLFramebuffer", // IMPORTANT: Do not change this list without review from a DOM peer! "WebGLProgram", +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "WebGLQuery", nightly: true}, // IMPORTANT: Do not change this list without review from a DOM peer! "WebGLRenderbuffer", // IMPORTANT: Do not change this list without review from a DOM peer! "WebGLRenderingContext", +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "WebGLRenderingContext2", nightly: true}, +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "WebGLSampler", nightly: true}, // IMPORTANT: Do not change this list without review from a DOM peer! "WebGLShader", // IMPORTANT: Do not change this list without review from a DOM peer! "WebGLShaderPrecisionFormat", +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "WebGLSync", nightly: true}, // IMPORTANT: Do not change this list without review from a DOM peer! "WebGLTexture", +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "WebGLTransformFeedback", nightly: true}, // IMPORTANT: Do not change this list without review from a DOM peer! "WebGLUniformLocation", +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "WebGLVertexArrayObject", nightly: true}, +// IMPORTANT: Do not change this list without review from a DOM peer! + "WebKitCSSMatrix", // IMPORTANT: Do not change this list without review from a DOM peer! "WebSocket", // IMPORTANT: Do not change this list without review from a DOM peer! diff --git a/dom/webidl/WebKitCSSMatrix.webidl b/dom/webidl/WebKitCSSMatrix.webidl new file mode 100644 index 0000000000..8115711a33 --- /dev/null +++ b/dom/webidl/WebKitCSSMatrix.webidl @@ -0,0 +1,39 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is + * https://compat.spec.whatwg.org/#webkitcssmatrix-interface + */ + +[Constructor, + Constructor(DOMString transformList), + Constructor(WebKitCSSMatrix other), + Exposed=Window, + Func="mozilla::dom::WebKitCSSMatrix::FeatureEnabled"] +interface WebKitCSSMatrix : DOMMatrix { + // Mutable transform methods + [Throws] + WebKitCSSMatrix setMatrixValue(DOMString transformList); + + // Immutable transform methods + WebKitCSSMatrix multiply(WebKitCSSMatrix other); + [Throws] + WebKitCSSMatrix inverse(); + WebKitCSSMatrix translate(optional unrestricted double tx = 0, + optional unrestricted double ty = 0, + optional unrestricted double tz = 0); + WebKitCSSMatrix scale(optional unrestricted double scaleX = 1, + optional unrestricted double scaleY, + optional unrestricted double scaleZ = 1); + WebKitCSSMatrix rotate(optional unrestricted double rotX = 0, + optional unrestricted double rotY, + optional unrestricted double rotZ); + WebKitCSSMatrix rotateAxisAngle(optional unrestricted double x = 0, + optional unrestricted double y = 0, + optional unrestricted double z = 0, + optional unrestricted double angle = 0); + WebKitCSSMatrix skewX(optional unrestricted double sx = 0); + WebKitCSSMatrix skewY(optional unrestricted double sy = 0); +}; diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index 72c4985c7c..433ddf9287 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -590,6 +590,7 @@ WEBIDL_FILES = [ 'WebComponents.webidl', 'WebGL2RenderingContext.webidl', 'WebGLRenderingContext.webidl', + 'WebKitCSSMatrix.webidl', 'WebSocket.webidl', 'WheelEvent.webidl', 'WifiOptions.webidl', diff --git a/gfx/layers/basic/BasicCompositor.cpp b/gfx/layers/basic/BasicCompositor.cpp index 8191d7190d..a016a16fa3 100644 --- a/gfx/layers/basic/BasicCompositor.cpp +++ b/gfx/layers/basic/BasicCompositor.cpp @@ -152,6 +152,32 @@ BasicCompositor::CreateRenderTargetFromSource(const IntRect &aRect, return nullptr; } +already_AddRefed +BasicCompositor::CreateRenderTargetForWindow(const IntRect& aRect, SurfaceInitMode aInit, BufferMode aBufferMode) +{ + if (aBufferMode != BufferMode::BUFFER_NONE) { + return CreateRenderTarget(aRect, aInit); + } + + MOZ_ASSERT(aRect.width != 0 && aRect.height != 0, "Trying to create a render target of invalid size"); + + if (aRect.width * aRect.height == 0) { + return nullptr; + } + + MOZ_ASSERT(mDrawTarget); + + // Adjust bounds rect to account for new origin at (0, 0). + IntRect rect(0, 0, aRect.XMost(), aRect.YMost()); + RefPtr rt = new BasicCompositingRenderTarget(mDrawTarget, rect); + + if (aInit == INIT_MODE_CLEAR) { + mDrawTarget->ClearRect(gfx::Rect(aRect)); + } + + return rt.forget(); +} + already_AddRefed BasicCompositor::CreateDataTextureSource(TextureFlags aFlags) { @@ -542,13 +568,14 @@ BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion, *aRenderBoundsOut = Rect(); } + BufferMode bufferMode = BufferMode::BUFFERED; if (mTarget) { // If we have a copy target, then we don't have a widget-provided mDrawTarget (currently). Use a dummy // placeholder so that CreateRenderTarget() works. mDrawTarget = gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget(); } else { // StartRemoteDrawingInRegion can mutate mInvalidRegion. - mDrawTarget = mWidget->StartRemoteDrawingInRegion(mInvalidRegion); + mDrawTarget = mWidget->StartRemoteDrawingInRegion(mInvalidRegion, &bufferMode); if (!mDrawTarget) { return; } @@ -566,7 +593,7 @@ BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion, // Setup an intermediate render target to buffer all compositing. We will // copy this into mDrawTarget (the widget), and/or mTarget in EndFrame() RefPtr target = - CreateRenderTarget(mInvalidRect.ToUnknownRect(), INIT_MODE_CLEAR); + CreateRenderTargetForWindow(mInvalidRect.ToUnknownRect(), INIT_MODE_CLEAR, bufferMode); if (!target) { if (!mTarget) { mWidget->EndRemoteDrawingInRegion(mDrawTarget, mInvalidRegion); @@ -577,8 +604,7 @@ BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion, // We only allocate a surface sized to the invalidated region, so we need to // translate future coordinates. - mRenderTarget->mDrawTarget->SetTransform(Matrix::Translation(-mInvalidRect.x, - -mInvalidRect.y)); + mRenderTarget->mDrawTarget->SetTransform(Matrix::Translation(-mRenderTarget->GetOrigin())); gfxUtils::ClipToRegion(mRenderTarget->mDrawTarget, mInvalidRegion.ToUnknownRegion()); @@ -616,22 +642,25 @@ BasicCompositor::EndFrame() // Pop aInvalidregion mRenderTarget->mDrawTarget->PopClip(); - // Note: Most platforms require us to buffer drawing to the widget surface. - // That's why we don't draw to mDrawTarget directly. - RefPtr source = mRenderTarget->mDrawTarget->Snapshot(); - RefPtr dest(mTarget ? mTarget : mDrawTarget); + if (mTarget || mRenderTarget->mDrawTarget != mDrawTarget) { + // Note: Most platforms require us to buffer drawing to the widget surface. + // That's why we don't draw to mDrawTarget directly. + RefPtr source = mRenderTarget->mDrawTarget->Snapshot(); + RefPtr dest(mTarget ? mTarget : mDrawTarget); - nsIntPoint offset = mTarget ? mTargetBounds.TopLeft() : nsIntPoint(); + nsIntPoint offset = mTarget ? mTargetBounds.TopLeft() : nsIntPoint(); - // The source DrawTarget is clipped to the invalidation region, so we have - // to copy the individual rectangles in the region or else we'll draw blank - // pixels. - for (auto iter = mInvalidRegion.RectIter(); !iter.Done(); iter.Next()) { - const LayoutDeviceIntRect& r = iter.Get(); - dest->CopySurface(source, - IntRect(r.x - mInvalidRect.x, r.y - mInvalidRect.y, r.width, r.height), - IntPoint(r.x - offset.x, r.y - offset.y)); + // The source DrawTarget is clipped to the invalidation region, so we have + // to copy the individual rectangles in the region or else we'll draw blank + // pixels. + for (auto iter = mInvalidRegion.RectIter(); !iter.Done(); iter.Next()) { + const LayoutDeviceIntRect& r = iter.Get(); + dest->CopySurface(source, + IntRect(r.x, r.y, r.width, r.height) - mRenderTarget->GetOrigin(), + IntPoint(r.x, r.y) - offset); + } } + if (!mTarget) { mWidget->EndRemoteDrawingInRegion(mDrawTarget, mInvalidRegion); } diff --git a/gfx/layers/basic/BasicCompositor.h b/gfx/layers/basic/BasicCompositor.h index 05e64e2fcb..882c0283e9 100644 --- a/gfx/layers/basic/BasicCompositor.h +++ b/gfx/layers/basic/BasicCompositor.h @@ -60,6 +60,11 @@ public: const CompositingRenderTarget *aSource, const gfx::IntPoint &aSourcePoint) override; + virtual already_AddRefed + CreateRenderTargetForWindow(const gfx::IntRect& aRect, + SurfaceInitMode aInit, + BufferMode aBufferMode); + virtual already_AddRefed CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) override; diff --git a/gfx/thebes/gfxCoreTextShaper.cpp b/gfx/thebes/gfxCoreTextShaper.cpp index 60500d2518..ab15e09466 100644 --- a/gfx/thebes/gfxCoreTextShaper.cpp +++ b/gfx/thebes/gfxCoreTextShaper.cpp @@ -13,40 +13,107 @@ #include +#include + using namespace mozilla; // standard font descriptors that we construct the first time they're needed CTFontDescriptorRef gfxCoreTextShaper::sDefaultFeaturesDescriptor = nullptr; CTFontDescriptorRef gfxCoreTextShaper::sDisableLigaturesDescriptor = nullptr; +CTFontDescriptorRef gfxCoreTextShaper::sIndicFeaturesDescriptor = nullptr; +CTFontDescriptorRef gfxCoreTextShaper::sIndicDisableLigaturesDescriptor = nullptr; + +static CFStringRef sCTWritingDirectionAttributeName = nullptr; + +// See CTStringAttributes.h +enum { + kMyCTWritingDirectionEmbedding = (0 << 1), + kMyCTWritingDirectionOverride = (1 << 1) +}; + +// Helper to create a CFDictionary with the right attributes for shaping our +// text, including imposing the given directionality. +// This will only be called if we're on 10.8 or later. +CFDictionaryRef +gfxCoreTextShaper::CreateAttrDict(bool aRightToLeft) +{ + // Because we always shape unidirectional runs, and may have applied + // directional overrides, we want to force a direction rather than + // allowing CoreText to do its own unicode-based bidi processing. + SInt16 dirOverride = kMyCTWritingDirectionOverride | + (aRightToLeft ? kCTWritingDirectionRightToLeft + : kCTWritingDirectionLeftToRight); + CFNumberRef dirNumber = + ::CFNumberCreate(kCFAllocatorDefault, + kCFNumberSInt16Type, &dirOverride); + CFArrayRef dirArray = + ::CFArrayCreate(kCFAllocatorDefault, + (const void **) &dirNumber, 1, + &kCFTypeArrayCallBacks); + ::CFRelease(dirNumber); + CFTypeRef attrs[] = { kCTFontAttributeName, sCTWritingDirectionAttributeName }; + CFTypeRef values[] = { mCTFont, dirArray }; + CFDictionaryRef attrDict = + ::CFDictionaryCreate(kCFAllocatorDefault, + attrs, values, ArrayLength(attrs), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + ::CFRelease(dirArray); + return attrDict; +} + +CFDictionaryRef +gfxCoreTextShaper::CreateAttrDictWithoutDirection() +{ + CFTypeRef attrs[] = { kCTFontAttributeName }; + CFTypeRef values[] = { mCTFont }; + CFDictionaryRef attrDict = + ::CFDictionaryCreate(kCFAllocatorDefault, + attrs, values, ArrayLength(attrs), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + return attrDict; +} gfxCoreTextShaper::gfxCoreTextShaper(gfxMacFont *aFont) : gfxFontShaper(aFont) + , mAttributesDictLTR(nullptr) + , mAttributesDictRTL(nullptr) { - // Create our CTFontRef - mCTFont = ::CTFontCreateWithGraphicsFont(aFont->GetCGFontRef(), - aFont->GetAdjustedSize(), - nullptr, - GetDefaultFeaturesDescriptor()); + static bool sInitialized = false; + if (!sInitialized) { + CFStringRef* pstr = (CFStringRef*) + dlsym(RTLD_DEFAULT, "kCTWritingDirectionAttributeName"); + if (pstr) { + sCTWritingDirectionAttributeName = *pstr; + } + sInitialized = true; + } - // Set up the default attribute dictionary that we will need each time we create a CFAttributedString - mAttributesDict = ::CFDictionaryCreate(kCFAllocatorDefault, - (const void**) &kCTFontAttributeName, - (const void**) &mCTFont, - 1, // count of attributes - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); + // Create our CTFontRef + mCTFont = CreateCTFontWithFeatures(aFont->GetAdjustedSize(), + GetDefaultFeaturesDescriptor()); } gfxCoreTextShaper::~gfxCoreTextShaper() { - if (mAttributesDict) { - ::CFRelease(mAttributesDict); + if (mAttributesDictLTR) { + ::CFRelease(mAttributesDictLTR); + } + if (mAttributesDictRTL) { + ::CFRelease(mAttributesDictRTL); } if (mCTFont) { ::CFRelease(mCTFont); } } +static bool +IsBuggyIndicScript(int32_t aScript) +{ + return aScript == MOZ_SCRIPT_BENGALI || aScript == MOZ_SCRIPT_KANNADA; +} + bool gfxCoreTextShaper::ShapeText(DrawTarget *aDrawTarget, const char16_t *aText, @@ -57,70 +124,112 @@ gfxCoreTextShaper::ShapeText(DrawTarget *aDrawTarget, gfxShapedText *aShapedText) { // Create a CFAttributedString with text and style info, so we can use CoreText to lay it out. - bool isRightToLeft = aShapedText->IsRightToLeft(); + const UniChar* text = reinterpret_cast(aText); uint32_t length = aLength; - // we need to bidi-wrap the text if the run is RTL, - // or if it is an LTR run but may contain (overridden) RTL chars - bool bidiWrap = isRightToLeft; - if (!bidiWrap && !aShapedText->TextIs8Bit()) { - uint32_t i; - for (i = 0; i < length; ++i) { - if (gfxFontUtils::PotentialRTLChar(aText[i])) { - bidiWrap = true; - break; - } - } - } - - // If there's a possibility of any bidi, we wrap the text with direction overrides - // to ensure neutrals or characters that were bidi-overridden in HTML behave properly. - const UniChar beginLTR[] = { 0x202d, 0x20 }; - const UniChar beginRTL[] = { 0x202e, 0x20 }; - const UniChar endBidiWrap[] = { 0x20, 0x2e, 0x202c }; - uint32_t startOffset; CFStringRef stringObj; - if (bidiWrap) { - startOffset = isRightToLeft ? - mozilla::ArrayLength(beginRTL) : mozilla::ArrayLength(beginLTR); - CFMutableStringRef mutableString = - ::CFStringCreateMutable(kCFAllocatorDefault, - length + startOffset + mozilla::ArrayLength(endBidiWrap)); - ::CFStringAppendCharacters(mutableString, - isRightToLeft ? beginRTL : beginLTR, - startOffset); - ::CFStringAppendCharacters(mutableString, reinterpret_cast(aText), length); - ::CFStringAppendCharacters(mutableString, - endBidiWrap, mozilla::ArrayLength(endBidiWrap)); - stringObj = mutableString; - } else { + CFDictionaryRef attrObj; + + if (sCTWritingDirectionAttributeName) { startOffset = 0; stringObj = ::CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, - reinterpret_cast(aText), - length, kCFAllocatorNull); + text, length, + kCFAllocatorNull); + + // Get an attributes dictionary suitable for shaping text in the + // current direction, creating it if necessary. + attrObj = isRightToLeft ? mAttributesDictRTL : mAttributesDictLTR; + if (!attrObj) { + attrObj = CreateAttrDict(isRightToLeft); + (isRightToLeft ? mAttributesDictRTL : mAttributesDictLTR) = attrObj; + } + } else { + // OS is too old to support kCTWritingDirectionAttributeName: + // we need to bidi-wrap the text if the run is RTL, + // or if it is an LTR run but may contain (overridden) RTL chars + bool bidiWrap = isRightToLeft; + if (!bidiWrap && !aShapedText->TextIs8Bit()) { + uint32_t i; + for (i = 0; i < length; ++i) { + if (gfxFontUtils::PotentialRTLChar(aText[i])) { + bidiWrap = true; + break; + } + } + } + + // If there's a possibility of any bidi, we wrap the text with + // direction overrides to ensure neutrals or characters that were + // bidi-overridden in HTML behave properly. + static const UniChar beginLTR[] = { 0x202d, 0x20 }; + static const UniChar beginRTL[] = { 0x202e, 0x20 }; + static const UniChar endBidiWrap[] = { 0x20, 0x2e, 0x202c }; + + if (bidiWrap) { + startOffset = isRightToLeft ? ArrayLength(beginRTL) + : ArrayLength(beginLTR); + CFMutableStringRef mutableString = + ::CFStringCreateMutable(kCFAllocatorDefault, + length + startOffset + + ArrayLength(endBidiWrap)); + ::CFStringAppendCharacters(mutableString, + isRightToLeft ? beginRTL : beginLTR, + startOffset); + ::CFStringAppendCharacters(mutableString, text, length); + ::CFStringAppendCharacters(mutableString, endBidiWrap, + ArrayLength(endBidiWrap)); + stringObj = mutableString; + } else { + startOffset = 0; + stringObj = + ::CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, + text, length, + kCFAllocatorNull); + } + + // Get an attributes dictionary suitable for shaping text, + // creating it if necessary. (This dict is not LTR-specific, + // but we use that field to store it anyway.) + if (!mAttributesDictLTR) { + mAttributesDictLTR = CreateAttrDictWithoutDirection(); + } + attrObj = mAttributesDictLTR; } - CFDictionaryRef attrObj; - if (aShapedText->DisableLigatures()) { - // For letterspacing (or maybe other situations) we need to make a copy of the CTFont - // with the ligature feature disabled - CTFontRef ctFont = - CreateCTFontWithDisabledLigatures(::CTFontGetSize(mCTFont)); + CTFontRef tempCTFont = nullptr; + if (IsBuggyIndicScript(aScript)) { + // To work around buggy Indic AAT fonts shipped with OS X, + // we re-enable the Line Initial Smart Swashes feature that is needed + // for "split vowels" to work in at least Bengali and Kannada fonts. + // Affected fonts include Bangla MN, Bangla Sangam MN, Kannada MN, + // Kannada Sangam MN. See bugs 686225, 728557, 953231, 1145515. + tempCTFont = + CreateCTFontWithFeatures(::CTFontGetSize(mCTFont), + aShapedText->DisableLigatures() + ? GetIndicDisableLigaturesDescriptor() + : GetIndicFeaturesDescriptor()); + } else if (aShapedText->DisableLigatures()) { + // For letterspacing (or maybe other situations) we need to make + // a copy of the CTFont with the ligature feature disabled. + tempCTFont = + CreateCTFontWithFeatures(::CTFontGetSize(mCTFont), + GetDisableLigaturesDescriptor()); + } - attrObj = - ::CFDictionaryCreate(kCFAllocatorDefault, - (const void**) &kCTFontAttributeName, - (const void**) &ctFont, - 1, // count of attributes - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - // Having created the dict, we're finished with our ligature-disabled CTFontRef - ::CFRelease(ctFont); - } else { - attrObj = mAttributesDict; - ::CFRetain(attrObj); + // For the disabled-ligature or buggy-indic-font case, we need to replace + // the standard CTFont in the attribute dictionary with a tweaked version. + CFMutableDictionaryRef mutableAttr = nullptr; + if (tempCTFont) { + mutableAttr = ::CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 2, + attrObj); + ::CFDictionaryReplaceValue(mutableAttr, + kCTFontAttributeName, tempCTFont); + // Having created the dict, we're finished with our temporary + // Indic and/or ligature-disabled CTFontRef. + ::CFRelease(tempCTFont); + attrObj = mutableAttr; } // Now we can create an attributed string @@ -143,34 +252,47 @@ gfxCoreTextShaper::ShapeText(DrawTarget *aDrawTarget, for (uint32_t runIndex = 0; runIndex < numRuns; runIndex++) { CTRunRef aCTRun = (CTRunRef)::CFArrayGetValueAtIndex(glyphRuns, runIndex); + // If the range is purely within bidi-wrapping text, ignore it. + CFRange range = ::CTRunGetStringRange(aCTRun); + if (uint32_t(range.location + range.length) <= startOffset || + range.location - startOffset >= aLength) { + continue; + } CFDictionaryRef runAttr = ::CTRunGetAttributes(aCTRun); if (runAttr != attrObj) { // If Core Text manufactured a new dictionary, this may indicate // unexpected font substitution. In that case, we fail (and fall // back to harfbuzz shaping)... - const void* font1 = ::CFDictionaryGetValue(attrObj, kCTFontAttributeName); - const void* font2 = ::CFDictionaryGetValue(runAttr, kCTFontAttributeName); + const void* font1 = + ::CFDictionaryGetValue(attrObj, kCTFontAttributeName); + const void* font2 = + ::CFDictionaryGetValue(runAttr, kCTFontAttributeName); if (font1 != font2) { // ...except that if the fallback was only for a variation - // selector that is otherwise unsupported, we just ignore it. - CFRange range = ::CTRunGetStringRange(aCTRun); - if (range.length == 1 && - gfxFontUtils::IsVarSelector(aText[range.location - - startOffset])) { - continue; + // selector or join control that is otherwise unsupported, + // we just ignore it. + if (range.length == 1) { + char16_t ch = aText[range.location - startOffset]; + if (gfxFontUtils::IsJoinControl(ch) || + gfxFontUtils::IsVarSelector(ch)) { + continue; + } } NS_WARNING("unexpected font fallback in Core Text"); success = false; break; } } - if (SetGlyphsFromRun(aShapedText, aOffset, aLength, aCTRun, startOffset) != NS_OK) { + if (SetGlyphsFromRun(aShapedText, aOffset, aLength, aCTRun, + startOffset) != NS_OK) { success = false; break; } } - ::CFRelease(attrObj); + if (mutableAttr) { + ::CFRelease(mutableAttr); + } ::CFRelease(line); return success; @@ -515,64 +637,57 @@ gfxCoreTextShaper::SetGlyphsFromRun(gfxShapedText *aShapedText, #undef SMALL_GLYPH_RUN -// Construct the font attribute descriptor that we'll apply by default when creating a CTFontRef. -// This will turn off line-edge swashes by default, because we don't know the actual line breaks -// when doing glyph shaping. -void -gfxCoreTextShaper::CreateDefaultFeaturesDescriptor() +// Construct the font attribute descriptor that we'll apply by default when +// creating a CTFontRef. This will turn off line-edge swashes by default, +// because we don't know the actual line breaks when doing glyph shaping. + +// We also cache feature descriptors for shaping with disabled ligatures, and +// for buggy Indic AAT font workarounds, created on an as-needed basis. + +#define MAX_FEATURES 3 // max used by any of our Get*Descriptor functions + +CTFontDescriptorRef +gfxCoreTextShaper::CreateFontFeaturesDescriptor( + const std::pair aFeatures[], + size_t aCount) { - if (sDefaultFeaturesDescriptor != nullptr) { - return; + MOZ_ASSERT(aCount <= MAX_FEATURES); + + CFDictionaryRef featureSettings[MAX_FEATURES]; + + for (size_t i = 0; i < aCount; i++) { + CFNumberRef type = ::CFNumberCreate(kCFAllocatorDefault, + kCFNumberSInt16Type, + &aFeatures[i].first); + CFNumberRef selector = ::CFNumberCreate(kCFAllocatorDefault, + kCFNumberSInt16Type, + &aFeatures[i].second); + + CFTypeRef keys[] = { kCTFontFeatureTypeIdentifierKey, + kCTFontFeatureSelectorIdentifierKey }; + CFTypeRef values[] = { type, selector }; + featureSettings[i] = + ::CFDictionaryCreate(kCFAllocatorDefault, + (const void **) keys, + (const void **) values, + ArrayLength(keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + ::CFRelease(selector); + ::CFRelease(type); } - SInt16 val = kSmartSwashType; - CFNumberRef swashesType = - ::CFNumberCreate(kCFAllocatorDefault, - kCFNumberSInt16Type, - &val); - val = kLineInitialSwashesOffSelector; - CFNumberRef lineInitialsOffSelector = - ::CFNumberCreate(kCFAllocatorDefault, - kCFNumberSInt16Type, - &val); - - CFTypeRef keys[] = { kCTFontFeatureTypeIdentifierKey, - kCTFontFeatureSelectorIdentifierKey }; - CFTypeRef values[] = { swashesType, - lineInitialsOffSelector }; - CFDictionaryRef featureSettings[2]; - featureSettings[0] = - ::CFDictionaryCreate(kCFAllocatorDefault, - (const void **) keys, - (const void **) values, - ArrayLength(keys), - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - ::CFRelease(lineInitialsOffSelector); - - val = kLineFinalSwashesOffSelector; - CFNumberRef lineFinalsOffSelector = - ::CFNumberCreate(kCFAllocatorDefault, - kCFNumberSInt16Type, - &val); - values[1] = lineFinalsOffSelector; - featureSettings[1] = - ::CFDictionaryCreate(kCFAllocatorDefault, - (const void **) keys, - (const void **) values, - ArrayLength(keys), - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - ::CFRelease(lineFinalsOffSelector); - ::CFRelease(swashesType); - CFArrayRef featuresArray = ::CFArrayCreate(kCFAllocatorDefault, (const void **) featureSettings, - ArrayLength(featureSettings), + aCount, // not ArrayLength(featureSettings), as we + // may not have used all the allocated slots &kCFTypeArrayCallBacks); - ::CFRelease(featureSettings[0]); - ::CFRelease(featureSettings[1]); + + for (size_t i = 0; i < aCount; i++) { + ::CFRelease(featureSettings[i]); + } const CFTypeRef attrKeys[] = { kCTFontFeatureSettingsAttribute }; const CFTypeRef attrValues[] = { featuresArray }; @@ -585,76 +700,97 @@ gfxCoreTextShaper::CreateDefaultFeaturesDescriptor() &kCFTypeDictionaryValueCallBacks); ::CFRelease(featuresArray); - sDefaultFeaturesDescriptor = + CTFontDescriptorRef descriptor = ::CTFontDescriptorCreateWithAttributes(attributesDict); ::CFRelease(attributesDict); + + return descriptor; } -// Create a CTFontRef, with the Common Ligatures feature disabled -CTFontRef -gfxCoreTextShaper::CreateCTFontWithDisabledLigatures(CGFloat aSize) +CTFontDescriptorRef +gfxCoreTextShaper::GetDefaultFeaturesDescriptor() +{ + if (sDefaultFeaturesDescriptor == nullptr) { + const std::pair kDefaultFeatures[] = { + { kSmartSwashType, kLineInitialSwashesOffSelector }, + { kSmartSwashType, kLineFinalSwashesOffSelector } + }; + sDefaultFeaturesDescriptor = + CreateFontFeaturesDescriptor(kDefaultFeatures, + ArrayLength(kDefaultFeatures)); + } + return sDefaultFeaturesDescriptor; +} + +CTFontDescriptorRef +gfxCoreTextShaper::GetDisableLigaturesDescriptor() { if (sDisableLigaturesDescriptor == nullptr) { - // initialize cached descriptor to turn off the Common Ligatures feature - SInt16 val = kLigaturesType; - CFNumberRef ligaturesType = - ::CFNumberCreate(kCFAllocatorDefault, - kCFNumberSInt16Type, - &val); - val = kCommonLigaturesOffSelector; - CFNumberRef commonLigaturesOffSelector = - ::CFNumberCreate(kCFAllocatorDefault, - kCFNumberSInt16Type, - &val); - - const CFTypeRef keys[] = { kCTFontFeatureTypeIdentifierKey, - kCTFontFeatureSelectorIdentifierKey }; - const CFTypeRef values[] = { ligaturesType, - commonLigaturesOffSelector }; - CFDictionaryRef featureSettingDict = - ::CFDictionaryCreate(kCFAllocatorDefault, - (const void **) keys, - (const void **) values, - ArrayLength(keys), - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - ::CFRelease(ligaturesType); - ::CFRelease(commonLigaturesOffSelector); - - CFArrayRef featuresArray = - ::CFArrayCreate(kCFAllocatorDefault, - (const void **) &featureSettingDict, - 1, - &kCFTypeArrayCallBacks); - ::CFRelease(featureSettingDict); - - CFDictionaryRef attributesDict = - ::CFDictionaryCreate(kCFAllocatorDefault, - (const void **) &kCTFontFeatureSettingsAttribute, - (const void **) &featuresArray, - 1, // count of keys & values - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - ::CFRelease(featuresArray); - + const std::pair kDisableLigatures[] = { + { kSmartSwashType, kLineInitialSwashesOffSelector }, + { kSmartSwashType, kLineFinalSwashesOffSelector }, + { kLigaturesType, kCommonLigaturesOffSelector } + }; sDisableLigaturesDescriptor = - ::CTFontDescriptorCreateCopyWithAttributes(GetDefaultFeaturesDescriptor(), - attributesDict); - ::CFRelease(attributesDict); + CreateFontFeaturesDescriptor(kDisableLigatures, + ArrayLength(kDisableLigatures)); } + return sDisableLigaturesDescriptor; +} +CTFontDescriptorRef +gfxCoreTextShaper::GetIndicFeaturesDescriptor() +{ + if (sIndicFeaturesDescriptor == nullptr) { + const std::pair kIndicFeatures[] = { + { kSmartSwashType, kLineFinalSwashesOffSelector } + }; + sIndicFeaturesDescriptor = + CreateFontFeaturesDescriptor(kIndicFeatures, + ArrayLength(kIndicFeatures)); + } + return sIndicFeaturesDescriptor; +} + +CTFontDescriptorRef +gfxCoreTextShaper::GetIndicDisableLigaturesDescriptor() +{ + if (sIndicDisableLigaturesDescriptor == nullptr) { + const std::pair kIndicDisableLigatures[] = { + { kSmartSwashType, kLineFinalSwashesOffSelector }, + { kLigaturesType, kCommonLigaturesOffSelector } + }; + sIndicDisableLigaturesDescriptor = + CreateFontFeaturesDescriptor(kIndicDisableLigatures, + ArrayLength(kIndicDisableLigatures)); + } + return sIndicDisableLigaturesDescriptor; +} + +CTFontRef +gfxCoreTextShaper::CreateCTFontWithFeatures(CGFloat aSize, + CTFontDescriptorRef aDescriptor) +{ gfxMacFont *f = static_cast(mFont); return ::CTFontCreateWithGraphicsFont(f->GetCGFontRef(), aSize, nullptr, - sDisableLigaturesDescriptor); + aDescriptor); } void gfxCoreTextShaper::Shutdown() // [static] { + if (sIndicDisableLigaturesDescriptor != nullptr) { + ::CFRelease(sIndicDisableLigaturesDescriptor); + sIndicDisableLigaturesDescriptor = nullptr; + } + if (sIndicFeaturesDescriptor != nullptr) { + ::CFRelease(sIndicFeaturesDescriptor); + sIndicFeaturesDescriptor = nullptr; + } if (sDisableLigaturesDescriptor != nullptr) { ::CFRelease(sDisableLigaturesDescriptor); sDisableLigaturesDescriptor = nullptr; - } + } if (sDefaultFeaturesDescriptor != nullptr) { ::CFRelease(sDefaultFeaturesDescriptor); sDefaultFeaturesDescriptor = nullptr; diff --git a/gfx/thebes/gfxCoreTextShaper.h b/gfx/thebes/gfxCoreTextShaper.h index 9026128e17..693e32d00e 100644 --- a/gfx/thebes/gfxCoreTextShaper.h +++ b/gfx/thebes/gfxCoreTextShaper.h @@ -31,7 +31,10 @@ public: protected: CTFontRef mCTFont; - CFDictionaryRef mAttributesDict; + + // attributes for shaping text with LTR or RTL directionality + CFDictionaryRef mAttributesDictLTR; + CFDictionaryRef mAttributesDictRTL; nsresult SetGlyphsFromRun(gfxShapedText *aShapedText, uint32_t aOffset, @@ -39,22 +42,30 @@ protected: CTRunRef aCTRun, int32_t aStringOffset); - CTFontRef CreateCTFontWithDisabledLigatures(CGFloat aSize); + CTFontRef CreateCTFontWithFeatures(CGFloat aSize, + CTFontDescriptorRef aDescriptor); - static void CreateDefaultFeaturesDescriptor(); + CFDictionaryRef CreateAttrDict(bool aRightToLeft); + CFDictionaryRef CreateAttrDictWithoutDirection(); - static CTFontDescriptorRef GetDefaultFeaturesDescriptor() { - if (sDefaultFeaturesDescriptor == nullptr) { - CreateDefaultFeaturesDescriptor(); - } - return sDefaultFeaturesDescriptor; - } + static CTFontDescriptorRef + CreateFontFeaturesDescriptor(const std::pair aFeatures[], + size_t aCount); + + static CTFontDescriptorRef GetDefaultFeaturesDescriptor(); + static CTFontDescriptorRef GetDisableLigaturesDescriptor(); + static CTFontDescriptorRef GetIndicFeaturesDescriptor(); + static CTFontDescriptorRef GetIndicDisableLigaturesDescriptor(); // cached font descriptor, created the first time it's needed static CTFontDescriptorRef sDefaultFeaturesDescriptor; // cached descriptor for adding disable-ligatures setting to a font static CTFontDescriptorRef sDisableLigaturesDescriptor; + + // feature descriptors for buggy Indic AAT font workaround + static CTFontDescriptorRef sIndicFeaturesDescriptor; + static CTFontDescriptorRef sIndicDisableLigaturesDescriptor; }; #endif /* GFX_CORETEXTSHAPER_H */ diff --git a/gfx/thebes/gfxGDIFontList.cpp b/gfx/thebes/gfxGDIFontList.cpp index be388f4c03..e9d6f682ee 100644 --- a/gfx/thebes/gfxGDIFontList.cpp +++ b/gfx/thebes/gfxGDIFontList.cpp @@ -918,22 +918,22 @@ gfxGDIFontList::GetDefaultFont(const gfxFontStyle* aStyle) gfxFontFamily *ff = nullptr; // this really shouldn't fail to find a font.... - HGDIOBJ hGDI = ::GetStockObject(DEFAULT_GUI_FONT); - LOGFONTW logFont; - if (hGDI && ::GetObjectW(hGDI, sizeof(logFont), &logFont)) { - ff = FindFamily(nsDependentString(logFont.lfFaceName)); - if (ff) { - return ff; - } - } - - // ...but just in case, try another approach as well NONCLIENTMETRICSW ncm; ncm.cbSize = sizeof(ncm); BOOL status = ::SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0); if (status) { ff = FindFamily(nsDependentString(ncm.lfMessageFont.lfFaceName)); + if (ff) { + return ff; + } + } + + // ...but just in case, try another (long-deprecated) approach as well + HGDIOBJ hGDI = ::GetStockObject(DEFAULT_GUI_FONT); + LOGFONTW logFont; + if (hGDI && ::GetObjectW(hGDI, sizeof(logFont), &logFont)) { + ff = FindFamily(nsDependentString(logFont.lfFaceName)); } return ff; diff --git a/layout/base/ActiveLayerTracker.cpp b/layout/base/ActiveLayerTracker.cpp index 45d532e6ff..35217c39e4 100644 --- a/layout/base/ActiveLayerTracker.cpp +++ b/layout/base/ActiveLayerTracker.cpp @@ -263,13 +263,15 @@ IncrementScaleRestyleCountIfNeeded(nsIFrame* aFrame, LayerActivity* aActivity) // Compute the new scale due to the CSS transform property. nsPresContext* presContext = aFrame->PresContext(); RuleNodeCacheConditions dummy; + bool dummyBool; nsStyleTransformMatrix::TransformReferenceBox refBox(aFrame); Matrix4x4 transform = nsStyleTransformMatrix::ReadTransforms(display->mSpecifiedTransform->mHead, aFrame->StyleContext(), presContext, dummy, refBox, - presContext->AppUnitsPerCSSPixel()); + presContext->AppUnitsPerCSSPixel(), + &dummyBool); Matrix transform2D; if (!transform.Is2D(&transform2D)) { // We don't attempt to handle 3D transforms; just assume the scale changed. diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 4b9ae5c559..aac5d4bc54 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -326,12 +326,14 @@ static void AddTransformFunctions(nsCSSValueList* aList, } case eCSSKeyword_interpolatematrix: { + bool dummy; Matrix4x4 matrix; nsStyleTransformMatrix::ProcessInterpolateMatrix(matrix, array, aContext, aPresContext, conditions, - aRefBox); + aRefBox, + &dummy); aFunctions.AppendElement(TransformMatrix(matrix)); break; } @@ -1936,7 +1938,6 @@ void nsDisplayList::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, point = aRect.Center(); } temp.AppendElement(FramesWithDepth(transform->GetHitDepthAtPoint(aBuilder, point))); - printf("depth %p %f\n", transform, transform->GetHitDepthAtPoint(aBuilder, point)); writeFrames = &temp[temp.Length() - 1].mFrames; } } else { @@ -5418,6 +5419,7 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProp /* Get the matrix, then change its basis to factor in the origin. */ RuleNodeCacheConditions dummy; + bool dummyBool; Matrix4x4 result; // Call IsSVGTransformed() regardless of the value of // disp->mSpecifiedTransform, since we still need any transformFromSVGParent. @@ -5431,7 +5433,8 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProp result = nsStyleTransformMatrix::ReadTransforms(aProperties.mTransformList->mHead, frame ? frame->StyleContext() : nullptr, frame ? frame->PresContext() : nullptr, - dummy, refBox, aAppUnitsPerPixel); + dummy, refBox, aAppUnitsPerPixel, + &dummyBool); } else if (hasSVGTransforms) { // Correct the translation components for zoom: float pixelsPerCSSPx = frame->PresContext()->AppUnitsPerCSSPixel() / diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 87cc8c7121..2d80921e55 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -557,9 +557,9 @@ skip-if(B2G||Mulet) == 363858-1.html 363858-1-ref.html # Initial mulet triage: p skip-if(B2G||Mulet) == 363858-2.html 363858-2-ref.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) == 363858-3.html 363858-3-ref.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) == 363858-4.html 363858-4-ref.html # Initial mulet triage: parity with B2G/B2G Desktop -fuzzy-if(OSX>=1008,45,2) == 363858-5a.html 363858-5-ref.html +fuzzy-if(OSX>=1008,45,2) fuzzy-if(winWidget,114,1) == 363858-5a.html 363858-5-ref.html == 363858-5b.html 363858-5-ref.html -fuzzy-if(OSX>=1008,45,2) == 363858-6a.html 363858-6-ref.html +fuzzy-if(OSX>=1008,45,2) fuzzy-if(winWidget,114,1) == 363858-6a.html 363858-6-ref.html == 363858-6b.html 363858-6-ref.html == 363874.html 363874-ref.html == 363874-max-width.html 363874-max-width-ref.html diff --git a/layout/reftests/forms/placeholder/reftest.list b/layout/reftests/forms/placeholder/reftest.list index d8ebda9bdd..ce3392438f 100644 --- a/layout/reftests/forms/placeholder/reftest.list +++ b/layout/reftests/forms/placeholder/reftest.list @@ -16,7 +16,7 @@ == placeholder-3.html placeholder-overridden-ref.html == placeholder-4.html placeholder-overridden-ref.html == placeholder-5.html placeholder-visible-ref.html -fuzzy-if(winWidget,160,7) fuzzy-if(asyncPan&&!layersGPUAccelerated,146,299) == placeholder-6.html placeholder-overflow-ref.html +fuzzy-if(winWidget,160,10) fuzzy-if(Android,1,1) fuzzy-if(asyncPan&&!layersGPUAccelerated,146,299) == placeholder-6.html placeholder-overflow-ref.html skip-if(B2G||Mulet) == placeholder-6-textarea.html placeholder-overflow-textarea-ref.html # Initial mulet triage: parity with B2G/B2G Desktop # needs-focus == placeholder-7.html placeholder-focus-ref.html # needs-focus == placeholder-8.html placeholder-focus-ref.html diff --git a/layout/reftests/text/reftest.list b/layout/reftests/text/reftest.list index 9080d40264..ec798daf71 100644 --- a/layout/reftests/text/reftest.list +++ b/layout/reftests/text/reftest.list @@ -165,6 +165,7 @@ fails-if(cocoaWidget||Android||B2G) HTTP(..) == arabic-fallback-2.html arabic-fa fails-if(cocoaWidget||Android||B2G) HTTP(..) == arabic-fallback-3.html arabic-fallback-3-ref.html fails-if(!cocoaWidget&&!Android&&!B2G) HTTP(..) != arabic-fallback-4.html arabic-fallback-4-notref.html == arabic-marks-1.html arabic-marks-1-ref.html +fails-if(OSX<1008) == arabic-final-ligature-spacing.html arabic-final-ligature-spacing-ref.html # harfbuzz fallback mark stacking in the absence of GPOS: HTTP(..) != fallback-mark-stacking-1.html fallback-mark-stacking-1-notref.html diff --git a/layout/style/CSSVariableImageTable.h b/layout/style/CSSVariableImageTable.h new file mode 100644 index 0000000000..1366f4d83c --- /dev/null +++ b/layout/style/CSSVariableImageTable.h @@ -0,0 +1,190 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* A global table that tracks images referenced by CSS variables. */ + +#ifndef mozilla_CSSVariableImageTable_h +#define mozilla_CSSVariableImageTable_h + +#include "nsClassHashtable.h" +#include "nsCSSProperty.h" +#include "nsCSSValue.h" +#include "nsStyleContext.h" +#include "nsTArray.h" + +/** + * CSSVariableImageTable maintains a global mapping + * (nsStyleContext, nsCSSProperty) -> nsTArray + * which allows us to track the relationship between CSS property values + * involving variables and any images they may reference. + * + * When properties like background-image contain a normal url(), the + * Declaration's data block will hold a reference to the ImageValue. When a + * token stream is used, the Declaration only holds on to an + * nsCSSValueTokenStream object, and the ImageValue would only exist for the + * duration of nsRuleNode::WalkRuleTree, in the AutoCSSValueArray. So instead + * when we re-parse a token stream and get an ImageValue, we record it in the + * CSSVariableImageTable to keep the ImageValue alive. Such ImageValues are + * eventually freed the next time the token stream is re-parsed, or when the + * associated style context is destroyed. + * + * To add ImageValues to the CSSVariableImageTable, callers should pass a lambda + * to CSSVariableImageTable::ReplaceAll() that calls + * CSSVariableImageTable::Add() for each ImageValue that needs to be added to + * the table. When callers are sure that the ImageValues for a given + * nsStyleContext won't be needed anymore, they can call + * CSSVariableImageTable::RemoveAll() to release them. + */ + +namespace mozilla { +namespace CSSVariableImageTable { + +namespace detail { + +typedef nsTArray> ImageValueArray; +typedef nsClassHashtable, ImageValueArray> + PerPropertyImageHashtable; +typedef nsClassHashtable, PerPropertyImageHashtable> + CSSVariableImageHashtable; + +inline CSSVariableImageHashtable& GetTable() +{ + static CSSVariableImageHashtable imageTable; + return imageTable; +} + +#ifdef DEBUG +inline bool& IsReplacing() +{ + static bool isReplacing = false; + return isReplacing; +} +#endif + +} // namespace detail + +/** + * ReplaceAll() allows callers to replace the ImageValues associated with a + * (nsStyleContext, nsCSSProperty) pair. The memory used by the previous list of + * ImageValues is automatically released. + * + * @param aContext The style context the ImageValues are associated with. + * @param aProp The CSS property the ImageValues are associated with. + * @param aFunc A lambda that calls CSSVariableImageTable::Add() to add new + * ImageValues which will replace the old ones. + */ +template +inline void ReplaceAll(nsStyleContext* aContext, + nsCSSProperty aProp, + Lambda aFunc) +{ + MOZ_ASSERT(aContext); + + auto& imageTable = detail::GetTable(); + + // Clear the existing image array, if any, for this property. + { + auto* perPropertyImageTable = imageTable.Get(aContext); + auto* imageList = perPropertyImageTable ? perPropertyImageTable->Get(aProp) + : nullptr; + if (imageList) { + imageList->ClearAndRetainStorage(); + } + } + +#ifdef DEBUG + MOZ_ASSERT(!detail::IsReplacing()); + detail::IsReplacing() = true; +#endif + + aFunc(); + +#ifdef DEBUG + detail::IsReplacing() = false; +#endif + + // Clean up. + auto* perPropertyImageTable = imageTable.Get(aContext); + auto* imageList = perPropertyImageTable ? perPropertyImageTable->Get(aProp) + : nullptr; + if (imageList) { + if (imageList->IsEmpty()) { + // We used to have an image array for this property, but now we don't. + // Remove the entry in the per-property image table for this property. + // That may then allow us to remove the entire per-property image table. + perPropertyImageTable->Remove(aProp); + if (perPropertyImageTable->Count() == 0) { + imageTable.Remove(aContext); + } + } else { + // We still have a non-empty image array for this property. Compact the + // storage it's using if possible. + imageList->Compact(); + } + } +} + +/** + * Adds a new ImageValue @aValue to the CSSVariableImageTable, which will be + * associated with @aContext and @aProp. + * + * It's illegal to call this function outside of a lambda passed to + * CSSVariableImageTable::ReplaceAll(). + */ +inline void +Add(nsStyleContext* aContext, nsCSSProperty aProp, css::ImageValue* aValue) +{ + MOZ_ASSERT(aValue); + MOZ_ASSERT(aContext); + MOZ_ASSERT(detail::IsReplacing()); + + auto& imageTable = detail::GetTable(); + + // Ensure there's a per-property image table for this style context. + auto* perPropertyImageTable = imageTable.Get(aContext); + if (!perPropertyImageTable) { + perPropertyImageTable = new detail::PerPropertyImageHashtable(); + imageTable.Put(aContext, perPropertyImageTable); + } + + // Ensure there's an image array for this property. + auto* imageList = perPropertyImageTable->Get(aProp); + if (!imageList) { + imageList = new detail::ImageValueArray(); + perPropertyImageTable->Put(aProp, imageList); + } + + // Append the provided ImageValue to the list. + imageList->AppendElement(aValue); +} + +/** + * Removes all ImageValues stored in the CSSVariableImageTable for the provided + * @aContext. + */ +inline void +RemoveAll(nsStyleContext* aContext) +{ + // Move all ImageValue references into removedImageList so that we can + // release them outside of any hashtable methods. (If we just call + // Remove(aContext) on the table then we can end up calling back + // re-entrantly into hashtable methods, as other style contexts + // are released.) + detail::ImageValueArray removedImages; + auto& imageTable = detail::GetTable(); + auto* perPropertyImageTable = imageTable.Get(aContext); + if (perPropertyImageTable) { + for (auto it = perPropertyImageTable->Iter(); !it.Done(); it.Next()) { + auto* imageList = it.UserData(); + removedImages.AppendElements(Move(*imageList)); + } + } + imageTable.Remove(aContext); +} + +} // namespace CSSVariableImageTable +} // namespace mozilla + +#endif // mozilla_CSSVariableImageTable_h diff --git a/layout/style/StyleAnimationValue.cpp b/layout/style/StyleAnimationValue.cpp index bee9df76af..db94f7e72a 100644 --- a/layout/style/StyleAnimationValue.cpp +++ b/layout/style/StyleAnimationValue.cpp @@ -1,4 +1,5 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -282,7 +283,8 @@ AppendCSSShadowValue(const nsCSSShadowItem *aShadow, // Like nsStyleCoord::CalcValue, but with length in float pixels instead // of nscoord. -struct PixelCalcValue { +struct PixelCalcValue +{ float mLength, mPercent; bool mHasPercent; }; @@ -3622,12 +3624,14 @@ StyleAnimationValue::GetScaleValue(const nsIFrame* aForFrame) const MOZ_ASSERT(list->mHead); RuleNodeCacheConditions dontCare; + bool dontCareBool; nsStyleTransformMatrix::TransformReferenceBox refBox(aForFrame); Matrix4x4 transform = nsStyleTransformMatrix::ReadTransforms( list->mHead, aForFrame->StyleContext(), aForFrame->PresContext(), dontCare, refBox, - aForFrame->PresContext()->AppUnitsPerDevPixel()); + aForFrame->PresContext()->AppUnitsPerDevPixel(), + &dontCareBool); Matrix transform2d; bool canDraw2D = transform.CanDraw2D(&transform2d); @@ -3856,11 +3860,11 @@ void StyleAnimationValue::SetAndAdoptCSSValueTripletValue( nsCSSValueTriplet *aValueTriplet, Unit aUnit) { - FreeValue(); - MOZ_ASSERT(IsCSSValueTripletUnit(aUnit), "bad unit"); - MOZ_ASSERT(aValueTriplet != nullptr, "value pairs may not be null"); - mUnit = aUnit; - mValue.mCSSValueTriplet = aValueTriplet; // take ownership + FreeValue(); + MOZ_ASSERT(IsCSSValueTripletUnit(aUnit), "bad unit"); + MOZ_ASSERT(aValueTriplet != nullptr, "value pairs may not be null"); + mUnit = aUnit; + mValue.mCSSValueTriplet = aValueTriplet; // take ownership } void diff --git a/layout/style/nsCSSDataBlock.cpp b/layout/style/nsCSSDataBlock.cpp index 8655d8f497..6431c745cc 100644 --- a/layout/style/nsCSSDataBlock.cpp +++ b/layout/style/nsCSSDataBlock.cpp @@ -1,4 +1,5 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -10,8 +11,10 @@ #include "nsCSSDataBlock.h" +#include "CSSVariableImageTable.h" #include "mozilla/css/Declaration.h" #include "mozilla/css/ImageLoader.h" +#include "mozilla/Maybe.h" #include "mozilla/MemoryReporting.h" #include "mozilla/WritingModes.h" #include "nsIDocument.h" @@ -20,6 +23,7 @@ #include "nsStyleSet.h" using namespace mozilla; +using namespace mozilla::css; /** * Does a fast move of aSource to aDest. The previous value in @@ -30,19 +34,63 @@ using namespace mozilla; static bool MoveValue(nsCSSValue* aSource, nsCSSValue* aDest) { - bool changed = (*aSource != *aDest); - aDest->~nsCSSValue(); - memcpy(aDest, aSource, sizeof(nsCSSValue)); - new (aSource) nsCSSValue(); - return changed; + bool changed = (*aSource != *aDest); + aDest->~nsCSSValue(); + memcpy(aDest, aSource, sizeof(nsCSSValue)); + new (aSource) nsCSSValue(); + return changed; +} + +/** + * This function maps "-webkit-box-orient" values to "flex-direction" values, + * for a given writing-mode (taken from aRuleData). + * + * Specifically: + * - If aBoxOrientVal is an enumerated value (representing a physical axis), + * then we'll map it to the appropriate logical "flex-direction" value, using + * the writing mode. The converted value will be emplace()'d into in the + * outparam aConvertedValStorage, and we'll return a pointer to that value. + * - Otherwise (e.g. if we have "inherit" or "initial"), we won't do any + * mapping, and we'll directly return the passed-in aBoxOrientVal. + * + * Either way, the idea is that our caller can treat the returned value as if + * it were a value for "flex-direction". + */ +static const nsCSSValue* +ConvertBoxOrientToFlexDirection(const nsCSSValue* aBoxOrientVal, + const nsRuleData* aRuleData, + Maybe& aConvertedValStorage) +{ + MOZ_ASSERT(aBoxOrientVal, "expecting a non-null value to convert"); + MOZ_ASSERT(aConvertedValStorage.isNothing(), + "expecting outparam for converted-value to be initially empty"); + + if (aBoxOrientVal->GetUnit() != eCSSUnit_Enumerated) { + // We probably have "inherit" or "initial" -- just return that & have the + // caller directly use it as a "flex-direction" value. + return aBoxOrientVal; + } + + // OK, we have an enumerated value -- "horizontal" or "vertical". + + WritingMode wm(aRuleData->mStyleContext); + // In a horizontal writing-mode, "horizontal" maps to "row". + // In a vertical writing-mode, "horizontal" maps to "column". + bool isRow = wm.IsVertical() != + (aBoxOrientVal->GetIntValue() == NS_STYLE_BOX_ORIENT_HORIZONTAL); + + aConvertedValStorage.emplace(isRow ? NS_STYLE_FLEX_DIRECTION_ROW : + NS_STYLE_FLEX_DIRECTION_COLUMN, + eCSSUnit_Enumerated); + return aConvertedValStorage.ptr(); } static bool ShouldIgnoreColors(nsRuleData *aRuleData) { - return aRuleData->mLevel != SheetType::Agent && - aRuleData->mLevel != SheetType::User && - !aRuleData->mPresContext->UseDocumentColors(); + return aRuleData->mLevel != SheetType::Agent && + aRuleData->mLevel != SheetType::User && + !aRuleData->mPresContext->UseDocumentColors(); } /** @@ -51,14 +99,16 @@ ShouldIgnoreColors(nsRuleData *aRuleData) */ static void TryToStartImageLoadOnValue(const nsCSSValue& aValue, nsIDocument* aDocument, - nsCSSValueTokenStream* aTokenStream) + nsStyleContext* aContext, nsCSSProperty aProperty, + bool aForTokenStream) { MOZ_ASSERT(aDocument); if (aValue.GetUnit() == eCSSUnit_URL) { aValue.StartImageLoad(aDocument); - if (aTokenStream) { - aTokenStream->mImageValues.PutEntry(aValue.GetImageStructValue()); + if (aForTokenStream && aContext) { + CSSVariableImageTable::Add(aContext, aProperty, + aValue.GetImageStructValue()); } } else if (aValue.GetUnit() == eCSSUnit_Image) { @@ -66,10 +116,10 @@ TryToStartImageLoadOnValue(const nsCSSValue& aValue, nsIDocument* aDocument, imgIRequest* request = aValue.GetImageValue(nullptr); if (request) { - mozilla::css::ImageValue* imageValue = aValue.GetImageStructValue(); + ImageValue* imageValue = aValue.GetImageStructValue(); aDocument->StyleImageLoader()->MaybeRegisterCSSImage(imageValue); - if (aTokenStream) { - aTokenStream->mImageValues.PutEntry(imageValue); + if (aForTokenStream && aContext) { + CSSVariableImageTable::Add(aContext, aProperty, imageValue); } } } @@ -78,27 +128,30 @@ TryToStartImageLoadOnValue(const nsCSSValue& aValue, nsIDocument* aDocument, MOZ_ASSERT(arguments->Count() == 6, "unexpected num of arguments"); const nsCSSValue& image = arguments->Item(1); - TryToStartImageLoadOnValue(image, aDocument, aTokenStream); + TryToStartImageLoadOnValue(image, aDocument, aContext, aProperty, + aForTokenStream); } } static void TryToStartImageLoad(const nsCSSValue& aValue, nsIDocument* aDocument, - nsCSSProperty aProperty, - nsCSSValueTokenStream* aTokenStream) + nsStyleContext* aContext, nsCSSProperty aProperty, + bool aForTokenStream) { if (aValue.GetUnit() == eCSSUnit_List) { for (const nsCSSValueList* l = aValue.GetListValue(); l; l = l->mNext) { - TryToStartImageLoad(l->mValue, aDocument, aProperty, aTokenStream); + TryToStartImageLoad(l->mValue, aDocument, aContext, aProperty, + aForTokenStream); } } else if (nsCSSProps::PropHasFlags(aProperty, CSS_PROPERTY_IMAGE_IS_IN_ARRAY_0)) { if (aValue.GetUnit() == eCSSUnit_Array) { TryToStartImageLoadOnValue(aValue.GetArrayValue()->Item(0), aDocument, - aTokenStream); + aContext, aProperty, aForTokenStream); } } else { - TryToStartImageLoadOnValue(aValue, aDocument, aTokenStream); + TryToStartImageLoadOnValue(aValue, aDocument, aContext, aProperty, + aForTokenStream); } } @@ -117,62 +170,84 @@ ShouldStartImageLoads(nsRuleData *aRuleData, nsCSSProperty aProperty) } static void -MapSinglePropertyInto(nsCSSProperty aProp, - const nsCSSValue* aValue, - nsCSSValue* aTarget, +MapSinglePropertyInto(nsCSSProperty aSrcProp, + const nsCSSValue* aSrcValue, + nsCSSProperty aTargetProp, + nsCSSValue* aTargetValue, nsRuleData* aRuleData) { - MOZ_ASSERT(aValue->GetUnit() != eCSSUnit_Null, "oops"); + MOZ_ASSERT(!nsCSSProps::PropHasFlags(aTargetProp, CSS_PROPERTY_LOGICAL), + "Can't map into a logical property"); + MOZ_ASSERT(aSrcProp == aTargetProp || + nsCSSProps::PropHasFlags(aSrcProp, CSS_PROPERTY_LOGICAL), + "Source & target property must be the same, except when we're " + "doing a logical-to-physical property mapping"); + MOZ_ASSERT(aSrcValue->GetUnit() != eCSSUnit_Null, "oops"); - // Although aTarget is the nsCSSValue we are going to write into, - // we also look at its value before writing into it. This is done - // when aTarget is a token stream value, which is the case when we - // have just re-parsed a property that had a variable reference (in - // nsCSSParser::ParsePropertyWithVariableReferences). TryToStartImageLoad - // then records any resulting ImageValue objects on the - // nsCSSValueTokenStream object we found on aTarget. See the comment - // above nsCSSValueTokenStream::mImageValues for why. - MOZ_ASSERT(aTarget->GetUnit() == eCSSUnit_TokenStream || - aTarget->GetUnit() == eCSSUnit_Null, - "aTarget must only be a token stream (when re-parsing " - "properties with variable references) or null"); - - nsCSSValueTokenStream* tokenStream = - aTarget->GetUnit() == eCSSUnit_TokenStream ? - aTarget->GetTokenStreamValue() : - nullptr; - - if (ShouldStartImageLoads(aRuleData, aProp)) { - nsIDocument* doc = aRuleData->mPresContext->Document(); - TryToStartImageLoad(*aValue, doc, aProp, tokenStream); + // Handle logical properties that have custom value-mapping behavior: + Maybe convertedVal; // storage for converted value, if needed + bool hasCustomValMapping = + nsCSSProps::PropHasFlags(aSrcProp, + CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING); + if (hasCustomValMapping) { + if (aSrcProp == eCSSProperty_webkit_box_orient) { + aSrcValue = ConvertBoxOrientToFlexDirection(aSrcValue, aRuleData, + convertedVal); } - *aTarget = *aValue; - if (nsCSSProps::PropHasFlags(aProp, - CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED) && - ShouldIgnoreColors(aRuleData)) - { - if (aProp == eCSSProperty_background_color) { - // Force non-'transparent' background - // colors to the user's default. - if (aTarget->IsNonTransparentColor()) { - aTarget->SetColorValue(aRuleData->mPresContext-> - DefaultBackgroundColor()); - } - } else { - // Ignore 'color', 'border-*-color', etc. - *aTarget = nsCSSValue(); - } + } + + // Although aTargetValue is the nsCSSValue we are going to write into, + // we also look at its value before writing into it. This is done + // when aTargetValue is a token stream value, which is the case when we + // have just re-parsed a property that had a variable reference (in + // nsCSSParser::ParsePropertyWithVariableReferences). TryToStartImageLoad + // then records any resulting ImageValue objects in the + // CSSVariableImageTable, to give them the appropriate lifetime. + MOZ_ASSERT(aTargetValue->GetUnit() == eCSSUnit_TokenStream || + aTargetValue->GetUnit() == eCSSUnit_Null, + "aTargetValue must only be a token stream (when re-parsing " + "properties with variable references) or null"); + + if (ShouldStartImageLoads(aRuleData, aTargetProp)) { + nsIDocument* doc = aRuleData->mPresContext->Document(); + TryToStartImageLoad(*aSrcValue, doc, aRuleData->mStyleContext, + aTargetProp, + aTargetValue->GetUnit() == eCSSUnit_TokenStream); + } + *aTargetValue = *aSrcValue; + if (nsCSSProps::PropHasFlags(aTargetProp, + CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED) && + ShouldIgnoreColors(aRuleData)) + { + if (aTargetProp == eCSSProperty_background_color) { + // Force non-'transparent' background + // colors to the user's default. + if (aTargetValue->IsNonTransparentColor()) { + aTargetValue->SetColorValue(aRuleData->mPresContext-> + DefaultBackgroundColor()); + } + } else { + // Ignore 'color', 'border-*-color', etc. + *aTargetValue = nsCSSValue(); } + } } /** - * If aProperty is a logical property, converts it to the equivalent physical + * If aProperty is a logical property, returns the equivalent physical * property based on writing mode information obtained from aRuleData's * style context. */ -static inline void -EnsurePhysicalProperty(nsCSSProperty& aProperty, nsRuleData* aRuleData) +static inline nsCSSProperty +EnsurePhysicalProperty(nsCSSProperty aProperty, nsRuleData* aRuleData) { + if (!nsCSSProps::PropHasFlags(aProperty, CSS_PROPERTY_LOGICAL)) { + return aProperty; + } + + bool isSingleProperty = + nsCSSProps::PropHasFlags(aProperty, + CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING); bool isAxisProperty = nsCSSProps::PropHasFlags(aProperty, CSS_PROPERTY_LOGICAL_AXIS); bool isBlock = @@ -180,7 +255,9 @@ EnsurePhysicalProperty(nsCSSProperty& aProperty, nsRuleData* aRuleData) int index; - if (isAxisProperty) { + if (isSingleProperty) { + index = 0; // We always map to the same physical property. + } else if (isAxisProperty) { LogicalAxis logicalAxis = isBlock ? eLogicalAxisBlock : eLogicalAxisInline; uint8_t wm = aRuleData->mStyleContext->StyleVisibility()->mWritingMode; PhysicalAxis axis = @@ -220,7 +297,8 @@ EnsurePhysicalProperty(nsCSSProperty& aProperty, nsRuleData* aRuleData) const nsCSSProperty* props = nsCSSProps::LogicalGroup(aProperty); #ifdef DEBUG { - size_t len = isAxisProperty ? 2 : 4; + // Table-length is 1 for single prop, 2 for axis prop, 4 for block prop. + size_t len = isSingleProperty ? 1 : (isAxisProperty ? 2 : 4); for (size_t i = 0; i < len; i++) { MOZ_ASSERT(props[i] != eCSSProperty_UNKNOWN, "unexpected logical group length"); @@ -229,73 +307,75 @@ EnsurePhysicalProperty(nsCSSProperty& aProperty, nsRuleData* aRuleData) "unexpected logical group length"); } #endif - aProperty = props[index]; + return props[index]; } void nsCSSCompressedDataBlock::MapRuleInfoInto(nsRuleData *aRuleData) const { - // If we have no data for these structs, then return immediately. - // This optimization should make us return most of the time, so we - // have to worry much less (although still some) about the speed of - // the rest of the function. - if (!(aRuleData->mSIDs & mStyleBits)) - return; + // If we have no data for these structs, then return immediately. + // This optimization should make us return most of the time, so we + // have to worry much less (although still some) about the speed of + // the rest of the function. + if (!(aRuleData->mSIDs & mStyleBits)) + return; - // We process these in reverse order so that we end up mapping the - // right property when one can be expressed using both logical and - // physical property names. - for (uint32_t i = mNumProps; i-- > 0; ) { - nsCSSProperty iProp = PropertyAtIndex(i); - if (nsCachedStyleData::GetBitForSID(nsCSSProps::kSIDTable[iProp]) & - aRuleData->mSIDs) { - if (nsCSSProps::PropHasFlags(iProp, CSS_PROPERTY_LOGICAL)) { - EnsurePhysicalProperty(iProp, aRuleData); - // We can't cache anything on the rule tree if we use any data from - // the style context, since data cached in the rule tree could be - // used with a style context with a different value. - uint8_t wm = WritingMode(aRuleData->mStyleContext).GetBits(); - aRuleData->mConditions.SetWritingModeDependency(wm); - } - nsCSSValue* target = aRuleData->ValueFor(iProp); - if (target->GetUnit() == eCSSUnit_Null) { - const nsCSSValue *val = ValueAtIndex(i); - // In order for variable resolution to have the right information - // about the stylesheet level of a value, that level needs to be - // stored on the token stream. We can't do that at creation time - // because the CSS parser (which creates the object) has no idea - // about the stylesheet level, so we do it here instead, where - // the rule walking will have just updated aRuleData. - if (val->GetUnit() == eCSSUnit_TokenStream) { - val->GetTokenStreamValue()->mLevel = aRuleData->mLevel; - } - MapSinglePropertyInto(iProp, val, target, aRuleData); - } + // We process these in reverse order so that we end up mapping the + // right property when one can be expressed using both logical and + // physical property names. + for (uint32_t i = mNumProps; i-- > 0; ) { + nsCSSProperty iProp = PropertyAtIndex(i); + if (nsCachedStyleData::GetBitForSID(nsCSSProps::kSIDTable[iProp]) & + aRuleData->mSIDs) { + nsCSSProperty physicalProp = EnsurePhysicalProperty(iProp, + aRuleData); + if (physicalProp != iProp) { + // We can't cache anything on the rule tree if we use any data from + // the style context, since data cached in the rule tree could be + // used with a style context with a different value. + uint8_t wm = WritingMode(aRuleData->mStyleContext).GetBits(); + aRuleData->mConditions.SetWritingModeDependency(wm); + } + nsCSSValue* target = aRuleData->ValueFor(physicalProp); + if (target->GetUnit() == eCSSUnit_Null) { + const nsCSSValue *val = ValueAtIndex(i); + // In order for variable resolution to have the right information + // about the stylesheet level of a value, that level needs to be + // stored on the token stream. We can't do that at creation time + // because the CSS parser (which creates the object) has no idea + // about the stylesheet level, so we do it here instead, where + // the rule walking will have just updated aRuleData. + if (val->GetUnit() == eCSSUnit_TokenStream) { + val->GetTokenStreamValue()->mLevel = aRuleData->mLevel; } + MapSinglePropertyInto(iProp, val, physicalProp, target, + aRuleData); + } } + } } const nsCSSValue* nsCSSCompressedDataBlock::ValueFor(nsCSSProperty aProperty) const { - MOZ_ASSERT(!nsCSSProps::IsShorthand(aProperty), - "Don't call for shorthands"); - - // If we have no data for this struct, then return immediately. - // This optimization should make us return most of the time, so we - // have to worry much less (although still some) about the speed of - // the rest of the function. - if (!(nsCachedStyleData::GetBitForSID(nsCSSProps::kSIDTable[aProperty]) & - mStyleBits)) - return nullptr; - - for (uint32_t i = 0; i < mNumProps; i++) { - if (PropertyAtIndex(i) == aProperty) { - return ValueAtIndex(i); - } - } + MOZ_ASSERT(!nsCSSProps::IsShorthand(aProperty), + "Don't call for shorthands"); + // If we have no data for this struct, then return immediately. + // This optimization should make us return most of the time, so we + // have to worry much less (although still some) about the speed of + // the rest of the function. + if (!(nsCachedStyleData::GetBitForSID(nsCSSProps::kSIDTable[aProperty]) & + mStyleBits)) return nullptr; + + for (uint32_t i = 0; i < mNumProps; i++) { + if (PropertyAtIndex(i) == aProperty) { + return ValueAtIndex(i); + } + } + + return nullptr; } bool @@ -303,64 +383,64 @@ nsCSSCompressedDataBlock::TryReplaceValue(nsCSSProperty aProperty, nsCSSExpandedDataBlock& aFromBlock, bool *aChanged) { - nsCSSValue* newValue = aFromBlock.PropertyAt(aProperty); - MOZ_ASSERT(newValue && newValue->GetUnit() != eCSSUnit_Null, - "cannot replace with empty value"); + nsCSSValue* newValue = aFromBlock.PropertyAt(aProperty); + MOZ_ASSERT(newValue && newValue->GetUnit() != eCSSUnit_Null, + "cannot replace with empty value"); - const nsCSSValue* oldValue = ValueFor(aProperty); - if (!oldValue) { - *aChanged = false; - return false; - } + const nsCSSValue* oldValue = ValueFor(aProperty); + if (!oldValue) { + *aChanged = false; + return false; + } - *aChanged = MoveValue(newValue, const_cast(oldValue)); - aFromBlock.ClearPropertyBit(aProperty); - return true; + *aChanged = MoveValue(newValue, const_cast(oldValue)); + aFromBlock.ClearPropertyBit(aProperty); + return true; } nsCSSCompressedDataBlock* nsCSSCompressedDataBlock::Clone() const { - nsAutoPtr - result(new(mNumProps) nsCSSCompressedDataBlock(mNumProps)); + nsAutoPtr + result(new(mNumProps) nsCSSCompressedDataBlock(mNumProps)); - result->mStyleBits = mStyleBits; + result->mStyleBits = mStyleBits; - for (uint32_t i = 0; i < mNumProps; i++) { - result->SetPropertyAtIndex(i, PropertyAtIndex(i)); - result->CopyValueToIndex(i, ValueAtIndex(i)); - } + for (uint32_t i = 0; i < mNumProps; i++) { + result->SetPropertyAtIndex(i, PropertyAtIndex(i)); + result->CopyValueToIndex(i, ValueAtIndex(i)); + } - return result.forget(); + return result.forget(); } nsCSSCompressedDataBlock::~nsCSSCompressedDataBlock() { - for (uint32_t i = 0; i < mNumProps; i++) { + for (uint32_t i = 0; i < mNumProps; i++) { #ifdef DEBUG - (void)PropertyAtIndex(i); // this checks the property is in range + (void)PropertyAtIndex(i); // this checks the property is in range #endif - const nsCSSValue* val = ValueAtIndex(i); - MOZ_ASSERT(val->GetUnit() != eCSSUnit_Null, "oops"); - val->~nsCSSValue(); - } + const nsCSSValue* val = ValueAtIndex(i); + MOZ_ASSERT(val->GetUnit() != eCSSUnit_Null, "oops"); + val->~nsCSSValue(); + } } /* static */ nsCSSCompressedDataBlock* nsCSSCompressedDataBlock::CreateEmptyBlock() { - nsCSSCompressedDataBlock *result = new(0) nsCSSCompressedDataBlock(0); - return result; + nsCSSCompressedDataBlock *result = new(0) nsCSSCompressedDataBlock(0); + return result; } size_t nsCSSCompressedDataBlock::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { - size_t n = aMallocSizeOf(this); - for (uint32_t i = 0; i < mNumProps; i++) { - n += ValueAtIndex(i)->SizeOfExcludingThis(aMallocSizeOf); - } - return n; + size_t n = aMallocSizeOf(this); + for (uint32_t i = 0; i < mNumProps; i++) { + n += ValueAtIndex(i)->SizeOfExcludingThis(aMallocSizeOf); + } + return n; } bool @@ -402,84 +482,84 @@ nsCSSCompressedDataBlock::HasDefaultBorderImageRepeat() const nsCSSExpandedDataBlock::nsCSSExpandedDataBlock() { - AssertInitialState(); + AssertInitialState(); } nsCSSExpandedDataBlock::~nsCSSExpandedDataBlock() { - AssertInitialState(); + AssertInitialState(); } void nsCSSExpandedDataBlock::DoExpand(nsCSSCompressedDataBlock *aBlock, bool aImportant) { - /* - * Save needless copying and allocation by copying the memory - * corresponding to the stored data in the compressed block. - */ - for (uint32_t i = 0; i < aBlock->mNumProps; i++) { - nsCSSProperty iProp = aBlock->PropertyAtIndex(i); - MOZ_ASSERT(!nsCSSProps::IsShorthand(iProp), "out of range"); - MOZ_ASSERT(!HasPropertyBit(iProp), - "compressed block has property multiple times"); - SetPropertyBit(iProp); - if (aImportant) - SetImportantBit(iProp); + /* + * Save needless copying and allocation by copying the memory + * corresponding to the stored data in the compressed block. + */ + for (uint32_t i = 0; i < aBlock->mNumProps; i++) { + nsCSSProperty iProp = aBlock->PropertyAtIndex(i); + MOZ_ASSERT(!nsCSSProps::IsShorthand(iProp), "out of range"); + MOZ_ASSERT(!HasPropertyBit(iProp), + "compressed block has property multiple times"); + SetPropertyBit(iProp); + if (aImportant) + SetImportantBit(iProp); - const nsCSSValue* val = aBlock->ValueAtIndex(i); - nsCSSValue* dest = PropertyAt(iProp); - MOZ_ASSERT(val->GetUnit() != eCSSUnit_Null, "oops"); - MOZ_ASSERT(dest->GetUnit() == eCSSUnit_Null, - "expanding into non-empty block"); + const nsCSSValue* val = aBlock->ValueAtIndex(i); + nsCSSValue* dest = PropertyAt(iProp); + MOZ_ASSERT(val->GetUnit() != eCSSUnit_Null, "oops"); + MOZ_ASSERT(dest->GetUnit() == eCSSUnit_Null, + "expanding into non-empty block"); #ifdef NS_BUILD_REFCNT_LOGGING - dest->~nsCSSValue(); + dest->~nsCSSValue(); #endif - memcpy(dest, val, sizeof(nsCSSValue)); - } + memcpy(dest, val, sizeof(nsCSSValue)); + } - // Set the number of properties to zero so that we don't destroy the - // remnants of what we just copied. - aBlock->SetNumPropsToZero(); - delete aBlock; + // Set the number of properties to zero so that we don't destroy the + // remnants of what we just copied. + aBlock->SetNumPropsToZero(); + delete aBlock; } void nsCSSExpandedDataBlock::Expand(nsCSSCompressedDataBlock *aNormalBlock, nsCSSCompressedDataBlock *aImportantBlock) { - MOZ_ASSERT(aNormalBlock, "unexpected null block"); - AssertInitialState(); + MOZ_ASSERT(aNormalBlock, "unexpected null block"); + AssertInitialState(); - DoExpand(aNormalBlock, false); - if (aImportantBlock) { - DoExpand(aImportantBlock, true); - } + DoExpand(aNormalBlock, false); + if (aImportantBlock) { + DoExpand(aImportantBlock, true); + } } void nsCSSExpandedDataBlock::ComputeNumProps(uint32_t* aNumPropsNormal, uint32_t* aNumPropsImportant) { - *aNumPropsNormal = *aNumPropsImportant = 0; - for (size_t iHigh = 0; iHigh < nsCSSPropertySet::kChunkCount; ++iHigh) { - if (!mPropertiesSet.HasPropertyInChunk(iHigh)) - continue; - for (size_t iLow = 0; iLow < nsCSSPropertySet::kBitsInChunk; ++iLow) { - if (!mPropertiesSet.HasPropertyAt(iHigh, iLow)) - continue; + *aNumPropsNormal = *aNumPropsImportant = 0; + for (size_t iHigh = 0; iHigh < nsCSSPropertySet::kChunkCount; ++iHigh) { + if (!mPropertiesSet.HasPropertyInChunk(iHigh)) + continue; + for (size_t iLow = 0; iLow < nsCSSPropertySet::kBitsInChunk; ++iLow) { + if (!mPropertiesSet.HasPropertyAt(iHigh, iLow)) + continue; #ifdef DEBUG - nsCSSProperty iProp = nsCSSPropertySet::CSSPropertyAt(iHigh, iLow); + nsCSSProperty iProp = nsCSSPropertySet::CSSPropertyAt(iHigh, iLow); #endif - MOZ_ASSERT(!nsCSSProps::IsShorthand(iProp), "out of range"); - MOZ_ASSERT(PropertyAt(iProp)->GetUnit() != eCSSUnit_Null, - "null value while computing size"); - if (mPropertiesImportant.HasPropertyAt(iHigh, iLow)) - (*aNumPropsImportant)++; - else - (*aNumPropsNormal)++; - } + MOZ_ASSERT(!nsCSSProps::IsShorthand(iProp), "out of range"); + MOZ_ASSERT(PropertyAt(iProp)->GetUnit() != eCSSUnit_Null, + "null value while computing size"); + if (mPropertiesImportant.HasPropertyAt(iHigh, iLow)) + (*aNumPropsImportant)++; + else + (*aNumPropsNormal)++; } + } } void @@ -487,110 +567,110 @@ nsCSSExpandedDataBlock::Compress(nsCSSCompressedDataBlock **aNormalBlock, nsCSSCompressedDataBlock **aImportantBlock, const nsTArray& aOrder) { - nsAutoPtr result_normal, result_important; - uint32_t i_normal = 0, i_important = 0; + nsAutoPtr result_normal, result_important; + uint32_t i_normal = 0, i_important = 0; - uint32_t numPropsNormal, numPropsImportant; - ComputeNumProps(&numPropsNormal, &numPropsImportant); + uint32_t numPropsNormal, numPropsImportant; + ComputeNumProps(&numPropsNormal, &numPropsImportant); - result_normal = - new(numPropsNormal) nsCSSCompressedDataBlock(numPropsNormal); + result_normal = + new(numPropsNormal) nsCSSCompressedDataBlock(numPropsNormal); - if (numPropsImportant != 0) { - result_important = - new(numPropsImportant) nsCSSCompressedDataBlock(numPropsImportant); - } else { - result_important = nullptr; + if (numPropsImportant != 0) { + result_important = + new(numPropsImportant) nsCSSCompressedDataBlock(numPropsImportant); + } else { + result_important = nullptr; + } + + /* + * Save needless copying and allocation by copying the memory + * corresponding to the stored data in the expanded block, and then + * clearing the data in the expanded block. + */ + for (size_t i = 0; i < aOrder.Length(); i++) { + nsCSSProperty iProp = static_cast(aOrder[i]); + if (iProp >= eCSSProperty_COUNT) { + // a custom property + continue; } + MOZ_ASSERT(mPropertiesSet.HasProperty(iProp), + "aOrder identifies a property not in the expanded " + "data block"); + MOZ_ASSERT(!nsCSSProps::IsShorthand(iProp), "out of range"); + bool important = mPropertiesImportant.HasProperty(iProp); + nsCSSCompressedDataBlock *result = + important ? result_important : result_normal; + uint32_t* ip = important ? &i_important : &i_normal; + nsCSSValue* val = PropertyAt(iProp); + MOZ_ASSERT(val->GetUnit() != eCSSUnit_Null, + "Null value while compressing"); + result->SetPropertyAtIndex(*ip, iProp); + result->RawCopyValueToIndex(*ip, val); + new (val) nsCSSValue(); + (*ip)++; + result->mStyleBits |= + nsCachedStyleData::GetBitForSID(nsCSSProps::kSIDTable[iProp]); + } - /* - * Save needless copying and allocation by copying the memory - * corresponding to the stored data in the expanded block, and then - * clearing the data in the expanded block. - */ - for (size_t i = 0; i < aOrder.Length(); i++) { - nsCSSProperty iProp = static_cast(aOrder[i]); - if (iProp >= eCSSProperty_COUNT) { - // a custom property - continue; - } - MOZ_ASSERT(mPropertiesSet.HasProperty(iProp), - "aOrder identifies a property not in the expanded " - "data block"); - MOZ_ASSERT(!nsCSSProps::IsShorthand(iProp), "out of range"); - bool important = mPropertiesImportant.HasProperty(iProp); - nsCSSCompressedDataBlock *result = - important ? result_important : result_normal; - uint32_t* ip = important ? &i_important : &i_normal; - nsCSSValue* val = PropertyAt(iProp); - MOZ_ASSERT(val->GetUnit() != eCSSUnit_Null, - "Null value while compressing"); - result->SetPropertyAtIndex(*ip, iProp); - result->RawCopyValueToIndex(*ip, val); - new (val) nsCSSValue(); - (*ip)++; - result->mStyleBits |= - nsCachedStyleData::GetBitForSID(nsCSSProps::kSIDTable[iProp]); - } + MOZ_ASSERT(numPropsNormal == i_normal, "bad numProps"); - MOZ_ASSERT(numPropsNormal == i_normal, "bad numProps"); - - if (result_important) { - MOZ_ASSERT(numPropsImportant == i_important, "bad numProps"); - } + if (result_important) { + MOZ_ASSERT(numPropsImportant == i_important, "bad numProps"); + } #ifdef DEBUG - { - // assert that we didn't have any other properties on this expanded data - // block that we didn't find in aOrder - uint32_t numPropsInSet = 0; - for (size_t iHigh = 0; iHigh < nsCSSPropertySet::kChunkCount; iHigh++) { - if (!mPropertiesSet.HasPropertyInChunk(iHigh)) { - continue; - } - for (size_t iLow = 0; iLow < nsCSSPropertySet::kBitsInChunk; iLow++) { - if (mPropertiesSet.HasPropertyAt(iHigh, iLow)) { - numPropsInSet++; - } - } + { + // assert that we didn't have any other properties on this expanded data + // block that we didn't find in aOrder + uint32_t numPropsInSet = 0; + for (size_t iHigh = 0; iHigh < nsCSSPropertySet::kChunkCount; iHigh++) { + if (!mPropertiesSet.HasPropertyInChunk(iHigh)) { + continue; + } + for (size_t iLow = 0; iLow < nsCSSPropertySet::kBitsInChunk; iLow++) { + if (mPropertiesSet.HasPropertyAt(iHigh, iLow)) { + numPropsInSet++; + } } - MOZ_ASSERT(numPropsNormal + numPropsImportant == numPropsInSet, - "aOrder missing properties from the expanded data block"); } + MOZ_ASSERT(numPropsNormal + numPropsImportant == numPropsInSet, + "aOrder missing properties from the expanded data block"); + } #endif - ClearSets(); - AssertInitialState(); - *aNormalBlock = result_normal.forget(); - *aImportantBlock = result_important.forget(); + ClearSets(); + AssertInitialState(); + *aNormalBlock = result_normal.forget(); + *aImportantBlock = result_important.forget(); } void nsCSSExpandedDataBlock::AddLonghandProperty(nsCSSProperty aProperty, const nsCSSValue& aValue) { - MOZ_ASSERT(!nsCSSProps::IsShorthand(aProperty), - "property out of range"); - nsCSSValue& storage = *static_cast(PropertyAt(aProperty)); - storage = aValue; - SetPropertyBit(aProperty); + MOZ_ASSERT(!nsCSSProps::IsShorthand(aProperty), + "property out of range"); + nsCSSValue& storage = *static_cast(PropertyAt(aProperty)); + storage = aValue; + SetPropertyBit(aProperty); } void nsCSSExpandedDataBlock::Clear() { - for (size_t iHigh = 0; iHigh < nsCSSPropertySet::kChunkCount; ++iHigh) { - if (!mPropertiesSet.HasPropertyInChunk(iHigh)) - continue; - for (size_t iLow = 0; iLow < nsCSSPropertySet::kBitsInChunk; ++iLow) { - if (!mPropertiesSet.HasPropertyAt(iHigh, iLow)) - continue; - nsCSSProperty iProp = nsCSSPropertySet::CSSPropertyAt(iHigh, iLow); - ClearLonghandProperty(iProp); - } + for (size_t iHigh = 0; iHigh < nsCSSPropertySet::kChunkCount; ++iHigh) { + if (!mPropertiesSet.HasPropertyInChunk(iHigh)) + continue; + for (size_t iLow = 0; iLow < nsCSSPropertySet::kBitsInChunk; ++iLow) { + if (!mPropertiesSet.HasPropertyAt(iHigh, iLow)) + continue; + nsCSSProperty iProp = nsCSSPropertySet::CSSPropertyAt(iHigh, iLow); + ClearLonghandProperty(iProp); } + } - AssertInitialState(); + AssertInitialState(); } void @@ -609,11 +689,11 @@ nsCSSExpandedDataBlock::ClearProperty(nsCSSProperty aPropID) void nsCSSExpandedDataBlock::ClearLonghandProperty(nsCSSProperty aPropID) { - MOZ_ASSERT(!nsCSSProps::IsShorthand(aPropID), "out of range"); + MOZ_ASSERT(!nsCSSProps::IsShorthand(aPropID), "out of range"); - ClearPropertyBit(aPropID); - ClearImportantBit(aPropID); - PropertyAt(aPropID)->Reset(); + ClearPropertyBit(aPropID); + ClearImportantBit(aPropID); + PropertyAt(aPropID)->Reset(); } bool @@ -626,26 +706,26 @@ nsCSSExpandedDataBlock::TransferFromBlock(nsCSSExpandedDataBlock& aFromBlock, css::Declaration* aDeclaration, nsIDocument* aSheetDocument) { - if (!nsCSSProps::IsShorthand(aPropID)) { - return DoTransferFromBlock(aFromBlock, aPropID, + if (!nsCSSProps::IsShorthand(aPropID)) { + return DoTransferFromBlock(aFromBlock, aPropID, + aIsImportant, aOverrideImportant, + aMustCallValueAppended, aDeclaration, + aSheetDocument); + } + + // We can pass eIgnoreEnabledState (here, and in ClearProperty above) rather + // than a value corresponding to whether we're parsing a UA style sheet or + // certified app because we assert in nsCSSProps::AddRefTable that shorthand + // properties available in these contexts also have all of their + // subproperties available in these contexts. + bool changed = false; + CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aPropID, aEnabledState) { + changed |= DoTransferFromBlock(aFromBlock, *p, aIsImportant, aOverrideImportant, aMustCallValueAppended, aDeclaration, aSheetDocument); - } - - // We can pass eIgnoreEnabledState (here, and in ClearProperty above) rather - // than a value corresponding to whether we're parsing a UA style sheet or - // certified app because we assert in nsCSSProps::AddRefTable that shorthand - // properties available in these contexts also have all of their - // subproperties available in these contexts. - bool changed = false; - CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aPropID, aEnabledState) { - changed |= DoTransferFromBlock(aFromBlock, *p, - aIsImportant, aOverrideImportant, - aMustCallValueAppended, aDeclaration, - aSheetDocument); - } - return changed; + } + return changed; } bool @@ -711,9 +791,8 @@ nsCSSExpandedDataBlock::MapRuleInfoInto(nsCSSProperty aPropID, const nsCSSValue* src = PropertyAt(aPropID); MOZ_ASSERT(src->GetUnit() != eCSSUnit_Null); - nsCSSProperty physicalProp = aPropID; - if (nsCSSProps::PropHasFlags(aPropID, CSS_PROPERTY_LOGICAL)) { - EnsurePhysicalProperty(physicalProp, aRuleData); + nsCSSProperty physicalProp = EnsurePhysicalProperty(aPropID, aRuleData); + if (physicalProp != aPropID) { uint8_t wm = WritingMode(aRuleData->mStyleContext).GetBits(); aRuleData->mConditions.SetWritingModeDependency(wm); } @@ -722,20 +801,22 @@ nsCSSExpandedDataBlock::MapRuleInfoInto(nsCSSProperty aPropID, MOZ_ASSERT(dest->GetUnit() == eCSSUnit_TokenStream && dest->GetTokenStreamValue()->mPropertyID == aPropID); - MapSinglePropertyInto(physicalProp, src, dest, aRuleData); + CSSVariableImageTable::ReplaceAll(aRuleData->mStyleContext, aPropID, [=] { + MapSinglePropertyInto(aPropID, src, physicalProp, dest, aRuleData); + }); } #ifdef DEBUG void nsCSSExpandedDataBlock::DoAssertInitialState() { - mPropertiesSet.AssertIsEmpty("not initial state"); - mPropertiesImportant.AssertIsEmpty("not initial state"); + mPropertiesSet.AssertIsEmpty("not initial state"); + mPropertiesImportant.AssertIsEmpty("not initial state"); - for (uint32_t i = 0; i < eCSSProperty_COUNT_no_shorthands; ++i) { - nsCSSProperty prop = nsCSSProperty(i); - MOZ_ASSERT(PropertyAt(prop)->GetUnit() == eCSSUnit_Null, - "not initial state"); - } + for (uint32_t i = 0; i < eCSSProperty_COUNT_no_shorthands; ++i) { + nsCSSProperty prop = nsCSSProperty(i); + MOZ_ASSERT(PropertyAt(prop)->GetUnit() == eCSSUnit_Null, + "not initial state"); + } } #endif diff --git a/layout/style/nsCSSDataBlock.h b/layout/style/nsCSSDataBlock.h index 1e558b56e6..67b53eddbc 100644 --- a/layout/style/nsCSSDataBlock.h +++ b/layout/style/nsCSSDataBlock.h @@ -1,4 +1,5 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -34,137 +35,138 @@ class Declaration; * |css::Declaration|). Mutation is accomplished through * |nsCSSExpandedDataBlock| or in some cases via direct slot access. */ -class nsCSSCompressedDataBlock { +class nsCSSCompressedDataBlock +{ private: - friend class nsCSSExpandedDataBlock; + friend class nsCSSExpandedDataBlock; - // Only this class (via |CreateEmptyBlock|) or nsCSSExpandedDataBlock - // (in |Compress|) can create compressed data blocks. - explicit nsCSSCompressedDataBlock(uint32_t aNumProps) - : mStyleBits(0), mNumProps(aNumProps) - {} + // Only this class (via |CreateEmptyBlock|) or nsCSSExpandedDataBlock + // (in |Compress|) can create compressed data blocks. + explicit nsCSSCompressedDataBlock(uint32_t aNumProps) + : mStyleBits(0), mNumProps(aNumProps) + {} public: - ~nsCSSCompressedDataBlock(); + ~nsCSSCompressedDataBlock(); - /** - * Do what |nsIStyleRule::MapRuleInfoInto| needs to do for a style - * rule using this block for storage. - */ - void MapRuleInfoInto(nsRuleData *aRuleData) const; + /** + * Do what |nsIStyleRule::MapRuleInfoInto| needs to do for a style + * rule using this block for storage. + */ + void MapRuleInfoInto(nsRuleData *aRuleData) const; - /** - * Return the location at which the *value* for the property is - * stored, or null if the block does not contain a value for the - * property. - * - * Inefficient (by design). - * - * Must not be called for shorthands. - */ - const nsCSSValue* ValueFor(nsCSSProperty aProperty) const; + /** + * Return the location at which the *value* for the property is + * stored, or null if the block does not contain a value for the + * property. + * + * Inefficient (by design). + * + * Must not be called for shorthands. + */ + const nsCSSValue* ValueFor(nsCSSProperty aProperty) const; - /** - * Attempt to replace the value for |aProperty| stored in this block - * with the matching value stored in |aFromBlock|. - * This method will fail (returning false) if |aProperty| is not - * already in this block. It will set |aChanged| to true if it - * actually made a change to the block, but regardless, if it - * returns true, the value in |aFromBlock| was erased. - */ - bool TryReplaceValue(nsCSSProperty aProperty, - nsCSSExpandedDataBlock& aFromBlock, - bool* aChanged); + /** + * Attempt to replace the value for |aProperty| stored in this block + * with the matching value stored in |aFromBlock|. + * This method will fail (returning false) if |aProperty| is not + * already in this block. It will set |aChanged| to true if it + * actually made a change to the block, but regardless, if it + * returns true, the value in |aFromBlock| was erased. + */ + bool TryReplaceValue(nsCSSProperty aProperty, + nsCSSExpandedDataBlock& aFromBlock, + bool* aChanged); - /** - * Clone this block, or return null on out-of-memory. - */ - nsCSSCompressedDataBlock* Clone() const; + /** + * Clone this block, or return null on out-of-memory. + */ + nsCSSCompressedDataBlock* Clone() const; - /** - * Create a new nsCSSCompressedDataBlock holding no declarations. - */ - static nsCSSCompressedDataBlock* CreateEmptyBlock(); + /** + * Create a new nsCSSCompressedDataBlock holding no declarations. + */ + static nsCSSCompressedDataBlock* CreateEmptyBlock(); - size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; - bool HasDefaultBorderImageSlice() const; - bool HasDefaultBorderImageWidth() const; - bool HasDefaultBorderImageOutset() const; - bool HasDefaultBorderImageRepeat() const; + bool HasDefaultBorderImageSlice() const; + bool HasDefaultBorderImageWidth() const; + bool HasDefaultBorderImageOutset() const; + bool HasDefaultBorderImageRepeat() const; - bool HasInheritedStyleData() const - { - return mStyleBits & NS_STYLE_INHERITED_STRUCT_MASK; - } + bool HasInheritedStyleData() const + { + return mStyleBits & NS_STYLE_INHERITED_STRUCT_MASK; + } private: - void* operator new(size_t aBaseSize, uint32_t aNumProps) { - MOZ_ASSERT(aBaseSize == sizeof(nsCSSCompressedDataBlock), - "unexpected size for nsCSSCompressedDataBlock"); - return ::operator new(aBaseSize + DataSize(aNumProps)); - } + void* operator new(size_t aBaseSize, uint32_t aNumProps) { + MOZ_ASSERT(aBaseSize == sizeof(nsCSSCompressedDataBlock), + "unexpected size for nsCSSCompressedDataBlock"); + return ::operator new(aBaseSize + DataSize(aNumProps)); + } public: - // Ideally, |nsCSSProperty| would be |enum nsCSSProperty : int16_t|. But - // not all of the compilers we use are modern enough to support small - // enums. So we manually squeeze nsCSSProperty into 16 bits ourselves. - // The static assertion below ensures it fits. - typedef int16_t CompressedCSSProperty; - static const size_t MaxCompressedCSSProperty = INT16_MAX; + // Ideally, |nsCSSProperty| would be |enum nsCSSProperty : int16_t|. But + // not all of the compilers we use are modern enough to support small + // enums. So we manually squeeze nsCSSProperty into 16 bits ourselves. + // The static assertion below ensures it fits. + typedef int16_t CompressedCSSProperty; + static const size_t MaxCompressedCSSProperty = INT16_MAX; private: - static size_t DataSize(uint32_t aNumProps) { - return size_t(aNumProps) * - (sizeof(nsCSSValue) + sizeof(CompressedCSSProperty)); - } + static size_t DataSize(uint32_t aNumProps) { + return size_t(aNumProps) * + (sizeof(nsCSSValue) + sizeof(CompressedCSSProperty)); + } - int32_t mStyleBits; // the structs for which we have data, according to - // |nsCachedStyleData::GetBitForSID|. - uint32_t mNumProps; - // nsCSSValue elements are stored after these fields, and - // nsCSSProperty elements are stored -- each one compressed as a - // CompressedCSSProperty -- after the nsCSSValue elements. Space for them - // is allocated in |operator new| above. The static assertions following - // this class make sure that the value and property elements are aligned - // appropriately. + int32_t mStyleBits; // the structs for which we have data, according to + // |nsCachedStyleData::GetBitForSID|. + uint32_t mNumProps; + // nsCSSValue elements are stored after these fields, and + // nsCSSProperty elements are stored -- each one compressed as a + // CompressedCSSProperty -- after the nsCSSValue elements. Space for them + // is allocated in |operator new| above. The static assertions following + // this class make sure that the value and property elements are aligned + // appropriately. - nsCSSValue* Values() const { - return (nsCSSValue*)(this + 1); - } + nsCSSValue* Values() const { + return (nsCSSValue*)(this + 1); + } - CompressedCSSProperty* CompressedProperties() const { - return (CompressedCSSProperty*)(Values() + mNumProps); - } + CompressedCSSProperty* CompressedProperties() const { + return (CompressedCSSProperty*)(Values() + mNumProps); + } - nsCSSValue* ValueAtIndex(uint32_t i) const { - MOZ_ASSERT(i < mNumProps, "value index out of range"); - return Values() + i; - } + nsCSSValue* ValueAtIndex(uint32_t i) const { + MOZ_ASSERT(i < mNumProps, "value index out of range"); + return Values() + i; + } - nsCSSProperty PropertyAtIndex(uint32_t i) const { - MOZ_ASSERT(i < mNumProps, "property index out of range"); - nsCSSProperty prop = (nsCSSProperty)CompressedProperties()[i]; - MOZ_ASSERT(!nsCSSProps::IsShorthand(prop), "out of range"); - return prop; - } + nsCSSProperty PropertyAtIndex(uint32_t i) const { + MOZ_ASSERT(i < mNumProps, "property index out of range"); + nsCSSProperty prop = (nsCSSProperty)CompressedProperties()[i]; + MOZ_ASSERT(!nsCSSProps::IsShorthand(prop), "out of range"); + return prop; + } - void CopyValueToIndex(uint32_t i, nsCSSValue* aValue) { - new (ValueAtIndex(i)) nsCSSValue(*aValue); - } + void CopyValueToIndex(uint32_t i, nsCSSValue* aValue) { + new (ValueAtIndex(i)) nsCSSValue(*aValue); + } - void RawCopyValueToIndex(uint32_t i, nsCSSValue* aValue) { - memcpy(ValueAtIndex(i), aValue, sizeof(nsCSSValue)); - } + void RawCopyValueToIndex(uint32_t i, nsCSSValue* aValue) { + memcpy(ValueAtIndex(i), aValue, sizeof(nsCSSValue)); + } - void SetPropertyAtIndex(uint32_t i, nsCSSProperty aProperty) { - MOZ_ASSERT(i < mNumProps, "set property index out of range"); - CompressedProperties()[i] = (CompressedCSSProperty)aProperty; - } + void SetPropertyAtIndex(uint32_t i, nsCSSProperty aProperty) { + MOZ_ASSERT(i < mNumProps, "set property index out of range"); + CompressedProperties()[i] = (CompressedCSSProperty)aProperty; + } - void SetNumPropsToZero() { - mNumProps = 0; - } + void SetNumPropsToZero() { + mNumProps = 0; + } }; // Make sure the values and properties are aligned appropriately. (These @@ -172,198 +174,199 @@ private: static_assert(sizeof(nsCSSCompressedDataBlock) == 8, "nsCSSCompressedDataBlock's size has changed"); static_assert(NS_ALIGNMENT_OF(nsCSSValue) == 4 || NS_ALIGNMENT_OF(nsCSSValue) == 8, - "nsCSSValue doesn't align with nsCSSCompressedDataBlock"); + "nsCSSValue doesn't align with nsCSSCompressedDataBlock"); static_assert(NS_ALIGNMENT_OF(nsCSSCompressedDataBlock::CompressedCSSProperty) == 2, - "CompressedCSSProperty doesn't align with nsCSSValue"); + "CompressedCSSProperty doesn't align with nsCSSValue"); // Make sure that sizeof(CompressedCSSProperty) is big enough. static_assert(eCSSProperty_COUNT_no_shorthands <= nsCSSCompressedDataBlock::MaxCompressedCSSProperty, "nsCSSProperty doesn't fit in StoredSizeOfCSSProperty"); -class nsCSSExpandedDataBlock { - friend class nsCSSCompressedDataBlock; +class nsCSSExpandedDataBlock +{ + friend class nsCSSCompressedDataBlock; public: - nsCSSExpandedDataBlock(); - ~nsCSSExpandedDataBlock(); + nsCSSExpandedDataBlock(); + ~nsCSSExpandedDataBlock(); private: - /* Property storage may not be accessed directly; use AddLonghandProperty - * and friends. - */ - nsCSSValue mValues[eCSSProperty_COUNT_no_shorthands]; + /* Property storage may not be accessed directly; use AddLonghandProperty + * and friends. + */ + nsCSSValue mValues[eCSSProperty_COUNT_no_shorthands]; public: - /** - * Transfer all of the state from a pair of compressed data blocks - * to this expanded block. This expanded block must be clear - * beforehand. - * - * This method DELETES both of the compressed data blocks it is - * passed. (This is necessary because ownership of sub-objects - * is transferred to the expanded block.) - */ - void Expand(nsCSSCompressedDataBlock *aNormalBlock, - nsCSSCompressedDataBlock *aImportantBlock); + /** + * Transfer all of the state from a pair of compressed data blocks + * to this expanded block. This expanded block must be clear + * beforehand. + * + * This method DELETES both of the compressed data blocks it is + * passed. (This is necessary because ownership of sub-objects + * is transferred to the expanded block.) + */ + void Expand(nsCSSCompressedDataBlock *aNormalBlock, + nsCSSCompressedDataBlock *aImportantBlock); - /** - * Allocate new compressed blocks and transfer all of the state - * from this expanded block to the new blocks, clearing this - * expanded block. A normal block will always be allocated, but - * an important block will only be allocated if there are - * !important properties in the expanded block; otherwise - * |*aImportantBlock| will be set to null. - * - * aOrder is an array of nsCSSProperty values specifying the order - * to store values in the two data blocks. - */ - void Compress(nsCSSCompressedDataBlock **aNormalBlock, - nsCSSCompressedDataBlock **aImportantBlock, - const nsTArray& aOrder); + /** + * Allocate new compressed blocks and transfer all of the state + * from this expanded block to the new blocks, clearing this + * expanded block. A normal block will always be allocated, but + * an important block will only be allocated if there are + * !important properties in the expanded block; otherwise + * |*aImportantBlock| will be set to null. + * + * aOrder is an array of nsCSSProperty values specifying the order + * to store values in the two data blocks. + */ + void Compress(nsCSSCompressedDataBlock **aNormalBlock, + nsCSSCompressedDataBlock **aImportantBlock, + const nsTArray& aOrder); - /** - * Copy a value into this expanded block. This does NOT destroy - * the source value object. |aProperty| cannot be a shorthand. - */ - void AddLonghandProperty(nsCSSProperty aProperty, const nsCSSValue& aValue); + /** + * Copy a value into this expanded block. This does NOT destroy + * the source value object. |aProperty| cannot be a shorthand. + */ + void AddLonghandProperty(nsCSSProperty aProperty, const nsCSSValue& aValue); - /** - * Clear the state of this expanded block. - */ - void Clear(); + /** + * Clear the state of this expanded block. + */ + void Clear(); - /** - * Clear the data for the given property (including the set and - * important bits). Can be used with shorthand properties. - */ - void ClearProperty(nsCSSProperty aPropID); + /** + * Clear the data for the given property (including the set and + * important bits). Can be used with shorthand properties. + */ + void ClearProperty(nsCSSProperty aPropID); - /** - * Same as ClearProperty, but faster and cannot be used with shorthands. - */ - void ClearLonghandProperty(nsCSSProperty aPropID); + /** + * Same as ClearProperty, but faster and cannot be used with shorthands. + */ + void ClearLonghandProperty(nsCSSProperty aPropID); - /** - * Transfer the state for |aPropID| (which may be a shorthand) - * from |aFromBlock| to this block. The property being transferred - * is !important if |aIsImportant| is true, and should replace an - * existing !important property regardless of its own importance - * if |aOverrideImportant| is true. |aEnabledState| is used to - * determine which longhand components of |aPropID| (if it is a - * shorthand) to transfer. - * - * Returns true if something changed, false otherwise. Calls - * |ValueAppended| on |aDeclaration| if the property was not - * previously set, or in any case if |aMustCallValueAppended| is true. - * Calls |SetDocumentAndPageUseCounter| on |aSheetDocument| if it is - * non-null and |aPropID| has a use counter. - */ - bool TransferFromBlock(nsCSSExpandedDataBlock& aFromBlock, - nsCSSProperty aPropID, - nsCSSProps::EnabledState aEnabledState, - bool aIsImportant, - bool aOverrideImportant, - bool aMustCallValueAppended, - mozilla::css::Declaration* aDeclaration, - nsIDocument* aSheetDocument); + /** + * Transfer the state for |aPropID| (which may be a shorthand) + * from |aFromBlock| to this block. The property being transferred + * is !important if |aIsImportant| is true, and should replace an + * existing !important property regardless of its own importance + * if |aOverrideImportant| is true. |aEnabledState| is used to + * determine which longhand components of |aPropID| (if it is a + * shorthand) to transfer. + * + * Returns true if something changed, false otherwise. Calls + * |ValueAppended| on |aDeclaration| if the property was not + * previously set, or in any case if |aMustCallValueAppended| is true. + * Calls |SetDocumentAndPageUseCounter| on |aSheetDocument| if it is + * non-null and |aPropID| has a use counter. + */ + bool TransferFromBlock(nsCSSExpandedDataBlock& aFromBlock, + nsCSSProperty aPropID, + nsCSSProps::EnabledState aEnabledState, + bool aIsImportant, + bool aOverrideImportant, + bool aMustCallValueAppended, + mozilla::css::Declaration* aDeclaration, + nsIDocument* aSheetDocument); - /** - * Copies the values for aPropID into the specified aRuleData object. - * - * This is used for copying parsed-at-computed-value-time properties - * that had variable references. aPropID must be a longhand property. - */ - void MapRuleInfoInto(nsCSSProperty aPropID, nsRuleData* aRuleData) const; + /** + * Copies the values for aPropID into the specified aRuleData object. + * + * This is used for copying parsed-at-computed-value-time properties + * that had variable references. aPropID must be a longhand property. + */ + void MapRuleInfoInto(nsCSSProperty aPropID, nsRuleData* aRuleData) const; - void AssertInitialState() { + void AssertInitialState() { #ifdef DEBUG - DoAssertInitialState(); + DoAssertInitialState(); #endif - } + } private: - /** - * Compute the number of properties that will be present in the - * result of |Compress|. - */ - void ComputeNumProps(uint32_t* aNumPropsNormal, - uint32_t* aNumPropsImportant); - - void DoExpand(nsCSSCompressedDataBlock *aBlock, bool aImportant); + /** + * Compute the number of properties that will be present in the + * result of |Compress|. + */ + void ComputeNumProps(uint32_t* aNumPropsNormal, + uint32_t* aNumPropsImportant); - /** - * Worker for TransferFromBlock; cannot be used with shorthands. - */ - bool DoTransferFromBlock(nsCSSExpandedDataBlock& aFromBlock, - nsCSSProperty aPropID, - bool aIsImportant, - bool aOverrideImportant, - bool aMustCallValueAppended, - mozilla::css::Declaration* aDeclaration, - nsIDocument* aSheetDocument); + void DoExpand(nsCSSCompressedDataBlock *aBlock, bool aImportant); + + /** + * Worker for TransferFromBlock; cannot be used with shorthands. + */ + bool DoTransferFromBlock(nsCSSExpandedDataBlock& aFromBlock, + nsCSSProperty aPropID, + bool aIsImportant, + bool aOverrideImportant, + bool aMustCallValueAppended, + mozilla::css::Declaration* aDeclaration, + nsIDocument* aSheetDocument); #ifdef DEBUG - void DoAssertInitialState(); + void DoAssertInitialState(); #endif - /* - * mPropertiesSet stores a bit for every property that is present, - * to optimize compression of blocks with small numbers of - * properties (the norm) and to allow quickly checking whether a - * property is set in this block. - */ - nsCSSPropertySet mPropertiesSet; - /* - * mPropertiesImportant indicates which properties are '!important'. - */ - nsCSSPropertySet mPropertiesImportant; + /* + * mPropertiesSet stores a bit for every property that is present, + * to optimize compression of blocks with small numbers of + * properties (the norm) and to allow quickly checking whether a + * property is set in this block. + */ + nsCSSPropertySet mPropertiesSet; + /* + * mPropertiesImportant indicates which properties are '!important'. + */ + nsCSSPropertySet mPropertiesImportant; - /* - * Return the storage location within |this| of the value of the - * property |aProperty|. - */ - nsCSSValue* PropertyAt(nsCSSProperty aProperty) { - MOZ_ASSERT(0 <= aProperty && - aProperty < eCSSProperty_COUNT_no_shorthands, - "property out of range"); - return &mValues[aProperty]; - } - const nsCSSValue* PropertyAt(nsCSSProperty aProperty) const { - MOZ_ASSERT(0 <= aProperty && - aProperty < eCSSProperty_COUNT_no_shorthands, - "property out of range"); - return &mValues[aProperty]; - } + /* + * Return the storage location within |this| of the value of the + * property |aProperty|. + */ + nsCSSValue* PropertyAt(nsCSSProperty aProperty) { + MOZ_ASSERT(0 <= aProperty && + aProperty < eCSSProperty_COUNT_no_shorthands, + "property out of range"); + return &mValues[aProperty]; + } + const nsCSSValue* PropertyAt(nsCSSProperty aProperty) const { + MOZ_ASSERT(0 <= aProperty && + aProperty < eCSSProperty_COUNT_no_shorthands, + "property out of range"); + return &mValues[aProperty]; + } - void SetPropertyBit(nsCSSProperty aProperty) { - mPropertiesSet.AddProperty(aProperty); - } + void SetPropertyBit(nsCSSProperty aProperty) { + mPropertiesSet.AddProperty(aProperty); + } - void ClearPropertyBit(nsCSSProperty aProperty) { - mPropertiesSet.RemoveProperty(aProperty); - } + void ClearPropertyBit(nsCSSProperty aProperty) { + mPropertiesSet.RemoveProperty(aProperty); + } - bool HasPropertyBit(nsCSSProperty aProperty) { - return mPropertiesSet.HasProperty(aProperty); - } + bool HasPropertyBit(nsCSSProperty aProperty) { + return mPropertiesSet.HasProperty(aProperty); + } - void SetImportantBit(nsCSSProperty aProperty) { - mPropertiesImportant.AddProperty(aProperty); - } + void SetImportantBit(nsCSSProperty aProperty) { + mPropertiesImportant.AddProperty(aProperty); + } - void ClearImportantBit(nsCSSProperty aProperty) { - mPropertiesImportant.RemoveProperty(aProperty); - } + void ClearImportantBit(nsCSSProperty aProperty) { + mPropertiesImportant.RemoveProperty(aProperty); + } - bool HasImportantBit(nsCSSProperty aProperty) { - return mPropertiesImportant.HasProperty(aProperty); - } + bool HasImportantBit(nsCSSProperty aProperty) { + return mPropertiesImportant.HasProperty(aProperty); + } - void ClearSets() { - mPropertiesSet.Empty(); - mPropertiesImportant.Empty(); - } + void ClearSets() { + mPropertiesSet.Empty(); + mPropertiesImportant.Empty(); + } }; #endif /* !defined(nsCSSDataBlock_h__) */ diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 71d7c2c589..48ffa5d02f 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -62,6 +62,7 @@ typedef nsCSSProps::KTableEntry KTableEntry; // pref-backed bool values (hooked up in nsCSSParser::Startup) static bool sOpentypeSVGEnabled; static bool sWebkitPrefixedAliasesEnabled; +static bool sWebkitDevicePixelRatioEnabled; static bool sUnprefixingServiceEnabled; #ifdef NIGHTLY_BUILD static bool sUnprefixingServiceGloballyWhitelisted; @@ -185,6 +186,10 @@ public: nsIPrincipal* aSheetPrincipal, nsCSSValue& aValue); + bool ParseTransformProperty(const nsAString& aPropValue, + bool aDisallowRelativeValues, + nsCSSValue& aResult); + void ParseMediaList(const nsSubstring& aBuffer, nsIURI* aURL, // for error reporting uint32_t aLineNumber, // for error reporting @@ -904,13 +909,13 @@ protected: bool ParseBorderStyle(); bool ParseBorderWidth(); - bool ParseCalc(nsCSSValue &aValue, int32_t aVariantMask); + bool ParseCalc(nsCSSValue &aValue, uint32_t aVariantMask); bool ParseCalcAdditiveExpression(nsCSSValue& aValue, - int32_t& aVariantMask); + uint32_t& aVariantMask); bool ParseCalcMultiplicativeExpression(nsCSSValue& aValue, - int32_t& aVariantMask, - bool *aHadFinalWS); - bool ParseCalcTerm(nsCSSValue& aValue, int32_t& aVariantMask); + uint32_t& aVariantMask, + bool *aHadFinalWS); + bool ParseCalcTerm(nsCSSValue& aValue, uint32_t& aVariantMask); bool RequireWhitespace(); // For "flex" shorthand property, defined in CSS Flexbox spec @@ -1021,7 +1026,7 @@ protected: bool ParseListStyleType(nsCSSValue& aValue); bool ParseMargin(); bool ParseClipPath(); - bool ParseTransform(bool aIsPrefixed); + bool ParseTransform(bool aIsPrefixed, bool aDisallowRelativeValues = false); bool ParseObjectPosition(); bool ParseOutline(); bool ParseOverflow(); @@ -1146,7 +1151,7 @@ protected: // Variant parsing methods CSSParseResult ParseVariant(nsCSSValue& aValue, - int32_t aVariantMask, + uint32_t aVariantMask, const KTableEntry aKeywordTable[]); CSSParseResult ParseVariantWithRestrictions(nsCSSValue& aValue, int32_t aVariantMask, @@ -1242,7 +1247,7 @@ protected: bool ParseAttr(nsCSSValue& aValue); bool ParseSymbols(nsCSSValue& aValue); bool SetValueToURL(nsCSSValue& aValue, const nsString& aURL); - bool TranslateDimension(nsCSSValue& aValue, int32_t aVariantMask, + bool TranslateDimension(nsCSSValue& aValue, uint32_t aVariantMask, float aNumber, const nsString& aUnit); bool ParseImageOrientation(nsCSSValue& aAngle); bool ParseImageRect(nsCSSValue& aImage); @@ -1295,12 +1300,13 @@ protected: bool ParseInsetFunction(nsCSSValue& aValue); /* Functions for transform Parsing */ - bool ParseSingleTransform(bool aIsPrefixed, nsCSSValue& aValue); - bool ParseFunction(nsCSSKeyword aFunction, const int32_t aAllowedTypes[], - int32_t aVariantMaskAll, uint16_t aMinElems, + bool ParseSingleTransform(bool aIsPrefixed, bool aDisallowRelativeValues, + nsCSSValue& aValue); + bool ParseFunction(nsCSSKeyword aFunction, const uint32_t aAllowedTypes[], + uint32_t aVariantMaskAll, uint16_t aMinElems, uint16_t aMaxElems, nsCSSValue &aValue); - bool ParseFunctionInternals(const int32_t aVariantMask[], - int32_t aVariantMaskAll, + bool ParseFunctionInternals(const uint32_t aVariantMask[], + uint32_t aVariantMaskAll, uint16_t aMinElems, uint16_t aMaxElems, InfallibleTArray& aOutput); @@ -1855,6 +1861,48 @@ CSSParserImpl::ParseLonghandProperty(const nsCSSProperty aPropID, } } +bool +CSSParserImpl::ParseTransformProperty(const nsAString& aPropValue, + bool aDisallowRelativeValues, + nsCSSValue& aValue) +{ + RefPtr declaration = new Declaration(); + declaration->InitializeEmpty(); + + mData.AssertInitialState(); + mTempData.AssertInitialState(); + + nsCSSScanner scanner(aPropValue, 0); + css::ErrorReporter reporter(scanner, mSheet, mChildLoader, nullptr); + InitScanner(scanner, reporter, nullptr, nullptr, nullptr); + + bool parsedOK = ParseTransform(false, aDisallowRelativeValues); + // We should now be at EOF + if (parsedOK && GetToken(true)) { + parsedOK = false; + } + + bool changed = false; + if (parsedOK) { + declaration->ExpandTo(&mData); + changed = mData.TransferFromBlock(mTempData, eCSSProperty_transform, + PropertyEnabledState(), false, + true, false, declaration, + GetDocument()); + declaration->CompressFrom(&mData); + } + + if (changed) { + aValue = *declaration->GetNormalBlock()->ValueFor(eCSSProperty_transform); + } else { + aValue.Reset(); + } + + ReleaseScanner(); + + return parsedOK; +} + void CSSParserImpl::ParseProperty(const nsCSSProperty aPropID, const nsAString& aPropValue, @@ -3485,6 +3533,9 @@ CSSParserImpl::ParseMediaQueryExpression(nsMediaQuery* aQuery) satisfiedReqFlags |= nsMediaFeature::eHasWebkitPrefix; featureString.Rebind(featureString, 8); } + if (sWebkitDevicePixelRatioEnabled) { + satisfiedReqFlags |= nsMediaFeature::eWebkitDevicePixelRatioPrefEnabled; + } // Strip off "min-"/"max-" prefix from featureString: if (StringBeginsWith(featureString, NS_LITERAL_STRING("min-"))) { @@ -7337,7 +7388,7 @@ const UnitInfo UnitData[] = { bool CSSParserImpl::TranslateDimension(nsCSSValue& aValue, - int32_t aVariantMask, + uint32_t aVariantMask, float aNumber, const nsString& aUnit) { @@ -7368,6 +7419,11 @@ CSSParserImpl::TranslateDimension(nsCSSValue& aValue, // inside an @page declaration. Fail. return false; } + + if ((VARIANT_ABSOLUTE_DIMENSION & aVariantMask) != 0 && + !nsCSSValue::IsPixelLengthUnit(units)) { + return false; + } } else { // Must be a zero number... NS_ASSERTION(0 == aNumber, "numbers without units must be 0"); @@ -7513,7 +7569,7 @@ CSSParserImpl::ParseOneOrLargerVariant(nsCSSValue& aValue, // Assigns to aValue iff it returns CSSParseResult::Ok. CSSParseResult CSSParserImpl::ParseVariant(nsCSSValue& aValue, - int32_t aVariantMask, + uint32_t aVariantMask, const KTableEntry aKeywordTable[]) { NS_ASSERTION(!(mHashlessColorQuirk && (aVariantMask & VARIANT_COLOR)) || @@ -9900,10 +9956,16 @@ CSSParserImpl::ParseLinearGradient(nsCSSValue& aValue, if (haveGradientLine) { // Parse a cssGradient->mIsLegacySyntax = true; - bool haveAngle = - ParseSingleTokenVariant(cssGradient->mAngle, VARIANT_ANGLE, nullptr); + // In -webkit-linear-gradient expressions (handled below), we need to accept + // unitless 0 for angles, to match WebKit/Blink. + int32_t angleFlags = (aFlags & eGradient_WebkitLegacy) ? + VARIANT_ANGLE | VARIANT_ZERO_ANGLE : + VARIANT_ANGLE; - // if we got an angle, we might now have a comma, ending the gradient-line + bool haveAngle = + ParseSingleTokenVariant(cssGradient->mAngle, angleFlags, nullptr); + + // If we got an angle, we might now have a comma, ending the gradient-line. bool haveAngleComma = haveAngle && ExpectSymbol(',', true); // If we're webkit-prefixed & didn't get an angle, @@ -12840,7 +12902,7 @@ CSSParserImpl::ParseBorderColors(nsCSSProperty aProperty) // Parse the top level of a calc() expression. bool -CSSParserImpl::ParseCalc(nsCSSValue &aValue, int32_t aVariantMask) +CSSParserImpl::ParseCalc(nsCSSValue &aValue, uint32_t aVariantMask) { // Parsing calc expressions requires, in a number of cases, looking // for a token that is *either* a value of the property or a number. @@ -12888,7 +12950,7 @@ CSSParserImpl::ParseCalc(nsCSSValue &aValue, int32_t aVariantMask) // data structure. bool CSSParserImpl::ParseCalcAdditiveExpression(nsCSSValue& aValue, - int32_t& aVariantMask) + uint32_t& aVariantMask) { MOZ_ASSERT(aVariantMask != 0, "unexpected variant mask"); nsCSSValue *storage = &aValue; @@ -12948,7 +13010,7 @@ struct ReduceNumberCalcOps : public mozilla::css::BasicFloatCalcOps, // aHadFinalWS parameter. bool CSSParserImpl::ParseCalcMultiplicativeExpression(nsCSSValue& aValue, - int32_t& aVariantMask, + uint32_t& aVariantMask, bool *aHadFinalWS) { MOZ_ASSERT(aVariantMask != 0, "unexpected variant mask"); @@ -12957,7 +13019,7 @@ CSSParserImpl::ParseCalcMultiplicativeExpression(nsCSSValue& aValue, nsCSSValue *storage = &aValue; for (;;) { - int32_t variantMask; + uint32_t variantMask; if (afterDivision || gotValue) { variantMask = VARIANT_NUMBER; } else { @@ -13045,7 +13107,7 @@ CSSParserImpl::ParseCalcMultiplicativeExpression(nsCSSValue& aValue, // aVariantMask*** to reflect which one it has parsed by either // removing VARIANT_NUMBER or removing all other bits. bool -CSSParserImpl::ParseCalcTerm(nsCSSValue& aValue, int32_t& aVariantMask) +CSSParserImpl::ParseCalcTerm(nsCSSValue& aValue, uint32_t& aVariantMask) { MOZ_ASSERT(aVariantMask != 0, "unexpected variant mask"); if (!GetToken(true)) @@ -14969,8 +15031,8 @@ CSSParserImpl::ParseTextCombineUpright(nsCSSValue& aValue) * ParseFunction. */ bool -CSSParserImpl::ParseFunctionInternals(const int32_t aVariantMask[], - int32_t aVariantMaskAll, +CSSParserImpl::ParseFunctionInternals(const uint32_t aVariantMask[], + uint32_t aVariantMaskAll, uint16_t aMinElems, uint16_t aMaxElems, InfallibleTArray &aOutput) @@ -14981,7 +15043,7 @@ CSSParserImpl::ParseFunctionInternals(const int32_t aVariantMask[], for (uint16_t index = 0; index < aMaxElems; ++index) { nsCSSValue newValue; - int32_t m = aVariantMaskAll ? aVariantMaskAll : aVariantMask[index]; + uint32_t m = aVariantMaskAll ? aVariantMaskAll : aVariantMask[index]; if (ParseVariant(newValue, m, nullptr) != CSSParseResult::Ok) { break; } @@ -15029,8 +15091,8 @@ CSSParserImpl::ParseFunctionInternals(const int32_t aVariantMask[], */ bool CSSParserImpl::ParseFunction(nsCSSKeyword aFunction, - const int32_t aAllowedTypes[], - int32_t aAllowedTypesAll, + const uint32_t aAllowedTypes[], + uint32_t aAllowedTypesAll, uint16_t aMinElems, uint16_t aMaxElems, nsCSSValue &aValue) { @@ -15081,6 +15143,10 @@ CSSParserImpl::ParseFunction(nsCSSKeyword aFunction, * returns an error. * * @param aToken The token identifying the function. + * @param aIsPrefixed If true, parse matrices using the matrix syntax + * for -moz-transform. + * @param aDisallowRelativeValues If true, only allow variants that are + * numbers or have non-relative dimensions. * @param aMinElems [out] The minimum number of elements to read. * @param aMaxElems [out] The maximum number of elements to read * @param aVariantMask [out] The variant mask to use during parsing @@ -15088,9 +15154,10 @@ CSSParserImpl::ParseFunction(nsCSSKeyword aFunction, */ static bool GetFunctionParseInformation(nsCSSKeyword aToken, bool aIsPrefixed, + bool aDisallowRelativeValues, uint16_t &aMinElems, uint16_t &aMaxElems, - const int32_t *& aVariantMask) + const uint32_t *& aVariantMask) { /* These types represent the common variant masks that will be used to * parse out the individual functions. The order in the enumeration @@ -15098,12 +15165,16 @@ static bool GetFunctionParseInformation(nsCSSKeyword aToken, */ enum { eLengthPercentCalc, eLengthCalc, + eAbsoluteLengthCalc, eTwoLengthPercentCalcs, + eTwoAbsoluteLengthCalcs, eTwoLengthPercentCalcsOneLengthCalc, + eThreeAbsoluteLengthCalc, eAngle, eTwoAngles, eNumber, ePositiveLength, + ePositiveAbsoluteLength, eTwoNumbers, eThreeNumbers, eThreeNumbersOneAngle, @@ -15113,15 +15184,19 @@ static bool GetFunctionParseInformation(nsCSSKeyword aToken, eMatrix3dPrefixed, eNumVariantMasks }; static const int32_t kMaxElemsPerFunction = 16; - static const int32_t kVariantMasks[eNumVariantMasks][kMaxElemsPerFunction] = { + static const uint32_t kVariantMasks[eNumVariantMasks][kMaxElemsPerFunction] = { {VARIANT_LPCALC}, - {VARIANT_LENGTH|VARIANT_CALC}, + {VARIANT_LCALC}, + {VARIANT_LB}, {VARIANT_LPCALC, VARIANT_LPCALC}, - {VARIANT_LPCALC, VARIANT_LPCALC, VARIANT_LENGTH|VARIANT_CALC}, + {VARIANT_LBCALC, VARIANT_LBCALC}, + {VARIANT_LPCALC, VARIANT_LPCALC, VARIANT_LCALC}, + {VARIANT_LBCALC, VARIANT_LBCALC, VARIANT_LBCALC}, {VARIANT_ANGLE_OR_ZERO}, {VARIANT_ANGLE_OR_ZERO, VARIANT_ANGLE_OR_ZERO}, {VARIANT_NUMBER}, {VARIANT_LENGTH|VARIANT_POSITIVE_DIMENSION}, + {VARIANT_LB|VARIANT_POSITIVE_DIMENSION}, {VARIANT_NUMBER, VARIANT_NUMBER}, {VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER}, {VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_ANGLE_OR_ZERO}, @@ -15137,10 +15212,31 @@ static bool GetFunctionParseInformation(nsCSSKeyword aToken, VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_LPNCALC, VARIANT_LPNCALC, VARIANT_LNCALC, VARIANT_NUMBER}}; + // Map from a mask to a congruent mask that excludes relative variants. + static const int32_t kNonRelativeVariantMap[eNumVariantMasks] = { + eAbsoluteLengthCalc, + eAbsoluteLengthCalc, + eAbsoluteLengthCalc, + eTwoAbsoluteLengthCalcs, + eTwoAbsoluteLengthCalcs, + eThreeAbsoluteLengthCalc, + eThreeAbsoluteLengthCalc, + eAngle, + eTwoAngles, + eNumber, + ePositiveAbsoluteLength, + ePositiveAbsoluteLength, + eTwoNumbers, + eThreeNumbers, + eThreeNumbersOneAngle, + eMatrix, + eMatrix, + eMatrix3d, + eMatrix3d }; #ifdef DEBUG static const uint8_t kVariantMaskLengths[eNumVariantMasks] = - {1, 1, 2, 3, 1, 2, 1, 1, 2, 3, 4, 6, 6, 16, 16}; + {1, 1, 1, 2, 2, 3, 3, 1, 2, 1, 1, 1, 2, 3, 4, 6, 6, 16, 16}; #endif int32_t variantIndex = eNumVariantMasks; @@ -15246,6 +15342,10 @@ static bool GetFunctionParseInformation(nsCSSKeyword aToken, return false; } + if (aDisallowRelativeValues) { + variantIndex = kNonRelativeVariantMap[variantIndex]; + } + NS_ASSERTION(aMinElems > 0, "Didn't update minimum elements!"); NS_ASSERTION(aMaxElems > 0, "Didn't update maximum elements!"); NS_ASSERTION(aMinElems <= aMaxElems, "aMinElems > aMaxElems!"); @@ -15318,7 +15418,9 @@ bool CSSParserImpl::ParseWillChange() * error if something goes wrong. */ bool -CSSParserImpl::ParseSingleTransform(bool aIsPrefixed, nsCSSValue& aValue) +CSSParserImpl::ParseSingleTransform(bool aIsPrefixed, + bool aDisallowRelativeValues, + nsCSSValue& aValue) { if (!GetToken(true)) return false; @@ -15328,12 +15430,14 @@ CSSParserImpl::ParseSingleTransform(bool aIsPrefixed, nsCSSValue& aValue) return false; } - const int32_t* variantMask; + const uint32_t* variantMask; uint16_t minElems, maxElems; nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent); if (!GetFunctionParseInformation(keyword, aIsPrefixed, - minElems, maxElems, variantMask)) + aDisallowRelativeValues, + minElems, maxElems, + variantMask)) return false; return ParseFunction(keyword, variantMask, 0, minElems, maxElems, aValue); @@ -15342,7 +15446,8 @@ CSSParserImpl::ParseSingleTransform(bool aIsPrefixed, nsCSSValue& aValue) /* Parses a transform property list by continuously reading in properties * and constructing a matrix from it. */ -bool CSSParserImpl::ParseTransform(bool aIsPrefixed) +bool +CSSParserImpl::ParseTransform(bool aIsPrefixed, bool aDisallowRelativeValues) { nsCSSValue value; // 'inherit', 'initial', 'unset' and 'none' must be alone @@ -15353,7 +15458,8 @@ bool CSSParserImpl::ParseTransform(bool aIsPrefixed) list->mHead = new nsCSSValueList; nsCSSValueList* cur = list->mHead; for (;;) { - if (!ParseSingleTransform(aIsPrefixed, cur->mValue)) { + if (!ParseSingleTransform(aIsPrefixed, aDisallowRelativeValues, + cur->mValue)) { return false; } if (CheckEndProperty()) { @@ -15727,7 +15833,7 @@ CSSParserImpl::ParseSingleFilter(nsCSSValue* aValue) } // Set up the parsing rules based on the filter function. - int32_t variantMask = VARIANT_PN; + uint32_t variantMask = VARIANT_PN; bool rejectNegativeArgument = true; bool clampArgumentToOne = false; switch (functionName) { @@ -16996,6 +17102,8 @@ nsCSSParser::Startup() "gfx.font_rendering.opentype_svg.enabled"); Preferences::AddBoolVarCache(&sWebkitPrefixedAliasesEnabled, "layout.css.prefixes.webkit"); + Preferences::AddBoolVarCache(&sWebkitDevicePixelRatioEnabled, + "layout.css.prefixes.device-pixel-ratio-webkit"); Preferences::AddBoolVarCache(&sUnprefixingServiceEnabled, "layout.css.unprefixing-service.enabled"); #ifdef NIGHTLY_BUILD @@ -17153,6 +17261,15 @@ nsCSSParser::ParseLonghandProperty(const nsCSSProperty aPropID, aSheetPrincipal, aResult); } +bool +nsCSSParser::ParseTransformProperty(const nsAString& aPropValue, + bool aDisallowRelativeValues, + nsCSSValue& aResult) +{ + return static_cast(mImpl)-> + ParseTransformProperty(aPropValue, aDisallowRelativeValues, aResult); +} + void nsCSSParser::ParseVariable(const nsAString& aVariableName, const nsAString& aPropValue, diff --git a/layout/style/nsCSSParser.h b/layout/style/nsCSSParser.h index ba538d1585..2fa600fd62 100644 --- a/layout/style/nsCSSParser.h +++ b/layout/style/nsCSSParser.h @@ -145,6 +145,15 @@ public: nsIPrincipal* aSheetPrincipal, nsCSSValue& aResult); + // Parse the value of a CSS transform property. Returns + // whether the value was successfully parsed. If + // aDisallowRelativeValues is true then this method will + // only successfully parse if all values are numbers or + // have non-relative dimensions. + bool ParseTransformProperty(const nsAString& aPropValue, + bool aDisallowRelativeValues, + nsCSSValue& aResult); + // The same as ParseProperty but for a variable. void ParseVariable(const nsAString& aVariableName, const nsAString& aPropValue, diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index 658b53286d..926faf3184 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -1644,6 +1644,22 @@ CSS_PROP_POSITION( kFlexDirectionKTable, offsetof(nsStylePosition, mFlexDirection), eStyleAnimType_EnumU8) +/* We treat -webkit-box-orient as a writing-mode-aware logical alias + * for "flex-direction": */ +CSS_PROP_LOGICAL( + -webkit-box-orient, + webkit_box_orient, + WebkitBoxOrient, + CSS_PROPERTY_PARSE_VALUE | + CSS_PROPERTY_LOGICAL | + CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING, + "layout.css.prefixes.webkit", + VARIANT_HK, + kBoxOrientKTable, + WebkitBoxOrient, + Position, + CSS_PROP_NO_OFFSET, + eStyleAnimType_None) CSS_PROP_SHORTHAND( flex-flow, flex_flow, diff --git a/layout/style/nsCSSPropLogicalGroupList.h b/layout/style/nsCSSPropLogicalGroupList.h index 3d8a52bc90..05371d9442 100644 --- a/layout/style/nsCSSPropLogicalGroupList.h +++ b/layout/style/nsCSSPropLogicalGroupList.h @@ -44,6 +44,17 @@ // defined in nCSSProps.cpp named gLogicalGroupTable // containing the two physical properties in vertical/horizontal // order, followed by an nsCSSProperty_UNKNOWN entry. +// +// CSS_PROP_LOGICAL_GROUP_SINGLE(name_) +// Defines a logical property group in which the logical property always +// maps to the same physical property. For such properties, the +// "logicalness" is in the value-mapping, not in the property-mapping. For +// example, the logical property "-webkit-box-orient" is always mapped to +// "flex-direction", but its values ("horizontal", "vertical") map to +// different flex-direction values ("row", "column") depending on the +// writing-mode. A table must be defined in nsCSSProps.cpp named +// gLogicalGroupTable containing the one physical property, +// followed by an nsCSSProperty_UNKNOWN entry. CSS_PROP_LOGICAL_GROUP_SHORTHAND(BorderColor) CSS_PROP_LOGICAL_GROUP_SHORTHAND(BorderStyle) @@ -54,3 +65,4 @@ CSS_PROP_LOGICAL_GROUP_BOX(Offset) CSS_PROP_LOGICAL_GROUP_SHORTHAND(Padding) CSS_PROP_LOGICAL_GROUP_AXIS(MinSize) CSS_PROP_LOGICAL_GROUP_AXIS(Size) +CSS_PROP_LOGICAL_GROUP_SINGLE(WebkitBoxOrient) diff --git a/layout/style/nsCSSProperty.h b/layout/style/nsCSSProperty.h index 0e0536da78..aef29c96ee 100644 --- a/layout/style/nsCSSProperty.h +++ b/layout/style/nsCSSProperty.h @@ -103,10 +103,13 @@ enum nsCSSPropertyLogicalGroup { eCSSPropertyLogicalGroup_##name_, #define CSS_PROP_LOGICAL_GROUP_BOX(name_) \ eCSSPropertyLogicalGroup_##name_, +#define CSS_PROP_LOGICAL_GROUP_SINGLE(name_) \ + eCSSPropertyLogicalGroup_##name_, #define CSS_PROP_LOGICAL_GROUP_SHORTHAND(name_) \ eCSSPropertyLogicalGroup_##name_, #include "nsCSSPropLogicalGroupList.h" #undef CSS_PROP_LOGICAL_GROUP_SHORTHAND +#undef CSS_PROP_LOGICAL_GROUP_SINGLE #undef CSS_PROP_LOGICAL_GROUP_BOX #undef CSS_PROP_LOGICAL_GROUP_AXIS eCSSPropertyLogicalGroup_COUNT diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp index c9c6097915..116351db7a 100644 --- a/layout/style/nsCSSProps.cpp +++ b/layout/style/nsCSSProps.cpp @@ -2881,12 +2881,19 @@ static const nsCSSProperty gSizeLogicalGroupTable[] = { eCSSProperty_UNKNOWN }; +static const nsCSSProperty gWebkitBoxOrientLogicalGroupTable[] = { + eCSSProperty_flex_direction, + eCSSProperty_UNKNOWN +}; + const nsCSSProperty* const nsCSSProps::kLogicalGroupTable[eCSSPropertyLogicalGroup_COUNT] = { #define CSS_PROP_LOGICAL_GROUP_SHORTHAND(id_) g##id_##SubpropTable, #define CSS_PROP_LOGICAL_GROUP_AXIS(name_) g##name_##LogicalGroupTable, #define CSS_PROP_LOGICAL_GROUP_BOX(name_) g##name_##LogicalGroupTable, +#define CSS_PROP_LOGICAL_GROUP_SINGLE(name_) g##name_##LogicalGroupTable, #include "nsCSSPropLogicalGroupList.h" +#undef CSS_PROP_LOGICAL_GROUP_SINGLE #undef CSS_PROP_LOGICAL_GROUP_BOX #undef CSS_PROP_LOGICAL_GROUP_AXIS #undef CSS_PROP_LOGICAL_GROUP_SHORTHAND @@ -3187,7 +3194,10 @@ nsCSSProps::gPropertyUseCounter[eCSSProperty_COUNT_no_shorthands] = { "the CSS_PROPERTY_LOGICAL_BLOCK_AXIS flag"); \ static_assert(!((flags_) & CSS_PROPERTY_LOGICAL_END_EDGE), \ "only properties defined with CSS_PROP_LOGICAL can use " \ - "the CSS_PROPERTY_LOGICAL_END_EDGE flag"); + "the CSS_PROPERTY_LOGICAL_END_EDGE flag"); \ + static_assert(!((flags_) & CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING),\ + "only properties defined with CSS_PROP_LOGICAL can use " \ + "the CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING flag"); #define CSS_PROP_LOGICAL(name_, id_, method_, flags_, pref_, parsevariant_, \ kwtable_, group_, stylestruct_, \ stylestructoffset_, animtype_) \ @@ -3200,7 +3210,21 @@ nsCSSProps::gPropertyUseCounter[eCSSProperty_COUNT_no_shorthands] = { static_assert(!(((flags_) & CSS_PROPERTY_LOGICAL_AXIS) && \ ((flags_) & CSS_PROPERTY_LOGICAL_END_EDGE)), \ "CSS_PROPERTY_LOGICAL_END_EDGE makes no sense when used " \ - "with CSS_PROPERTY_LOGICAL_AXIS"); + "with CSS_PROPERTY_LOGICAL_AXIS"); \ + /* Make sure CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING isn't used */ \ + /* with other mutually-exclusive flags: */ \ + static_assert(!(((flags_) & CSS_PROPERTY_LOGICAL_AXIS) && \ + ((flags_) & CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING)),\ + "CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING makes no " \ + "sense when used with CSS_PROPERTY_LOGICAL_AXIS"); \ + static_assert(!(((flags_) & CSS_PROPERTY_LOGICAL_BLOCK_AXIS) && \ + ((flags_) & CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING)),\ + "CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING makes no " \ + "sense when used with CSS_PROPERTY_LOGICAL_BLOCK_AXIS"); \ + static_assert(!(((flags_) & CSS_PROPERTY_LOGICAL_END_EDGE) && \ + ((flags_) & CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING)),\ + "CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING makes no " \ + "sense when used with CSS_PROPERTY_LOGICAL_END_EDGE"); #include "nsCSSPropList.h" #undef CSS_PROP_LOGICAL #undef CSS_PROP diff --git a/layout/style/nsCSSProps.h b/layout/style/nsCSSProps.h index 54e4c80c52..12c58f17aa 100644 --- a/layout/style/nsCSSProps.h +++ b/layout/style/nsCSSProps.h @@ -55,6 +55,7 @@ #define VARIANT_NONNEGATIVE_DIMENSION 0x20000000 // Only lengths greater than or equal to 0.0 // Keyword used iff gfx.font_rendering.opentype_svg.enabled is true: #define VARIANT_OPENTYPE_SVG_KEYWORD 0x40000000 +#define VARIANT_ABSOLUTE_DIMENSION 0x80000000 // B Only lengths with absolute length unit // Variants that can consume more than one token #define VARIANT_MULTIPLE_TOKENS \ @@ -106,6 +107,8 @@ #define VARIANT_UK (VARIANT_URL | VARIANT_KEYWORD) #define VARIANT_UO (VARIANT_URL | VARIANT_NONE) #define VARIANT_ANGLE_OR_ZERO (VARIANT_ANGLE | VARIANT_ZERO_ANGLE) +#define VARIANT_LB (VARIANT_LENGTH | VARIANT_ABSOLUTE_DIMENSION) +#define VARIANT_LBCALC (VARIANT_LB | VARIANT_CALC) #define VARIANT_LCALC (VARIANT_LENGTH | VARIANT_CALC) #define VARIANT_LPCALC (VARIANT_LCALC | VARIANT_PERCENT) #define VARIANT_LNCALC (VARIANT_LCALC | VARIANT_NUMBER) @@ -247,20 +250,26 @@ static_assert((CSS_PROPERTY_PARSE_PROPERTY_MASK & // margin-block-start or margin-inline-start). #define CSS_PROPERTY_LOGICAL_END_EDGE (1<<26) +// This property is a logical property which always maps to the same physical +// property, and its values have some custom processing when being mapped to +// the physical property's values. Must not be used in conjunction with +// CSS_PROPERTY_LOGICAL_{AXIS,BLOCK_AXIS,END_EDGE}. +#define CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING (1<<27) + // This property can be animated on the compositor. -#define CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR (1<<27) +#define CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR (1<<28) // This property is an internal property that is not represented // in the DOM. Properties with this flag must be defined in an #ifndef // CSS_PROP_LIST_EXCLUDE_INTERNAL section of nsCSSPropList.h. -#define CSS_PROPERTY_INTERNAL (1<<28) +#define CSS_PROPERTY_INTERNAL (1<<29) // This property has values that can establish a containing block for // fixed positioned and absolutely positioned elements. // This should be set for any properties that can cause an element to be // such a containing block, as implemented in // nsStyleDisplay::IsFixedPosContainingBlock. -#define CSS_PROPERTY_FIXPOS_CB (1<<29) +#define CSS_PROPERTY_FIXPOS_CB (1<<30) // This property has values that can establish a containing block for // absolutely positioned elements. @@ -269,7 +278,10 @@ static_assert((CSS_PROPERTY_PARSE_PROPERTY_MASK & // nsStyleDisplay::IsAbsPosContainingBlock. // It does not need to be set for properties that also have // CSS_PROPERTY_FIXPOS_CB set. -#define CSS_PROPERTY_ABSPOS_CB (1<<30) +#define CSS_PROPERTY_ABSPOS_CB (1u<<31) + +// NOTE: Before adding any new CSS_PROPERTY_* flags here, we'll need to +// upgrade kFlagsTable to 64-bits -- see bug 1231384. /** * Types of animatable values. @@ -543,8 +555,11 @@ public: * by the sentinel. * * When called with a property that has the CSS_PROPERTY_LOGICAL_AXIS - * flag, the returned array will have two values preceding the sentinel; - * otherwise it will have four. + * flag, the returned array will have two values preceding the sentinel. + * When called with a property that has the + * CSS_PROPERTY_LOGICAL_SINGLE_CUSTOM_VALMAPPING flag, the returned array + * will have one value preceding the sentinel. + * Otherwise it will have four values preceding the sentinel. * * (Note that the running time of this function is proportional to the * number of logical longhand properties that exist. If we start diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index 9ce556bc87..b69399b73e 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -1168,16 +1168,6 @@ InitSystemMetrics() sSystemMetrics->AppendElement(nsGkAtoms::mac_yosemite_theme); } - rv = LookAndFeel::GetInt(LookAndFeel::eIntID_WindowsAccentColorApplies, &metricResult); - if (NS_SUCCEEDED(rv) && metricResult) { - sSystemMetrics->AppendElement(nsGkAtoms::windows_accent_color_applies); - } - - rv = LookAndFeel::GetInt(LookAndFeel::eIntID_WindowsAccentColorIsDark, &metricResult); - if (NS_SUCCEEDED(rv) && metricResult) { - sSystemMetrics->AppendElement(nsGkAtoms::windows_accent_color_is_dark); - } - rv = LookAndFeel::GetInt(LookAndFeel::eIntID_DWMCompositor, &metricResult); if (NS_SUCCEEDED(rv) && metricResult) { sSystemMetrics->AppendElement(nsGkAtoms::windows_compositor); diff --git a/layout/style/nsCSSValue.cpp b/layout/style/nsCSSValue.cpp index cc65078840..7a0524629c 100644 --- a/layout/style/nsCSSValue.cpp +++ b/layout/style/nsCSSValue.cpp @@ -543,48 +543,48 @@ void nsCSSValue::SetPairValue(const nsCSSValue& xValue, void nsCSSValue::SetTripletValue(const nsCSSValueTriplet* aValue) { - // triplet should not be used for null/inherit/initial values - MOZ_ASSERT(aValue && - aValue->mXValue.GetUnit() != eCSSUnit_Null && - aValue->mYValue.GetUnit() != eCSSUnit_Null && - aValue->mZValue.GetUnit() != eCSSUnit_Null && - aValue->mXValue.GetUnit() != eCSSUnit_Inherit && - aValue->mYValue.GetUnit() != eCSSUnit_Inherit && - aValue->mZValue.GetUnit() != eCSSUnit_Inherit && - aValue->mXValue.GetUnit() != eCSSUnit_Initial && - aValue->mYValue.GetUnit() != eCSSUnit_Initial && - aValue->mZValue.GetUnit() != eCSSUnit_Initial && - aValue->mXValue.GetUnit() != eCSSUnit_Unset && - aValue->mYValue.GetUnit() != eCSSUnit_Unset && - aValue->mZValue.GetUnit() != eCSSUnit_Unset, - "missing or inappropriate triplet value"); - Reset(); - mUnit = eCSSUnit_Triplet; - mValue.mTriplet = new nsCSSValueTriplet_heap(aValue->mXValue, aValue->mYValue, aValue->mZValue); - mValue.mTriplet->AddRef(); + // triplet should not be used for null/inherit/initial values + MOZ_ASSERT(aValue && + aValue->mXValue.GetUnit() != eCSSUnit_Null && + aValue->mYValue.GetUnit() != eCSSUnit_Null && + aValue->mZValue.GetUnit() != eCSSUnit_Null && + aValue->mXValue.GetUnit() != eCSSUnit_Inherit && + aValue->mYValue.GetUnit() != eCSSUnit_Inherit && + aValue->mZValue.GetUnit() != eCSSUnit_Inherit && + aValue->mXValue.GetUnit() != eCSSUnit_Initial && + aValue->mYValue.GetUnit() != eCSSUnit_Initial && + aValue->mZValue.GetUnit() != eCSSUnit_Initial && + aValue->mXValue.GetUnit() != eCSSUnit_Unset && + aValue->mYValue.GetUnit() != eCSSUnit_Unset && + aValue->mZValue.GetUnit() != eCSSUnit_Unset, + "missing or inappropriate triplet value"); + Reset(); + mUnit = eCSSUnit_Triplet; + mValue.mTriplet = new nsCSSValueTriplet_heap(aValue->mXValue, aValue->mYValue, aValue->mZValue); + mValue.mTriplet->AddRef(); } void nsCSSValue::SetTripletValue(const nsCSSValue& xValue, const nsCSSValue& yValue, const nsCSSValue& zValue) { - // Only allow Null for the z component - MOZ_ASSERT(xValue.GetUnit() != eCSSUnit_Null && - yValue.GetUnit() != eCSSUnit_Null && - xValue.GetUnit() != eCSSUnit_Inherit && - yValue.GetUnit() != eCSSUnit_Inherit && - zValue.GetUnit() != eCSSUnit_Inherit && - xValue.GetUnit() != eCSSUnit_Initial && - yValue.GetUnit() != eCSSUnit_Initial && - zValue.GetUnit() != eCSSUnit_Initial && - xValue.GetUnit() != eCSSUnit_Unset && - yValue.GetUnit() != eCSSUnit_Unset && - zValue.GetUnit() != eCSSUnit_Unset, - "inappropriate triplet value"); - Reset(); - mUnit = eCSSUnit_Triplet; - mValue.mTriplet = new nsCSSValueTriplet_heap(xValue, yValue, zValue); - mValue.mTriplet->AddRef(); + // Only allow Null for the z component + MOZ_ASSERT(xValue.GetUnit() != eCSSUnit_Null && + yValue.GetUnit() != eCSSUnit_Null && + xValue.GetUnit() != eCSSUnit_Inherit && + yValue.GetUnit() != eCSSUnit_Inherit && + zValue.GetUnit() != eCSSUnit_Inherit && + xValue.GetUnit() != eCSSUnit_Initial && + yValue.GetUnit() != eCSSUnit_Initial && + zValue.GetUnit() != eCSSUnit_Initial && + xValue.GetUnit() != eCSSUnit_Unset && + yValue.GetUnit() != eCSSUnit_Unset && + zValue.GetUnit() != eCSSUnit_Unset, + "inappropriate triplet value"); + Reset(); + mUnit = eCSSUnit_Triplet; + mValue.mTriplet = new nsCSSValueTriplet_heap(xValue, yValue, zValue); + mValue.mTriplet->AddRef(); } nsCSSRect& nsCSSValue::SetRectValue() @@ -1978,9 +1978,9 @@ nsCSSValueList::Clone() const void nsCSSValueList::CloneInto(nsCSSValueList* aList) const { - NS_ASSERTION(!aList->mNext, "Must be an empty list!"); - aList->mValue = mValue; - aList->mNext = mNext ? mNext->Clone() : nullptr; + NS_ASSERTION(!aList->mNext, "Must be an empty list!"); + aList->mValue = mValue; + aList->mNext = mNext ? mNext->Clone() : nullptr; } static void @@ -2307,15 +2307,15 @@ nsCSSValueTriplet::AppendToString(nsCSSProperty aProperty, nsAString& aResult, nsCSSValue::Serialization aSerialization) const { - mXValue.AppendToString(aProperty, aResult, aSerialization); - if (mYValue.GetUnit() != eCSSUnit_Null) { - aResult.Append(char16_t(' ')); - mYValue.AppendToString(aProperty, aResult, aSerialization); - if (mZValue.GetUnit() != eCSSUnit_Null) { - aResult.Append(char16_t(' ')); - mZValue.AppendToString(aProperty, aResult, aSerialization); - } + mXValue.AppendToString(aProperty, aResult, aSerialization); + if (mYValue.GetUnit() != eCSSUnit_Null) { + aResult.Append(char16_t(' ')); + mYValue.AppendToString(aProperty, aResult, aSerialization); + if (mZValue.GetUnit() != eCSSUnit_Null) { + aResult.Append(char16_t(' ')); + mZValue.AppendToString(aProperty, aResult, aSerialization); } + } } size_t diff --git a/layout/style/nsCSSValue.h b/layout/style/nsCSSValue.h index 38e318d720..ce5f66f610 100644 --- a/layout/style/nsCSSValue.h +++ b/layout/style/nsCSSValue.h @@ -468,8 +468,10 @@ public: /** * A "pixel" length unit is a some multiple of CSS pixels. */ + static bool IsPixelLengthUnit(nsCSSUnit aUnit) + { return eCSSUnit_Point <= aUnit && aUnit <= eCSSUnit_Pixel; } bool IsPixelLengthUnit() const - { return eCSSUnit_Point <= mUnit && mUnit <= eCSSUnit_Pixel; } + { return IsPixelLengthUnit(mUnit); } bool IsAngularUnit() const { return eCSSUnit_Degree <= mUnit && mUnit <= eCSSUnit_Turn; } bool IsFrequencyUnit() const @@ -1561,18 +1563,6 @@ public: uint32_t mLineOffset; mozilla::SheetType mLevel; - // This table is used to hold a reference on to any ImageValue that results - // from re-parsing this token stream at computed value time. When properties - // like background-image contain a normal url(), the Declaration's data block - // will hold a reference to the ImageValue. When a token stream is used, - // the Declaration only holds on to this nsCSSValueTokenStream object, and - // the ImageValue would only exist for the duration of - // nsRuleNode::WalkRuleTree, in the AutoCSSValueArray. So instead when - // we re-parse a token stream and get an ImageValue, we record it in this - // table so that the Declaration can be the object that keeps holding - // a reference to it. - nsTHashtable > mImageValues; - private: nsCSSValueTokenStream(const nsCSSValueTokenStream& aOther) = delete; nsCSSValueTokenStream& operator=(const nsCSSValueTokenStream& aOther) = delete; diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index 233d60bbe2..9a718a5d4c 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -1,5 +1,5 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set tw=78 expandtab softtabstop=2 ts=2 sw=2: */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -1284,29 +1284,29 @@ nsComputedDOMStyle::DoGetPerspectiveOrigin() already_AddRefed nsComputedDOMStyle::DoGetPerspective() { - RefPtr val = new nsROCSSPrimitiveValue; - SetValueToCoord(val, StyleDisplay()->mChildPerspective, false); - return val.forget(); + RefPtr val = new nsROCSSPrimitiveValue; + SetValueToCoord(val, StyleDisplay()->mChildPerspective, false); + return val.forget(); } already_AddRefed nsComputedDOMStyle::DoGetBackfaceVisibility() { - RefPtr val = new nsROCSSPrimitiveValue; - val->SetIdent( - nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mBackfaceVisibility, - nsCSSProps::kBackfaceVisibilityKTable)); - return val.forget(); + RefPtr val = new nsROCSSPrimitiveValue; + val->SetIdent( + nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mBackfaceVisibility, + nsCSSProps::kBackfaceVisibilityKTable)); + return val.forget(); } already_AddRefed nsComputedDOMStyle::DoGetTransformStyle() { - RefPtr val = new nsROCSSPrimitiveValue; - val->SetIdent( - nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mTransformStyle, - nsCSSProps::kTransformStyleKTable)); - return val.forget(); + RefPtr val = new nsROCSSPrimitiveValue; + val->SetIdent( + nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mTransformStyle, + nsCSSProps::kTransformStyleKTable)); + return val.forget(); } /* If the property is "none", hand back "none" wrapped in a value. @@ -1349,13 +1349,15 @@ nsComputedDOMStyle::DoGetTransform() nsSize(0, 0)); RuleNodeCacheConditions dummy; + bool dummyBool; gfx::Matrix4x4 matrix = nsStyleTransformMatrix::ReadTransforms(display->mSpecifiedTransform->mHead, mStyleContext, mStyleContext->PresContext(), dummy, refBox, - float(mozilla::AppUnitsPerCSSPixel())); + float(mozilla::AppUnitsPerCSSPixel()), + &dummyBool); return MatrixToCSSValue(matrix); } diff --git a/layout/style/nsMediaFeatures.cpp b/layout/style/nsMediaFeatures.cpp index e7a7cd6368..22966c192b 100644 --- a/layout/style/nsMediaFeatures.cpp +++ b/layout/style/nsMediaFeatures.cpp @@ -1,4 +1,5 @@ -/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -34,34 +35,34 @@ static const nsCSSProps::KTableEntry kScanKeywords[] = { #ifdef XP_WIN struct WindowsThemeName { - LookAndFeel::WindowsTheme id; - const wchar_t* name; + LookAndFeel::WindowsTheme id; + const wchar_t* name; }; // Windows theme identities used in the -moz-windows-theme media query. const WindowsThemeName themeStrings[] = { - { LookAndFeel::eWindowsTheme_Aero, L"aero" }, - { LookAndFeel::eWindowsTheme_AeroLite, L"aero-lite" }, - { LookAndFeel::eWindowsTheme_LunaBlue, L"luna-blue" }, - { LookAndFeel::eWindowsTheme_LunaOlive, L"luna-olive" }, - { LookAndFeel::eWindowsTheme_LunaSilver, L"luna-silver" }, - { LookAndFeel::eWindowsTheme_Royale, L"royale" }, - { LookAndFeel::eWindowsTheme_Zune, L"zune" }, - { LookAndFeel::eWindowsTheme_Generic, L"generic" } + { LookAndFeel::eWindowsTheme_Aero, L"aero" }, + { LookAndFeel::eWindowsTheme_AeroLite, L"aero-lite" }, + { LookAndFeel::eWindowsTheme_LunaBlue, L"luna-blue" }, + { LookAndFeel::eWindowsTheme_LunaOlive, L"luna-olive" }, + { LookAndFeel::eWindowsTheme_LunaSilver, L"luna-silver" }, + { LookAndFeel::eWindowsTheme_Royale, L"royale" }, + { LookAndFeel::eWindowsTheme_Zune, L"zune" }, + { LookAndFeel::eWindowsTheme_Generic, L"generic" } }; struct OperatingSystemVersionInfo { - LookAndFeel::OperatingSystemVersion id; - const wchar_t* name; + LookAndFeel::OperatingSystemVersion id; + const wchar_t* name; }; // Os version identities used in the -moz-os-version media query. const OperatingSystemVersionInfo osVersionStrings[] = { - { LookAndFeel::eOperatingSystemVersion_WindowsXP, L"windows-xp" }, - { LookAndFeel::eOperatingSystemVersion_WindowsVista, L"windows-vista" }, - { LookAndFeel::eOperatingSystemVersion_Windows7, L"windows-win7" }, - { LookAndFeel::eOperatingSystemVersion_Windows8, L"windows-win8" }, - { LookAndFeel::eOperatingSystemVersion_Windows10, L"windows-win10" } + { LookAndFeel::eOperatingSystemVersion_WindowsXP, L"windows-xp" }, + { LookAndFeel::eOperatingSystemVersion_WindowsVista, L"windows-vista" }, + { LookAndFeel::eOperatingSystemVersion_Windows7, L"windows-win7" }, + { LookAndFeel::eOperatingSystemVersion_Windows8, L"windows-win8" }, + { LookAndFeel::eOperatingSystemVersion_Windows10, L"windows-win10" } }; #endif @@ -69,33 +70,33 @@ const OperatingSystemVersionInfo osVersionStrings[] = { static nsSize GetSize(nsPresContext* aPresContext) { - nsSize size; - if (aPresContext->IsRootPaginatedDocument()) - // We want the page size, including unprintable areas and margins. - size = aPresContext->GetPageSize(); - else - size = aPresContext->GetVisibleArea().Size(); - return size; + nsSize size; + if (aPresContext->IsRootPaginatedDocument()) + // We want the page size, including unprintable areas and margins. + size = aPresContext->GetPageSize(); + else + size = aPresContext->GetVisibleArea().Size(); + return size; } static nsresult GetWidth(nsPresContext* aPresContext, const nsMediaFeature*, nsCSSValue& aResult) { - nsSize size = GetSize(aPresContext); - float pixelWidth = aPresContext->AppUnitsToFloatCSSPixels(size.width); - aResult.SetFloatValue(pixelWidth, eCSSUnit_Pixel); - return NS_OK; + nsSize size = GetSize(aPresContext); + float pixelWidth = aPresContext->AppUnitsToFloatCSSPixels(size.width); + aResult.SetFloatValue(pixelWidth, eCSSUnit_Pixel); + return NS_OK; } static nsresult GetHeight(nsPresContext* aPresContext, const nsMediaFeature*, nsCSSValue& aResult) { - nsSize size = GetSize(aPresContext); - float pixelHeight = aPresContext->AppUnitsToFloatCSSPixels(size.height); - aResult.SetFloatValue(pixelHeight, eCSSUnit_Pixel); - return NS_OK; + nsSize size = GetSize(aPresContext); + float pixelHeight = aPresContext->AppUnitsToFloatCSSPixels(size.height); + aResult.SetFloatValue(pixelHeight, eCSSUnit_Pixel); + return NS_OK; } inline static nsDeviceContext* @@ -112,81 +113,81 @@ GetDeviceContextFor(nsPresContext* aPresContext) static bool ShouldResistFingerprinting(nsPresContext* aPresContext) { - return nsContentUtils::ShouldResistFingerprinting(aPresContext->GetDocShell()); + return nsContentUtils::ShouldResistFingerprinting(aPresContext->GetDocShell()); } // A helper for three features below. static nsSize GetDeviceSize(nsPresContext* aPresContext) { - nsSize size; + nsSize size; - if (ShouldResistFingerprinting(aPresContext) || aPresContext->IsDeviceSizePageSize()) { - size = GetSize(aPresContext); - } else if (aPresContext->IsRootPaginatedDocument()) { - // We want the page size, including unprintable areas and margins. - // XXX The spec actually says we want the "page sheet size", but - // how is that different? - size = aPresContext->GetPageSize(); - } else { - GetDeviceContextFor(aPresContext)-> - GetDeviceSurfaceDimensions(size.width, size.height); - } - return size; + if (ShouldResistFingerprinting(aPresContext) || aPresContext->IsDeviceSizePageSize()) { + size = GetSize(aPresContext); + } else if (aPresContext->IsRootPaginatedDocument()) { + // We want the page size, including unprintable areas and margins. + // XXX The spec actually says we want the "page sheet size", but + // how is that different? + size = aPresContext->GetPageSize(); + } else { + GetDeviceContextFor(aPresContext)-> + GetDeviceSurfaceDimensions(size.width, size.height); + } + return size; } static nsresult GetDeviceWidth(nsPresContext* aPresContext, const nsMediaFeature*, nsCSSValue& aResult) { - nsSize size = GetDeviceSize(aPresContext); - float pixelWidth = aPresContext->AppUnitsToFloatCSSPixels(size.width); - aResult.SetFloatValue(pixelWidth, eCSSUnit_Pixel); - return NS_OK; + nsSize size = GetDeviceSize(aPresContext); + float pixelWidth = aPresContext->AppUnitsToFloatCSSPixels(size.width); + aResult.SetFloatValue(pixelWidth, eCSSUnit_Pixel); + return NS_OK; } static nsresult GetDeviceHeight(nsPresContext* aPresContext, const nsMediaFeature*, nsCSSValue& aResult) { - nsSize size = GetDeviceSize(aPresContext); - float pixelHeight = aPresContext->AppUnitsToFloatCSSPixels(size.height); - aResult.SetFloatValue(pixelHeight, eCSSUnit_Pixel); - return NS_OK; + nsSize size = GetDeviceSize(aPresContext); + float pixelHeight = aPresContext->AppUnitsToFloatCSSPixels(size.height); + aResult.SetFloatValue(pixelHeight, eCSSUnit_Pixel); + return NS_OK; } static nsresult GetOrientation(nsPresContext* aPresContext, const nsMediaFeature*, nsCSSValue& aResult) { - nsSize size = GetSize(aPresContext); - int32_t orientation; - if (size.width > size.height) { - orientation = NS_STYLE_ORIENTATION_LANDSCAPE; - } else { - // Per spec, square viewports should be 'portrait' - orientation = NS_STYLE_ORIENTATION_PORTRAIT; - } + nsSize size = GetSize(aPresContext); + int32_t orientation; + if (size.width > size.height) { + orientation = NS_STYLE_ORIENTATION_LANDSCAPE; + } else { + // Per spec, square viewports should be 'portrait' + orientation = NS_STYLE_ORIENTATION_PORTRAIT; + } - aResult.SetIntValue(orientation, eCSSUnit_Enumerated); - return NS_OK; + aResult.SetIntValue(orientation, eCSSUnit_Enumerated); + return NS_OK; } static nsresult GetDeviceOrientation(nsPresContext* aPresContext, const nsMediaFeature*, nsCSSValue& aResult) { - nsSize size = GetDeviceSize(aPresContext); - int32_t orientation; - if (size.width > size.height) { - orientation = NS_STYLE_ORIENTATION_LANDSCAPE; - } else { - // Per spec, square viewports should be 'portrait' - orientation = NS_STYLE_ORIENTATION_PORTRAIT; - } + nsSize size = GetDeviceSize(aPresContext); + int32_t orientation; + if (size.width > size.height) { + orientation = NS_STYLE_ORIENTATION_LANDSCAPE; + } else { + // Per spec, square viewports should be 'portrait' + orientation = NS_STYLE_ORIENTATION_PORTRAIT; + } - aResult.SetIntValue(orientation, eCSSUnit_Enumerated); - return NS_OK; + aResult.SetIntValue(orientation, eCSSUnit_Enumerated); + return NS_OK; } static nsresult @@ -202,207 +203,216 @@ GetIsResourceDocument(nsPresContext* aPresContext, const nsMediaFeature*, static nsresult MakeArray(const nsSize& aSize, nsCSSValue& aResult) { - RefPtr a = nsCSSValue::Array::Create(2); + RefPtr a = nsCSSValue::Array::Create(2); - a->Item(0).SetIntValue(aSize.width, eCSSUnit_Integer); - a->Item(1).SetIntValue(aSize.height, eCSSUnit_Integer); + a->Item(0).SetIntValue(aSize.width, eCSSUnit_Integer); + a->Item(1).SetIntValue(aSize.height, eCSSUnit_Integer); - aResult.SetArrayValue(a, eCSSUnit_Array); - return NS_OK; + aResult.SetArrayValue(a, eCSSUnit_Array); + return NS_OK; } static nsresult GetAspectRatio(nsPresContext* aPresContext, const nsMediaFeature*, nsCSSValue& aResult) { - return MakeArray(GetSize(aPresContext), aResult); + return MakeArray(GetSize(aPresContext), aResult); } static nsresult GetDeviceAspectRatio(nsPresContext* aPresContext, const nsMediaFeature*, nsCSSValue& aResult) { - return MakeArray(GetDeviceSize(aPresContext), aResult); + return MakeArray(GetDeviceSize(aPresContext), aResult); } static nsresult GetColor(nsPresContext* aPresContext, const nsMediaFeature*, nsCSSValue& aResult) { - uint32_t depth = 24; // Use depth of 24 when resisting fingerprinting. + uint32_t depth = 24; // Use depth of 24 when resisting fingerprinting. - if (!ShouldResistFingerprinting(aPresContext)) { - // FIXME: This implementation is bogus. nsDeviceContext - // doesn't provide reliable information (should be fixed in bug - // 424386). - // FIXME: On a monochrome device, return 0! - nsDeviceContext *dx = GetDeviceContextFor(aPresContext); - dx->GetDepth(depth); - } + if (!ShouldResistFingerprinting(aPresContext)) { + // FIXME: This implementation is bogus. nsDeviceContext + // doesn't provide reliable information (should be fixed in bug + // 424386). + // FIXME: On a monochrome device, return 0! + nsDeviceContext *dx = GetDeviceContextFor(aPresContext); + dx->GetDepth(depth); + } - // The spec says to use bits *per color component*, so divide by 3, - // and round down, since the spec says to use the smallest when the - // color components differ. - depth /= 3; - aResult.SetIntValue(int32_t(depth), eCSSUnit_Integer); - return NS_OK; + // The spec says to use bits *per color component*, so divide by 3, + // and round down, since the spec says to use the smallest when the + // color components differ. + depth /= 3; + aResult.SetIntValue(int32_t(depth), eCSSUnit_Integer); + return NS_OK; } static nsresult GetColorIndex(nsPresContext* aPresContext, const nsMediaFeature*, nsCSSValue& aResult) { - // We should return zero if the device does not use a color lookup - // table. Stuart says that our handling of displays with 8-bit - // color is bad enough that we never change the lookup table to - // match what we're trying to display, so perhaps we should always - // return zero. Given that there isn't any better information - // exposed, we don't have much other choice. - aResult.SetIntValue(0, eCSSUnit_Integer); - return NS_OK; + // We should return zero if the device does not use a color lookup + // table. Stuart says that our handling of displays with 8-bit + // color is bad enough that we never change the lookup table to + // match what we're trying to display, so perhaps we should always + // return zero. Given that there isn't any better information + // exposed, we don't have much other choice. + aResult.SetIntValue(0, eCSSUnit_Integer); + return NS_OK; } static nsresult GetMonochrome(nsPresContext* aPresContext, const nsMediaFeature*, nsCSSValue& aResult) { - // For color devices we should return 0. - // FIXME: On a monochrome device, return the actual color depth, not - // 0! - aResult.SetIntValue(0, eCSSUnit_Integer); - return NS_OK; + // For color devices we should return 0. + // FIXME: On a monochrome device, return the actual color depth, not + // 0! + aResult.SetIntValue(0, eCSSUnit_Integer); + return NS_OK; } static nsresult GetResolution(nsPresContext* aPresContext, const nsMediaFeature*, nsCSSValue& aResult) { - float dpi = 96; // Use 96 when resisting fingerprinting. + float dpi = 96; // Use 96 when resisting fingerprinting. - if (!ShouldResistFingerprinting(aPresContext)) { - // Resolution measures device pixels per CSS (inch/cm/pixel). We - // return it in device pixels per CSS inches. - dpi = float(nsPresContext::AppUnitsPerCSSInch()) / - float(aPresContext->AppUnitsPerDevPixel()); - } + if (!ShouldResistFingerprinting(aPresContext)) { + // Resolution measures device pixels per CSS (inch/cm/pixel). We + // return it in device pixels per CSS inches. + dpi = float(nsPresContext::AppUnitsPerCSSInch()) / + float(aPresContext->AppUnitsPerDevPixel()); + } - aResult.SetFloatValue(dpi, eCSSUnit_Inch); - return NS_OK; + aResult.SetFloatValue(dpi, eCSSUnit_Inch); + return NS_OK; } static nsresult GetScan(nsPresContext* aPresContext, const nsMediaFeature*, nsCSSValue& aResult) { - // Since Gecko doesn't support the 'tv' media type, the 'scan' - // feature is never present. - aResult.Reset(); - return NS_OK; + // Since Gecko doesn't support the 'tv' media type, the 'scan' + // feature is never present. + aResult.Reset(); + return NS_OK; } static nsresult GetGrid(nsPresContext* aPresContext, const nsMediaFeature*, nsCSSValue& aResult) { - // Gecko doesn't support grid devices (e.g., ttys), so the 'grid' - // feature is always 0. - aResult.SetIntValue(0, eCSSUnit_Integer); - return NS_OK; + // Gecko doesn't support grid devices (e.g., ttys), so the 'grid' + // feature is always 0. + aResult.SetIntValue(0, eCSSUnit_Integer); + return NS_OK; } static nsresult GetDevicePixelRatio(nsPresContext* aPresContext, const nsMediaFeature*, nsCSSValue& aResult) { - if (!ShouldResistFingerprinting(aPresContext)) { - float ratio = aPresContext->CSSPixelsToDevPixels(1.0f); - aResult.SetFloatValue(ratio, eCSSUnit_Number); - } else { - aResult.SetFloatValue(1.0, eCSSUnit_Number); - } - return NS_OK; + if (!ShouldResistFingerprinting(aPresContext)) { + float ratio = aPresContext->CSSPixelsToDevPixels(1.0f); + aResult.SetFloatValue(ratio, eCSSUnit_Number); + } else { + aResult.SetFloatValue(1.0, eCSSUnit_Number); + } + return NS_OK; +} + +static nsresult +GetTransform3d(nsPresContext* aPresContext, const nsMediaFeature*, + nsCSSValue& aResult) +{ + // Gecko supports 3d transforms, so this feature is always 1. + aResult.SetIntValue(1, eCSSUnit_Integer); + return NS_OK; } static nsresult GetSystemMetric(nsPresContext* aPresContext, const nsMediaFeature* aFeature, nsCSSValue& aResult) { - aResult.Reset(); - if (ShouldResistFingerprinting(aPresContext)) { - // If "privacy.resistFingerprinting" is enabled, then we simply don't - // return any system-backed media feature values. (No spoofed values returned.) - return NS_OK; - } - - MOZ_ASSERT(aFeature->mValueType == nsMediaFeature::eBoolInteger, - "unexpected type"); - nsIAtom *metricAtom = *aFeature->mData.mMetric; - bool hasMetric = nsCSSRuleProcessor::HasSystemMetric(metricAtom); - aResult.SetIntValue(hasMetric ? 1 : 0, eCSSUnit_Integer); + aResult.Reset(); + if (ShouldResistFingerprinting(aPresContext)) { + // If "privacy.resistFingerprinting" is enabled, then we simply don't + // return any system-backed media feature values. (No spoofed values returned.) return NS_OK; + } + + MOZ_ASSERT(aFeature->mValueType == nsMediaFeature::eBoolInteger, + "unexpected type"); + nsIAtom *metricAtom = *aFeature->mData.mMetric; + bool hasMetric = nsCSSRuleProcessor::HasSystemMetric(metricAtom); + aResult.SetIntValue(hasMetric ? 1 : 0, eCSSUnit_Integer); + return NS_OK; } static nsresult GetWindowsTheme(nsPresContext* aPresContext, const nsMediaFeature* aFeature, nsCSSValue& aResult) { - aResult.Reset(); - if (ShouldResistFingerprinting(aPresContext)) { - return NS_OK; - } + aResult.Reset(); + if (ShouldResistFingerprinting(aPresContext)) { + return NS_OK; + } #ifdef XP_WIN - uint8_t windowsThemeId = - nsCSSRuleProcessor::GetWindowsThemeIdentifier(); + uint8_t windowsThemeId = + nsCSSRuleProcessor::GetWindowsThemeIdentifier(); - // Classic mode should fail to match. - if (windowsThemeId == LookAndFeel::eWindowsTheme_Classic) - return NS_OK; - - // Look up the appropriate theme string - for (size_t i = 0; i < ArrayLength(themeStrings); ++i) { - if (windowsThemeId == themeStrings[i].id) { - aResult.SetStringValue(nsDependentString(themeStrings[i].name), - eCSSUnit_Ident); - break; - } - } -#endif + // Classic mode should fail to match. + if (windowsThemeId == LookAndFeel::eWindowsTheme_Classic) return NS_OK; + + // Look up the appropriate theme string + for (size_t i = 0; i < ArrayLength(themeStrings); ++i) { + if (windowsThemeId == themeStrings[i].id) { + aResult.SetStringValue(nsDependentString(themeStrings[i].name), + eCSSUnit_Ident); + break; + } + } +#endif + return NS_OK; } static nsresult GetOperatingSystemVersion(nsPresContext* aPresContext, const nsMediaFeature* aFeature, nsCSSValue& aResult) { - aResult.Reset(); - if (ShouldResistFingerprinting(aPresContext)) { - return NS_OK; - } + aResult.Reset(); + if (ShouldResistFingerprinting(aPresContext)) { + return NS_OK; + } #ifdef XP_WIN - int32_t metricResult; - if (NS_SUCCEEDED( - LookAndFeel::GetInt(LookAndFeel::eIntID_OperatingSystemVersionIdentifier, - &metricResult))) { - for (size_t i = 0; i < ArrayLength(osVersionStrings); ++i) { - if (metricResult == osVersionStrings[i].id) { - aResult.SetStringValue(nsDependentString(osVersionStrings[i].name), - eCSSUnit_Ident); - break; - } - } + int32_t metricResult; + if (NS_SUCCEEDED( + LookAndFeel::GetInt(LookAndFeel::eIntID_OperatingSystemVersionIdentifier, + &metricResult))) { + for (size_t i = 0; i < ArrayLength(osVersionStrings); ++i) { + if (metricResult == osVersionStrings[i].id) { + aResult.SetStringValue(nsDependentString(osVersionStrings[i].name), + eCSSUnit_Ident); + break; + } } + } #endif - return NS_OK; + return NS_OK; } static nsresult GetIsGlyph(nsPresContext* aPresContext, const nsMediaFeature* aFeature, nsCSSValue& aResult) { - aResult.SetIntValue(aPresContext->IsGlyph() ? 1 : 0, eCSSUnit_Integer); - return NS_OK; + aResult.SetIntValue(aPresContext->IsGlyph() ? 1 : 0, eCSSUnit_Integer); + return NS_OK; } /* @@ -416,360 +426,354 @@ GetIsGlyph(nsPresContext* aPresContext, const nsMediaFeature* aFeature, /* static */ const nsMediaFeature nsMediaFeatures::features[] = { - { - &nsGkAtoms::width, - nsMediaFeature::eMinMaxAllowed, - nsMediaFeature::eLength, - nsMediaFeature::eNoRequirements, - { nullptr }, - GetWidth - }, - { - &nsGkAtoms::height, - nsMediaFeature::eMinMaxAllowed, - nsMediaFeature::eLength, - nsMediaFeature::eNoRequirements, - { nullptr }, - GetHeight - }, - { - &nsGkAtoms::deviceWidth, - nsMediaFeature::eMinMaxAllowed, - nsMediaFeature::eLength, - nsMediaFeature::eNoRequirements, - { nullptr }, - GetDeviceWidth - }, - { - &nsGkAtoms::deviceHeight, - nsMediaFeature::eMinMaxAllowed, - nsMediaFeature::eLength, - nsMediaFeature::eNoRequirements, - { nullptr }, - GetDeviceHeight - }, - { - &nsGkAtoms::orientation, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eEnumerated, - nsMediaFeature::eNoRequirements, - { kOrientationKeywords }, - GetOrientation - }, - { - &nsGkAtoms::aspectRatio, - nsMediaFeature::eMinMaxAllowed, - nsMediaFeature::eIntRatio, - nsMediaFeature::eNoRequirements, - { nullptr }, - GetAspectRatio - }, - { - &nsGkAtoms::deviceAspectRatio, - nsMediaFeature::eMinMaxAllowed, - nsMediaFeature::eIntRatio, - nsMediaFeature::eNoRequirements, - { nullptr }, - GetDeviceAspectRatio - }, - { - &nsGkAtoms::color, - nsMediaFeature::eMinMaxAllowed, - nsMediaFeature::eInteger, - nsMediaFeature::eNoRequirements, - { nullptr }, - GetColor - }, - { - &nsGkAtoms::colorIndex, - nsMediaFeature::eMinMaxAllowed, - nsMediaFeature::eInteger, - nsMediaFeature::eNoRequirements, - { nullptr }, - GetColorIndex - }, - { - &nsGkAtoms::monochrome, - nsMediaFeature::eMinMaxAllowed, - nsMediaFeature::eInteger, - nsMediaFeature::eNoRequirements, - { nullptr }, - GetMonochrome - }, - { - &nsGkAtoms::resolution, - nsMediaFeature::eMinMaxAllowed, - nsMediaFeature::eResolution, - nsMediaFeature::eNoRequirements, - { nullptr }, - GetResolution - }, - { - &nsGkAtoms::scan, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eEnumerated, - nsMediaFeature::eNoRequirements, - { kScanKeywords }, - GetScan - }, - { - &nsGkAtoms::grid, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { nullptr }, - GetGrid - }, + { + &nsGkAtoms::width, + nsMediaFeature::eMinMaxAllowed, + nsMediaFeature::eLength, + nsMediaFeature::eNoRequirements, + { nullptr }, + GetWidth + }, + { + &nsGkAtoms::height, + nsMediaFeature::eMinMaxAllowed, + nsMediaFeature::eLength, + nsMediaFeature::eNoRequirements, + { nullptr }, + GetHeight + }, + { + &nsGkAtoms::deviceWidth, + nsMediaFeature::eMinMaxAllowed, + nsMediaFeature::eLength, + nsMediaFeature::eNoRequirements, + { nullptr }, + GetDeviceWidth + }, + { + &nsGkAtoms::deviceHeight, + nsMediaFeature::eMinMaxAllowed, + nsMediaFeature::eLength, + nsMediaFeature::eNoRequirements, + { nullptr }, + GetDeviceHeight + }, + { + &nsGkAtoms::orientation, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eEnumerated, + nsMediaFeature::eNoRequirements, + { kOrientationKeywords }, + GetOrientation + }, + { + &nsGkAtoms::aspectRatio, + nsMediaFeature::eMinMaxAllowed, + nsMediaFeature::eIntRatio, + nsMediaFeature::eNoRequirements, + { nullptr }, + GetAspectRatio + }, + { + &nsGkAtoms::deviceAspectRatio, + nsMediaFeature::eMinMaxAllowed, + nsMediaFeature::eIntRatio, + nsMediaFeature::eNoRequirements, + { nullptr }, + GetDeviceAspectRatio + }, + { + &nsGkAtoms::color, + nsMediaFeature::eMinMaxAllowed, + nsMediaFeature::eInteger, + nsMediaFeature::eNoRequirements, + { nullptr }, + GetColor + }, + { + &nsGkAtoms::colorIndex, + nsMediaFeature::eMinMaxAllowed, + nsMediaFeature::eInteger, + nsMediaFeature::eNoRequirements, + { nullptr }, + GetColorIndex + }, + { + &nsGkAtoms::monochrome, + nsMediaFeature::eMinMaxAllowed, + nsMediaFeature::eInteger, + nsMediaFeature::eNoRequirements, + { nullptr }, + GetMonochrome + }, + { + &nsGkAtoms::resolution, + nsMediaFeature::eMinMaxAllowed, + nsMediaFeature::eResolution, + nsMediaFeature::eNoRequirements, + { nullptr }, + GetResolution + }, + { + &nsGkAtoms::scan, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eEnumerated, + nsMediaFeature::eNoRequirements, + { kScanKeywords }, + GetScan + }, + { + &nsGkAtoms::grid, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { nullptr }, + GetGrid + }, - // Webkit extensions that we support for de-facto web compatibility - // -webkit-{min|max}-device-pixel-ratio: - { - &nsGkAtoms::devicePixelRatio, - nsMediaFeature::eMinMaxAllowed, - nsMediaFeature::eFloat, - nsMediaFeature::eHasWebkitPrefix, - { nullptr }, - GetDevicePixelRatio - }, + // Webkit extensions that we support for de-facto web compatibility + // -webkit-{min|max}-device-pixel-ratio (controlled with its own pref): + { + &nsGkAtoms::devicePixelRatio, + nsMediaFeature::eMinMaxAllowed, + nsMediaFeature::eFloat, + nsMediaFeature::eHasWebkitPrefix | + nsMediaFeature::eWebkitDevicePixelRatioPrefEnabled, + { nullptr }, + GetDevicePixelRatio + }, + // -webkit-transform-3d: + { + &nsGkAtoms::transform_3d, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eHasWebkitPrefix, + { nullptr }, + GetTransform3d + }, - // Mozilla extensions - { - &nsGkAtoms::_moz_device_pixel_ratio, - nsMediaFeature::eMinMaxAllowed, - nsMediaFeature::eFloat, - nsMediaFeature::eNoRequirements, - { nullptr }, - GetDevicePixelRatio - }, - { - &nsGkAtoms::_moz_device_orientation, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eEnumerated, - nsMediaFeature::eNoRequirements, - { kOrientationKeywords }, - GetDeviceOrientation - }, - { - &nsGkAtoms::_moz_is_resource_document, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { nullptr }, - GetIsResourceDocument - }, - { - &nsGkAtoms::_moz_color_picker_available, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::color_picker_available }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_scrollbar_start_backward, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::scrollbar_start_backward }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_scrollbar_start_forward, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::scrollbar_start_forward }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_scrollbar_end_backward, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::scrollbar_end_backward }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_scrollbar_end_forward, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::scrollbar_end_forward }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_scrollbar_thumb_proportional, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::scrollbar_thumb_proportional }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_images_in_menus, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::images_in_menus }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_images_in_buttons, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::images_in_buttons }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_overlay_scrollbars, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::overlay_scrollbars }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_windows_default_theme, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::windows_default_theme }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_mac_graphite_theme, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::mac_graphite_theme }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_mac_lion_theme, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::mac_lion_theme }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_mac_yosemite_theme, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::mac_yosemite_theme }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_windows_accent_color_applies, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::windows_accent_color_applies }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_windows_accent_color_is_dark, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::windows_accent_color_is_dark }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_windows_compositor, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::windows_compositor }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_windows_classic, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::windows_classic }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_windows_glass, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::windows_glass }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_touch_enabled, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::touch_enabled }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_menubar_drag, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::menubar_drag }, - GetSystemMetric - }, - { - &nsGkAtoms::_moz_windows_theme, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eIdent, - nsMediaFeature::eNoRequirements, - { nullptr }, - GetWindowsTheme - }, - { - &nsGkAtoms::_moz_os_version, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eIdent, - nsMediaFeature::eNoRequirements, - { nullptr }, - GetOperatingSystemVersion - }, + // Mozilla extensions + { + &nsGkAtoms::_moz_device_pixel_ratio, + nsMediaFeature::eMinMaxAllowed, + nsMediaFeature::eFloat, + nsMediaFeature::eNoRequirements, + { nullptr }, + GetDevicePixelRatio + }, + { + &nsGkAtoms::_moz_device_orientation, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eEnumerated, + nsMediaFeature::eNoRequirements, + { kOrientationKeywords }, + GetDeviceOrientation + }, + { + &nsGkAtoms::_moz_is_resource_document, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { nullptr }, + GetIsResourceDocument + }, + { + &nsGkAtoms::_moz_color_picker_available, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::color_picker_available }, + GetSystemMetric + }, + { + &nsGkAtoms::_moz_scrollbar_start_backward, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::scrollbar_start_backward }, + GetSystemMetric + }, + { + &nsGkAtoms::_moz_scrollbar_start_forward, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::scrollbar_start_forward }, + GetSystemMetric + }, + { + &nsGkAtoms::_moz_scrollbar_end_backward, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::scrollbar_end_backward }, + GetSystemMetric + }, + { + &nsGkAtoms::_moz_scrollbar_end_forward, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::scrollbar_end_forward }, + GetSystemMetric + }, + { + &nsGkAtoms::_moz_scrollbar_thumb_proportional, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::scrollbar_thumb_proportional }, + GetSystemMetric + }, + { + &nsGkAtoms::_moz_images_in_menus, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::images_in_menus }, + GetSystemMetric + }, + { + &nsGkAtoms::_moz_images_in_buttons, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::images_in_buttons }, + GetSystemMetric + }, + { + &nsGkAtoms::_moz_overlay_scrollbars, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::overlay_scrollbars }, + GetSystemMetric + }, + { + &nsGkAtoms::_moz_windows_default_theme, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::windows_default_theme }, + GetSystemMetric + }, + { + &nsGkAtoms::_moz_mac_graphite_theme, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::mac_graphite_theme }, + GetSystemMetric + }, + { + &nsGkAtoms::_moz_mac_lion_theme, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::mac_lion_theme }, + GetSystemMetric + }, + { + &nsGkAtoms::_moz_mac_yosemite_theme, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::mac_yosemite_theme }, + GetSystemMetric + }, + { + &nsGkAtoms::_moz_windows_compositor, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::windows_compositor }, + GetSystemMetric + }, + { + &nsGkAtoms::_moz_windows_classic, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::windows_classic }, + GetSystemMetric + }, + { + &nsGkAtoms::_moz_windows_glass, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::windows_glass }, + GetSystemMetric + }, + { + &nsGkAtoms::_moz_touch_enabled, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::touch_enabled }, + GetSystemMetric + }, + { + &nsGkAtoms::_moz_menubar_drag, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::menubar_drag }, + GetSystemMetric + }, + { + &nsGkAtoms::_moz_windows_theme, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eIdent, + nsMediaFeature::eNoRequirements, + { nullptr }, + GetWindowsTheme + }, + { + &nsGkAtoms::_moz_os_version, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eIdent, + nsMediaFeature::eNoRequirements, + { nullptr }, + GetOperatingSystemVersion + }, - { - &nsGkAtoms::_moz_swipe_animation_enabled, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::swipe_animation_enabled }, - GetSystemMetric - }, + { + &nsGkAtoms::_moz_swipe_animation_enabled, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::swipe_animation_enabled }, + GetSystemMetric + }, - { - &nsGkAtoms::_moz_physical_home_button, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { &nsGkAtoms::physical_home_button }, - GetSystemMetric - }, + { + &nsGkAtoms::_moz_physical_home_button, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { &nsGkAtoms::physical_home_button }, + GetSystemMetric + }, - // Internal -moz-is-glyph media feature: applies only inside SVG glyphs. - // Internal because it is really only useful in the user agent anyway - // and therefore not worth standardizing. - { - &nsGkAtoms::_moz_is_glyph, - nsMediaFeature::eMinMaxNotAllowed, - nsMediaFeature::eBoolInteger, - nsMediaFeature::eNoRequirements, - { nullptr }, - GetIsGlyph - }, - // Null-mName terminator: - { - nullptr, - nsMediaFeature::eMinMaxAllowed, - nsMediaFeature::eInteger, - nsMediaFeature::eNoRequirements, - { nullptr }, - nullptr - }, + // Internal -moz-is-glyph media feature: applies only inside SVG glyphs. + // Internal because it is really only useful in the user agent anyway + // and therefore not worth standardizing. + { + &nsGkAtoms::_moz_is_glyph, + nsMediaFeature::eMinMaxNotAllowed, + nsMediaFeature::eBoolInteger, + nsMediaFeature::eNoRequirements, + { nullptr }, + GetIsGlyph + }, + // Null-mName terminator: + { + nullptr, + nsMediaFeature::eMinMaxAllowed, + nsMediaFeature::eInteger, + nsMediaFeature::eNoRequirements, + { nullptr }, + nullptr + }, }; diff --git a/layout/style/nsMediaFeatures.h b/layout/style/nsMediaFeatures.h index 0d0403ea99..76e94837d6 100644 --- a/layout/style/nsMediaFeatures.h +++ b/layout/style/nsMediaFeatures.h @@ -1,4 +1,5 @@ -/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -20,64 +21,71 @@ typedef nsresult const nsMediaFeature* aFeature, nsCSSValue& aResult); -struct nsMediaFeature { - nsIAtom **mName; // extra indirection to point to nsGkAtoms members +struct nsMediaFeature +{ + nsIAtom **mName; // extra indirection to point to nsGkAtoms members - enum RangeType { eMinMaxAllowed, eMinMaxNotAllowed }; - RangeType mRangeType; + enum RangeType { eMinMaxAllowed, eMinMaxNotAllowed }; + RangeType mRangeType; - enum ValueType { - // All value types allow eCSSUnit_Null to indicate that no value - // was given (in addition to the types listed below). - eLength, // values are such that nsCSSValue::IsLengthUnit() is true - eInteger, // values are eCSSUnit_Integer - eFloat, // values are eCSSUnit_Number - eBoolInteger,// values are eCSSUnit_Integer (0, -0, or 1 only) - eIntRatio, // values are eCSSUnit_Array of two eCSSUnit_Integer - eResolution, // values are in eCSSUnit_Inch (for dpi), - // eCSSUnit_Pixel (for dppx), or - // eCSSUnit_Centimeter (for dpcm) - eEnumerated, // values are eCSSUnit_Enumerated (uses keyword table) - eIdent // values are eCSSUnit_Ident - // Note that a number of pieces of code (both for parsing and - // for matching of valueless expressions) assume that all numeric - // value types cannot be negative. The parsing code also does - // not allow zeros in eIntRatio types. - }; - ValueType mValueType; + enum ValueType { + // All value types allow eCSSUnit_Null to indicate that no value + // was given (in addition to the types listed below). + eLength, // values are such that nsCSSValue::IsLengthUnit() is true + eInteger, // values are eCSSUnit_Integer + eFloat, // values are eCSSUnit_Number + eBoolInteger,// values are eCSSUnit_Integer (0, -0, or 1 only) + eIntRatio, // values are eCSSUnit_Array of two eCSSUnit_Integer + eResolution, // values are in eCSSUnit_Inch (for dpi), + // eCSSUnit_Pixel (for dppx), or + // eCSSUnit_Centimeter (for dpcm) + eEnumerated, // values are eCSSUnit_Enumerated (uses keyword table) + eIdent // values are eCSSUnit_Ident + // Note that a number of pieces of code (both for parsing and + // for matching of valueless expressions) assume that all numeric + // value types cannot be negative. The parsing code also does + // not allow zeros in eIntRatio types. + }; + ValueType mValueType; - enum RequirementFlags : uint8_t { - // Bitfield of requirements that must be satisfied in order for this - // media feature to be active. - eNoRequirements = 0, - eHasWebkitPrefix = 1 // Feature name must start w/ "-webkit-", even - // before any "min-"/"max-" qualifier. - }; - uint8_t mReqFlags; + enum RequirementFlags : uint8_t { + // Bitfield of requirements that must be satisfied in order for this + // media feature to be active. + eNoRequirements = 0, + eHasWebkitPrefix = 1 << 0, // Feature name must start w/ "-webkit-", even + // before any "min-"/"max-" qualifier. - union { - // In static arrays, it's the first member that's initialized. We - // need that to be void* so we can initialize both other types. - // This member should never be accessed by name. - const void* mInitializer_; - // If mValueType == eEnumerated: const int32_t*: keyword table in - // the same format as the keyword tables in nsCSSProps. - const nsCSSProps::KTableEntry* mKeywordTable; - // If mGetter == GetSystemMetric (which implies mValueType == - // eBoolInteger): nsIAtom * const *, for the system metric. - nsIAtom * const * mMetric; - } mData; + // Feature is only supported if the pref + // "layout.css.prefixes.device-pixel-ratio-webkit" is enabled. + // (Should only be used for -webkit-device-pixel-ratio.) + eWebkitDevicePixelRatioPrefEnabled = 1 << 1 + }; + uint8_t mReqFlags; - // A function that returns the current value for this feature for a - // given presentation. If it returns eCSSUnit_Null, the feature is - // not present. - nsMediaFeatureValueGetter mGetter; + union { + // In static arrays, it's the first member that's initialized. We + // need that to be void* so we can initialize both other types. + // This member should never be accessed by name. + const void* mInitializer_; + // If mValueType == eEnumerated: const int32_t*: keyword table in + // the same format as the keyword tables in nsCSSProps. + const nsCSSProps::KTableEntry* mKeywordTable; + // If mGetter == GetSystemMetric (which implies mValueType == + // eBoolInteger): nsIAtom * const *, for the system metric. + nsIAtom * const * mMetric; + } mData; + + // A function that returns the current value for this feature for a + // given presentation. If it returns eCSSUnit_Null, the feature is + // not present. + nsMediaFeatureValueGetter mGetter; }; -class nsMediaFeatures { +class nsMediaFeatures +{ public: - // Terminated with an entry whose mName is null. - static const nsMediaFeature features[]; + // Terminated with an entry whose mName is null. + static const nsMediaFeature features[]; }; #endif /* !defined(nsMediaFeatures_h_) */ diff --git a/layout/style/nsROCSSPrimitiveValue.cpp b/layout/style/nsROCSSPrimitiveValue.cpp index 83a01651b1..7c66d0b203 100644 --- a/layout/style/nsROCSSPrimitiveValue.cpp +++ b/layout/style/nsROCSSPrimitiveValue.cpp @@ -1,4 +1,5 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -526,9 +527,9 @@ nsROCSSPrimitiveValue::GetRGBColorValue(ErrorResult& aRv) void nsROCSSPrimitiveValue::SetNumber(float aValue) { - Reset(); - mValue.mFloat = aValue; - mType = CSS_NUMBER; + Reset(); + mValue.mFloat = aValue; + mType = CSS_NUMBER; } void diff --git a/layout/style/nsStyleContext.cpp b/layout/style/nsStyleContext.cpp index ff108b956a..b61ae63276 100644 --- a/layout/style/nsStyleContext.cpp +++ b/layout/style/nsStyleContext.cpp @@ -5,6 +5,7 @@ /* the interface (to internal code) for retrieving computed style data */ +#include "CSSVariableImageTable.h" #include "mozilla/DebugOnly.h" #include "nsCSSAnonBoxes.h" @@ -167,6 +168,9 @@ nsStyleContext::~nsStyleContext() if (mCachedResetData) { mCachedResetData->Destroy(mBits, presContext); } + + // Free any ImageValues we were holding on to for CSS variable values. + CSSVariableImageTable::RemoveAll(this); } #ifdef DEBUG @@ -600,7 +604,7 @@ nsStyleContext::ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup) presContext->StyleSet()->ResolveStyleFor(docElement, nullptr); auto dir = rootStyle->StyleVisibility()->mDirection; if (dir != StyleVisibility()->mDirection) { - nsStyleVisibility* uniqueVisibility = + nsStyleVisibility* uniqueVisibility = (nsStyleVisibility*)GetUniqueStyleData(eStyleStruct_Visibility); uniqueVisibility->mDirection = dir; } @@ -1596,6 +1600,6 @@ nsStyleContext::Initialize() { Preferences::AddBoolVarCache( &sExpensiveStyleStructAssertionsEnabled, - "layout.css.expensive-style-struct-assertions.enabed"); + "layout.css.expensive-style-struct-assertions.enabled"); } #endif diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 9230c6b663..f71ac549a8 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -1,4 +1,5 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -820,44 +821,43 @@ nsChangeHint nsStyleColumn::CalcDifference(const nsStyleColumn& aOther) const // -------------------- // nsStyleSVG // -nsStyleSVG::nsStyleSVG() +nsStyleSVG::nsStyleSVG() { - MOZ_COUNT_CTOR(nsStyleSVG); - mFill.mType = eStyleSVGPaintType_Color; - mFill.mPaint.mColor = NS_RGB(0,0,0); - mFill.mFallbackColor = NS_RGB(0,0,0); - mStroke.mType = eStyleSVGPaintType_None; - mStroke.mPaint.mColor = NS_RGB(0,0,0); - mStroke.mFallbackColor = NS_RGB(0,0,0); - mStrokeDasharray = nullptr; + MOZ_COUNT_CTOR(nsStyleSVG); + mFill.mType = eStyleSVGPaintType_Color; + mFill.mPaint.mColor = NS_RGB(0,0,0); + mFill.mFallbackColor = NS_RGB(0,0,0); + mStroke.mType = eStyleSVGPaintType_None; + mStroke.mPaint.mColor = NS_RGB(0,0,0); + mStroke.mFallbackColor = NS_RGB(0,0,0); + mStrokeDasharray = nullptr; - mStrokeDashoffset.SetCoordValue(0); - mStrokeWidth.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1)); + mStrokeDashoffset.SetCoordValue(0); + mStrokeWidth.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1)); - mFillOpacity = 1.0f; - mStrokeMiterlimit = 4.0f; - mStrokeOpacity = 1.0f; + mFillOpacity = 1.0f; + mStrokeMiterlimit = 4.0f; + mStrokeOpacity = 1.0f; - mStrokeDasharrayLength = 0; - mClipRule = NS_STYLE_FILL_RULE_NONZERO; - mColorInterpolation = NS_STYLE_COLOR_INTERPOLATION_SRGB; - mColorInterpolationFilters = NS_STYLE_COLOR_INTERPOLATION_LINEARRGB; - mFillRule = NS_STYLE_FILL_RULE_NONZERO; - mImageRendering = NS_STYLE_IMAGE_RENDERING_AUTO; - mPaintOrder = NS_STYLE_PAINT_ORDER_NORMAL; - mShapeRendering = NS_STYLE_SHAPE_RENDERING_AUTO; - mStrokeLinecap = NS_STYLE_STROKE_LINECAP_BUTT; - mStrokeLinejoin = NS_STYLE_STROKE_LINEJOIN_MITER; - mTextAnchor = NS_STYLE_TEXT_ANCHOR_START; - mTextRendering = NS_STYLE_TEXT_RENDERING_AUTO; - mFillOpacitySource = eStyleSVGOpacitySource_Normal; - mStrokeOpacitySource = eStyleSVGOpacitySource_Normal; - mStrokeDasharrayFromObject = false; - mStrokeDashoffsetFromObject = false; - mStrokeWidthFromObject = false; -} - -nsStyleSVG::~nsStyleSVG() + mStrokeDasharrayLength = 0; + mClipRule = NS_STYLE_FILL_RULE_NONZERO; + mColorInterpolation = NS_STYLE_COLOR_INTERPOLATION_SRGB; + mColorInterpolationFilters = NS_STYLE_COLOR_INTERPOLATION_LINEARRGB; + mFillRule = NS_STYLE_FILL_RULE_NONZERO; + mImageRendering = NS_STYLE_IMAGE_RENDERING_AUTO; + mPaintOrder = NS_STYLE_PAINT_ORDER_NORMAL; + mShapeRendering = NS_STYLE_SHAPE_RENDERING_AUTO; + mStrokeLinecap = NS_STYLE_STROKE_LINECAP_BUTT; + mStrokeLinejoin = NS_STYLE_STROKE_LINEJOIN_MITER; + mTextAnchor = NS_STYLE_TEXT_ANCHOR_START; + mTextRendering = NS_STYLE_TEXT_RENDERING_AUTO; + mFillOpacitySource = eStyleSVGOpacitySource_Normal; + mStrokeOpacitySource = eStyleSVGOpacitySource_Normal; + mStrokeDasharrayFromObject = false; + mStrokeDashoffsetFromObject = false; + mStrokeWidthFromObject = false; +} +nsStyleSVG::~nsStyleSVG() { MOZ_COUNT_DTOR(nsStyleSVG); delete [] mStrokeDasharray; @@ -1240,21 +1240,21 @@ nsStyleFilter::SetDropShadow(nsCSSShadowArray* aDropShadow) // -------------------- // nsStyleSVGReset // -nsStyleSVGReset::nsStyleSVGReset() +nsStyleSVGReset::nsStyleSVGReset() { - MOZ_COUNT_CTOR(nsStyleSVGReset); - mStopColor = NS_RGB(0,0,0); - mFloodColor = NS_RGB(0,0,0); - mLightingColor = NS_RGB(255,255,255); - 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; + MOZ_COUNT_CTOR(nsStyleSVGReset); + mStopColor = NS_RGB(0,0,0); + mFloodColor = NS_RGB(0,0,0); + mLightingColor = NS_RGB(255,255,255); + 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() +nsStyleSVGReset::~nsStyleSVGReset() { MOZ_COUNT_DTOR(nsStyleSVGReset); } diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 3b79073f2b..927696e541 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -1,4 +1,5 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -97,7 +98,8 @@ static_assert(int(mozilla::SheetType::Count) - 1 <= // The lifetime of these objects is managed by the presshell's arena. -struct nsStyleFont { +struct nsStyleFont +{ nsStyleFont(const nsFont& aFont, nsPresContext *aPresContext); nsStyleFont(const nsStyleFont& aStyleFont); explicit nsStyleFont(nsPresContext *aPresContext); @@ -174,7 +176,8 @@ struct nsStyleFont { nsCOMPtr mLanguage; // [inherited] }; -struct nsStyleGradientStop { +struct nsStyleGradientStop +{ nsStyleCoord mLocation; // percent, coord, calc, none nscolor mColor; bool mIsInterpolationHint; @@ -184,7 +187,8 @@ struct nsStyleGradientStop { bool operator!=(const nsStyleGradientStop&) const = delete; }; -class nsStyleGradient final { +class nsStyleGradient final +{ public: nsStyleGradient(); uint8_t mShape; // NS_STYLE_GRADIENT_SHAPE_* @@ -239,7 +243,8 @@ enum nsStyleImageType { * region of an image. (Currently, this feature is only supported with an * image of type (1)). */ -struct nsStyleImage { +struct nsStyleImage +{ nsStyleImage(); ~nsStyleImage(); nsStyleImage(const nsStyleImage& aOther); @@ -360,7 +365,8 @@ private: #endif }; -struct nsStyleColor { +struct nsStyleColor +{ explicit nsStyleColor(nsPresContext* aPresContext); nsStyleColor(const nsStyleColor& aOther); ~nsStyleColor(void) { @@ -392,7 +398,8 @@ struct nsStyleColor { nscolor mColor; // [inherited] }; -struct nsStyleBackground { +struct nsStyleBackground +{ nsStyleBackground(); nsStyleBackground(const nsStyleBackground& aOther); ~nsStyleBackground(); @@ -629,7 +636,8 @@ struct nsStyleBackground { #define NS_SPACING_BORDER 2 -struct nsStyleMargin { +struct nsStyleMargin +{ nsStyleMargin(void); nsStyleMargin(const nsStyleMargin& aMargin); ~nsStyleMargin(void) { @@ -673,7 +681,8 @@ protected: }; -struct nsStylePadding { +struct nsStylePadding +{ nsStylePadding(void); nsStylePadding(const nsStylePadding& aPadding); ~nsStylePadding(void) { @@ -721,7 +730,8 @@ protected: nsMargin mCachedPadding; }; -struct nsBorderColors { +struct nsBorderColors +{ nsBorderColors* mNext; nscolor mColor; @@ -750,7 +760,8 @@ private: nsBorderColors* Clone(bool aDeep) const; }; -struct nsCSSShadowItem { +struct nsCSSShadowItem +{ nscoord mXOffset; nscoord mYOffset; nscoord mRadius; @@ -781,74 +792,75 @@ struct nsCSSShadowItem { } }; -class nsCSSShadowArray final { - public: - void* operator new(size_t aBaseSize, uint32_t aArrayLen) { - // We can allocate both this nsCSSShadowArray and the - // actual array in one allocation. The amount of memory to - // allocate is equal to the class's size + the number of bytes for all - // but the first array item (because aBaseSize includes one - // item, see the private declarations) - return ::operator new(aBaseSize + - (aArrayLen - 1) * sizeof(nsCSSShadowItem)); - } +class nsCSSShadowArray final +{ +public: + void* operator new(size_t aBaseSize, uint32_t aArrayLen) { + // We can allocate both this nsCSSShadowArray and the + // actual array in one allocation. The amount of memory to + // allocate is equal to the class's size + the number of bytes for all + // but the first array item (because aBaseSize includes one + // item, see the private declarations) + return ::operator new(aBaseSize + + (aArrayLen - 1) * sizeof(nsCSSShadowItem)); + } - explicit nsCSSShadowArray(uint32_t aArrayLen) : - mLength(aArrayLen) - { - MOZ_COUNT_CTOR(nsCSSShadowArray); - for (uint32_t i = 1; i < mLength; ++i) { - // Make sure we call the constructors of each nsCSSShadowItem - // (the first one is called for us because we declared it under private) - new (&mArray[i]) nsCSSShadowItem(); - } + explicit nsCSSShadowArray(uint32_t aArrayLen) : + mLength(aArrayLen) + { + MOZ_COUNT_CTOR(nsCSSShadowArray); + for (uint32_t i = 1; i < mLength; ++i) { + // Make sure we call the constructors of each nsCSSShadowItem + // (the first one is called for us because we declared it under private) + new (&mArray[i]) nsCSSShadowItem(); } + } private: - // Private destructor, to discourage deletion outside of Release(): - ~nsCSSShadowArray() { - MOZ_COUNT_DTOR(nsCSSShadowArray); - for (uint32_t i = 1; i < mLength; ++i) { - mArray[i].~nsCSSShadowItem(); - } + // Private destructor, to discourage deletion outside of Release(): + ~nsCSSShadowArray() { + MOZ_COUNT_DTOR(nsCSSShadowArray); + for (uint32_t i = 1; i < mLength; ++i) { + mArray[i].~nsCSSShadowItem(); } + } public: - uint32_t Length() const { return mLength; } - nsCSSShadowItem* ShadowAt(uint32_t i) { - MOZ_ASSERT(i < mLength, "Accessing too high an index in the text shadow array!"); - return &mArray[i]; - } - const nsCSSShadowItem* ShadowAt(uint32_t i) const { - MOZ_ASSERT(i < mLength, "Accessing too high an index in the text shadow array!"); - return &mArray[i]; - } + uint32_t Length() const { return mLength; } + nsCSSShadowItem* ShadowAt(uint32_t i) { + MOZ_ASSERT(i < mLength, "Accessing too high an index in the text shadow array!"); + return &mArray[i]; + } + const nsCSSShadowItem* ShadowAt(uint32_t i) const { + MOZ_ASSERT(i < mLength, "Accessing too high an index in the text shadow array!"); + return &mArray[i]; + } - bool HasShadowWithInset(bool aInset) { - for (uint32_t i = 0; i < mLength; ++i) { - if (mArray[i].mInset == aInset) - return true; - } + bool HasShadowWithInset(bool aInset) { + for (uint32_t i = 0; i < mLength; ++i) { + if (mArray[i].mInset == aInset) + return true; + } + return false; + } + + bool operator==(const nsCSSShadowArray& aOther) const { + if (mLength != aOther.Length()) return false; - } - bool operator==(const nsCSSShadowArray& aOther) const { - if (mLength != aOther.Length()) + for (uint32_t i = 0; i < mLength; ++i) { + if (ShadowAt(i) != aOther.ShadowAt(i)) return false; - - for (uint32_t i = 0; i < mLength; ++i) { - if (ShadowAt(i) != aOther.ShadowAt(i)) - return false; - } - - return true; } - NS_INLINE_DECL_REFCOUNTING(nsCSSShadowArray) + return true; + } - private: - uint32_t mLength; - nsCSSShadowItem mArray[1]; // This MUST be the last item + NS_INLINE_DECL_REFCOUNTING(nsCSSShadowArray) + +private: + uint32_t mLength; + nsCSSShadowItem mArray[1]; // This MUST be the last item }; // Border widths are rounded to the nearest-below integer number of pixels, @@ -871,7 +883,8 @@ static bool IsVisibleBorderStyle(uint8_t aStyle) aStyle != NS_STYLE_BORDER_STYLE_HIDDEN); } -struct nsStyleBorder { +struct nsStyleBorder +{ explicit nsStyleBorder(nsPresContext* aContext); nsStyleBorder(const nsStyleBorder& aBorder); ~nsStyleBorder(); @@ -1097,7 +1110,8 @@ private: }; -struct nsStyleOutline { +struct nsStyleOutline +{ explicit nsStyleOutline(nsPresContext* aPresContext); nsStyleOutline(const nsStyleOutline& aOutline); ~nsStyleOutline(void) { @@ -1195,7 +1209,8 @@ protected: }; -struct nsStyleList { +struct nsStyleList +{ explicit nsStyleList(nsPresContext* aPresContext); nsStyleList(const nsStyleList& aStyleList); ~nsStyleList(void); @@ -1261,7 +1276,8 @@ public: nsRect mImageRegion; // [inherited] the rect to use within an image }; -struct nsStyleGridLine { +struct nsStyleGridLine +{ // http://dev.w3.org/csswg/css-grid/#typedef-grid-line // XXXmats we could optimize memory size here bool mHasSpan; @@ -1322,7 +1338,8 @@ struct nsStyleGridLine { } }; -struct nsStyleTextOverflowSide { +struct nsStyleTextOverflowSide +{ nsStyleTextOverflowSide() : mType(NS_STYLE_TEXT_OVERFLOW_CLIP) {} bool operator==(const nsStyleTextOverflowSide& aOther) const { @@ -1338,7 +1355,8 @@ struct nsStyleTextOverflowSide { uint8_t mType; }; -struct nsStyleTextOverflow { +struct nsStyleTextOverflow +{ nsStyleTextOverflow() : mLogicalDirections(true) {} bool operator==(const nsStyleTextOverflow& aOther) const { return mLeft == aOther.mLeft && mRight == aOther.mRight; @@ -1378,7 +1396,8 @@ struct nsStyleTextOverflow { bool mLogicalDirections; // true when only one value was specified }; -struct nsStyleTextReset { +struct nsStyleTextReset +{ nsStyleTextReset(void); nsStyleTextReset(const nsStyleTextReset& aOther); ~nsStyleTextReset(void); @@ -1455,7 +1474,8 @@ protected: nscolor mTextDecorationColor; // [reset] the colors to use for a decoration lines, not used at currentColor }; -struct nsStyleText { +struct nsStyleText +{ explicit nsStyleText(nsPresContext* aPresContext); nsStyleText(const nsStyleText& aOther); ~nsStyleText(void); @@ -1566,7 +1586,8 @@ struct nsStyleText { mozilla::LogicalSide TextEmphasisSide(mozilla::WritingMode aWM) const; }; -struct nsStyleImageOrientation { +struct nsStyleImageOrientation +{ static nsStyleImageOrientation CreateAsAngleAndFlip(double aRadians, bool aFlip) { uint8_t orientation(0); @@ -1658,7 +1679,8 @@ protected: uint8_t mOrientation; }; -struct nsStyleVisibility { +struct nsStyleVisibility +{ explicit nsStyleVisibility(nsPresContext* aPresContext); nsStyleVisibility(const nsStyleVisibility& aVisibility); ~nsStyleVisibility() { @@ -1706,7 +1728,8 @@ struct nsStyleVisibility { inline uint8_t GetEffectivePointerEvents(nsIFrame* aFrame) const; }; -struct nsTimingFunction { +struct nsTimingFunction +{ enum class Type { Ease, // ease @@ -1833,7 +1856,8 @@ private: namespace mozilla { -struct StyleTransition { +struct StyleTransition +{ StyleTransition() { /* leaves uninitialized; see also SetInitialValues */ } explicit StyleTransition(const StyleTransition& aCopy); @@ -1887,7 +1911,8 @@ private: // eCSSPropertyExtra_variable }; -struct StyleAnimation { +struct StyleAnimation +{ StyleAnimation() { /* leaves uninitialized; see also SetInitialValues */ } explicit StyleAnimation(const StyleAnimation& aCopy); @@ -1934,7 +1959,8 @@ private: } // namespace mozilla -struct nsStyleDisplay { +struct nsStyleDisplay +{ nsStyleDisplay(); nsStyleDisplay(const nsStyleDisplay& aOther); ~nsStyleDisplay() { @@ -2213,7 +2239,8 @@ struct nsStyleDisplay { inline uint8_t PhysicalBreakType(mozilla::WritingMode aWM) const; }; -struct nsStyleTable { +struct nsStyleTable +{ nsStyleTable(void); nsStyleTable(const nsStyleTable& aOther); ~nsStyleTable(void); @@ -2282,7 +2309,8 @@ struct nsStyleTable { // when there is no track, i.e. when mRepeatAutoIndex == -1). // When mIsSubgrid is true, mRepeatAutoLineNameListBefore contains the line // names and mRepeatAutoLineNameListAfter is empty. -struct nsStyleGridTemplate { +struct nsStyleGridTemplate +{ nsTArray> mLineNameLists; nsTArray mMinTrackSizingFunctions; nsTArray mMaxTrackSizingFunctions; @@ -2321,7 +2349,8 @@ struct nsStyleGridTemplate { } }; -struct nsStylePosition { +struct nsStylePosition +{ nsStylePosition(void); nsStylePosition(const nsStylePosition& aOther); ~nsStylePosition(void); @@ -2512,7 +2541,8 @@ private: }; -struct nsStyleTableBorder { +struct nsStyleTableBorder +{ nsStyleTableBorder(); nsStyleTableBorder(const nsStyleTableBorder& aOther); ~nsStyleTableBorder(void); @@ -2560,7 +2590,8 @@ enum nsStyleContentType { eStyleContentType_Uninitialized }; -struct nsStyleContentData { +struct nsStyleContentData +{ nsStyleContentType mType; union { char16_t *mString; @@ -2600,7 +2631,8 @@ private: nsStyleContentData(const nsStyleContentData&); // not to be implemented }; -struct nsStyleCounterData { +struct nsStyleCounterData +{ nsString mCounter; int32_t mValue; }; @@ -2608,7 +2640,8 @@ struct nsStyleCounterData { #define DELETE_ARRAY_IF(array) if (array) { delete[] array; array = nullptr; } -struct nsStyleQuotes { +struct nsStyleQuotes +{ nsStyleQuotes(); nsStyleQuotes(const nsStyleQuotes& aQuotes); ~nsStyleQuotes(); @@ -2690,7 +2723,8 @@ protected: nsString* mQuotes; }; -struct nsStyleContent { +struct nsStyleContent +{ nsStyleContent(void); nsStyleContent(const nsStyleContent& aContent); ~nsStyleContent(void); @@ -2799,7 +2833,8 @@ protected: uint32_t mResetCount; }; -struct nsStyleUIReset { +struct nsStyleUIReset +{ nsStyleUIReset(void); nsStyleUIReset(const nsStyleUIReset& aOther); ~nsStyleUIReset(void); @@ -2832,7 +2867,8 @@ struct nsStyleUIReset { uint8_t mWindowShadow; // [reset] }; -struct nsCursorImage { +struct nsCursorImage +{ bool mHaveHotspot; float mHotspotX, mHotspotY; @@ -2861,7 +2897,8 @@ private: nsCOMPtr mImage; }; -struct nsStyleUserInterface { +struct nsStyleUserInterface +{ nsStyleUserInterface(void); nsStyleUserInterface(const nsStyleUserInterface& aOther); ~nsStyleUserInterface(void); @@ -2908,7 +2945,8 @@ struct nsStyleUserInterface { void CopyCursorArrayFrom(const nsStyleUserInterface& aSource); }; -struct nsStyleXUL { +struct nsStyleXUL +{ nsStyleXUL(); nsStyleXUL(const nsStyleXUL& aSource); ~nsStyleXUL(); @@ -2944,7 +2982,8 @@ struct nsStyleXUL { bool mStretchStack; // [reset] see nsStyleConsts.h }; -struct nsStyleColumn { +struct nsStyleColumn +{ explicit nsStyleColumn(nsPresContext* aPresContext); nsStyleColumn(const nsStyleColumn& aSource); ~nsStyleColumn(); @@ -3037,7 +3076,8 @@ struct nsStyleSVGPaint } }; -struct nsStyleSVG { +struct nsStyleSVG +{ nsStyleSVG(); nsStyleSVG(const nsStyleSVG& aSource); ~nsStyleSVG(); @@ -3124,7 +3164,8 @@ struct nsStyleSVG { } }; -class nsStyleBasicShape final { +class nsStyleBasicShape final +{ public: enum Type { eInset, @@ -3266,7 +3307,8 @@ private: uint8_t mSizingBox; // see NS_STYLE_CLIP_SHAPE_SIZING_* constants in nsStyleConsts.h }; -struct nsStyleFilter { +struct nsStyleFilter +{ nsStyleFilter(); nsStyleFilter(const nsStyleFilter& aSource); ~nsStyleFilter(); @@ -3315,11 +3357,13 @@ private: }; template<> -struct nsTArray_CopyChooser { +struct nsTArray_CopyChooser +{ typedef nsTArray_CopyWithConstructors Type; }; -struct nsStyleSVGReset { +struct nsStyleSVGReset +{ nsStyleSVGReset(); nsStyleSVGReset(const nsStyleSVGReset& aSource); ~nsStyleSVGReset(); @@ -3370,7 +3414,8 @@ struct nsStyleSVGReset { uint8_t mMaskType; // [reset] see nsStyleConsts.h }; -struct nsStyleVariables { +struct nsStyleVariables +{ nsStyleVariables(); nsStyleVariables(const nsStyleVariables& aSource); ~nsStyleVariables(); diff --git a/layout/style/nsStyleTransformMatrix.cpp b/layout/style/nsStyleTransformMatrix.cpp index d4a3916f37..d0ef7512bd 100644 --- a/layout/style/nsStyleTransformMatrix.cpp +++ b/layout/style/nsStyleTransformMatrix.cpp @@ -279,7 +279,8 @@ ProcessInterpolateMatrix(Matrix4x4& aMatrix, nsStyleContext* aContext, nsPresContext* aPresContext, RuleNodeCacheConditions& aConditions, - TransformReferenceBox& aRefBox) + TransformReferenceBox& aRefBox, + bool* aContains3dTransform) { NS_PRECONDITION(aData->Count() == 4, "Invalid array!"); @@ -288,13 +289,15 @@ ProcessInterpolateMatrix(Matrix4x4& aMatrix, matrix1 = nsStyleTransformMatrix::ReadTransforms(aData->Item(1).GetListValue(), aContext, aPresContext, aConditions, - aRefBox, nsPresContext::AppUnitsPerCSSPixel()); + aRefBox, nsPresContext::AppUnitsPerCSSPixel(), + aContains3dTransform); } if (aData->Item(2).GetUnit() == eCSSUnit_List) { matrix2 = ReadTransforms(aData->Item(2).GetListValue(), aContext, aPresContext, aConditions, - aRefBox, nsPresContext::AppUnitsPerCSSPixel()); + aRefBox, nsPresContext::AppUnitsPerCSSPixel(), + aContains3dTransform); } double progress = aData->Item(3).GetPercentValue(); @@ -614,8 +617,10 @@ MatrixForTransformFunction(Matrix4x4& aMatrix, nsStyleContext* aContext, nsPresContext* aPresContext, RuleNodeCacheConditions& aConditions, - TransformReferenceBox& aRefBox) + TransformReferenceBox& aRefBox, + bool* aContains3dTransform) { + MOZ_ASSERT(aContains3dTransform); NS_PRECONDITION(aData, "Why did you want to get data from a null array?"); // It's OK if aContext and aPresContext are null if the caller already // knows that all length units have been converted to pixels (as @@ -633,6 +638,7 @@ MatrixForTransformFunction(Matrix4x4& aMatrix, aConditions, aRefBox); break; case eCSSKeyword_translatez: + *aContains3dTransform = true; ProcessTranslateZ(aMatrix, aData, aContext, aPresContext, aConditions); break; @@ -641,6 +647,7 @@ MatrixForTransformFunction(Matrix4x4& aMatrix, aConditions, aRefBox); break; case eCSSKeyword_translate3d: + *aContains3dTransform = true; ProcessTranslate3D(aMatrix, aData, aContext, aPresContext, aConditions, aRefBox); break; @@ -651,12 +658,14 @@ MatrixForTransformFunction(Matrix4x4& aMatrix, ProcessScaleY(aMatrix, aData); break; case eCSSKeyword_scalez: + *aContains3dTransform = true; ProcessScaleZ(aMatrix, aData); break; case eCSSKeyword_scale: ProcessScale(aMatrix, aData); break; case eCSSKeyword_scale3d: + *aContains3dTransform = true; ProcessScale3D(aMatrix, aData); break; case eCSSKeyword_skewx: @@ -669,16 +678,20 @@ MatrixForTransformFunction(Matrix4x4& aMatrix, ProcessSkew(aMatrix, aData); break; case eCSSKeyword_rotatex: + *aContains3dTransform = true; ProcessRotateX(aMatrix, aData); break; case eCSSKeyword_rotatey: + *aContains3dTransform = true; ProcessRotateY(aMatrix, aData); break; case eCSSKeyword_rotatez: + *aContains3dTransform = true; case eCSSKeyword_rotate: ProcessRotateZ(aMatrix, aData); break; case eCSSKeyword_rotate3d: + *aContains3dTransform = true; ProcessRotate3D(aMatrix, aData); break; case eCSSKeyword_matrix: @@ -686,14 +699,17 @@ MatrixForTransformFunction(Matrix4x4& aMatrix, aConditions, aRefBox); break; case eCSSKeyword_matrix3d: + *aContains3dTransform = true; ProcessMatrix3D(aMatrix, aData, aContext, aPresContext, aConditions, aRefBox); break; case eCSSKeyword_interpolatematrix: ProcessInterpolateMatrix(aMatrix, aData, aContext, aPresContext, - aConditions, aRefBox); + aConditions, aRefBox, + aContains3dTransform); break; case eCSSKeyword_perspective: + *aContains3dTransform = true; ProcessPerspective(aMatrix, aData, aContext, aPresContext, aConditions); break; @@ -719,7 +735,8 @@ ReadTransforms(const nsCSSValueList* aList, nsPresContext* aPresContext, RuleNodeCacheConditions& aConditions, TransformReferenceBox& aRefBox, - float aAppUnitsPerMatrixUnit) + float aAppUnitsPerMatrixUnit, + bool* aContains3dTransform) { Matrix4x4 result; @@ -737,13 +754,14 @@ ReadTransforms(const nsCSSValueList* aList, /* Read in a single transform matrix. */ MatrixForTransformFunction(result, currElem.GetArrayValue(), aContext, - aPresContext, aConditions, aRefBox); + aPresContext, aConditions, aRefBox, + aContains3dTransform); } float scale = float(nsPresContext::AppUnitsPerCSSPixel()) / aAppUnitsPerMatrixUnit; result.PreScale(1/scale, 1/scale, 1/scale); result.PostScale(scale, scale, scale); - + return result; } diff --git a/layout/style/nsStyleTransformMatrix.h b/layout/style/nsStyleTransformMatrix.h index 0c2580cfc1..a03a0cfd50 100644 --- a/layout/style/nsStyleTransformMatrix.h +++ b/layout/style/nsStyleTransformMatrix.h @@ -140,7 +140,8 @@ namespace nsStyleTransformMatrix { nsStyleContext* aContext, nsPresContext* aPresContext, mozilla::RuleNodeCacheConditions& aConditions, - TransformReferenceBox& aBounds); + TransformReferenceBox& aBounds, + bool* aContains3dTransform); /** * Given an nsCSSValueList containing -moz-transform functions, @@ -153,6 +154,9 @@ namespace nsStyleTransformMatrix { * result cannot be cached in the rule tree, otherwise untouched. * @param aBounds The frame's bounding rectangle. * @param aAppUnitsPerMatrixUnit The number of app units per device pixel. + * @param aContains3dTransform [out] Set to true if aList contains at least + * one 3d transform function (as defined in the CSS transforms + * specification), false otherwise. * * aContext and aPresContext may be null if all of the (non-percent) * length values in aData are already known to have been converted to @@ -163,8 +167,8 @@ namespace nsStyleTransformMatrix { nsPresContext* aPresContext, mozilla::RuleNodeCacheConditions& aConditions, TransformReferenceBox& aBounds, - float aAppUnitsPerMatrixUnit); - + float aAppUnitsPerMatrixUnit, + bool* aContains3dTransform); } // namespace nsStyleTransformMatrix #endif diff --git a/layout/style/test/mochitest.ini b/layout/style/test/mochitest.ini index 25ea4ce851..a803bd6440 100644 --- a/layout/style/test/mochitest.ini +++ b/layout/style/test/mochitest.ini @@ -284,4 +284,5 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(bug 870262, skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(bug 870262, :visited support) b2g-debug(bug 870262, :visited support) b2g-desktop(bug 870262, :visited support) [test_visited_reftests.html] skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(bug 870262, :visited support) b2g-debug(bug 870262, :visited support) b2g-desktop(bug 870262, :visited support) +[test_webkit_box_orient.html] [test_webkit_device_pixel_ratio.html] diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index a08b265441..b65b306c79 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -162,6 +162,8 @@ var validGradientAndElementValues = [ "-moz-linear-gradient(10% 10em, red, blue)", "-moz-linear-gradient(44px top, red, blue)", + "-moz-linear-gradient(0px, red, blue)", + "-moz-linear-gradient(0, red, blue)", "-moz-linear-gradient(top left 45deg, red, blue)", "-moz-linear-gradient(20% bottom -300deg, red, blue)", "-moz-linear-gradient(center 20% 1.95929rad, red, blue)", @@ -386,6 +388,10 @@ var invalidGradientAndElementValues = [ "-moz-linear-gradient(10 10px -45deg, red, blue) repeat", "-moz-linear-gradient(10px 10 -45deg, red, blue) repeat", "linear-gradient(red -99, yellow, green, blue 120%)", + /* Unitless 0 is invalid as an */ + "-moz-linear-gradient(top left 0, red, blue)", + "-moz-linear-gradient(5px 5px 0, red, blue)", + "linear-gradient(0, red, blue)", /* Invalid color, calc() or -moz-image-rect() function */ "linear-gradient(red, rgb(0, rubbish, 0) 50%, red)", "linear-gradient(red, red calc(50% + rubbish), red)", @@ -702,6 +708,11 @@ if (IsCSSPropertyPrefEnabled("layout.css.prefixes.webkit")) { "-webkit-linear-gradient(135deg, red, blue)", "-webkit-linear-gradient(280deg, red 60%, blue)", + // Linear-gradient with unitless-0 (normally invalid for + // but accepted here for better webkit emulation): + "-webkit-linear-gradient(0, red, blue)", + "-webkit-linear-gradient(0 red, blue)", + // Basic radial-gradient syntax (valid when prefixed or unprefixed): "-webkit-radial-gradient(circle, white, black)", "-webkit-radial-gradient(circle, white, black)", @@ -4848,6 +4859,25 @@ function logical_box_prop_get_computed(cs, property) return cs.getPropertyValue(property); } +// Helper to get computed style of "-webkit-box-orient" from "flex-direction" +// and the "writing-mode". +function webkit_orient_get_computed(cs, property) +{ + var writingMode = cs.getPropertyValue("writing-mode") || "horizontal-tb"; + + var mapping; // map from flex-direction values to -webkit-box-orient values. + if (writingMode == "horizontal-tb") { + // Horizontal writing-mode + mapping = { "row" : "horizontal", "column" : "vertical"}; + } else { + // Vertical writing-mode + mapping = { "row" : "vertical", "column" : "horizontal"}; + } + + var flexDirection = cs.getPropertyValue("flex-direction"); + return mapping[flexDirection]; +} + // Get the computed value for a property. For shorthands, return the // computed values of all the subproperties, delimited by " ; ". function get_computed_value(cs, property) @@ -6992,6 +7022,21 @@ if (IsCSSPropertyPrefEnabled("layout.css.prefixes.webkit")) { alias_for: "order", subproperties: [ "order" ], }; + /* This one is not an alias - it's implemented as a logical property: */ + gCSSProperties["-webkit-box-orient"] = { + domProp: "webkitBoxOrient", + inherited: false, + type: CSS_TYPE_LONGHAND, + logical: true, + get_computed: webkit_orient_get_computed, + initial_values: [ "horizontal" ], + other_values: [ "vertical" ], + invalid_values: [ + "0", "0px", "auto", + /* Flex-direction values: */ + "row", "column", "row-reverse", "column-reverse", + ], + }; gCSSProperties["-webkit-box-align"] = { domProp: "webkitBoxAlign", inherited: false, diff --git a/layout/style/test/test_media_queries.html b/layout/style/test/test_media_queries.html index 4360e3d820..49ffcb099d 100644 --- a/layout/style/test/test_media_queries.html +++ b/layout/style/test/test_media_queries.html @@ -439,6 +439,8 @@ function run() { expression_should_be_parseable("-webkit-max-device-pixel-ratio: 1.0"); expression_should_not_be_parseable("max-device-pixel-ratio: 1.0"); + should_apply("(-webkit-transform-3d)"); + features = [ "max-aspect-ratio", "device-aspect-ratio" ]; for (i in features) { feature = features[i]; diff --git a/layout/style/test/test_webkit_box_orient.html b/layout/style/test/test_webkit_box_orient.html new file mode 100644 index 0000000000..63eadf551b --- /dev/null +++ b/layout/style/test/test_webkit_box_orient.html @@ -0,0 +1,54 @@ + + + + Test the writing-mode-dependent mapping of '-webkit-box-orient' values to + 'flex-direction' values, when emulating -webkit-box styles with modern flexbox + + + + + + diff --git a/layout/svg/crashtests/1156581-1.svg b/layout/svg/crashtests/1156581-1.svg new file mode 100644 index 0000000000..97e5fb1ca9 --- /dev/null +++ b/layout/svg/crashtests/1156581-1.svg @@ -0,0 +1,12 @@ + + + + + diff --git a/layout/svg/crashtests/crashtests.list b/layout/svg/crashtests/crashtests.list index 115315abbc..ba3820dc1e 100644 --- a/layout/svg/crashtests/crashtests.list +++ b/layout/svg/crashtests/crashtests.list @@ -192,6 +192,7 @@ load 1016145.svg load 1028512.svg load 1140080-1.svg load 1149542-1.svg +load 1156581-1.svg load 1182496-1.html load 1209525-1.svg load 1223281-1.svg diff --git a/layout/svg/nsSVGEffects.cpp b/layout/svg/nsSVGEffects.cpp index 6dc1b47c84..b47b4f7ce5 100644 --- a/layout/svg/nsSVGEffects.cpp +++ b/layout/svg/nsSVGEffects.cpp @@ -776,14 +776,15 @@ nsSVGEffects::InvalidateRenderingObservers(nsIFrame *aFrame) { NS_ASSERTION(!aFrame->GetPrevContinuation(), "aFrame must be first continuation"); - if (!aFrame->GetContent()->IsElement()) + nsIContent* content = aFrame->GetContent(); + if (!content || !content->IsElement()) return; // If the rendering has changed, the bounds may well have changed too: aFrame->Properties().Delete(nsSVGUtils::ObjectBoundingBoxProperty()); nsSVGRenderingObserverList *observerList = - GetObserverList(aFrame->GetContent()->AsElement()); + GetObserverList(content->AsElement()); if (observerList) { observerList->InvalidateAll(); return; @@ -827,7 +828,8 @@ nsSVGEffects::InvalidateDirectRenderingObservers(Element *aElement, uint32_t aFl void nsSVGEffects::InvalidateDirectRenderingObservers(nsIFrame *aFrame, uint32_t aFlags /* = 0 */) { - if (aFrame->GetContent() && aFrame->GetContent()->IsElement()) { - InvalidateDirectRenderingObservers(aFrame->GetContent()->AsElement(), aFlags); + nsIContent* content = aFrame->GetContent(); + if (content && content->IsElement()) { + InvalidateDirectRenderingObservers(content->AsElement(), aFlags); } } diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index e8da36bb9b..2512064b97 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -2669,6 +2669,11 @@ pref("layout.css.prefixes.gradients", true); // Are webkit-prefixed properties & property-values supported? pref("layout.css.prefixes.webkit", false); +// Are "-webkit-{min|max}-device-pixel-ratio" media queries supported? +// (Note: this pref has no effect if the master 'layout.css.prefixes.webkit' +// pref is set to false.) +pref("layout.css.prefixes.device-pixel-ratio-webkit", false); + // Is the CSS Unprefixing Service enabled? (This service emulates support // for certain vendor-prefixed properties & values, for sites on a "fixlist".) pref("layout.css.unprefixing-service.enabled", true); diff --git a/testing/profiles/prefs_general.js b/testing/profiles/prefs_general.js index 73cb5c59e1..69ad052e05 100644 --- a/testing/profiles/prefs_general.js +++ b/testing/profiles/prefs_general.js @@ -154,6 +154,9 @@ 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); + // Disable spammy layout warnings because they pollute test logs user_pref("layout.spammy_warnings.enabled", false); diff --git a/widget/cocoa/nsChildView.h b/widget/cocoa/nsChildView.h index 198dbc9ad0..1b36a573c9 100644 --- a/widget/cocoa/nsChildView.h +++ b/widget/cocoa/nsChildView.h @@ -536,7 +536,9 @@ public: return nsCocoaUtils::DevPixelsToCocoaPoints(aRect, BackingScaleFactor()); } - already_AddRefed StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion) override; + already_AddRefed + StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion, + mozilla::layers::BufferMode* aBufferMode) override; void EndRemoteDrawing() override; void CleanupRemoteDrawing() override; bool InitCompositor(mozilla::layers::Compositor* aCompositor) override; diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index d471c64bb2..f6f3fa6c78 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -2637,7 +2637,8 @@ nsChildView::SwipeFinished() } already_AddRefed -nsChildView::StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion) +nsChildView::StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion, + BufferMode* aBufferMode) { // should have created the GLPresenter in InitCompositor. MOZ_ASSERT(mGLPresenter); @@ -4406,7 +4407,7 @@ NSEvent* gLastDragMouseDownEvent = nil; if (!nsCocoaFeatures::OnLionOrLater()) { return false; } - +#if defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7) // This method checks whether the AppleEnableSwipeNavigateWithScrolls global // preference is set. If it isn't, fluid swipe tracking is disabled, and a // horizontal two-finger gesture is always a scroll (even in Safari). This @@ -4435,6 +4436,7 @@ NSEvent* gLastDragMouseDownEvent = nil; CGFloat deltaX = [anEvent scrollingDeltaX]; CGFloat deltaY = [anEvent scrollingDeltaY]; return std::abs(deltaX) > std::abs(deltaY) * 8; +#endif } - (void)setUsingOMTCompositor:(BOOL)aUseOMTC diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp index 79240904f6..8add3546d8 100644 --- a/widget/gtk/nsWindow.cpp +++ b/widget/gtk/nsWindow.cpp @@ -2227,7 +2227,8 @@ nsWindow::OnExposeEvent(cairo_t *cr) return TRUE; } - RefPtr dt = GetDrawTarget(region); + BufferMode layerBuffering = BufferMode::BUFFERED; + RefPtr dt = GetDrawTarget(region, &layerBuffering); if (!dt) { return FALSE; } @@ -2247,7 +2248,6 @@ nsWindow::OnExposeEvent(cairo_t *cr) gfxUtils::ClipToRegion(dt, region.ToUnknownRegion()); } - BufferMode layerBuffering; if (shaped) { // The double buffering is done here to extract the shape mask. // (The shape mask won't be necessary when a visual with an alpha @@ -2256,16 +2256,6 @@ nsWindow::OnExposeEvent(cairo_t *cr) RefPtr destDT = dt->CreateSimilarDrawTarget(boundsRect.Size(), SurfaceFormat::B8G8R8A8); ctx = new gfxContext(destDT, boundsRect.TopLeft()); } else { -#ifdef MOZ_HAVE_SHMIMAGE - if (nsShmImage::UseShm()) { - // We're using an xshm mapping as a back buffer. - layerBuffering = BufferMode::BUFFER_NONE; - } else -#endif // MOZ_HAVE_SHMIMAGE - { - // Get the layer manager to do double buffering (if necessary). - layerBuffering = BufferMode::BUFFERED; - } ctx = new gfxContext(dt); } @@ -6329,7 +6319,7 @@ nsWindow::GetSurfaceForGdkDrawable(GdkDrawable* aDrawable, #endif already_AddRefed -nsWindow::GetDrawTarget(const LayoutDeviceIntRegion& aRegion) +nsWindow::GetDrawTarget(const LayoutDeviceIntRegion& aRegion, BufferMode* aBufferMode) { if (!mGdkWindow) { return nullptr; @@ -6348,12 +6338,14 @@ nsWindow::GetDrawTarget(const LayoutDeviceIntRegion& aRegion) if (nsShmImage::UseShm()) { dt = nsShmImage::EnsureShmImage(size, mXDisplay, mXVisual, mXDepth, mShmImage); + *aBufferMode = BufferMode::BUFFER_NONE; } # endif // MOZ_HAVE_SHMIMAGE if (!dt) { RefPtr surf = new gfxXlibSurface(mXDisplay, mXWindow, mXVisual, size.ToUnknownSize()); if (!surf->CairoStatus()) { dt = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surf.get(), surf->GetSize()); + *aBufferMode = BufferMode::BUFFERED; } } #endif // MOZ_X11 @@ -6362,9 +6354,9 @@ nsWindow::GetDrawTarget(const LayoutDeviceIntRegion& aRegion) } already_AddRefed -nsWindow::StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion) +nsWindow::StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion, BufferMode* aBufferMode) { - return GetDrawTarget(aInvalidRegion); + return GetDrawTarget(aInvalidRegion, aBufferMode); } void diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h index 724fb2852a..458dcb8933 100644 --- a/widget/gtk/nsWindow.h +++ b/widget/gtk/nsWindow.h @@ -206,7 +206,8 @@ public: #endif virtual already_AddRefed - StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion) override; + StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion, + mozilla::layers::BufferMode* aBufferMode) override; virtual void EndRemoteDrawingInRegion(mozilla::gfx::DrawTarget* aDrawTarget, LayoutDeviceIntRegion& aInvalidRegion) override; @@ -299,7 +300,9 @@ public: virtual nsresult ConfigureChildren(const nsTArray& aConfigurations) override; nsresult UpdateTranslucentWindowAlphaInternal(const nsIntRect& aRect, uint8_t* aAlphas, int32_t aStride); - virtual already_AddRefed GetDrawTarget(const LayoutDeviceIntRegion& aRegion); + + already_AddRefed GetDrawTarget(const LayoutDeviceIntRegion& aRegion, + mozilla::layers::BufferMode* aBufferMode); #if (MOZ_WIDGET_GTK == 2) static already_AddRefed GetSurfaceForGdkDrawable(GdkDrawable* aDrawable, diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h index e36e199a91..66b2ad00e2 100644 --- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -1259,9 +1259,13 @@ class nsIWidget : public nsISupports { * * Called by BasicCompositor on the compositor thread for OMTC drawing * before each composition. + * + * The window may specify its buffer mode. If unspecified, it is assumed + * to require double-buffering. */ virtual already_AddRefed StartRemoteDrawing() = 0; - virtual already_AddRefed StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion) { + virtual already_AddRefed StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion, + mozilla::layers::BufferMode* aBufferMode) { return StartRemoteDrawing(); } diff --git a/widget/windows/WinUtils.cpp b/widget/windows/WinUtils.cpp index da3023a2cc..215c57f0e5 100644 --- a/widget/windows/WinUtils.cpp +++ b/widget/windows/WinUtils.cpp @@ -524,6 +524,22 @@ WinUtils::Log(const char *fmt, ...) delete[] buffer; } +// static +double +WinUtils::SystemScaleFactor() +{ + // The result of GetDeviceCaps won't change dynamically, as it predates + // per-monitor DPI and support for on-the-fly resolution changes. + // Therefore, we only need to look it up once. + static int logPixelsY = 0; + if (!logPixelsY) { + HDC screenDC = GetDC(nullptr); + logPixelsY = GetDeviceCaps(screenDC, LOGPIXELSY); + ReleaseDC(nullptr, screenDC); + } + return logPixelsY / 96.0; +} + #ifndef WM_DPICHANGED typedef enum { MDT_EFFECTIVE_DPI = 0, diff --git a/widget/windows/WinUtils.h b/widget/windows/WinUtils.h index 6dcbe4bfab..f835876e39 100644 --- a/widget/windows/WinUtils.h +++ b/widget/windows/WinUtils.h @@ -128,6 +128,15 @@ public: class WinUtils { public: + /** + * Get the system's default logical-to-physical DPI scaling factor, + * which is based on the primary display. Note however that unlike + * LogToPhysFactor(GetPrimaryMonitor()), this will not change during + * a session even if the displays are reconfigured. This scale factor + * is used by Windows theme metrics etc, which do not fully support + * dynamic resolution changes but are only updated on logout. + */ + static double SystemScaleFactor(); static bool IsPerMonitorDPIAware(); /** diff --git a/widget/windows/nsLookAndFeel.cpp b/widget/windows/nsLookAndFeel.cpp index 068fdd2d71..a145e62e38 100644 --- a/widget/windows/nsLookAndFeel.cpp +++ b/widget/windows/nsLookAndFeel.cpp @@ -65,7 +65,9 @@ static int32_t GetSystemParam(long flag, int32_t def) return ::SystemParametersInfo(flag, 0, &value, 0) ? value : def; } -nsLookAndFeel::nsLookAndFeel() : nsXPLookAndFeel() +nsLookAndFeel::nsLookAndFeel() + : nsXPLookAndFeel() + , mUseAccessibilityTheme(0) { mozilla::Telemetry::Accumulate(mozilla::Telemetry::TOUCH_ENABLED_DEVICE, WinUtils::IsTouchDeviceSupportPresent()); @@ -265,23 +267,6 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor) case eColorID__moz_cellhighlight: idx = COLOR_3DFACE; break; - case eColorID__moz_win_accentcolor: - res = GetAccentColor(aColor); - if (NS_SUCCEEDED(res)) { - return res; - } - NS_WARNING("Using fallback for accent color - UI code failed to use the " - "-moz-windows-accent-color-applies media query properly"); - // Seems to be the default color (hardcoded because of bug 1065998) - aColor = NS_RGB(158, 158, 158); - return NS_OK; - case eColorID__moz_win_accentcolortext: - res = GetAccentColorText(aColor); - if (NS_SUCCEEDED(res)) { - return res; - } - aColor = NS_RGB(0, 0, 0); - return NS_OK; case eColorID__moz_win_mediatext: if (IsVistaOrLater() && IsAppThemed()) { res = ::GetColorFromTheme(eUXMediaToolbar, @@ -376,7 +361,16 @@ nsLookAndFeel::GetIntImpl(IntID aID, int32_t &aResult) // High contrast is a misnomer under Win32 -- any theme can be used with it, // e.g. normal contrast with large fonts, low contrast, etc. // The high contrast flag really means -- use this theme and don't override it. - aResult = nsUXThemeData::IsHighContrastOn(); + if (XRE_IsContentProcess()) { + // If we're running in the content process, then the parent should + // have sent us the accessibility state when nsLookAndFeel + // initialized, and stashed it in the mUseAccessibilityTheme cache. + aResult = mUseAccessibilityTheme; + } else { + // Otherwise, we can ask the OS to see if we're using High Contrast + // mode. + aResult = nsUXThemeData::IsHighContrastOn(); + } break; case eIntID_ScrollArrowStyle: aResult = eScrollArrowStyle_Single; @@ -426,20 +420,6 @@ nsLookAndFeel::GetIntImpl(IntID aID, int32_t &aResult) case eIntID_DWMCompositor: aResult = nsUXThemeData::CheckForCompositor(); break; - case eIntID_WindowsAccentColorApplies: - { - nscolor unused; - aResult = NS_SUCCEEDED(GetAccentColor(unused)) ? 1 : 0; - } - break; - case eIntID_WindowsAccentColorIsDark: - { - nscolor accentColor; - if (NS_SUCCEEDED(GetAccentColor(accentColor))) { - aResult = AccentColorIsDark(accentColor) ? 1 : 0; - } - } - break; case eIntID_WindowsGlass: // Aero Glass is only available prior to Windows 8 when DWM is used. aResult = (nsUXThemeData::CheckForCompositor() && !IsWin8OrLater()); @@ -559,10 +539,10 @@ GetSysFontInfo(HDC aHDC, LookAndFeel::FontID anID, LOGFONTW* ptrLogFont = nullptr; LOGFONTW logFont; NONCLIENTMETRICSW ncm; - HGDIOBJ hGDI; char16_t name[LF_FACESIZE]; + bool useShellDlg = false; - // Depending on which stock font we want, there are three different + // Depending on which stock font we want, there are a couple of // places we might have to look it up. switch (anID) { case LookAndFeel::eFont_Icon: @@ -573,11 +553,7 @@ GetSysFontInfo(HDC aHDC, LookAndFeel::FontID anID, ptrLogFont = &logFont; break; - case LookAndFeel::eFont_Menu: - case LookAndFeel::eFont_MessageBox: - case LookAndFeel::eFont_SmallCaption: - case LookAndFeel::eFont_StatusBar: - case LookAndFeel::eFont_Tooltips: + default: ncm.cbSize = sizeof(NONCLIENTMETRICSW); if (!::SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), (PVOID)&ncm, 0)) @@ -585,10 +561,11 @@ GetSysFontInfo(HDC aHDC, LookAndFeel::FontID anID, switch (anID) { case LookAndFeel::eFont_Menu: + case LookAndFeel::eFont_PullDownMenu: ptrLogFont = &ncm.lfMenuFont; break; - case LookAndFeel::eFont_MessageBox: - ptrLogFont = &ncm.lfMessageFont; + case LookAndFeel::eFont_Caption: + ptrLogFont = &ncm.lfCaptionFont; break; case LookAndFeel::eFont_SmallCaption: ptrLogFont = &ncm.lfSmCaptionFont; @@ -597,36 +574,28 @@ GetSysFontInfo(HDC aHDC, LookAndFeel::FontID anID, case LookAndFeel::eFont_Tooltips: ptrLogFont = &ncm.lfStatusFont; break; + case LookAndFeel::eFont_Widget: + case LookAndFeel::eFont_Dialog: + case LookAndFeel::eFont_Button: + case LookAndFeel::eFont_Field: + case LookAndFeel::eFont_List: + // XXX It's not clear to me whether this is exactly the right + // set of LookAndFeel values to map to the dialog font; we may + // want to add or remove cases here after reviewing the visual + // results under various Windows versions. + useShellDlg = true; + // Fall through so that we can get size from lfMessageFont; + // but later we'll use the (virtual) "MS Shell Dlg 2" font name + // instead of the LOGFONT's. default: - MOZ_CRASH(); + ptrLogFont = &ncm.lfMessageFont; + break; } break; - - case LookAndFeel::eFont_Widget: - case LookAndFeel::eFont_Window: // css3 - case LookAndFeel::eFont_Document: - case LookAndFeel::eFont_Workspace: - case LookAndFeel::eFont_Desktop: - case LookAndFeel::eFont_Info: - case LookAndFeel::eFont_Dialog: - case LookAndFeel::eFont_Button: - case LookAndFeel::eFont_PullDownMenu: - case LookAndFeel::eFont_List: - case LookAndFeel::eFont_Field: - case LookAndFeel::eFont_Caption: - hGDI = ::GetStockObject(DEFAULT_GUI_FONT); - if (!hGDI) - return false; - - if (::GetObjectW(hGDI, sizeof(logFont), &logFont) <= 0) - return false; - - ptrLogFont = &logFont; - break; } // Get scaling factor from physical to logical pixels - double pixelScale = 1.0 / WinUtils::LogToPhysFactor(aHDC); + double pixelScale = 1.0 / WinUtils::SystemScaleFactor(); // The lfHeight is in pixels, and it needs to be adjusted for the // device it will be displayed on. @@ -675,9 +644,12 @@ GetSysFontInfo(HDC aHDC, LookAndFeel::FontID anID, aFontStyle.systemFont = true; - name[0] = 0; - memcpy(name, ptrLogFont->lfFaceName, LF_FACESIZE*sizeof(char16_t)); - aFontName = name; + if (useShellDlg) { + aFontName = NS_LITERAL_STRING("MS Shell Dlg 2"); + } else { + memcpy(name, ptrLogFont->lfFaceName, LF_FACESIZE*sizeof(char16_t)); + aFontName = name; + } return true; } @@ -703,73 +675,28 @@ nsLookAndFeel::GetPasswordCharacterImpl() return UNICODE_BLACK_CIRCLE_CHAR; } -/* static */ nsresult -nsLookAndFeel::GetAccentColor(nscolor& aColor) +nsTArray +nsLookAndFeel::GetIntCacheImpl() { - nsresult rv; + nsTArray lookAndFeelIntCache = + nsXPLookAndFeel::GetIntCacheImpl(); - if (!mDwmKey) { - mDwmKey = do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; + LookAndFeelInt useAccessibilityTheme; + useAccessibilityTheme.id = eIntID_UseAccessibilityTheme; + useAccessibilityTheme.value = GetInt(eIntID_UseAccessibilityTheme); + lookAndFeelIntCache.AppendElement(useAccessibilityTheme); + + return lookAndFeelIntCache; +} + +void +nsLookAndFeel::SetIntCacheImpl(const nsTArray& aLookAndFeelIntCache) +{ + for (auto entry : aLookAndFeelIntCache) { + if (entry.id == eIntID_UseAccessibilityTheme) { + mUseAccessibilityTheme = entry.value; + break; } } - - rv = mDwmKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, - NS_LITERAL_STRING("SOFTWARE\\Microsoft\\Windows\\DWM"), - nsIWindowsRegKey::ACCESS_QUERY_VALUE); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - // The ColorPrevalence value is set to 1 when the "Show color on title bar" - // setting in the Color section of Window's Personalization settings is - // turned on. - uint32_t accentColor, colorPrevalence; - if (NS_SUCCEEDED(mDwmKey->ReadIntValue(NS_LITERAL_STRING("AccentColor"), &accentColor)) && - NS_SUCCEEDED(mDwmKey->ReadIntValue(NS_LITERAL_STRING("ColorPrevalence"), &colorPrevalence)) && - colorPrevalence == 1) { - // The order of the color components in the DWORD stored in the registry - // happens to be the same order as we store the components in nscolor - // so we can just assign directly here. - aColor = accentColor; - rv = NS_OK; - } else { - rv = NS_ERROR_NOT_AVAILABLE; - } - - mDwmKey->Close(); - - return rv; } -bool -nsLookAndFeel::AccentColorIsDark(nscolor aColor) -{ - float luminance = (NS_GET_R(aColor) * 2 + - NS_GET_G(aColor) * 5 + - NS_GET_B(aColor)) / 8; - - return (luminance <= 128); -} - -/* static */ nsresult -nsLookAndFeel::GetAccentColorText(nscolor& aColor) -{ - nscolor accentColor; - nsresult rv = GetAccentColor(accentColor); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - // We want the color that we return for text that will be drawn over - // a background that has the accent color to have good contrast with - // the accent color. Windows itself uses either white or black text - // depending on how light or dark the accent color is. We do the same - // here based on the luminance of the accent color with a threshhold - // value that seems consistent with what Windows does. - - aColor = AccentColorIsDark(accentColor) ? NS_RGB(255, 255, 255) : NS_RGB(0, 0, 0); - - return NS_OK; -} \ No newline at end of file diff --git a/widget/windows/nsLookAndFeel.h b/widget/windows/nsLookAndFeel.h index 9a372d3660..bc2d158b6f 100644 --- a/widget/windows/nsLookAndFeel.h +++ b/widget/windows/nsLookAndFeel.h @@ -5,9 +5,7 @@ #ifndef __nsLookAndFeel #define __nsLookAndFeel - #include "nsXPLookAndFeel.h" -#include "nsIWindowsRegKey.h" /* * Gesture System Metrics @@ -56,29 +54,12 @@ public: gfxFontStyle& aFontStyle, float aDevPixPerCSSPixel); virtual char16_t GetPasswordCharacterImpl(); -private: - /** - * Fetches the Windows accent color from the Windows settings if - * the accent color is set to apply to the title bar, otherwise - * returns an error code. - */ - nsresult GetAccentColor(nscolor& aColor); - /** - * check if the accent color is dark enough to need white text - **/ - bool AccentColorIsDark(nscolor aColor); - - /** - * If the Windows accent color from the Windows settings is set - * to apply to the title bar, this computes the color that should - * be used for text that is to be written over a background that has - * the accent color. Otherwise, (if the accent color should not - * apply to the title bar) this returns an error code. - */ - nsresult GetAccentColorText(nscolor& aColor); - - nsCOMPtr mDwmKey; + virtual nsTArray GetIntCacheImpl(); + virtual void SetIntCacheImpl(const nsTArray& aLookAndFeelIntCache); + +private: + int32_t mUseAccessibilityTheme; }; #endif diff --git a/widget/windows/nsNativeThemeWin.cpp b/widget/windows/nsNativeThemeWin.cpp index 28b17e7d15..3e14159763 100644 --- a/widget/windows/nsNativeThemeWin.cpp +++ b/widget/windows/nsNativeThemeWin.cpp @@ -1550,16 +1550,20 @@ AssumeThemePartAndStateAreTransparent(int32_t aPart, int32_t aState) } // When running with per-monitor DPI (on Win8.1+), and rendering on a display -// with a different DPI setting from the system's primary monitor, we need to +// with a different DPI setting from the system's default scaling, we need to // apply scaling to native-themed elements as the Windows theme APIs assume -// the primary monitor's resolution. -static double +// the system default resolution. +static inline double GetThemeDpiScaleFactor(nsIFrame* aFrame) { - double primaryScale = - WinUtils::LogToPhysFactor(WinUtils::GetPrimaryMonitor()); - nsIWidget* rootWidget = aFrame->PresContext()->GetRootWidget(); - return rootWidget ? rootWidget->GetDefaultScale().scale / primaryScale : 1.0; + if (WinUtils::IsPerMonitorDPIAware() && GetSystemMetrics(SM_CMONITORS) > 1) { + nsIWidget* rootWidget = aFrame->PresContext()->GetRootWidget(); + if (rootWidget) { + double systemScale = WinUtils::SystemScaleFactor(); + return rootWidget->GetDefaultScale().scale / systemScale; + } + } + return 1.0; } NS_IMETHODIMP