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)
This commit is contained in:
2023-08-24 10:00:58 +08:00
parent 557785125c
commit dcbe25ed45
67 changed files with 3448 additions and 1878 deletions
+8 -3
View File
@@ -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*
+1
View File
@@ -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;
+56
View File
@@ -9,6 +9,7 @@
#include "mozilla/a11y/Accessible.h"
#include "mozilla/a11y/ProxyAccessible.h"
#include "mozilla/a11y/Role.h"
#include <stdint.h>
@@ -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; }
+4 -2
View File
@@ -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
+260
View File
@@ -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>
WebKitCSSMatrix::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
{
RefPtr<WebKitCSSMatrix> obj = new WebKitCSSMatrix(aGlobal.GetAsSupports());
return obj.forget();
}
already_AddRefed<WebKitCSSMatrix>
WebKitCSSMatrix::Constructor(const GlobalObject& aGlobal,
const nsAString& aTransformList, ErrorResult& aRv)
{
RefPtr<WebKitCSSMatrix> obj = new WebKitCSSMatrix(aGlobal.GetAsSupports());
obj = obj->SetMatrixValue(aTransformList, aRv);
return obj.forget();
}
already_AddRefed<WebKitCSSMatrix>
WebKitCSSMatrix::Constructor(const GlobalObject& aGlobal,
const DOMMatrixReadOnly& aOther, ErrorResult& aRv)
{
RefPtr<WebKitCSSMatrix> obj = new WebKitCSSMatrix(aGlobal.GetAsSupports(),
aOther);
return obj.forget();
}
JSObject*
WebKitCSSMatrix::WrapObject(JSContext* aCx, JS::Handle<JSObject*> 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>
WebKitCSSMatrix::Multiply(const WebKitCSSMatrix& other) const
{
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
retval->MultiplySelf(other);
return retval.forget();
}
already_AddRefed<WebKitCSSMatrix>
WebKitCSSMatrix::Inverse(ErrorResult& aRv) const
{
RefPtr<WebKitCSSMatrix> 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>
WebKitCSSMatrix::Translate(double aTx,
double aTy,
double aTz) const
{
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
retval->TranslateSelf(aTx, aTy, aTz);
return retval.forget();
}
already_AddRefed<WebKitCSSMatrix>
WebKitCSSMatrix::Scale(double aScaleX,
const Optional<double>& aScaleY,
double aScaleZ) const
{
double scaleX = aScaleX;
double scaleY = aScaleY.WasPassed() ? aScaleY.Value() : scaleX;
double scaleZ = aScaleZ;
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
retval->ScaleNonUniformSelf(scaleX, scaleY, scaleZ);
return retval.forget();
}
already_AddRefed<WebKitCSSMatrix>
WebKitCSSMatrix::Rotate(double aRotX,
const Optional<double>& aRotY,
const Optional<double>& 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<WebKitCSSMatrix> 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>
WebKitCSSMatrix::RotateAxisAngle(double aX,
double aY,
double aZ,
double aAngle) const
{
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
retval->RotateAxisAngleSelf(aX, aY, aZ, aAngle);
return retval.forget();
}
already_AddRefed<WebKitCSSMatrix>
WebKitCSSMatrix::SkewX(double aSx) const
{
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
retval->SkewXSelf(aSx);
return retval.forget();
}
already_AddRefed<WebKitCSSMatrix>
WebKitCSSMatrix::SkewY(double aSy) const
{
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
retval->SkewYSelf(aSy);
return retval.forget();
}
} // namespace dom
} // namespace mozilla
+72
View File
@@ -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<WebKitCSSMatrix>
Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
static already_AddRefed<WebKitCSSMatrix>
Constructor(const GlobalObject& aGlobal,
const nsAString& aTransformList, ErrorResult& aRv);
static already_AddRefed<WebKitCSSMatrix>
Constructor(const GlobalObject& aGlobal,
const DOMMatrixReadOnly& aOther, ErrorResult& aRv);
nsISupports* GetParentObject() const { return mParent; }
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
WebKitCSSMatrix* SetMatrixValue(const nsAString& aTransformList,
ErrorResult& aRv);
already_AddRefed<WebKitCSSMatrix> Multiply(const WebKitCSSMatrix& aOther) const;
already_AddRefed<WebKitCSSMatrix> Inverse(ErrorResult& aRv) const;
already_AddRefed<WebKitCSSMatrix> Translate(double aTx,
double aTy,
double aTz) const;
already_AddRefed<WebKitCSSMatrix> Scale(double aScaleX,
const Optional<double>& aScaleY,
double aScaleZ) const;
already_AddRefed<WebKitCSSMatrix> Rotate(double aRotX,
const Optional<double>& aRotY,
const Optional<double>& aRotZ) const;
already_AddRefed<WebKitCSSMatrix> RotateAxisAngle(double aX,
double aY,
double aZ,
double aAngle) const;
already_AddRefed<WebKitCSSMatrix> SkewX(double aSx) const;
already_AddRefed<WebKitCSSMatrix> 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__ */
@@ -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"
+2
View File
@@ -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',
+1 -4
View File
@@ -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")
+1
View File
@@ -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"
@@ -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]
@@ -0,0 +1,326 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Test for WebKitCSSMatrix</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script>
function RoughCompareMatrix(dm1, dm2)
{
var m1 = dm1.toFloat32Array();
var m2 = dm2.toFloat32Array();
if (m1.length != m2.length) {
return false;
}
const tolerance = 1 / 65535;
for (var x = 0; x < m1.length; x++) {
if (Math.abs(m1[x] - m2[x]) > tolerance) {
return false;
}
}
return true;
}
function CompareMatrix(dm1, dm2)
{
var m1 = dm1.toFloat32Array();
var m2 = dm2.toFloat32Array();
if (m1.length != m2.length) {
return false;
}
for (var x = 0; x < m1.length; x++) {
if (m1[x] != m2[x]) {
return false;
}
}
return true;
}
test(function() {
var m = new WebKitCSSMatrix();
assert_equals(m.m11, 1, "m11 should be 1");
assert_equals(m.m22, 1, "m22 should be 1");
assert_equals(m.m33, 1, "m33 should be 1");
assert_equals(m.m44, 1, "m44 should be 1");
assert_equals(m.m12, 0, "m12 should be 0");
assert_equals(m.m13, 0, "m13 should be 0");
assert_equals(m.m14, 0, "m14 should be 0");
assert_equals(m.m21, 0, "m21 should be 0");
assert_equals(m.m23, 0, "m23 should be 0");
assert_equals(m.m24, 0, "m24 should be 0");
assert_equals(m.m31, 0, "m31 should be 0");
assert_equals(m.m32, 0, "m32 should be 0");
assert_equals(m.m34, 0, "m34 should be 0");
assert_equals(m.m41, 0, "m41 should be 0");
assert_equals(m.m42, 0, "m42 should be 0");
assert_equals(m.m43, 0, "m43 should be 0");
}, "Test constructor with no arguments.");
test(function() {
var m = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
assert_equals(m.m11, 1, "m11 should be 1");
assert_equals(m.m12, 2, "m12 should be 2");
assert_equals(m.m21, 3, "m21 should be 3");
assert_equals(m.m22, 4, "m22 should be 4");
assert_equals(m.m41, 5, "m41 should be 5");
assert_equals(m.m42, 6, "m42 should be 6");
}, "Test constructor with transform list.");
test(function() {
var m1 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m2 = new WebKitCSSMatrix(m1);
assert_true(RoughCompareMatrix(m1, m2), "Matrix should be equal.");
}, "Test constructor with other matrix.");
test(function() {
var m = new WebKitCSSMatrix();
var mr = m.setMatrixValue("matrix(1,2,3,4,5,6)");
assert_equals(m.m11, 1, "m11 should be 1");
assert_equals(m.m12, 2, "m12 should be 2");
assert_equals(m.m21, 3, "m21 should be 3");
assert_equals(m.m22, 4, "m22 should be 4");
assert_equals(m.m41, 5, "m41 should be 5");
assert_equals(m.m42, 6, "m42 should be 6");
assert_equals(m, mr, "Return value of setMatrixValue should be the same matrix.");
}, "Test setMatrixValue.");
test(function() {
var m1 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m2 = new DOMMatrix("matrix(1,2,3,4,5,6)");
var m3 = new WebKitCSSMatrix("matrix(6,5,4,3,2,1)");
var m4 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m1r = m1.multiply(m3);
var m2r = m2.multiply(m3);
assert_true(RoughCompareMatrix(m1r, m2r), "multiply should return the same result as DOMMatrixReadOnly.");
assert_true(CompareMatrix(m1, m4), "Multiply should not mutate original matrix.");
}, "Test multiply.");
test(function() {
var m1 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m2 = new DOMMatrix("matrix(1,2,3,4,5,6)");
var m3 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m1r = m1.inverse();
var m2r = m2.inverse();
assert_true(RoughCompareMatrix(m1r, m2r), "inverse should return the same result as DOMMatrixReadOnly.");
assert_true(CompareMatrix(m1, m3), "inverse should not mutate original matrix.");
}, "Test inverse.");
test(function() {
var m1 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m2 = new DOMMatrix("matrix(1,2,3,4,5,6)");
var m3 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m1r = m1.translate(2, 3, 4);
var m2r = m2.translate(2, 3, 4);
assert_true(RoughCompareMatrix(m1r, m2r), "translate should return the same result as DOMMatrixReadOnly.");
assert_true(CompareMatrix(m1, m3), "translate should not mutate original matrix.");
}, "Test inverse.");
test(function() {
var m1 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m2 = new DOMMatrix("matrix(1,2,3,4,5,6)");
var m3 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m1r = m1.scale(2);
var m2r = m2.scaleNonUniform(2, 2, 1);
assert_true(RoughCompareMatrix(m1r, m2r), "scale should return the same result as DOMMatrixReadOnly.");
assert_true(CompareMatrix(m1, m3), "scale should not mutate original matrix.");
}, "Test scale with 1 argument.");
test(function() {
var m1 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m2 = new DOMMatrix("matrix(1,2,3,4,5,6)");
var m3 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m1r = m1.scale(2, 3);
var m2r = m2.scaleNonUniform(2, 3, 1);
assert_true(RoughCompareMatrix(m1r, m2r), "scale should return the same result as DOMMatrixReadOnly.");
assert_true(CompareMatrix(m1, m3), "scale should not mutate original matrix.");
}, "Test scale with 2 arguments.");
test(function() {
var m1 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m2 = new DOMMatrix("matrix(1,2,3,4,5,6)");
var m3 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m1r = m1.scale(2, 3, 4);
var m2r = m2.scaleNonUniform(2, 3, 4);
assert_true(RoughCompareMatrix(m1r, m2r), "scale should return the same result as DOMMatrixReadOnly.");
assert_true(CompareMatrix(m1, m3), "scale should not mutate original matrix.");
}, "Test scale with 3 arguments.");
test(function() {
var m1 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m2 = new DOMMatrix("matrix(1,2,3,4,5,6)");
var m3 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m1r = m1.scale(undefined, 3, 4);
var m2r = m2.scaleNonUniform(1, 3, 4);
assert_true(RoughCompareMatrix(m1r, m2r), "scale should return the same result as DOMMatrixReadOnly.");
assert_true(CompareMatrix(m1, m3), "scale should not mutate original matrix.");
}, "Test scale with undefined scaleX argument.");
test(function() {
var m1 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m2 = new DOMMatrix("matrix(1,2,3,4,5,6)");
var m3 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m1r = m1.scale(2, undefined, 4);
var m2r = m2.scaleNonUniform(2, 2, 4);
assert_true(RoughCompareMatrix(m1r, m2r), "scale should return the same result as DOMMatrixReadOnly.");
assert_true(CompareMatrix(m1, m3), "scale should not mutate original matrix.");
}, "Test scale with undefined scaleY argument.");
test(function() {
var m1 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m2 = new DOMMatrix("matrix(1,2,3,4,5,6)");
var m3 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m1r = m1.scale(2, 3, undefined);
var m2r = m2.scaleNonUniform(2, 3, 1);
assert_true(RoughCompareMatrix(m1r, m2r), "scale should return the same result as DOMMatrixReadOnly.");
assert_true(CompareMatrix(m1, m3), "scale should not mutate original matrix.");
}, "Test scale with undefined scaleZ argument.");
test(function() {
var m1 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m2 = new DOMMatrix("matrix(1,2,3,4,5,6)");
var m3 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m1r = m1.rotate(2);
var m2r = m2.rotateAxisAngle(0, 0, 1, 2); // Rotate around unit vector on z-axis.
assert_true(RoughCompareMatrix(m1r, m2r));
assert_true(CompareMatrix(m1, m3), "rotate should not mutate original matrix.");
}, "Test rotate with 1 argument.");
test(function() {
var m1 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m2 = new DOMMatrix("matrix(1,2,3,4,5,6)");
var m3 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m1r = m1.rotate(2, 3);
var m2r = m2.rotateAxisAngle(0, 1, 0, 3); // Rotate around unit vector on x-axis.
m2r = m2r.rotateAxisAngle(1, 0, 0, 2); // Rotate around unit vector on y-axis.
assert_true(RoughCompareMatrix(m1r, m2r));
assert_true(CompareMatrix(m1, m3), "rotate should not mutate original matrix.");
}, "Test rotate with 2 arguments.");
test(function() {
var m1 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m2 = new DOMMatrix("matrix(1,2,3,4,5,6)");
var m3 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m1r = m1.rotate(2, 3, 4);
var m2r = m2.rotateAxisAngle(0, 0, 1, 4); // Rotate around unit vector on z-axis.
m2r = m2r.rotateAxisAngle(0, 1, 0, 3); // Rotate around unit vector on y-axis.
m2r = m2r.rotateAxisAngle(1, 0, 0, 2); // Rotate around unit vector on x-axis.
assert_true(RoughCompareMatrix(m1r, m2r));
assert_true(CompareMatrix(m1, m3), "rotate should not mutate original matrix.");
}, "Test rotate with 3 arguments.");
test(function() {
var m1 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m2 = new DOMMatrix("matrix(1,2,3,4,5,6)");
var m3 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m1r = m1.rotate(2, undefined, undefined);
var m2r = m2.rotateAxisAngle(0, 0, 1, 2); // Rotate around unit vector on z-axis.
assert_true(RoughCompareMatrix(m1r, m2r));
assert_true(CompareMatrix(m1, m3), "rotate should not mutate original matrix.");
}, "Test rotate with rotY and rotZ as undefined.");
test(function() {
var m1 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m2 = new DOMMatrix("matrix(1,2,3,4,5,6)");
var m3 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m1r = m1.rotate(undefined, 3, 4);
var m2r = m2.rotateAxisAngle(0, 0, 1, 4); // Rotate around unit vector on z-axis.
m2r = m2r.rotateAxisAngle(0, 1, 0, 3); // Rotate around unit vector on y-axis.
assert_true(RoughCompareMatrix(m1r, m2r));
assert_true(CompareMatrix(m1, m3), "rotate should not mutate original matrix.");
}, "Test rotate with rotX as undefined.");
test(function() {
var m1 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m2 = new DOMMatrix("matrix(1,2,3,4,5,6)");
var m3 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m1r = m1.rotateAxisAngle(2, 3, 4, 5);
var m2r = m2.rotateAxisAngle(2, 3, 4, 5);
assert_true(RoughCompareMatrix(m1r, m2r), "rotateAxisAngle should return the same result as DOMMatrixReadOnly.");
assert_true(CompareMatrix(m1, m3), "rotateAxisAngle should not mutate original matrix.");
}, "Test rotateAxisAngle.");
test(function() {
var m1 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m2 = new DOMMatrix("matrix(1,2,3,4,5,6)");
var m3 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m1r = m1.skewX(2);
var m2r = m2.skewX(2);
assert_true(RoughCompareMatrix(m1r, m2r), "skewX should return the same result as DOMMatrixReadOnly.");
assert_true(CompareMatrix(m1, m3), "skewX should not mutate original matrix.");
}, "Test skewX.");
test(function() {
var m1 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m2 = new DOMMatrix("matrix(1,2,3,4,5,6)");
var m3 = new WebKitCSSMatrix("matrix(1,2,3,4,5,6)");
var m1r = m1.skewY(2);
var m2r = m2.skewY(2);
assert_true(RoughCompareMatrix(m1r, m2r), "skewY should return the same result as DOMMatrixReadOnly.");
assert_true(CompareMatrix(m1, m3), "skewY should not mutate original matrix.");
}, "Test skewY.");
test(function() {
var m = new WebKitCSSMatrix("matrix(1,0,0,0,0,0)");
assert_throws("NotSupportedError", function() { m.inverse(); }, "Inverting an invertible matrix should throw.")
}, "Test that inverting an invertible matrix throws.");
test(function() {
var m1 = new WebKitCSSMatrix("translate(10px, 10px)");
var m2 = new DOMMatrix();
m2.translateSelf(10, 10);
assert_true(RoughCompareMatrix(m1, m2), "translate in constructor should result in translated matrix");
assert_throws("SyntaxError", function() { new WebKitCSSMatrix("translate(10em, 10em)"); }, "Transform function may not contain relative units.")
assert_throws("SyntaxError", function() { new WebKitCSSMatrix("translate(10%, 10%)"); }, "Transform function may not contain percentage.")
}, "Test constructor with translate");
test(function() {
assert_throws("SyntaxError", function() { new WebKitCSSMatrix("initial"); }, "initial is not a valid constructor argument.")
assert_throws("SyntaxError", function() { new WebKitCSSMatrix("inherit"); }, "inherit is not a valid constructor arugment.")
}, "Test invalid constructor arguments.");
</script>
@@ -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!
+39
View File
@@ -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);
};
+1
View File
@@ -590,6 +590,7 @@ WEBIDL_FILES = [
'WebComponents.webidl',
'WebGL2RenderingContext.webidl',
'WebGLRenderingContext.webidl',
'WebKitCSSMatrix.webidl',
'WebSocket.webidl',
'WheelEvent.webidl',
'WifiOptions.webidl',
+46 -17
View File
@@ -152,6 +152,32 @@ BasicCompositor::CreateRenderTargetFromSource(const IntRect &aRect,
return nullptr;
}
already_AddRefed<CompositingRenderTarget>
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<BasicCompositingRenderTarget> rt = new BasicCompositingRenderTarget(mDrawTarget, rect);
if (aInit == INIT_MODE_CLEAR) {
mDrawTarget->ClearRect(gfx::Rect(aRect));
}
return rt.forget();
}
already_AddRefed<DataTextureSource>
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<CompositingRenderTarget> 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<SourceSurface> source = mRenderTarget->mDrawTarget->Snapshot();
RefPtr<DrawTarget> 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<SourceSurface> source = mRenderTarget->mDrawTarget->Snapshot();
RefPtr<DrawTarget> 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);
}
+5
View File
@@ -60,6 +60,11 @@ public:
const CompositingRenderTarget *aSource,
const gfx::IntPoint &aSourcePoint) override;
virtual already_AddRefed<CompositingRenderTarget>
CreateRenderTargetForWindow(const gfx::IntRect& aRect,
SurfaceInitMode aInit,
BufferMode aBufferMode);
virtual already_AddRefed<DataTextureSource>
CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) override;
+316 -180
View File
@@ -13,40 +13,107 @@
#include <algorithm>
#include <dlfcn.h>
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<const UniChar*>(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<const UniChar*>(aText), length);
::CFStringAppendCharacters(mutableString,
endBidiWrap, mozilla::ArrayLength(endBidiWrap));
stringObj = mutableString;
} else {
CFDictionaryRef attrObj;
if (sCTWritingDirectionAttributeName) {
startOffset = 0;
stringObj = ::CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault,
reinterpret_cast<const UniChar*>(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<SInt16,SInt16> 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<SInt16,SInt16> 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<SInt16,SInt16> 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<SInt16,SInt16> kIndicFeatures[] = {
{ kSmartSwashType, kLineFinalSwashesOffSelector }
};
sIndicFeaturesDescriptor =
CreateFontFeaturesDescriptor(kIndicFeatures,
ArrayLength(kIndicFeatures));
}
return sIndicFeaturesDescriptor;
}
CTFontDescriptorRef
gfxCoreTextShaper::GetIndicDisableLigaturesDescriptor()
{
if (sIndicDisableLigaturesDescriptor == nullptr) {
const std::pair<SInt16,SInt16> kIndicDisableLigatures[] = {
{ kSmartSwashType, kLineFinalSwashesOffSelector },
{ kLigaturesType, kCommonLigaturesOffSelector }
};
sIndicDisableLigaturesDescriptor =
CreateFontFeaturesDescriptor(kIndicDisableLigatures,
ArrayLength(kIndicDisableLigatures));
}
return sIndicDisableLigaturesDescriptor;
}
CTFontRef
gfxCoreTextShaper::CreateCTFontWithFeatures(CGFloat aSize,
CTFontDescriptorRef aDescriptor)
{
gfxMacFont *f = static_cast<gfxMacFont*>(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;
+20 -9
View File
@@ -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<SInt16,SInt16> 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 */
+10 -10
View File
@@ -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;
+3 -1
View File
@@ -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.
+6 -3
View File
@@ -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() /
+2 -2
View File
@@ -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
@@ -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
+1
View File
@@ -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
+190
View File
@@ -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<ImageValue>
* 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<RefPtr<css::ImageValue>> ImageValueArray;
typedef nsClassHashtable<nsGenericHashKey<nsCSSProperty>, ImageValueArray>
PerPropertyImageHashtable;
typedef nsClassHashtable<nsPtrHashKey<nsStyleContext>, 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 <typename Lambda>
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
+12 -8
View File
@@ -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
+391 -310
View File
@@ -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<nsCSSValue>& 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<nsCSSValue> 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<nsCSSValue*>(oldValue));
aFromBlock.ClearPropertyBit(aProperty);
return true;
*aChanged = MoveValue(newValue, const_cast<nsCSSValue*>(oldValue));
aFromBlock.ClearPropertyBit(aProperty);
return true;
}
nsCSSCompressedDataBlock*
nsCSSCompressedDataBlock::Clone() const
{
nsAutoPtr<nsCSSCompressedDataBlock>
result(new(mNumProps) nsCSSCompressedDataBlock(mNumProps));
nsAutoPtr<nsCSSCompressedDataBlock>
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<uint32_t>& aOrder)
{
nsAutoPtr<nsCSSCompressedDataBlock> result_normal, result_important;
uint32_t i_normal = 0, i_important = 0;
nsAutoPtr<nsCSSCompressedDataBlock> 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<nsCSSProperty>(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<nsCSSProperty>(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<nsCSSValue*>(PropertyAt(aProperty));
storage = aValue;
SetPropertyBit(aProperty);
MOZ_ASSERT(!nsCSSProps::IsShorthand(aProperty),
"property out of range");
nsCSSValue& storage = *static_cast<nsCSSValue*>(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
+262 -259
View File
@@ -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<uint32_t>& 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<uint32_t>& 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__) */
+156 -39
View File
@@ -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<nsCSSValue>& aOutput);
@@ -1855,6 +1861,48 @@ CSSParserImpl::ParseLonghandProperty(const nsCSSProperty aPropID,
}
}
bool
CSSParserImpl::ParseTransformProperty(const nsAString& aPropValue,
bool aDisallowRelativeValues,
nsCSSValue& aValue)
{
RefPtr<Declaration> 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 <legacy-gradient-line>
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<nsCSSValue> &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<CSSParserImpl*>(mImpl)->
ParseTransformProperty(aPropValue, aDisallowRelativeValues, aResult);
}
void
nsCSSParser::ParseVariable(const nsAString& aVariableName,
const nsAString& aPropValue,
+9
View File
@@ -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,
+16
View File
@@ -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,
+12
View File
@@ -44,6 +44,17 @@
// defined in nCSSProps.cpp named g<name_>LogicalGroupTable
// 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
// g<name_>LogicalGroupTable 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)
+3
View File
@@ -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
+26 -2
View File
@@ -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
+21 -6
View File
@@ -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
-10
View File
@@ -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);
+47 -47
View File
@@ -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
+3 -13
View File
@@ -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<nsRefPtrHashKey<mozilla::css::ImageValue> > mImageValues;
private:
nsCSSValueTokenStream(const nsCSSValueTokenStream& aOther) = delete;
nsCSSValueTokenStream& operator=(const nsCSSValueTokenStream& aOther) = delete;
+18 -16
View File
@@ -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<CSSValue>
nsComputedDOMStyle::DoGetPerspective()
{
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
SetValueToCoord(val, StyleDisplay()->mChildPerspective, false);
return val.forget();
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
SetValueToCoord(val, StyleDisplay()->mChildPerspective, false);
return val.forget();
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetBackfaceVisibility()
{
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetIdent(
nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mBackfaceVisibility,
nsCSSProps::kBackfaceVisibilityKTable));
return val.forget();
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetIdent(
nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mBackfaceVisibility,
nsCSSProps::kBackfaceVisibilityKTable));
return val.forget();
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetTransformStyle()
{
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetIdent(
nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mTransformStyle,
nsCSSProps::kTransformStyleKTable));
return val.forget();
RefPtr<nsROCSSPrimitiveValue> 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);
}
File diff suppressed because it is too large Load Diff
+59 -51
View File
@@ -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_) */
+5 -4
View File
@@ -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
+6 -2
View File
@@ -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
+47 -47
View File
@@ -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);
}
+143 -98
View File
@@ -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<nsIAtom> 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 <auto-repeat> track, i.e. when mRepeatAutoIndex == -1).
// When mIsSubgrid is true, mRepeatAutoLineNameListBefore contains the line
// names and mRepeatAutoLineNameListAfter is empty.
struct nsStyleGridTemplate {
struct nsStyleGridTemplate
{
nsTArray<nsTArray<nsString>> mLineNameLists;
nsTArray<nsStyleCoord> mMinTrackSizingFunctions;
nsTArray<nsStyleCoord> 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<imgIRequest> 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<nsStyleFilter> {
struct nsTArray_CopyChooser<nsStyleFilter>
{
typedef nsTArray_CopyWithConstructors<nsStyleFilter> 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();
+26 -8
View File
@@ -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;
}
+7 -3
View File
@@ -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
+1
View File
@@ -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]
+45
View File
@@ -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 <angle> */
"-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 <angle> (normally invalid for <angle>
// 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,
@@ -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];
@@ -0,0 +1,54 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>
Test the writing-mode-dependent mapping of '-webkit-box-orient' values to
'flex-direction' values, when emulating -webkit-box styles with modern flexbox
</title>
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="testDiv" style="display: none"></div>
<script>
// Mappings from "-webkit-box-orient" values to "flex-direction" values,
// when writing-mode is horizontal:
const horizMapping =
{ "horizontal" : "row",
"vertical" : "column" };
// Same as above, but now when writing-mode is vertical:
const vertMapping =
{ "horizontal" : "column",
"vertical" : "row" };
const div = document.getElementById("testDiv");
// Test the various writing-mode values:
testWM("unset", horizMapping);
testWM("horizontal-tb", horizMapping);
testWM("vertical-lr", vertMapping);
testWM("vertical-rl", vertMapping);
testWM("sideways-lr", vertMapping);
testWM("sideways-rl", vertMapping);
/**
* Main test function:
* @param aWritingMode The writing-mode value to test.
* @param aMapping Mapping from -webkit-box-orient values to equivalent
* flex-direction values, for this writing-mode.
*/
function testWM(aWritingMode, aMapping) {
div.style.writingMode = aWritingMode;
for (var webkitBoxOrientVal in aMapping) {
div.style.webkitBoxOrient = webkitBoxOrientVal;
test(function() {
var expectedFlexDir = aMapping[webkitBoxOrientVal];
var actualFlexDir = window.getComputedStyle(div, "").flexDirection;
assert_equals(actualFlexDir, expectedFlexDir,
"Testing the 'flex-direction' value produced by " +
"'-webkit-box-orient:" + webkitBoxOrientVal + "'");
}, "Testing how '-webkit-box-orient' values influence 'flex-direction' " +
"in presence of 'writing-mode:" + aWritingMode + "'");
}
}
</script>
+12
View File
@@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" style="filter: url(#a); clip: rect(0px, 4rem, 2px, 2px);">
<script>
function boom()
{
document.getElementById("a").style.overflow = "hidden";
document.documentElement.style.fontSize = "10px";
}
window.addEventListener("load", boom, false);
</script>
<set id="a"/>
</svg>

After

Width:  |  Height:  |  Size: 380 B

+1
View File
@@ -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
+6 -4
View File
@@ -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);
}
}
+5
View File
@@ -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);
+3
View File
@@ -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);
+3 -1
View File
@@ -536,7 +536,9 @@ public:
return nsCocoaUtils::DevPixelsToCocoaPoints(aRect, BackingScaleFactor());
}
already_AddRefed<mozilla::gfx::DrawTarget> StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion) override;
already_AddRefed<mozilla::gfx::DrawTarget>
StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion,
mozilla::layers::BufferMode* aBufferMode) override;
void EndRemoteDrawing() override;
void CleanupRemoteDrawing() override;
bool InitCompositor(mozilla::layers::Compositor* aCompositor) override;
+4 -2
View File
@@ -2637,7 +2637,8 @@ nsChildView::SwipeFinished()
}
already_AddRefed<gfx::DrawTarget>
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
+7 -15
View File
@@ -2227,7 +2227,8 @@ nsWindow::OnExposeEvent(cairo_t *cr)
return TRUE;
}
RefPtr<DrawTarget> dt = GetDrawTarget(region);
BufferMode layerBuffering = BufferMode::BUFFERED;
RefPtr<DrawTarget> 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<DrawTarget> 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<DrawTarget>
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<gfxXlibSurface> 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<DrawTarget>
nsWindow::StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion)
nsWindow::StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion, BufferMode* aBufferMode)
{
return GetDrawTarget(aInvalidRegion);
return GetDrawTarget(aInvalidRegion, aBufferMode);
}
void
+5 -2
View File
@@ -206,7 +206,8 @@ public:
#endif
virtual already_AddRefed<mozilla::gfx::DrawTarget>
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<Configuration>& aConfigurations) override;
nsresult UpdateTranslucentWindowAlphaInternal(const nsIntRect& aRect,
uint8_t* aAlphas, int32_t aStride);
virtual already_AddRefed<mozilla::gfx::DrawTarget> GetDrawTarget(const LayoutDeviceIntRegion& aRegion);
already_AddRefed<mozilla::gfx::DrawTarget> GetDrawTarget(const LayoutDeviceIntRegion& aRegion,
mozilla::layers::BufferMode* aBufferMode);
#if (MOZ_WIDGET_GTK == 2)
static already_AddRefed<gfxASurface> GetSurfaceForGdkDrawable(GdkDrawable* aDrawable,
+5 -1
View File
@@ -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<mozilla::gfx::DrawTarget> StartRemoteDrawing() = 0;
virtual already_AddRefed<mozilla::gfx::DrawTarget> StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion) {
virtual already_AddRefed<mozilla::gfx::DrawTarget> StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion,
mozilla::layers::BufferMode* aBufferMode) {
return StartRemoteDrawing();
}
+16
View File
@@ -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,
+9
View File
@@ -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();
/**
+60 -133
View File
@@ -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<LookAndFeelInt>
nsLookAndFeel::GetIntCacheImpl()
{
nsresult rv;
nsTArray<LookAndFeelInt> 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<LookAndFeelInt>& 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;
}
+5 -24
View File
@@ -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<nsIWindowsRegKey> mDwmKey;
virtual nsTArray<LookAndFeelInt> GetIntCacheImpl();
virtual void SetIntCacheImpl(const nsTArray<LookAndFeelInt>& aLookAndFeelIntCache);
private:
int32_t mUseAccessibilityTheme;
};
#endif
+11 -7
View File
@@ -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