mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 13:43:44 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 382721 - Part 1: Fix spacing of simple 2px dotted border without radius. r=jrmuizel (8e83589f45)
- Bug 382721 - Part 2: Split constants for border rendering to BorderConsts.h. r=jrmuizel (88ae5aee7f)
- Bug 1237805 part 1 - [css-grid] Remove all empty 'auto-fit' tracks, not just those at the end. r=dholbert (1c0530b87b)
- Bug 1237805 part 2 - [css-grid] 'auto-fit' reftest removing empty start/middle tracks. (3bfc688e2b)
- Bug 1239036 - [css-grid] Deal with implicit tracks when computing grid-template-{columns,rows}. r=dholbert (cf36d9193a)
- Bug 1239036 - [css-grid] Tests. (4aaec0499f)
- Bug 1238294 part 1 - [css-grid] Make GridLineEdge() a method on the Tracks class rather than a static function (idempotent change). r=dholbert (ab81994ec6)
- Bug 1238294 part 2 - [css-grid] Treat any gaps at the grid edges as "line thickness" so they behave the same as gaps between tracks for positioning areas. r=dholbert (fafdc1ceef)
- Bug 1230695 - [css-grid] More abs.pos. grid alignment reftests. (330770cf1a)
- Bug 1238294 part 3 - [css-grid] Add/tweak reftests for new behavior of gaps at the grid edges. (58ff8670a1)
- Bug 1240795 - [css-grid] Refactor GetComputedTemplateColumns/Rows to return a self-contained value. r=dholbert (9c5e68418f)
- Bug 1229739 - Use the color of shadow if available for drawing emphasis marks in shadow. r=jfkthame (c19c3deb1c)
- Bug 1191597 part 3 - Convert fullscreen-api-keys to a browser chrome test. r=smaug (ad740d4c4c)
- Bug 1174575 - Part 1: Define CSSPseudoElement interface. r=birtles, r=smaug (1a304d59c4)
- Bug 1214536 - Part 1: Use unrestricted double for iterations. r=birtles (0dbb02e423)
- Bug 1214536 - Part 2: Replace mIterationCount in layers::Animation. r=birtles (8a573046f5)
- Bug 1214536 - Part 3: Store the original value of fill. r=birtles (df548c244a)
- Bug 1214536 - Part 4: Use OwingUnrestrictedDoubleOrString for duration. r=birtles (567cfd1555)
- Bug 1214536 - Part 5: Add AnimationEffectTimingReadOnly interface. r=birtles, r=smaug (47138ec7f0)
- Bug 1214536 - Part 6: Revise AnimationTiming::operator==. r=birtles (616fc2c711)
- Bug 1214536 - Part 7: Rename AnimationTiming as TimingParams. r=birtles, r=smaug (d7de0ec72b)
- Bug 1214536 - Part 8: Add an operator=() for TimingParams. r=birtles (bfe22c6501)
- Bug 1215406 - Part 6: Test. r=birtles (3f16796304)
- Bug 1214536 - Part 9: Test. r=birtles (526419cc1d)
- Bug 1147673 - Unadjust clip before intersecting it with the scroll clip. r=botond (85cd06d2d5)
- Bug 1147673 - Determine more accurately whether an async transform affects a layer's clip rect. r=kats (8ce7d1e887)
- Bug 1096773 part 1 - Make the frames argument to the KeyframeEffectReadOnly constructor NOT optional; r=bz (6e63b08671)
- Bug 1096773 part 2 - Add a KeyframeEffectReadOnly constructor that takes a TimingParams argument; r=boris (24971306e6)
- Bug 1096773 part 3 - Implement Animatable.animate(); r=bz (9d95ea800e)
- Bug 1096773 part 4 - Add tests for Animatable.animate(); r=bz (03b866b2d8)
- Bug 1179627 - Part 1: Implement Animation.id. r=smaug, r=birtles (51bbed6e9d)
- Bug 1096774 - Part 1: Implement Animation Constructor. r=birtles, r=smaug (e09d7fbd7c)
- Bug 1179627 - Part 2: Add animation.id for CSS animations test files. r=bbirtles, r=hiikezoe (329ea31f33)
- Bug 1096774 - Part 2: Fix crash if animation has no timeline. r=birtles (d989b44866)
- Bug 1096774 - Part 3: Tests for Animation Contructor. r=birtles (23786774bc)
- Bug 1240265 - Annotate intentional switch fallthroughs in dom/. r=mrbkap (ffd9da3d5f)
- Bug 1227458. Make setAttributeNode be an alias for setAttributeNodeNS and setNamedItem on the attribute map be an alias for setNamedItemNS. r=smaug (f804d28b93)
- Bug 1226091 - Use MayHaveAnimations in Element::UnbindFromTree; r=smaug (1ec85f75b3)
This commit is contained in:
@@ -81,6 +81,41 @@ namespace {
|
||||
// Animation interface:
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
/* static */ already_AddRefed<Animation>
|
||||
Animation::Constructor(const GlobalObject& aGlobal,
|
||||
KeyframeEffectReadOnly* aEffect,
|
||||
AnimationTimeline* aTimeline,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
RefPtr<Animation> animation = new Animation(global);
|
||||
|
||||
if (!aTimeline) {
|
||||
// Bug 1096776: We do not support null timeline yet.
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
if (!aEffect) {
|
||||
// Bug 1049975: We do not support null effect yet.
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
animation->SetTimeline(aTimeline);
|
||||
animation->SetEffect(aEffect);
|
||||
|
||||
return animation.forget();
|
||||
}
|
||||
|
||||
void
|
||||
Animation::SetId(const nsAString& aId)
|
||||
{
|
||||
if (mId == aId) {
|
||||
return;
|
||||
}
|
||||
mId = aId;
|
||||
nsNodeUtils::AnimationChanged(this);
|
||||
}
|
||||
|
||||
void
|
||||
Animation::SetEffect(KeyframeEffectReadOnly* aEffect)
|
||||
@@ -1132,7 +1167,7 @@ Animation::EffectEnd() const
|
||||
return StickyTimeDuration(0);
|
||||
}
|
||||
|
||||
return mEffect->Timing().mDelay
|
||||
return mEffect->SpecifiedTiming().mDelay
|
||||
+ mEffect->GetComputedTiming().mActiveDuration;
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,13 @@ public:
|
||||
};
|
||||
|
||||
// Animation interface methods
|
||||
|
||||
static already_AddRefed<Animation>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
KeyframeEffectReadOnly* aEffect,
|
||||
AnimationTimeline* aTimeline,
|
||||
ErrorResult& aRv);
|
||||
void GetId(nsAString& aResult) const { aResult = mId; }
|
||||
void SetId(const nsAString& aId);
|
||||
KeyframeEffectReadOnly* GetEffect() const { return mEffect; }
|
||||
void SetEffect(KeyframeEffectReadOnly* aEffect);
|
||||
AnimationTimeline* GetTimeline() const { return mTimeline; }
|
||||
@@ -422,6 +428,8 @@ protected:
|
||||
// in that case mFinished is immediately reset to represent a new current
|
||||
// finished promise.
|
||||
bool mFinishedIsResolved;
|
||||
|
||||
nsString mId;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AnimationEffectTimingReadOnly;
|
||||
struct ComputedTimingProperties;
|
||||
|
||||
class AnimationEffectReadOnly : public nsISupports,
|
||||
@@ -30,9 +31,9 @@ public:
|
||||
|
||||
nsISupports* GetParentObject() const { return mParent; }
|
||||
|
||||
virtual void GetComputedTimingAsDict(ComputedTimingProperties& aRetVal) const
|
||||
{
|
||||
}
|
||||
virtual already_AddRefed<AnimationEffectTimingReadOnly> Timing() const = 0;
|
||||
|
||||
virtual void GetComputedTimingAsDict(ComputedTimingProperties& aRetVal) const = 0;
|
||||
|
||||
protected:
|
||||
virtual ~AnimationEffectReadOnly() = default;
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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/AnimationEffectTimingReadOnly.h"
|
||||
|
||||
#include "mozilla/dom/AnimatableBinding.h"
|
||||
#include "mozilla/dom/AnimationEffectTimingReadOnlyBinding.h"
|
||||
#include "mozilla/dom/KeyframeEffectBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
TimingParams::TimingParams(const dom::AnimationEffectTimingProperties& aRhs)
|
||||
: mDuration(aRhs.mDuration)
|
||||
, mDelay(TimeDuration::FromMilliseconds(aRhs.mDelay))
|
||||
, mIterations(aRhs.mIterations)
|
||||
, mDirection(aRhs.mDirection)
|
||||
, mFill(aRhs.mFill)
|
||||
{
|
||||
}
|
||||
|
||||
TimingParams::TimingParams(double aDuration)
|
||||
{
|
||||
mDuration.SetAsUnrestrictedDouble() = aDuration;
|
||||
}
|
||||
|
||||
/* static */ TimingParams
|
||||
TimingParams::FromOptionsUnion(
|
||||
const dom::UnrestrictedDoubleOrKeyframeEffectOptions& aOptions)
|
||||
{
|
||||
if (aOptions.IsUnrestrictedDouble()) {
|
||||
return TimingParams(aOptions.GetAsUnrestrictedDouble());
|
||||
} else {
|
||||
MOZ_ASSERT(aOptions.IsKeyframeEffectOptions());
|
||||
return TimingParams(aOptions.GetAsKeyframeEffectOptions());
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ TimingParams
|
||||
TimingParams::FromOptionsUnion(
|
||||
const dom::UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions)
|
||||
{
|
||||
if (aOptions.IsUnrestrictedDouble()) {
|
||||
return TimingParams(aOptions.GetAsUnrestrictedDouble());
|
||||
} else {
|
||||
MOZ_ASSERT(aOptions.IsKeyframeAnimationOptions());
|
||||
return TimingParams(aOptions.GetAsKeyframeAnimationOptions());
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TimingParams::operator==(const TimingParams& aOther) const
|
||||
{
|
||||
bool durationEqual;
|
||||
if (mDuration.IsUnrestrictedDouble()) {
|
||||
durationEqual = aOther.mDuration.IsUnrestrictedDouble() &&
|
||||
(mDuration.GetAsUnrestrictedDouble() ==
|
||||
aOther.mDuration.GetAsUnrestrictedDouble());
|
||||
} else {
|
||||
// We consider all string values and uninitialized values as meaning "auto".
|
||||
// Since mDuration is either a string or uninitialized, we consider it equal
|
||||
// if aOther.mDuration is also either a string or uninitialized.
|
||||
durationEqual = !aOther.mDuration.IsUnrestrictedDouble();
|
||||
}
|
||||
return durationEqual &&
|
||||
mDelay == aOther.mDelay &&
|
||||
mIterations == aOther.mIterations &&
|
||||
mDirection == aOther.mDirection &&
|
||||
mFill == aOther.mFill;
|
||||
}
|
||||
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationEffectTimingReadOnly, mParent)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AnimationEffectTimingReadOnly, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AnimationEffectTimingReadOnly, Release)
|
||||
|
||||
JSObject*
|
||||
AnimationEffectTimingReadOnly::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return AnimationEffectTimingReadOnlyBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
@@ -0,0 +1,103 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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_AnimationEffectTimingReadOnly_h
|
||||
#define mozilla_dom_AnimationEffectTimingReadOnly_h
|
||||
|
||||
#include "js/TypeDecls.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/UnionTypes.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
// X11 has a #define for None
|
||||
#ifdef None
|
||||
#undef None
|
||||
#endif
|
||||
#include "mozilla/dom/AnimationEffectReadOnlyBinding.h" // for FillMode
|
||||
// and PlaybackDirection
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
struct AnimationEffectTimingProperties;
|
||||
class UnrestrictedDoubleOrKeyframeEffectOptions;
|
||||
class UnrestrictedDoubleOrKeyframeAnimationOptions;
|
||||
}
|
||||
|
||||
struct TimingParams
|
||||
{
|
||||
TimingParams() = default;
|
||||
explicit TimingParams(
|
||||
const dom::AnimationEffectTimingProperties& aTimingProperties);
|
||||
explicit TimingParams(double aDuration);
|
||||
|
||||
static TimingParams FromOptionsUnion(
|
||||
const dom::UnrestrictedDoubleOrKeyframeEffectOptions& aOptions);
|
||||
static TimingParams FromOptionsUnion(
|
||||
const dom::UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions);
|
||||
|
||||
// The unitialized state of mDuration represents "auto".
|
||||
// Bug 1237173: We will replace this with Maybe<TimeDuration>.
|
||||
dom::OwningUnrestrictedDoubleOrString mDuration;
|
||||
TimeDuration mDelay; // Initializes to zero
|
||||
double mIterations = 1.0; // Can be NaN, negative, +/-Infinity
|
||||
dom::PlaybackDirection mDirection = dom::PlaybackDirection::Normal;
|
||||
dom::FillMode mFill = dom::FillMode::Auto;
|
||||
|
||||
bool operator==(const TimingParams& aOther) const;
|
||||
bool operator!=(const TimingParams& aOther) const
|
||||
{
|
||||
return !(*this == aOther);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace dom {
|
||||
|
||||
class AnimationEffectTimingReadOnly : public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
AnimationEffectTimingReadOnly() = default;
|
||||
explicit AnimationEffectTimingReadOnly(const TimingParams& aTiming)
|
||||
: mTiming(aTiming) { }
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AnimationEffectTimingReadOnly)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AnimationEffectTimingReadOnly)
|
||||
|
||||
protected:
|
||||
virtual ~AnimationEffectTimingReadOnly() = default;
|
||||
|
||||
public:
|
||||
nsISupports* GetParentObject() const { return mParent; }
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
double Delay() const { return mTiming.mDelay.ToMilliseconds(); }
|
||||
double EndDelay() const { return 0.0; }
|
||||
FillMode Fill() const { return mTiming.mFill; }
|
||||
double IterationStart() const { return 0.0; }
|
||||
double Iterations() const { return mTiming.mIterations; }
|
||||
void GetDuration(OwningUnrestrictedDoubleOrString& aRetVal) const
|
||||
{
|
||||
aRetVal = mTiming.mDuration;
|
||||
}
|
||||
PlaybackDirection Direction() const { return mTiming.mDirection; }
|
||||
void GetEasing(nsString& aRetVal) const { aRetVal.AssignLiteral("linear"); }
|
||||
|
||||
const TimingParams& AsTimingParams() const { return mTiming; }
|
||||
void SetTimingParams(const TimingParams& aTiming) { mTiming = aTiming; }
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
TimingParams mTiming;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_AnimationEffectTimingReadOnly_h
|
||||
@@ -0,0 +1,44 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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/CSSPseudoElement.h"
|
||||
#include "mozilla/dom/CSSPseudoElementBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(CSSPseudoElement)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(CSSPseudoElement, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(CSSPseudoElement, Release)
|
||||
|
||||
JSObject*
|
||||
CSSPseudoElement::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return CSSPseudoElementBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void
|
||||
CSSPseudoElement::GetAnimations(nsTArray<RefPtr<Animation>>& aRetVal)
|
||||
{
|
||||
// Bug 1234403: Implement this API.
|
||||
NS_NOTREACHED("CSSPseudoElement::GetAnimations() is not implemented yet.");
|
||||
}
|
||||
|
||||
already_AddRefed<Animation>
|
||||
CSSPseudoElement::Animate(
|
||||
JSContext* aContext,
|
||||
JS::Handle<JSObject*> aFrames,
|
||||
const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
|
||||
ErrorResult& aError)
|
||||
{
|
||||
// Bug 1241784: Implement this API.
|
||||
NS_NOTREACHED("CSSPseudoElement::Animate() is not implemented yet.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
@@ -0,0 +1,56 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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_CSSPseudoElement_h
|
||||
#define mozilla_dom_CSSPseudoElement_h
|
||||
|
||||
#include "js/TypeDecls.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class Animation;
|
||||
class Element;
|
||||
class UnrestrictedDoubleOrKeyframeAnimationOptions;
|
||||
|
||||
class CSSPseudoElement final : public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CSSPseudoElement)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CSSPseudoElement)
|
||||
|
||||
protected:
|
||||
virtual ~CSSPseudoElement() = default;
|
||||
|
||||
public:
|
||||
ParentObject GetParentObject() const
|
||||
{
|
||||
// This will be implemented in later patch.
|
||||
return ParentObject(nullptr, nullptr);
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
void GetType(nsString& aRetVal) const { }
|
||||
already_AddRefed<Element> ParentElement() const { return nullptr; }
|
||||
|
||||
void GetAnimations(nsTArray<RefPtr<Animation>>& aRetVal);
|
||||
already_AddRefed<Animation>
|
||||
Animate(JSContext* aContext,
|
||||
JS::Handle<JSObject*> aFrames,
|
||||
const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
|
||||
ErrorResult& aError);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_CSSPseudoElement_h
|
||||
@@ -50,4 +50,4 @@ private:
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_AnimationEffectReadOnly_h
|
||||
#endif // mozilla_ComputedTimingFunction_h
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
#include "mozilla/dom/KeyframeEffect.h"
|
||||
|
||||
#include "mozilla/dom/AnimationEffectReadOnlyBinding.h"
|
||||
#include "mozilla/dom/KeyframeEffectBinding.h"
|
||||
#include "mozilla/dom/PropertyIndexedKeyframesBinding.h"
|
||||
#include "mozilla/AnimationUtils.h"
|
||||
@@ -24,32 +23,19 @@
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
bool
|
||||
AnimationTiming::FillsForwards() const
|
||||
{
|
||||
return mFillMode == dom::FillMode::Both ||
|
||||
mFillMode == dom::FillMode::Forwards;
|
||||
}
|
||||
|
||||
bool
|
||||
AnimationTiming::FillsBackwards() const
|
||||
{
|
||||
return mFillMode == dom::FillMode::Both ||
|
||||
mFillMode == dom::FillMode::Backwards;
|
||||
}
|
||||
|
||||
// Helper functions for generating a ComputedTimingProperties dictionary
|
||||
static void
|
||||
GetComputedTimingDictionary(const ComputedTiming& aComputedTiming,
|
||||
const Nullable<TimeDuration>& aLocalTime,
|
||||
const AnimationTiming& aTiming,
|
||||
const TimingParams& aTiming,
|
||||
dom::ComputedTimingProperties& aRetVal)
|
||||
{
|
||||
// AnimationEffectTimingProperties
|
||||
aRetVal.mDelay = aTiming.mDelay.ToMilliseconds();
|
||||
aRetVal.mFill = aTiming.mFillMode;
|
||||
aRetVal.mIterations = aTiming.mIterationCount;
|
||||
aRetVal.mDuration.SetAsUnrestrictedDouble() = aTiming.mIterationDuration.ToMilliseconds();
|
||||
aRetVal.mFill = aComputedTiming.mFill;
|
||||
aRetVal.mIterations = aComputedTiming.mIterations;
|
||||
aRetVal.mDuration.SetAsUnrestrictedDouble() =
|
||||
aComputedTiming.mDuration.ToMilliseconds();
|
||||
aRetVal.mDirection = aTiming.mDirection;
|
||||
|
||||
// ComputedTimingProperties
|
||||
@@ -89,14 +75,15 @@ KeyframeEffectReadOnly::KeyframeEffectReadOnly(
|
||||
nsIDocument* aDocument,
|
||||
Element* aTarget,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
const AnimationTiming& aTiming)
|
||||
const TimingParams& aTiming)
|
||||
: AnimationEffectReadOnly(aDocument)
|
||||
, mTarget(aTarget)
|
||||
, mTiming(aTiming)
|
||||
, mPseudoType(aPseudoType)
|
||||
, mInEffectOnLastAnimationTimingUpdate(false)
|
||||
{
|
||||
MOZ_ASSERT(aTarget, "null animation target is not yet supported");
|
||||
|
||||
mTiming = new AnimationEffectTimingReadOnly(aTiming);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
@@ -118,13 +105,20 @@ KeyframeEffectReadOnly::Composite() const
|
||||
return CompositeOperation::Replace;
|
||||
}
|
||||
|
||||
void
|
||||
KeyframeEffectReadOnly::SetTiming(const AnimationTiming& aTiming)
|
||||
already_AddRefed<AnimationEffectTimingReadOnly>
|
||||
KeyframeEffectReadOnly::Timing() const
|
||||
{
|
||||
if (mTiming == aTiming) {
|
||||
RefPtr<AnimationEffectTimingReadOnly> temp(mTiming);
|
||||
return temp.forget();
|
||||
}
|
||||
|
||||
void
|
||||
KeyframeEffectReadOnly::SetSpecifiedTiming(const TimingParams& aTiming)
|
||||
{
|
||||
if (mTiming->AsTimingParams() == aTiming) {
|
||||
return;
|
||||
}
|
||||
mTiming = aTiming;
|
||||
mTiming->SetTimingParams(aTiming);
|
||||
if (mAnimation) {
|
||||
mAnimation->NotifyEffectTimingUpdated();
|
||||
}
|
||||
@@ -205,31 +199,36 @@ void
|
||||
KeyframeEffectReadOnly::GetComputedTimingAsDict(ComputedTimingProperties& aRetVal) const
|
||||
{
|
||||
const Nullable<TimeDuration> currentTime = GetLocalTime();
|
||||
GetComputedTimingDictionary(GetComputedTimingAt(currentTime, mTiming),
|
||||
GetComputedTimingDictionary(GetComputedTimingAt(currentTime,
|
||||
SpecifiedTiming()),
|
||||
currentTime,
|
||||
mTiming,
|
||||
SpecifiedTiming(),
|
||||
aRetVal);
|
||||
}
|
||||
|
||||
ComputedTiming
|
||||
KeyframeEffectReadOnly::GetComputedTimingAt(
|
||||
const Nullable<TimeDuration>& aLocalTime,
|
||||
const AnimationTiming& aTiming)
|
||||
const TimingParams& aTiming)
|
||||
{
|
||||
const TimeDuration zeroDuration;
|
||||
|
||||
// Currently we expect negative durations to be picked up during CSS
|
||||
// parsing but when we start receiving timing parameters from other sources
|
||||
// we will need to clamp negative durations here.
|
||||
// For now, if we're hitting this it probably means we're overflowing
|
||||
// integer arithmetic in mozilla::TimeStamp.
|
||||
MOZ_ASSERT(aTiming.mIterationDuration >= zeroDuration,
|
||||
"Expecting iteration duration >= 0");
|
||||
const StickyTimeDuration zeroDuration;
|
||||
|
||||
// Always return the same object to benefit from return-value optimization.
|
||||
ComputedTiming result;
|
||||
|
||||
result.mActiveDuration = ActiveDuration(aTiming);
|
||||
if (aTiming.mDuration.IsUnrestrictedDouble()) {
|
||||
double durationMs = aTiming.mDuration.GetAsUnrestrictedDouble();
|
||||
if (!IsNaN(durationMs) && durationMs >= 0.0f) {
|
||||
result.mDuration = StickyTimeDuration::FromMilliseconds(durationMs);
|
||||
}
|
||||
}
|
||||
result.mIterations = IsNaN(aTiming.mIterations) || aTiming.mIterations < 0.0f ?
|
||||
1.0f :
|
||||
aTiming.mIterations;
|
||||
result.mActiveDuration = ActiveDuration(result.mDuration, result.mIterations);
|
||||
result.mFill = aTiming.mFill == dom::FillMode::Auto ?
|
||||
dom::FillMode::None :
|
||||
aTiming.mFill;
|
||||
|
||||
// The default constructor for ComputedTiming sets all other members to
|
||||
// values consistent with an animation that has not been sampled.
|
||||
@@ -247,7 +246,7 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
|
||||
StickyTimeDuration activeTime;
|
||||
if (localTime >= aTiming.mDelay + result.mActiveDuration) {
|
||||
result.mPhase = ComputedTiming::AnimationPhase::After;
|
||||
if (!aTiming.FillsForwards()) {
|
||||
if (!result.FillsForwards()) {
|
||||
// The animation isn't active or filling at this time.
|
||||
result.mProgress.SetNull();
|
||||
return result;
|
||||
@@ -255,12 +254,11 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
|
||||
activeTime = result.mActiveDuration;
|
||||
// Note that infinity == floor(infinity) so this will also be true when we
|
||||
// have finished an infinitely repeating animation of zero duration.
|
||||
isEndOfFinalIteration =
|
||||
aTiming.mIterationCount != 0.0 &&
|
||||
aTiming.mIterationCount == floor(aTiming.mIterationCount);
|
||||
isEndOfFinalIteration = result.mIterations != 0.0 &&
|
||||
result.mIterations == floor(result.mIterations);
|
||||
} else if (localTime < aTiming.mDelay) {
|
||||
result.mPhase = ComputedTiming::AnimationPhase::Before;
|
||||
if (!aTiming.FillsBackwards()) {
|
||||
if (!result.FillsBackwards()) {
|
||||
// The animation isn't active or filling at this time.
|
||||
result.mProgress.SetNull();
|
||||
return result;
|
||||
@@ -275,19 +273,19 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
|
||||
|
||||
// Get the position within the current iteration.
|
||||
StickyTimeDuration iterationTime;
|
||||
if (aTiming.mIterationDuration != zeroDuration) {
|
||||
if (result.mDuration != zeroDuration) {
|
||||
iterationTime = isEndOfFinalIteration
|
||||
? StickyTimeDuration(aTiming.mIterationDuration)
|
||||
: activeTime % aTiming.mIterationDuration;
|
||||
? result.mDuration
|
||||
: activeTime % result.mDuration;
|
||||
} /* else, iterationTime is zero */
|
||||
|
||||
// Determine the 0-based index of the current iteration.
|
||||
if (isEndOfFinalIteration) {
|
||||
result.mCurrentIteration =
|
||||
aTiming.mIterationCount == NS_IEEEPositiveInfinity()
|
||||
IsInfinite(result.mIterations) // Positive Infinity?
|
||||
? UINT64_MAX // In GetComputedTimingDictionary(), we will convert this
|
||||
// into Infinity.
|
||||
: static_cast<uint64_t>(aTiming.mIterationCount) - 1;
|
||||
: static_cast<uint64_t>(result.mIterations) - 1;
|
||||
} else if (activeTime == zeroDuration) {
|
||||
// If the active time is zero we're either in the first iteration
|
||||
// (including filling backwards) or we have finished an animation with an
|
||||
@@ -295,11 +293,11 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
|
||||
// the exact end of an iteration since we deal with that above).
|
||||
result.mCurrentIteration =
|
||||
result.mPhase == ComputedTiming::AnimationPhase::After
|
||||
? static_cast<uint64_t>(aTiming.mIterationCount) // floor
|
||||
? static_cast<uint64_t>(result.mIterations) // floor
|
||||
: 0;
|
||||
} else {
|
||||
result.mCurrentIteration =
|
||||
static_cast<uint64_t>(activeTime / aTiming.mIterationDuration); // floor
|
||||
static_cast<uint64_t>(activeTime / result.mDuration); // floor
|
||||
}
|
||||
|
||||
// Normalize the iteration time into a fraction of the iteration duration.
|
||||
@@ -308,15 +306,15 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
|
||||
} else if (result.mPhase == ComputedTiming::AnimationPhase::After) {
|
||||
double progress = isEndOfFinalIteration
|
||||
? 1.0
|
||||
: fmod(aTiming.mIterationCount, 1.0f);
|
||||
: fmod(result.mIterations, 1.0);
|
||||
result.mProgress.SetValue(progress);
|
||||
} else {
|
||||
// We are in the active phase so the iteration duration can't be zero.
|
||||
MOZ_ASSERT(aTiming.mIterationDuration != zeroDuration,
|
||||
MOZ_ASSERT(result.mDuration != zeroDuration,
|
||||
"In the active phase of a zero-duration animation?");
|
||||
double progress = aTiming.mIterationDuration == TimeDuration::Forever()
|
||||
double progress = result.mDuration == StickyTimeDuration::Forever()
|
||||
? 0.0
|
||||
: iterationTime / aTiming.mIterationDuration;
|
||||
: iterationTime / result.mDuration;
|
||||
result.mProgress.SetValue(progress);
|
||||
}
|
||||
|
||||
@@ -345,19 +343,19 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
|
||||
}
|
||||
|
||||
StickyTimeDuration
|
||||
KeyframeEffectReadOnly::ActiveDuration(const AnimationTiming& aTiming)
|
||||
KeyframeEffectReadOnly::ActiveDuration(const StickyTimeDuration& aIterationDuration,
|
||||
double aIterationCount)
|
||||
{
|
||||
if (aTiming.mIterationCount == mozilla::PositiveInfinity<float>()) {
|
||||
if (IsInfinite(aIterationCount)) {
|
||||
// An animation that repeats forever has an infinite active duration
|
||||
// unless its iteration duration is zero, in which case it has a zero
|
||||
// active duration.
|
||||
const StickyTimeDuration zeroDuration;
|
||||
return aTiming.mIterationDuration == zeroDuration
|
||||
? zeroDuration
|
||||
: StickyTimeDuration::Forever();
|
||||
return aIterationDuration == zeroDuration ?
|
||||
zeroDuration :
|
||||
StickyTimeDuration::Forever();
|
||||
}
|
||||
return StickyTimeDuration(
|
||||
aTiming.mIterationDuration.MultDouble(aTiming.mIterationCount));
|
||||
return aIterationDuration.MultDouble(aIterationCount);
|
||||
}
|
||||
|
||||
// https://w3c.github.io/web-animations/#in-play
|
||||
@@ -641,55 +639,6 @@ DumpAnimationProperties(nsTArray<AnimationProperty>& aAnimationProperties)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Extract an iteration duration from an UnrestrictedDoubleOrXXX object.
|
||||
template <typename T>
|
||||
static TimeDuration
|
||||
GetIterationDuration(const T& aDuration) {
|
||||
// Always return the same object to benefit from return-value optimization.
|
||||
TimeDuration result;
|
||||
if (aDuration.IsUnrestrictedDouble()) {
|
||||
double durationMs = aDuration.GetAsUnrestrictedDouble();
|
||||
if (!IsNaN(durationMs) && durationMs >= 0.0f) {
|
||||
result = TimeDuration::FromMilliseconds(durationMs);
|
||||
}
|
||||
}
|
||||
// else, aDuration should be zero
|
||||
return result;
|
||||
}
|
||||
|
||||
/* static */ AnimationTiming
|
||||
KeyframeEffectReadOnly::ConvertKeyframeEffectOptions(
|
||||
const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions)
|
||||
{
|
||||
AnimationTiming animationTiming;
|
||||
|
||||
if (aOptions.IsKeyframeEffectOptions()) {
|
||||
const KeyframeEffectOptions& opt = aOptions.GetAsKeyframeEffectOptions();
|
||||
|
||||
animationTiming.mIterationDuration = GetIterationDuration(opt.mDuration);
|
||||
animationTiming.mDelay = TimeDuration::FromMilliseconds(opt.mDelay);
|
||||
// FIXME: Covert mIterationCount to a valid value.
|
||||
// Bug 1214536 should revise this and keep the original value, so
|
||||
// AnimationTimingEffectReadOnly can get the original iterations.
|
||||
animationTiming.mIterationCount = (IsNaN(opt.mIterations) ||
|
||||
opt.mIterations < 0.0f) ?
|
||||
1.0f :
|
||||
opt.mIterations;
|
||||
animationTiming.mDirection = opt.mDirection;
|
||||
// FIXME: We should store original value.
|
||||
animationTiming.mFillMode = (opt.mFill == FillMode::Auto) ?
|
||||
FillMode::None :
|
||||
opt.mFill;
|
||||
} else {
|
||||
animationTiming.mIterationDuration = GetIterationDuration(aOptions);
|
||||
animationTiming.mDelay = TimeDuration(0);
|
||||
animationTiming.mIterationCount = 1.0f;
|
||||
animationTiming.mDirection = PlaybackDirection::Normal;
|
||||
animationTiming.mFillMode = FillMode::None;
|
||||
}
|
||||
return animationTiming;
|
||||
}
|
||||
|
||||
/**
|
||||
* A property and StyleAnimationValue pair.
|
||||
*/
|
||||
@@ -1666,7 +1615,7 @@ BuildAnimationPropertyListFromPropertyIndexedKeyframes(
|
||||
KeyframeEffectReadOnly::BuildAnimationPropertyList(
|
||||
JSContext* aCx,
|
||||
Element* aTarget,
|
||||
const Optional<JS::Handle<JSObject*>>& aFrames,
|
||||
JS::Handle<JSObject*> aFrames,
|
||||
InfallibleTArray<AnimationProperty>& aResult,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
@@ -1682,17 +1631,16 @@ KeyframeEffectReadOnly::BuildAnimationPropertyList(
|
||||
// we can look at the open-ended set of properties on a
|
||||
// PropertyIndexedKeyframes or Keyframe.
|
||||
|
||||
if (!aFrames.WasPassed() || !aFrames.Value().get()) {
|
||||
// The argument was omitted, or was explicitly null. In both cases,
|
||||
// the default dictionary value for PropertyIndexedKeyframes would
|
||||
// result in no keyframes.
|
||||
if (!aFrames) {
|
||||
// The argument was explicitly null. In this case, the default dictionary
|
||||
// value for PropertyIndexedKeyframes would result in no keyframes.
|
||||
return;
|
||||
}
|
||||
|
||||
// At this point we know we have an object. We try to convert it to a
|
||||
// sequence<Keyframe> first, and if that fails due to not being iterable,
|
||||
// we try to convert it to PropertyIndexedKeyframes.
|
||||
JS::Rooted<JS::Value> objectValue(aCx, JS::ObjectValue(*aFrames.Value()));
|
||||
JS::Rooted<JS::Value> objectValue(aCx, JS::ObjectValue(*aFrames));
|
||||
JS::ForOfIterator iter(aCx);
|
||||
if (!iter.init(objectValue, JS::ForOfIterator::AllowNonIterable)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
@@ -1713,8 +1661,8 @@ KeyframeEffectReadOnly::BuildAnimationPropertyList(
|
||||
KeyframeEffectReadOnly::Constructor(
|
||||
const GlobalObject& aGlobal,
|
||||
Element* aTarget,
|
||||
const Optional<JS::Handle<JSObject*>>& aFrames,
|
||||
const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions,
|
||||
JS::Handle<JSObject*> aFrames,
|
||||
const TimingParams& aTiming,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (!aTarget) {
|
||||
@@ -1723,8 +1671,6 @@ KeyframeEffectReadOnly::Constructor(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AnimationTiming timing = ConvertKeyframeEffectOptions(aOptions);
|
||||
|
||||
InfallibleTArray<AnimationProperty> animationProperties;
|
||||
BuildAnimationPropertyList(aGlobal.Context(), aTarget, aFrames,
|
||||
animationProperties, aRv);
|
||||
@@ -1736,7 +1682,7 @@ KeyframeEffectReadOnly::Constructor(
|
||||
RefPtr<KeyframeEffectReadOnly> effect =
|
||||
new KeyframeEffectReadOnly(aTarget->OwnerDoc(), aTarget,
|
||||
nsCSSPseudoElements::ePseudo_NotPseudoElement,
|
||||
timing);
|
||||
aTiming);
|
||||
effect->mProperties = Move(animationProperties);
|
||||
return effect.forget();
|
||||
}
|
||||
|
||||
@@ -15,14 +15,17 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ComputedTimingFunction.h" // ComputedTimingFunction
|
||||
#include "mozilla/LayerAnimationInfo.h" // LayerAnimations::kRecords
|
||||
#include "mozilla/OwningNonNull.h" // OwningNonNull<...>
|
||||
#include "mozilla/StickyTimeDuration.h"
|
||||
#include "mozilla/StyleAnimationValue.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/dom/AnimationEffectReadOnly.h"
|
||||
#include "mozilla/dom/AnimationEffectTimingReadOnly.h" // TimingParams
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/KeyframeBinding.h"
|
||||
#include "mozilla/dom/Nullable.h"
|
||||
|
||||
|
||||
struct JSContext;
|
||||
class nsCSSPropertySet;
|
||||
class nsIContent;
|
||||
@@ -36,41 +39,11 @@ struct AnimationCollection;
|
||||
class AnimValuesStyleRule;
|
||||
|
||||
namespace dom {
|
||||
struct ComputedTimingProperties;
|
||||
class UnrestrictedDoubleOrKeyframeEffectOptions;
|
||||
enum class IterationCompositeOperation : uint32_t;
|
||||
enum class CompositeOperation : uint32_t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Input timing parameters.
|
||||
*
|
||||
* Eventually this will represent all the input timing parameters specified
|
||||
* by content but for now it encapsulates just the subset of those
|
||||
* parameters passed to GetPositionInIteration.
|
||||
*/
|
||||
struct AnimationTiming
|
||||
{
|
||||
TimeDuration mIterationDuration;
|
||||
TimeDuration mDelay;
|
||||
float mIterationCount; // mozilla::PositiveInfinity<float>() means infinite
|
||||
dom::PlaybackDirection mDirection;
|
||||
dom::FillMode mFillMode;
|
||||
|
||||
bool FillsForwards() const;
|
||||
bool FillsBackwards() const;
|
||||
bool operator==(const AnimationTiming& aOther) const {
|
||||
return mIterationDuration == aOther.mIterationDuration &&
|
||||
mDelay == aOther.mDelay &&
|
||||
mIterationCount == aOther.mIterationCount &&
|
||||
mDirection == aOther.mDirection &&
|
||||
mFillMode == aOther.mFillMode;
|
||||
}
|
||||
bool operator!=(const AnimationTiming& aOther) const {
|
||||
return !(*this == aOther);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Stores the results of calculating the timing properties of an animation
|
||||
* at a given sample time.
|
||||
@@ -88,6 +61,25 @@ struct ComputedTiming
|
||||
Nullable<double> mProgress;
|
||||
// Zero-based iteration index (meaningless if mProgress is null).
|
||||
uint64_t mCurrentIteration = 0;
|
||||
// Unlike TimingParams::mIterations, this value is
|
||||
// guaranteed to be in the range [0, Infinity].
|
||||
double mIterations = 1.0;
|
||||
StickyTimeDuration mDuration;
|
||||
|
||||
// This is the computed fill mode so it is never auto
|
||||
dom::FillMode mFill = dom::FillMode::None;
|
||||
bool FillsForwards() const {
|
||||
MOZ_ASSERT(mFill != dom::FillMode::Auto,
|
||||
"mFill should not be Auto in ComputedTiming.");
|
||||
return mFill == dom::FillMode::Both ||
|
||||
mFill == dom::FillMode::Forwards;
|
||||
}
|
||||
bool FillsBackwards() const {
|
||||
MOZ_ASSERT(mFill != dom::FillMode::Auto,
|
||||
"mFill should not be Auto in ComputedTiming.");
|
||||
return mFill == dom::FillMode::Both ||
|
||||
mFill == dom::FillMode::Backwards;
|
||||
}
|
||||
|
||||
enum class AnimationPhase {
|
||||
Null, // Not sampled (null sample time)
|
||||
@@ -178,7 +170,7 @@ public:
|
||||
KeyframeEffectReadOnly(nsIDocument* aDocument,
|
||||
Element* aTarget,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
const AnimationTiming& aTiming);
|
||||
const TimingParams& aTiming);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(KeyframeEffectReadOnly,
|
||||
@@ -197,9 +189,23 @@ public:
|
||||
static already_AddRefed<KeyframeEffectReadOnly>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
Element* aTarget,
|
||||
const Optional<JS::Handle<JSObject*>>& aFrames,
|
||||
JS::Handle<JSObject*> aFrames,
|
||||
const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
return Constructor(aGlobal, aTarget, aFrames,
|
||||
TimingParams::FromOptionsUnion(aOptions), aRv);
|
||||
}
|
||||
|
||||
// More generalized version for Animatable.animate.
|
||||
// Not exposed to content.
|
||||
static already_AddRefed<KeyframeEffectReadOnly>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
Element* aTarget,
|
||||
JS::Handle<JSObject*> aFrames,
|
||||
const TimingParams& aTiming,
|
||||
ErrorResult& aRv);
|
||||
|
||||
Element* GetTarget() const {
|
||||
// Currently we never return animations from the API whose effect
|
||||
// targets a pseudo-element so this should never be called when
|
||||
@@ -227,9 +233,13 @@ public:
|
||||
aRetVal.AssignLiteral("distribute");
|
||||
}
|
||||
|
||||
const AnimationTiming& Timing() const { return mTiming; }
|
||||
AnimationTiming& Timing() { return mTiming; }
|
||||
void SetTiming(const AnimationTiming& aTiming);
|
||||
already_AddRefed<AnimationEffectTimingReadOnly> Timing() const override;
|
||||
|
||||
const TimingParams& SpecifiedTiming() const
|
||||
{
|
||||
return mTiming->AsTimingParams();
|
||||
}
|
||||
void SetSpecifiedTiming(const TimingParams& aTiming);
|
||||
void NotifyAnimationTimingUpdated();
|
||||
|
||||
Nullable<TimeDuration> GetLocalTime() const;
|
||||
@@ -246,22 +256,25 @@ public:
|
||||
// (because it is not currently active and is not filling at this time).
|
||||
static ComputedTiming
|
||||
GetComputedTimingAt(const Nullable<TimeDuration>& aLocalTime,
|
||||
const AnimationTiming& aTiming);
|
||||
const TimingParams& aTiming);
|
||||
|
||||
// Shortcut for that gets the computed timing using the current local time as
|
||||
// calculated from the timeline time.
|
||||
ComputedTiming
|
||||
GetComputedTiming(const AnimationTiming* aTiming = nullptr) const
|
||||
GetComputedTiming(const TimingParams* aTiming = nullptr) const
|
||||
{
|
||||
return GetComputedTimingAt(GetLocalTime(), aTiming ? *aTiming : mTiming);
|
||||
return GetComputedTimingAt(GetLocalTime(),
|
||||
aTiming ? *aTiming : SpecifiedTiming());
|
||||
}
|
||||
|
||||
void
|
||||
GetComputedTimingAsDict(ComputedTimingProperties& aRetVal) const override;
|
||||
|
||||
// Return the duration of the active interval for the given timing parameters.
|
||||
// Return the duration of the active interval for the given duration and
|
||||
// iteration count.
|
||||
static StickyTimeDuration
|
||||
ActiveDuration(const AnimationTiming& aTiming);
|
||||
ActiveDuration(const StickyTimeDuration& aIterationDuration,
|
||||
double aIterationCount);
|
||||
|
||||
bool IsInPlay() const;
|
||||
bool IsCurrent() const;
|
||||
@@ -334,20 +347,17 @@ protected:
|
||||
// owning Animation's timing.
|
||||
void UpdateTargetRegistration();
|
||||
|
||||
static AnimationTiming ConvertKeyframeEffectOptions(
|
||||
const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions);
|
||||
|
||||
static void BuildAnimationPropertyList(
|
||||
JSContext* aCx,
|
||||
Element* aTarget,
|
||||
const Optional<JS::Handle<JSObject*>>& aFrames,
|
||||
JS::Handle<JSObject*> aFrames,
|
||||
InfallibleTArray<AnimationProperty>& aResult,
|
||||
ErrorResult& aRv);
|
||||
|
||||
nsCOMPtr<Element> mTarget;
|
||||
RefPtr<Animation> mAnimation;
|
||||
|
||||
AnimationTiming mTiming;
|
||||
OwningNonNull<AnimationEffectTimingReadOnly> mTiming;
|
||||
nsCSSPseudoElements::Type mPseudoType;
|
||||
|
||||
InfallibleTArray<AnimationProperty> mProperties;
|
||||
|
||||
@@ -63,6 +63,7 @@ PendingAnimationTracker::TriggerPendingAnimationsOnNextTick(const TimeStamp&
|
||||
// itself on the next tick where it has a timeline.
|
||||
if (!timeline) {
|
||||
iter.Remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
// When the timeline's refresh driver is under test control, its values
|
||||
|
||||
@@ -10,7 +10,9 @@ MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
|
||||
EXPORTS.mozilla.dom += [
|
||||
'Animation.h',
|
||||
'AnimationEffectReadOnly.h',
|
||||
'AnimationEffectTimingReadOnly.h',
|
||||
'AnimationTimeline.h',
|
||||
'CSSPseudoElement.h',
|
||||
'DocumentTimeline.h',
|
||||
'KeyframeEffect.h',
|
||||
]
|
||||
@@ -29,10 +31,12 @@ EXPORTS.mozilla += [
|
||||
UNIFIED_SOURCES += [
|
||||
'Animation.cpp',
|
||||
'AnimationEffectReadOnly.cpp',
|
||||
'AnimationEffectTimingReadOnly.cpp',
|
||||
'AnimationTimeline.cpp',
|
||||
'AnimationUtils.cpp',
|
||||
'AnimValuesStyleRule.cpp',
|
||||
'ComputedTimingFunction.cpp',
|
||||
'CSSPseudoElement.cpp',
|
||||
'DocumentTimeline.cpp',
|
||||
'EffectCompositor.cpp',
|
||||
'EffectSet.cpp',
|
||||
|
||||
@@ -3,6 +3,9 @@ support-files =
|
||||
testcommon.js
|
||||
../../imptests/testharness.js
|
||||
../../imptests/testharnessreport.js
|
||||
[chrome/test_animate_xrays.html]
|
||||
# file_animate_xrays.html needs to go in mochitest.ini since it is served
|
||||
# over HTTP
|
||||
[chrome/test_animation_observers.html]
|
||||
[chrome/test_restyles.html]
|
||||
[chrome/test_running_on_compositor.html]
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<script>
|
||||
Element.prototype.animate = function() {
|
||||
throw 'Called animate() as defined in content document';
|
||||
}
|
||||
// Bug 1211783: Use KeyframeEffect (not KeyframeEffectReadOnly) here
|
||||
for (var obj of [KeyframeEffectReadOnly, Animation]) {
|
||||
obj = function() {
|
||||
throw 'Called overridden ' + String(obj) + ' constructor';
|
||||
};
|
||||
}
|
||||
</script>
|
||||
<body>
|
||||
<div id="target"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,31 @@
|
||||
<!doctype html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<script type="application/javascript" src="../testharness.js"></script>
|
||||
<script type="application/javascript" src="../testharnessreport.js"></script>
|
||||
<script type="application/javascript" src="../testcommon.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1045994"
|
||||
target="_blank">Mozilla Bug 1045994</a>
|
||||
<div id="log"></div>
|
||||
<iframe id="iframe"
|
||||
src="http://example.org/tests/dom/animation/test/chrome/file_animate_xrays.html"></iframe>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
var win = document.getElementById('iframe').contentWindow;
|
||||
|
||||
async_test(function(t) {
|
||||
window.addEventListener('load', t.step_func(function() {
|
||||
var target = win.document.getElementById('target');
|
||||
var anim = target.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
// In the x-ray case, the frames object will be given an opaque wrapper
|
||||
// so it won't be possible to fetch any frames from it.
|
||||
assert_equals(anim.effect.getFrames().length, 0);
|
||||
t.done();
|
||||
}));
|
||||
}, 'Calling animate() across x-rays');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
@@ -763,6 +763,27 @@ function assert_records(expected, desc) {
|
||||
});
|
||||
});
|
||||
|
||||
addAsyncAnimTest("change_id", aOptions, function*() {
|
||||
e.style.animation = "anim 100s";
|
||||
|
||||
var animation = div.getAnimations()[0];
|
||||
yield await_frame();
|
||||
assert_records([{ added: [animation], changed: [], removed: []}],
|
||||
"records after creation");
|
||||
animation.id = "new id";
|
||||
yield await_frame();
|
||||
assert_records([{ added: [], changed: [animation], removed: []}],
|
||||
"records after id is changed");
|
||||
|
||||
animation.id = "new id";
|
||||
yield await_frame();
|
||||
assert_records([],
|
||||
"records after assigning same value with id");
|
||||
|
||||
e.style.animation = "";
|
||||
yield await_frame();
|
||||
});
|
||||
|
||||
// Test that making a redundant change to currentTime while an Animation
|
||||
// is pause-pending still generates a change MutationRecord since setting
|
||||
// the currentTime to any value in this state aborts the pending pause.
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<script src="../testcommon.js"></script>
|
||||
<style>
|
||||
@keyframes abc { }
|
||||
</style>
|
||||
<body>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
div.style.animation = 'abc 100s';
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
assert_equals(animation.id, '', 'id for CSS Animation is initially empty');
|
||||
|
||||
animation.id = 'anim'
|
||||
|
||||
assert_equals(animation.id, 'anim', 'animation.id reflects the value set');
|
||||
}, 'Animation.id for CSS Animations');
|
||||
|
||||
done();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,15 @@
|
||||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
setup({explicit_done: true});
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{ "set": [["dom.animations-api.core.enabled", true]]},
|
||||
function() {
|
||||
window.open("file_animation-id.html");
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
@@ -1,6 +1,9 @@
|
||||
[DEFAULT]
|
||||
# Support files for chrome tests that we want to load over HTTP need
|
||||
# to go in here, not chrome.ini.
|
||||
support-files =
|
||||
testcommon.js
|
||||
chrome/file_animate_xrays.html
|
||||
|
||||
[css-animations/test_animations-dynamic-changes.html]
|
||||
support-files = css-animations/file_animations-dynamic-changes.html
|
||||
@@ -14,6 +17,8 @@ support-files = css-animations/file_animation-currenttime.html
|
||||
support-files = css-animations/file_animation-finish.html
|
||||
[css-animations/test_animation-finished.html]
|
||||
support-files = css-animations/file_animation-finished.html
|
||||
[css-animations/test_animation-id.html]
|
||||
support-files = css-animations/file_animation-id.html
|
||||
[css-animations/test_animation-oncancel.html]
|
||||
support-files = css-animations/file_animation-oncancel.html
|
||||
[css-animations/test_animation-onfinish.html]
|
||||
|
||||
+60
-5
@@ -21,6 +21,7 @@
|
||||
#include "nsIContentInlines.h"
|
||||
#include "mozilla/dom/NodeInfo.h"
|
||||
#include "nsIDocumentInlines.h"
|
||||
#include "mozilla/dom/DocumentTimeline.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIContentIterator.h"
|
||||
@@ -51,6 +52,7 @@
|
||||
#include "nsDOMString.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIDOMMutationEvent.h"
|
||||
#include "mozilla/dom/AnimatableBinding.h"
|
||||
#include "mozilla/AnimationComparator.h"
|
||||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
#include "mozilla/ContentEvents.h"
|
||||
@@ -1267,9 +1269,11 @@ Element::GetAttributeNode(const nsAString& aName)
|
||||
already_AddRefed<Attr>
|
||||
Element::SetAttributeNode(Attr& aNewAttr, ErrorResult& aError)
|
||||
{
|
||||
// XXXbz can we just remove this warning and the one in setAttributeNodeNS and
|
||||
// alias setAttributeNode to setAttributeNodeNS?
|
||||
OwnerDoc()->WarnOnceAbout(nsIDocument::eSetAttributeNode);
|
||||
|
||||
return Attributes()->SetNamedItem(aNewAttr, aError);
|
||||
return Attributes()->SetNamedItemNS(aNewAttr, aError);
|
||||
}
|
||||
|
||||
already_AddRefed<Attr>
|
||||
@@ -1812,8 +1816,7 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
// We need to delete the properties while we're still in document
|
||||
// (if we were in document).
|
||||
// FIXME (Bug 522599): Need a test for this.
|
||||
//XXXsmaug this looks slow.
|
||||
if (HasFlag(NODE_HAS_PROPERTIES)) {
|
||||
if (MayHaveAnimations()) {
|
||||
DeleteProperty(nsGkAtoms::transitionsOfBeforeProperty);
|
||||
DeleteProperty(nsGkAtoms::transitionsOfAfterProperty);
|
||||
DeleteProperty(nsGkAtoms::transitionsProperty);
|
||||
@@ -2966,7 +2969,7 @@ Element::PreHandleEventForLinks(EventChainPreVisitor& aVisitor)
|
||||
// Set the status bar similarly for mouseover and focus
|
||||
case eMouseOver:
|
||||
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
||||
// FALL THROUGH
|
||||
MOZ_FALLTHROUGH;
|
||||
case eFocus: {
|
||||
InternalFocusEvent* focusEvent = aVisitor.mEvent->AsFocusEvent();
|
||||
if (!focusEvent || !focusEvent->isRefocus) {
|
||||
@@ -2981,7 +2984,7 @@ Element::PreHandleEventForLinks(EventChainPreVisitor& aVisitor)
|
||||
}
|
||||
case eMouseOut:
|
||||
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
||||
// FALL THROUGH
|
||||
MOZ_FALLTHROUGH;
|
||||
case eBlur:
|
||||
rv = LeaveLink(aVisitor.mPresContext);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
@@ -3370,6 +3373,58 @@ Element::MozRequestPointerLock()
|
||||
OwnerDoc()->RequestPointerLock(this);
|
||||
}
|
||||
|
||||
already_AddRefed<Animation>
|
||||
Element::Animate(JSContext* aContext,
|
||||
JS::Handle<JSObject*> aFrames,
|
||||
const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
|
||||
ErrorResult& aError)
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> ownerGlobal = GetOwnerGlobal();
|
||||
if (!ownerGlobal) {
|
||||
aError.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
GlobalObject global(aContext, ownerGlobal->GetGlobalJSObject());
|
||||
MOZ_ASSERT(!global.Failed());
|
||||
|
||||
// Wrap the aFrames object for the cross-compartment case.
|
||||
JS::Rooted<JSObject*> frames(aContext);
|
||||
frames = aFrames;
|
||||
Maybe<JSAutoCompartment> ac;
|
||||
if (js::GetContextCompartment(aContext) !=
|
||||
js::GetObjectCompartment(ownerGlobal->GetGlobalJSObject())) {
|
||||
ac.emplace(aContext, ownerGlobal->GetGlobalJSObject());
|
||||
if (!JS_WrapObject(aContext, &frames)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Bug 1211783: Use KeyframeEffect here (instead of KeyframeEffectReadOnly)
|
||||
RefPtr<KeyframeEffectReadOnly> effect =
|
||||
KeyframeEffectReadOnly::Constructor(global, this, frames,
|
||||
TimingParams::FromOptionsUnion(aOptions), aError);
|
||||
if (aError.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<Animation> animation =
|
||||
Animation::Constructor(global, effect, OwnerDoc()->Timeline(), aError);
|
||||
if (aError.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aOptions.IsKeyframeAnimationOptions()) {
|
||||
animation->SetId(aOptions.GetAsKeyframeAnimationOptions().mId);
|
||||
}
|
||||
|
||||
animation->Play(aError, Animation::LimitBehavior::AutoRewind);
|
||||
if (aError.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return animation.forget();
|
||||
}
|
||||
|
||||
void
|
||||
Element::GetAnimations(nsTArray<RefPtr<Animation>>& aAnimations)
|
||||
{
|
||||
|
||||
@@ -58,6 +58,7 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
struct ScrollIntoViewOptions;
|
||||
struct ScrollToOptions;
|
||||
class UnrestrictedDoubleOrKeyframeAnimationOptions;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -852,6 +853,12 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
already_AddRefed<Animation> Animate(
|
||||
JSContext* aContext,
|
||||
JS::Handle<JSObject*> aFrames,
|
||||
const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
|
||||
ErrorResult& aError);
|
||||
|
||||
// Note: GetAnimations will flush style while GetAnimationsUnsorted won't.
|
||||
void GetAnimations(nsTArray<RefPtr<Animation>>& aAnimations);
|
||||
void GetAnimationsUnsorted(nsTArray<RefPtr<Animation>>& aAnimations);
|
||||
|
||||
@@ -221,7 +221,7 @@ nsDOMAttributeMap::SetNamedItem(nsIDOMAttr* aAttr, nsIDOMAttr** aReturn)
|
||||
NS_ENSURE_ARG(attribute);
|
||||
|
||||
ErrorResult rv;
|
||||
*aReturn = SetNamedItem(*attribute, rv).take();
|
||||
*aReturn = SetNamedItemNS(*attribute, rv).take();
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
@@ -237,9 +237,7 @@ nsDOMAttributeMap::SetNamedItemNS(nsIDOMAttr* aAttr, nsIDOMAttr** aReturn)
|
||||
}
|
||||
|
||||
already_AddRefed<Attr>
|
||||
nsDOMAttributeMap::SetNamedItemInternal(Attr& aAttr,
|
||||
bool aWithNS,
|
||||
ErrorResult& aError)
|
||||
nsDOMAttributeMap::SetNamedItemNS(Attr& aAttr, ErrorResult& aError)
|
||||
{
|
||||
NS_ENSURE_TRUE(mContent, nullptr);
|
||||
|
||||
@@ -274,24 +272,18 @@ nsDOMAttributeMap::SetNamedItemInternal(Attr& aAttr,
|
||||
// Get nodeinfo and preexisting attribute (if it exists)
|
||||
RefPtr<NodeInfo> oldNi;
|
||||
|
||||
if (!aWithNS) {
|
||||
nsAutoString name;
|
||||
aAttr.GetName(name);
|
||||
oldNi = mContent->GetExistingAttrNameFromQName(name);
|
||||
} else {
|
||||
uint32_t i, count = mContent->GetAttrCount();
|
||||
for (i = 0; i < count; ++i) {
|
||||
const nsAttrName* name = mContent->GetAttrNameAt(i);
|
||||
int32_t attrNS = name->NamespaceID();
|
||||
nsIAtom* nameAtom = name->LocalName();
|
||||
uint32_t i, count = mContent->GetAttrCount();
|
||||
for (i = 0; i < count; ++i) {
|
||||
const nsAttrName* name = mContent->GetAttrNameAt(i);
|
||||
int32_t attrNS = name->NamespaceID();
|
||||
nsIAtom* nameAtom = name->LocalName();
|
||||
|
||||
// we're purposefully ignoring the prefix.
|
||||
if (aAttr.NodeInfo()->Equals(nameAtom, attrNS)) {
|
||||
oldNi = mContent->NodeInfo()->NodeInfoManager()->
|
||||
GetNodeInfo(nameAtom, name->GetPrefix(), aAttr.NodeInfo()->NamespaceID(),
|
||||
nsIDOMNode::ATTRIBUTE_NODE);
|
||||
break;
|
||||
}
|
||||
// we're purposefully ignoring the prefix.
|
||||
if (aAttr.NodeInfo()->Equals(nameAtom, attrNS)) {
|
||||
oldNi = mContent->NodeInfo()->NodeInfoManager()->
|
||||
GetNodeInfo(nameAtom, name->GetPrefix(), aAttr.NodeInfo()->NamespaceID(),
|
||||
nsIDOMNode::ATTRIBUTE_NODE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -141,11 +141,6 @@ public:
|
||||
Attr* NamedGetter(const nsAString& aAttrName, bool& aFound);
|
||||
bool NameIsEnumerable(const nsAString& aName);
|
||||
already_AddRefed<Attr>
|
||||
SetNamedItem(Attr& aAttr, ErrorResult& aError)
|
||||
{
|
||||
return SetNamedItemInternal(aAttr, false, aError);
|
||||
}
|
||||
already_AddRefed<Attr>
|
||||
RemoveNamedItem(mozilla::dom::NodeInfo* aNodeInfo, ErrorResult& aError);
|
||||
already_AddRefed<Attr>
|
||||
RemoveNamedItem(const nsAString& aName, ErrorResult& aError);
|
||||
@@ -158,10 +153,7 @@ public:
|
||||
GetNamedItemNS(const nsAString& aNamespaceURI,
|
||||
const nsAString& aLocalName);
|
||||
already_AddRefed<Attr>
|
||||
SetNamedItemNS(Attr& aNode, ErrorResult& aError)
|
||||
{
|
||||
return SetNamedItemInternal(aNode, true, aError);
|
||||
}
|
||||
SetNamedItemNS(Attr& aNode, ErrorResult& aError);
|
||||
already_AddRefed<Attr>
|
||||
RemoveNamedItemNS(const nsAString& aNamespaceURI, const nsAString& aLocalName,
|
||||
ErrorResult& aError);
|
||||
@@ -184,13 +176,6 @@ private:
|
||||
*/
|
||||
AttrCache mAttributeCache;
|
||||
|
||||
/**
|
||||
* SetNamedItem() (aWithNS = false) and SetNamedItemNS() (aWithNS =
|
||||
* true) implementation.
|
||||
*/
|
||||
already_AddRefed<Attr>
|
||||
SetNamedItemInternal(Attr& aNode, bool aWithNS, ErrorResult& aError);
|
||||
|
||||
already_AddRefed<mozilla::dom::NodeInfo>
|
||||
GetAttrNodeInfo(const nsAString& aNamespaceURI,
|
||||
const nsAString& aLocalName);
|
||||
|
||||
@@ -6671,6 +6671,7 @@ nsIDocument::ImportNode(nsINode& aNode, bool aDeep, ErrorResult& rv) const
|
||||
if (ShadowRoot::FromNode(imported)) {
|
||||
break;
|
||||
}
|
||||
MOZ_FALLTHROUGH;
|
||||
}
|
||||
case nsIDOMNode::ATTRIBUTE_NODE:
|
||||
case nsIDOMNode::ELEMENT_NODE:
|
||||
@@ -7705,6 +7706,7 @@ nsIDocument::AdoptNode(nsINode& aAdoptedNode, ErrorResult& rv)
|
||||
rv.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_FALLTHROUGH;
|
||||
}
|
||||
case nsIDOMNode::ELEMENT_NODE:
|
||||
case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
|
||||
@@ -7992,6 +7994,7 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
|
||||
mValidMaxScale = !maxScaleStr.IsEmpty() && NS_SUCCEEDED(scaleMaxErrorCode);
|
||||
|
||||
mViewportType = Specified;
|
||||
MOZ_FALLTHROUGH;
|
||||
}
|
||||
case Specified:
|
||||
default:
|
||||
|
||||
@@ -8031,6 +8031,7 @@ nsGlobalWindow::RevisePopupAbuseLevel(PopupControlState aControl)
|
||||
case openOverridden:
|
||||
if (PopupWhitelisted())
|
||||
abuse = PopupControlState(abuse - 1);
|
||||
break;
|
||||
case openAllowed: break;
|
||||
default:
|
||||
NS_WARNING("Strange PopupControlState!");
|
||||
|
||||
@@ -1388,7 +1388,7 @@ nsXMLContentSerializer::AppendFormatedWrapped_WhitespaceSequence(
|
||||
case ' ':
|
||||
case '\t':
|
||||
sawBlankOrTab = true;
|
||||
// no break
|
||||
MOZ_FALLTHROUGH;
|
||||
case '\n':
|
||||
++aPos;
|
||||
// do not increase mColPos,
|
||||
|
||||
@@ -29,7 +29,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1075702
|
||||
document.documentElement.setAttributeNode(a1);
|
||||
document.documentElement.setAttributeNode(a2);
|
||||
|
||||
is(document.documentElement.getAttributeNS("", "aa"), null, "Should be NULL!");
|
||||
is(document.documentElement.getAttributeNS("", "aa"), "lowercase", "Should be lowercase!");
|
||||
is(document.documentElement.getAttributeNS("", "AA"), "UPPERCASE", "Should be UPPERCASE!");
|
||||
|
||||
var a3 = document.createAttribute("AA");
|
||||
|
||||
Vendored
+1
@@ -483,6 +483,7 @@ AutoParentOpResult::~AutoParentOpResult()
|
||||
break;
|
||||
}
|
||||
Unused << PCacheParent::Send__delete__(result.actorParent());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// other types do not need clean up
|
||||
|
||||
@@ -3805,6 +3805,7 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
||||
break; // If we are submitting, do not send click event
|
||||
}
|
||||
// else fall through and treat Space like click...
|
||||
MOZ_FALLTHROUGH;
|
||||
}
|
||||
case NS_FORM_INPUT_BUTTON:
|
||||
case NS_FORM_INPUT_RESET:
|
||||
@@ -3826,7 +3827,7 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
||||
case NS_VK_UP:
|
||||
case NS_VK_LEFT:
|
||||
isMovingBack = true;
|
||||
// FALLTHROUGH
|
||||
MOZ_FALLTHROUGH;
|
||||
case NS_VK_DOWN:
|
||||
case NS_VK_RIGHT:
|
||||
// Arrow key pressed, focus+select prev/next radio button
|
||||
|
||||
@@ -4,6 +4,7 @@ support-files =
|
||||
dummy_page.html
|
||||
file_bug649778.html
|
||||
file_bug649778.html^headers^
|
||||
file_fullscreen-api-keys.html
|
||||
head.js
|
||||
|
||||
[browser_bug592641.js]
|
||||
@@ -16,4 +17,5 @@ support-files =
|
||||
file_bug1108547-2.html
|
||||
file_bug1108547-3.html
|
||||
[browser_DOMDocElementInserted.js]
|
||||
[browser_fullscreen-api-keys.js]
|
||||
[browser_fullscreen-contextmenu-esc.js]
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
"use strict";
|
||||
|
||||
/** Test for Bug 545812 **/
|
||||
|
||||
// List of key codes which should exit full-screen mode.
|
||||
const kKeyList = [
|
||||
{ code: "VK_ESCAPE", suppressed: true},
|
||||
{ code: "VK_F11", suppressed: false},
|
||||
];
|
||||
|
||||
function frameScript() {
|
||||
let doc = content.document;
|
||||
addMessageListener("Test:RequestFullscreen", () => {
|
||||
doc.body.mozRequestFullScreen();
|
||||
});
|
||||
addMessageListener("Test:DispatchUntrustedKeyEvents", msg => {
|
||||
var evt = new content.CustomEvent("Test:DispatchKeyEvents", {
|
||||
detail: { code: msg.data }
|
||||
});
|
||||
content.dispatchEvent(evt);
|
||||
});
|
||||
|
||||
doc.addEventListener("mozfullscreenchange", () => {
|
||||
sendAsyncMessage("Test:FullscreenChanged", !!doc.mozFullScreenElement);
|
||||
});
|
||||
|
||||
function keyHandler(evt) {
|
||||
sendAsyncMessage("Test:KeyReceived", {
|
||||
type: evt.type,
|
||||
keyCode: evt.keyCode
|
||||
});
|
||||
}
|
||||
doc.addEventListener("keydown", keyHandler, true);
|
||||
doc.addEventListener("keyup", keyHandler, true);
|
||||
doc.addEventListener("keypress", keyHandler, true);
|
||||
|
||||
function waitUntilActive() {
|
||||
if (doc.docShell.isActive && doc.hasFocus()) {
|
||||
sendAsyncMessage("Test:Activated");
|
||||
} else {
|
||||
setTimeout(waitUntilActive, 10);
|
||||
}
|
||||
}
|
||||
waitUntilActive();
|
||||
}
|
||||
|
||||
var gMessageManager;
|
||||
|
||||
function listenOneMessage(aMsg, aListener) {
|
||||
function listener({ data }) {
|
||||
gMessageManager.removeMessageListener(aMsg, listener);
|
||||
aListener(data);
|
||||
}
|
||||
gMessageManager.addMessageListener(aMsg, listener);
|
||||
}
|
||||
|
||||
function promiseOneMessage(aMsg) {
|
||||
return new Promise(resolve => listenOneMessage(aMsg, resolve));
|
||||
}
|
||||
|
||||
function captureUnexpectedFullscreenChange() {
|
||||
ok(false, "Caught an unexpected fullscreen change");
|
||||
}
|
||||
|
||||
function* temporaryRemoveUnexpectedFullscreenChangeCapture(callback) {
|
||||
gMessageManager.removeMessageListener(
|
||||
"Test:FullscreenChanged", captureUnexpectedFullscreenChange);
|
||||
yield* callback();
|
||||
gMessageManager.addMessageListener(
|
||||
"Test:FullscreenChanged", captureUnexpectedFullscreenChange);
|
||||
}
|
||||
|
||||
function captureUnexpectedKeyEvent(type) {
|
||||
ok(false, `Caught an unexpected ${type} event`);
|
||||
}
|
||||
|
||||
function* temporaryRemoveUnexpectedKeyEventCapture(callback) {
|
||||
gMessageManager.removeMessageListener(
|
||||
"Test:KeyReceived", captureUnexpectedKeyEvent);
|
||||
yield* callback();
|
||||
gMessageManager.addMessageListener(
|
||||
"Test:KeyReceived", captureUnexpectedKeyEvent);
|
||||
}
|
||||
|
||||
function* receiveExpectedKeyEvents(keyCode) {
|
||||
info("Waiting for key events");
|
||||
let events = ["keydown", "keypress", "keyup"];
|
||||
while (events.length > 0) {
|
||||
let evt = yield promiseOneMessage("Test:KeyReceived");
|
||||
let expected = events.shift();
|
||||
is(evt.type, expected, `Should receive a ${expected} event`);
|
||||
is(evt.keyCode, keyCode,
|
||||
`Should receive the event with key code ${keyCode}`);
|
||||
}
|
||||
}
|
||||
|
||||
const kPage = "http://example.org/browser/" +
|
||||
"dom/html/test/file_fullscreen-api-keys.html";
|
||||
|
||||
add_task(function* () {
|
||||
yield pushPrefs(
|
||||
["full-screen-api.transition-duration.enter", "0 0"],
|
||||
["full-screen-api.transition-duration.leave", "0 0"]);
|
||||
|
||||
let tab = gBrowser.addTab(kPage);
|
||||
let browser = tab.linkedBrowser;
|
||||
gBrowser.selectedTab = tab;
|
||||
registerCleanupFunction(() => gBrowser.removeTab(tab));
|
||||
yield waitForDocLoadComplete();
|
||||
|
||||
gMessageManager = browser.messageManager;
|
||||
gMessageManager.loadFrameScript(
|
||||
"data:,(" + frameScript.toString() + ")();", false);
|
||||
|
||||
// Wait for the document being actived, so that
|
||||
// fullscreen request won't be denied.
|
||||
yield promiseOneMessage("Test:Activated");
|
||||
|
||||
// Register listener to capture unexpected events
|
||||
gMessageManager.addMessageListener(
|
||||
"Test:FullscreenChanged", captureUnexpectedFullscreenChange);
|
||||
gMessageManager.addMessageListener(
|
||||
"Test:KeyReceived", captureUnexpectedKeyEvent);
|
||||
registerCleanupFunction(() => {
|
||||
gMessageManager.removeMessageListener(
|
||||
"Test:FullscreenChanged", captureUnexpectedFullscreenChange);
|
||||
gMessageManager.removeMessageListener(
|
||||
"Test:KeyReceived", captureUnexpectedKeyEvent);
|
||||
});
|
||||
|
||||
for (let {code, suppressed} of kKeyList) {
|
||||
var keyCode = KeyEvent["DOM_" + code];
|
||||
info(`Test keycode ${code} (${keyCode})`);
|
||||
|
||||
info("Enter fullscreen");
|
||||
yield* temporaryRemoveUnexpectedFullscreenChangeCapture(function* () {
|
||||
gMessageManager.sendAsyncMessage("Test:RequestFullscreen");
|
||||
let state = yield promiseOneMessage("Test:FullscreenChanged");
|
||||
ok(state, "The content should have entered fullscreen");
|
||||
ok(document.mozFullScreenElement,
|
||||
"The chrome should also be in fullscreen");
|
||||
});
|
||||
|
||||
info("Dispatch untrusted key events from content");
|
||||
yield* temporaryRemoveUnexpectedKeyEventCapture(function* () {
|
||||
gMessageManager.sendAsyncMessage("Test:DispatchUntrustedKeyEvents", code);
|
||||
yield* receiveExpectedKeyEvents(keyCode);
|
||||
});
|
||||
|
||||
info("Send trusted key events");
|
||||
yield* temporaryRemoveUnexpectedFullscreenChangeCapture(function* () {
|
||||
yield* temporaryRemoveUnexpectedKeyEventCapture(function* () {
|
||||
EventUtils.synthesizeKey(code, {});
|
||||
if (!suppressed) {
|
||||
yield* receiveExpectedKeyEvents(keyCode);
|
||||
}
|
||||
let state = yield promiseOneMessage("Test:FullscreenChanged");
|
||||
ok(!state, "The content should have exited fullscreen");
|
||||
ok(!document.mozFullScreenElement,
|
||||
"The chrome should also have exited fullscreen");
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -58,6 +58,10 @@ function e(id) {
|
||||
return document.getElementById(id);
|
||||
}
|
||||
|
||||
function removeElement(e) {
|
||||
e.parentNode.removeChild(e);
|
||||
}
|
||||
|
||||
const isMacOs = navigator.appVersion.indexOf("Macintosh") != -1;
|
||||
|
||||
var windowedPlugin = null;
|
||||
@@ -108,6 +112,10 @@ function nonMacTest2() {
|
||||
|
||||
function nonMacTest3() {
|
||||
ok(!document.mozFullScreen, "Full-screen should have been revoked when windowed-plugin was focused.");
|
||||
// Remove windowed plugins before closing the window
|
||||
// to work around bug 1237853.
|
||||
removeElement(e("windowed-plugin"));
|
||||
removeElement(e("subdoc-plugin").contentDocument.getElementById("windowed-plugin"));
|
||||
opener.nextTest();
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@ support-files =
|
||||
file_bug893537.html
|
||||
file_formSubmission_img.jpg
|
||||
file_formSubmission_text.txt
|
||||
file_fullscreen-api-keys.html
|
||||
file_fullscreen-api.html
|
||||
file_fullscreen-backdrop.html
|
||||
file_fullscreen-denied-inner.html
|
||||
|
||||
@@ -33,7 +33,6 @@ var gTestWindows = [
|
||||
"file_fullscreen-esc-exit.html",
|
||||
"file_fullscreen-denied.html",
|
||||
"file_fullscreen-api.html",
|
||||
"file_fullscreen-api-keys.html",
|
||||
"file_fullscreen-plugins.html",
|
||||
"file_fullscreen-hidden.html",
|
||||
"file_fullscreen-svg-element.html",
|
||||
|
||||
@@ -220,7 +220,7 @@ DOMStorageDBThread::InsertDBOp(DOMStorageDBThread::DBOperation* aOperation)
|
||||
aOperation->Finalize(NS_OK);
|
||||
return NS_OK;
|
||||
}
|
||||
// NO BREAK
|
||||
MOZ_FALLTHROUGH;
|
||||
|
||||
case DBOperation::opGetUsage:
|
||||
if (aOperation->Type() == DBOperation::opPreloadUrgent) {
|
||||
|
||||
@@ -126,6 +126,8 @@ var interfaceNamesInGlobalScope =
|
||||
{name: "Animation", release: false},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "AnimationEffectReadOnly", release: false},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "AnimationEffectTimingReadOnly", release: false},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"AnimationEvent",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
@@ -349,6 +351,8 @@ var interfaceNamesInGlobalScope =
|
||||
"CSSPageRule",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"CSSPrimitiveValue",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "CSSPseudoElement", release: false},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"CSSRule",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
||||
@@ -10,8 +10,16 @@
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
dictionary KeyframeAnimationOptions : KeyframeEffectOptions {
|
||||
DOMString id = "";
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface Animatable {
|
||||
[Func="nsDocument::IsWebAnimationsEnabled", Throws]
|
||||
Animation animate(object? frames,
|
||||
optional (unrestricted double or KeyframeAnimationOptions)
|
||||
options);
|
||||
[Func="nsDocument::IsWebAnimationsEnabled"]
|
||||
sequence<Animation> getAnimations();
|
||||
};
|
||||
|
||||
@@ -12,8 +12,11 @@
|
||||
|
||||
enum AnimationPlayState { "idle", "pending", "running", "paused", "finished" };
|
||||
|
||||
[Func="nsDocument::IsWebAnimationsEnabled"]
|
||||
[Func="nsDocument::IsWebAnimationsEnabled",
|
||||
Constructor (optional KeyframeEffectReadOnly? effect = null,
|
||||
optional AnimationTimeline? timeline = null)]
|
||||
interface Animation : EventTarget {
|
||||
attribute DOMString id;
|
||||
// Bug 1049975: Make 'effect' writeable
|
||||
[Pure]
|
||||
readonly attribute AnimationEffectReadOnly? effect;
|
||||
|
||||
@@ -46,9 +46,8 @@ dictionary ComputedTimingProperties : AnimationEffectTimingProperties {
|
||||
|
||||
[Func="nsDocument::IsWebAnimationsEnabled"]
|
||||
interface AnimationEffectReadOnly {
|
||||
// Not yet implemented:
|
||||
// readonly attribute AnimationEffectTimingReadOnly timing;
|
||||
|
||||
[Cached, Constant]
|
||||
readonly attribute AnimationEffectTimingReadOnly timing;
|
||||
[BinaryName="getComputedTimingAsDict"]
|
||||
ComputedTimingProperties getComputedTiming();
|
||||
};
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/* -*- 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://w3c.github.io/web-animations/#animationeffecttimingreadonly
|
||||
*
|
||||
* Copyright © 2015 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
[Func="nsDocument::IsWebAnimationsEnabled"]
|
||||
interface AnimationEffectTimingReadOnly {
|
||||
readonly attribute double delay;
|
||||
readonly attribute double endDelay;
|
||||
readonly attribute FillMode fill;
|
||||
readonly attribute double iterationStart;
|
||||
readonly attribute unrestricted double iterations;
|
||||
readonly attribute (unrestricted double or DOMString) duration;
|
||||
readonly attribute PlaybackDirection direction;
|
||||
readonly attribute DOMString easing;
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
/* -*- 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://drafts.csswg.org/css-pseudo/#CSSPseudoElement-interface
|
||||
* https://drafts.csswg.org/cssom/#pseudoelement
|
||||
*
|
||||
* Copyright © 2015 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
// Both CSSOM and CSS Pseudo-Elements 4 provide contradictory definitions for
|
||||
// this interface.
|
||||
// What we implement here is a minimal subset of the two definitions which we
|
||||
// ship behind a pref until the specification issues have been resolved.
|
||||
[Func="nsDocument::IsWebAnimationsEnabled"]
|
||||
interface CSSPseudoElement {
|
||||
readonly attribute DOMString type;
|
||||
readonly attribute Element parentElement;
|
||||
};
|
||||
|
||||
// https://w3c.github.io/web-animations/#extensions-to-the-pseudoelement-interface
|
||||
CSSPseudoElement implements Animatable;
|
||||
@@ -21,22 +21,12 @@ dictionary KeyframeEffectOptions : AnimationEffectTimingProperties {
|
||||
DOMString spacing = "distribute";
|
||||
};
|
||||
|
||||
// For the constructor:
|
||||
//
|
||||
// 1. We use Element? for the first argument since we don't support Animatable
|
||||
// for pseudo-elements yet.
|
||||
//
|
||||
// 2. We use object? instead of
|
||||
//
|
||||
// (PropertyIndexedKeyframes or sequence<Keyframe> or SharedKeyframeList)
|
||||
//
|
||||
// for the second argument so that we can get the property-value pairs from
|
||||
// the PropertyIndexedKeyframes or Keyframe objects. We also don't support
|
||||
// SharedKeyframeList yet.
|
||||
// For the constructor we use Element? for the first argument since we
|
||||
// don't support Animatable for pseudo-elements yet.
|
||||
[HeaderFile="mozilla/dom/KeyframeEffect.h",
|
||||
Func="nsDocument::IsWebAnimationsEnabled",
|
||||
Constructor(Element? target,
|
||||
optional object? frames,
|
||||
object? frames,
|
||||
optional (unrestricted double or KeyframeEffectOptions) options)]
|
||||
interface KeyframeEffectReadOnly : AnimationEffectReadOnly {
|
||||
readonly attribute Element? target;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
interface NamedNodeMap {
|
||||
getter Attr? getNamedItem(DOMString name);
|
||||
[Throws]
|
||||
[Throws, BinaryName="setNamedItemNS"]
|
||||
Attr? setNamedItem(Attr arg);
|
||||
[Throws]
|
||||
Attr removeNamedItem(DOMString name);
|
||||
|
||||
@@ -25,6 +25,7 @@ WEBIDL_FILES = [
|
||||
'Animatable.webidl',
|
||||
'Animation.webidl',
|
||||
'AnimationEffectReadOnly.webidl',
|
||||
'AnimationEffectTimingReadOnly.webidl',
|
||||
'AnimationEvent.webidl',
|
||||
'AnimationTimeline.webidl',
|
||||
'AnonymousContent.webidl',
|
||||
@@ -98,6 +99,7 @@ WEBIDL_FILES = [
|
||||
'CSSAnimation.webidl',
|
||||
'CSSLexer.webidl',
|
||||
'CSSPrimitiveValue.webidl',
|
||||
'CSSPseudoElement.webidl',
|
||||
'CSSRuleList.webidl',
|
||||
'CSSStyleDeclaration.webidl',
|
||||
'CSSStyleSheet.webidl',
|
||||
|
||||
@@ -1970,7 +1970,7 @@ void ReportLoadError(JSContext* aCx, nsresult aLoadResult)
|
||||
|
||||
case NS_ERROR_MALFORMED_URI:
|
||||
aLoadResult = NS_ERROR_DOM_SYNTAX_ERR;
|
||||
// fall through
|
||||
MOZ_FALLTHROUGH;
|
||||
case NS_ERROR_DOM_SECURITY_ERR:
|
||||
case NS_ERROR_DOM_SYNTAX_ERR:
|
||||
Throw(aCx, aLoadResult);
|
||||
|
||||
@@ -385,7 +385,8 @@ AsyncCompositionManager::AlignFixedAndStickyLayers(Layer* aLayer,
|
||||
FrameMetrics::ViewID aTransformScrollId,
|
||||
const Matrix4x4& aPreviousTransformForRoot,
|
||||
const Matrix4x4& aCurrentTransformForRoot,
|
||||
const ScreenMargin& aFixedLayerMargins)
|
||||
const ScreenMargin& aFixedLayerMargins,
|
||||
bool aTransformAffectsLayerClip)
|
||||
{
|
||||
FrameMetrics::ViewID fixedTo; // the scroll id of the scroll frame we are fixed/sticky to
|
||||
bool isRootOfFixedSubtree = aLayer->GetIsFixedPosition() &&
|
||||
@@ -411,7 +412,8 @@ AsyncCompositionManager::AlignFixedAndStickyLayers(Layer* aLayer,
|
||||
for (Layer* child = aLayer->GetFirstChild(); child; child = child->GetNextSibling()) {
|
||||
AlignFixedAndStickyLayers(child, aTransformedSubtreeRoot, aTransformScrollId,
|
||||
aPreviousTransformForRoot,
|
||||
aCurrentTransformForRoot, aFixedLayerMargins);
|
||||
aCurrentTransformForRoot, aFixedLayerMargins,
|
||||
true /* descendants' clip rects are always affected */);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -489,18 +491,15 @@ AsyncCompositionManager::AlignFixedAndStickyLayers(Layer* aLayer,
|
||||
IntervalOverlap(translation.x, stickyInner.x, stickyInner.XMost());
|
||||
}
|
||||
|
||||
// Finally, apply the translation to the layer transform. Note that in
|
||||
// general we need to apply the same translation to the layer's clip rect, so
|
||||
// Finally, apply the translation to the layer transform. Note that in cases
|
||||
// where the async transform on |aTransformedSubtreeRoot| affects this layer's
|
||||
// clip rect, we need to apply the same translation to said clip rect, so
|
||||
// that the effective transform on the clip rect takes it back to where it was
|
||||
// originally, had there been no async scroll. In the case where the
|
||||
// fixed/sticky layer is the same as aTransformedSubtreeRoot, then the clip
|
||||
// rect is not affected by the scroll-induced async scroll transform anyway
|
||||
// (since the clip is applied post-transform) so we don't need to make the
|
||||
// adjustment. Also, some layers want async scrolling to move their clip rect
|
||||
// originally, had there been no async scroll.
|
||||
// Also, some layers want async scrolling to move their clip rect
|
||||
// (IsClipFixed() = false), so we don't make a compensating adjustment for
|
||||
// those.
|
||||
bool adjustClipRect = aLayer != aTransformedSubtreeRoot &&
|
||||
aLayer->IsClipFixed();
|
||||
bool adjustClipRect = aTransformAffectsLayerClip && aLayer->IsClipFixed();
|
||||
TranslateShadowLayer(aLayer, ThebesPoint(translation.ToUnknownPoint()), adjustClipRect);
|
||||
}
|
||||
|
||||
@@ -580,18 +579,20 @@ SampleAnimations(Layer* aLayer, TimeStamp aPoint)
|
||||
continue;
|
||||
}
|
||||
|
||||
AnimationTiming timing;
|
||||
timing.mIterationDuration = animation.duration();
|
||||
TimingParams timing;
|
||||
timing.mDuration.SetAsUnrestrictedDouble() =
|
||||
animation.duration().ToMilliseconds();
|
||||
// Currently animations run on the compositor have their delay factored
|
||||
// into their start time, hence the delay is effectively zero.
|
||||
timing.mDelay = TimeDuration(0);
|
||||
timing.mIterationCount = animation.iterationCount();
|
||||
timing.mDirection = static_cast<dom::PlaybackDirection>(animation.direction());
|
||||
timing.mIterations = animation.iterations();
|
||||
timing.mDirection =
|
||||
static_cast<dom::PlaybackDirection>(animation.direction());
|
||||
// Animations typically only run on the compositor during their active
|
||||
// interval but if we end up sampling them outside that range (for
|
||||
// example, while they are waiting to be removed) we currently just
|
||||
// assume that we should fill.
|
||||
timing.mFillMode = dom::FillMode::Both;
|
||||
timing.mFill = dom::FillMode::Both;
|
||||
|
||||
ComputedTiming computedTiming =
|
||||
dom::KeyframeEffectReadOnly::GetComputedTimingAt(
|
||||
@@ -900,6 +901,29 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer,
|
||||
asyncClip = Some(TransformBy(
|
||||
ViewAs<ParentLayerToParentLayerMatrix4x4>(asyncTransform), *asyncClip));
|
||||
}
|
||||
aLayer->AsLayerComposite()->SetShadowClipRect(asyncClip);
|
||||
|
||||
combinedAsyncTransform *= asyncTransform;
|
||||
|
||||
// For the purpose of aligning fixed and sticky layers, we disregard
|
||||
// the overscroll transform as well as any OMTA transform when computing the
|
||||
// 'aCurrentTransformForRoot' parameter. This ensures that the overscroll
|
||||
// and OMTA transforms are not unapplied, and therefore that the visual
|
||||
// effects apply to fixed and sticky layers. We do this by using
|
||||
// GetTransform() as the base transform rather than GetLocalTransform(),
|
||||
// which would include those factors.
|
||||
Matrix4x4 transformWithoutOverscrollOrOmta = aLayer->GetTransform() *
|
||||
AdjustForClip(asyncTransformWithoutOverscroll, aLayer);
|
||||
|
||||
// Since fixed/sticky layers are relative to their nearest scrolling ancestor,
|
||||
// we use the ViewID from the bottommost scrollable metrics here.
|
||||
AlignFixedAndStickyLayers(aLayer, aLayer, metrics.GetScrollId(), oldTransform,
|
||||
transformWithoutOverscrollOrOmta, fixedLayerMargins,
|
||||
asyncClip.isSome());
|
||||
|
||||
// AlignFixedAndStickyLayers may have changed the clip rect, so we have to
|
||||
// read it from the layer again.
|
||||
asyncClip = aLayer->AsLayerComposite()->GetShadowClipRect();
|
||||
|
||||
// Combine the local clip with the ancestor scrollframe clip. This is not
|
||||
// included in the async transform above, since the ancestor clip should not
|
||||
@@ -932,23 +956,6 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer,
|
||||
Layer* ancestorMaskLayer = aLayer->GetAncestorMaskLayerAt(maskLayerIndex);
|
||||
ancestorMaskLayers.AppendElement(ancestorMaskLayer);
|
||||
}
|
||||
|
||||
combinedAsyncTransform *= asyncTransform;
|
||||
|
||||
// For the purpose of aligning fixed and sticky layers, we disregard
|
||||
// the overscroll transform as well as any OMTA transform when computing the
|
||||
// 'aCurrentTransformForRoot' parameter. This ensures that the overscroll
|
||||
// and OMTA transforms are not unapplied, and therefore that the visual
|
||||
// effects apply to fixed and sticky layers. We do this by using
|
||||
// GetTransform() as the base transform rather than GetLocalTransform(),
|
||||
// which would include those factors.
|
||||
Matrix4x4 transformWithoutOverscrollOrOmta = aLayer->GetTransform() *
|
||||
AdjustForClip(asyncTransformWithoutOverscroll, aLayer);
|
||||
|
||||
// Since fixed/sticky layers are relative to their nearest scrolling ancestor,
|
||||
// we use the ViewID from the bottommost scrollable metrics here.
|
||||
AlignFixedAndStickyLayers(aLayer, aLayer, metrics.GetScrollId(), oldTransform,
|
||||
transformWithoutOverscrollOrOmta, fixedLayerMargins);
|
||||
}
|
||||
|
||||
if (hasAsyncTransform || clipDeferredFromChildren) {
|
||||
@@ -1331,7 +1338,8 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer)
|
||||
// Make sure fixed position layers don't move away from their anchor points
|
||||
// when we're asynchronously panning or zooming
|
||||
AlignFixedAndStickyLayers(aLayer, aLayer, metrics.GetScrollId(), oldTransform,
|
||||
aLayer->GetLocalTransform(), fixedLayerMargins);
|
||||
aLayer->GetLocalTransform(), fixedLayerMargins,
|
||||
false);
|
||||
|
||||
ExpandRootClipRect(aLayer, fixedLayerMargins);
|
||||
}
|
||||
|
||||
@@ -177,12 +177,17 @@ private:
|
||||
* This function will also adjust layers so that the given content document
|
||||
* fixed position margins will be respected during asynchronous panning and
|
||||
* zooming.
|
||||
* aTransformAffectsLayerClip indicates whether the transform on
|
||||
* aTransformedSubtreeRoot affects aLayer's clip rects, so we know
|
||||
* whether we need to perform a corresponding unadjustment to keep
|
||||
* the clip rect fixed.
|
||||
*/
|
||||
void AlignFixedAndStickyLayers(Layer* aLayer, Layer* aTransformedSubtreeRoot,
|
||||
FrameMetrics::ViewID aTransformScrollId,
|
||||
const gfx::Matrix4x4& aPreviousTransformForRoot,
|
||||
const gfx::Matrix4x4& aCurrentTransformForRoot,
|
||||
const ScreenMargin& aFixedLayerMargins);
|
||||
const ScreenMargin& aFixedLayerMargins,
|
||||
bool aTransformAffectsLayerClip);
|
||||
|
||||
/**
|
||||
* DRAWING PHASE ONLY
|
||||
|
||||
@@ -193,7 +193,7 @@ struct Animation {
|
||||
// Number of times to repeat the animation, including positive infinity.
|
||||
// Values <= 0 mean the animation will not play (although events are still
|
||||
// dispatched on the main thread).
|
||||
float iterationCount;
|
||||
float iterations;
|
||||
// This uses the NS_STYLE_ANIMATION_DIRECTION_* constants.
|
||||
int32_t direction;
|
||||
nsCSSProperty property;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#ifndef mozilla_BorderConsts_h_
|
||||
#define mozilla_BorderConsts_h_
|
||||
|
||||
// thickness of dashed line relative to dotted line
|
||||
#define DOT_LENGTH 1 // square
|
||||
#define DASH_LENGTH 3 // 3 times longer than dot
|
||||
|
||||
// some shorthand for side bits
|
||||
#define SIDE_BIT_TOP (1 << NS_SIDE_TOP)
|
||||
#define SIDE_BIT_RIGHT (1 << NS_SIDE_RIGHT)
|
||||
#define SIDE_BIT_BOTTOM (1 << NS_SIDE_BOTTOM)
|
||||
#define SIDE_BIT_LEFT (1 << NS_SIDE_LEFT)
|
||||
#define SIDE_BITS_ALL (SIDE_BIT_TOP|SIDE_BIT_RIGHT|SIDE_BIT_BOTTOM|SIDE_BIT_LEFT)
|
||||
|
||||
#define C_TL NS_CORNER_TOP_LEFT
|
||||
#define C_TR NS_CORNER_TOP_RIGHT
|
||||
#define C_BR NS_CORNER_BOTTOM_RIGHT
|
||||
#define C_BL NS_CORNER_BOTTOM_LEFT
|
||||
|
||||
#endif /* mozilla_BorderConsts_h_ */
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
|
||||
#include "BorderConsts.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIFrame.h"
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/Helpers.h"
|
||||
#include "mozilla/gfx/PathHelpers.h"
|
||||
#include "BorderConsts.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsCSSColorUtils.h"
|
||||
@@ -1616,7 +1617,7 @@ nsCSSBorderRenderer::DrawBorders()
|
||||
Float dash = mBorderWidths[0];
|
||||
strokeOptions.mDashPattern = ‐
|
||||
strokeOptions.mDashLength = 1;
|
||||
strokeOptions.mDashOffset = 0.5f;
|
||||
strokeOptions.mDashOffset = 0.5f * dash;
|
||||
DrawOptions drawOptions;
|
||||
drawOptions.mAntialiasMode = AntialiasMode::NONE;
|
||||
mDrawTarget->StrokeRect(rect, color, strokeOptions, drawOptions);
|
||||
|
||||
@@ -28,22 +28,6 @@ class GradientStops;
|
||||
// define this to enable a bunch of debug dump info
|
||||
#undef DEBUG_NEW_BORDERS
|
||||
|
||||
//thickness of dashed line relative to dotted line
|
||||
#define DOT_LENGTH 1 //square
|
||||
#define DASH_LENGTH 3 //3 times longer than dot
|
||||
|
||||
//some shorthand for side bits
|
||||
#define SIDE_BIT_TOP (1 << NS_SIDE_TOP)
|
||||
#define SIDE_BIT_RIGHT (1 << NS_SIDE_RIGHT)
|
||||
#define SIDE_BIT_BOTTOM (1 << NS_SIDE_BOTTOM)
|
||||
#define SIDE_BIT_LEFT (1 << NS_SIDE_LEFT)
|
||||
#define SIDE_BITS_ALL (SIDE_BIT_TOP|SIDE_BIT_RIGHT|SIDE_BIT_BOTTOM|SIDE_BIT_LEFT)
|
||||
|
||||
#define C_TL NS_CORNER_TOP_LEFT
|
||||
#define C_TR NS_CORNER_TOP_RIGHT
|
||||
#define C_BR NS_CORNER_BOTTOM_RIGHT
|
||||
#define C_BL NS_CORNER_BOTTOM_LEFT
|
||||
|
||||
/*
|
||||
* Helper class that handles border rendering.
|
||||
*
|
||||
|
||||
@@ -383,7 +383,9 @@ AddAnimationForProperty(nsIFrame* aFrame, const AnimationProperty& aProperty,
|
||||
aLayer->AddAnimationForNextTransaction() :
|
||||
aLayer->AddAnimation();
|
||||
|
||||
const AnimationTiming& timing = aAnimation->GetEffect()->Timing();
|
||||
const TimingParams& timing = aAnimation->GetEffect()->SpecifiedTiming();
|
||||
const ComputedTiming computedTiming =
|
||||
aAnimation->GetEffect()->GetComputedTiming();
|
||||
Nullable<TimeDuration> startTime = aAnimation->GetCurrentOrPendingStartTime();
|
||||
animation->startTime() = startTime.IsNull()
|
||||
? TimeStamp()
|
||||
@@ -391,8 +393,8 @@ AddAnimationForProperty(nsIFrame* aFrame, const AnimationProperty& aProperty,
|
||||
StickyTimeDuration(timing.mDelay));
|
||||
animation->initialCurrentTime() = aAnimation->GetCurrentTime().Value()
|
||||
- timing.mDelay;
|
||||
animation->duration() = timing.mIterationDuration;
|
||||
animation->iterationCount() = timing.mIterationCount;
|
||||
animation->duration() = computedTiming.mDuration;
|
||||
animation->iterations() = computedTiming.mIterations;
|
||||
animation->direction() = static_cast<uint32_t>(timing.mDirection);
|
||||
animation->property() = aProperty.mProperty;
|
||||
animation->playbackRate() = aAnimation->PlaybackRate();
|
||||
|
||||
@@ -35,6 +35,12 @@ const uint32_t nsGridContainerFrame::kAutoLine = kTranslatedMaxLine + 3457U;
|
||||
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(TrackSize::StateBits)
|
||||
|
||||
enum class GridLineSide
|
||||
{
|
||||
eBeforeGridGap,
|
||||
eAfterGridGap,
|
||||
};
|
||||
|
||||
class nsGridContainerFrame::GridItemCSSOrderIterator
|
||||
{
|
||||
public:
|
||||
@@ -914,6 +920,27 @@ struct MOZ_STACK_CLASS nsGridContainerFrame::Tracks
|
||||
void AlignJustifyContent(const nsHTMLReflowState& aReflowState,
|
||||
const LogicalSize& aContainerSize);
|
||||
|
||||
nscoord GridLineEdge(uint32_t aLine, GridLineSide aSide) const
|
||||
{
|
||||
if (MOZ_UNLIKELY(mSizes.IsEmpty())) {
|
||||
// https://drafts.csswg.org/css-grid/#grid-definition
|
||||
// "... the explicit grid still contains one grid line in each axis."
|
||||
MOZ_ASSERT(aLine == 0, "We should only resolve line 1 in an empty grid");
|
||||
return nscoord(0);
|
||||
}
|
||||
MOZ_ASSERT(aLine <= mSizes.Length(), "mSizes is too small");
|
||||
if (aSide == GridLineSide::eBeforeGridGap) {
|
||||
if (aLine == 0) {
|
||||
return nscoord(0);
|
||||
}
|
||||
const TrackSize& sz = mSizes[aLine - 1];
|
||||
return sz.mPosition + sz.mBase;
|
||||
}
|
||||
if (aLine == mSizes.Length()) {
|
||||
return mContentBoxSize;
|
||||
}
|
||||
return mSizes[aLine].mPosition;
|
||||
}
|
||||
|
||||
nscoord SumOfGridGaps() const {
|
||||
auto len = mSizes.Length();
|
||||
@@ -932,6 +959,7 @@ struct MOZ_STACK_CLASS nsGridContainerFrame::Tracks
|
||||
#endif
|
||||
|
||||
nsAutoTArray<TrackSize, 32> mSizes;
|
||||
nscoord mContentBoxSize;
|
||||
nscoord mGridGap;
|
||||
LogicalAxis mAxis;
|
||||
};
|
||||
@@ -1041,36 +1069,6 @@ IsNameWithStartSuffix(const nsString& aString, uint32_t* aIndex)
|
||||
return IsNameWithSuffix(aString, NS_LITERAL_STRING("-start"), aIndex);
|
||||
}
|
||||
|
||||
enum class GridLineSide {
|
||||
eBeforeGridGap,
|
||||
eAfterGridGap,
|
||||
};
|
||||
|
||||
static nscoord
|
||||
GridLineEdge(uint32_t aLine, const nsTArray<TrackSize>& aTrackSizes,
|
||||
GridLineSide aSide)
|
||||
{
|
||||
if (MOZ_UNLIKELY(aTrackSizes.IsEmpty())) {
|
||||
// https://drafts.csswg.org/css-grid/#grid-definition
|
||||
// "... the explicit grid still contains one grid line in each axis."
|
||||
MOZ_ASSERT(aLine == 0, "We should only resolve line 1 in an empty grid");
|
||||
return nscoord(0);
|
||||
}
|
||||
MOZ_ASSERT(aLine <= aTrackSizes.Length(), "aTrackSizes is too small");
|
||||
if (aSide == GridLineSide::eBeforeGridGap) {
|
||||
if (aLine == 0) {
|
||||
return aTrackSizes[0].mPosition;
|
||||
}
|
||||
const TrackSize& sz = aTrackSizes[aLine - 1];
|
||||
return sz.mPosition + sz.mBase;
|
||||
}
|
||||
if (aLine == aTrackSizes.Length()) {
|
||||
const TrackSize& sz = aTrackSizes[aLine - 1];
|
||||
return sz.mPosition + sz.mBase;
|
||||
}
|
||||
return aTrackSizes[aLine].mPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* (XXX share this utility function with nsFlexContainerFrame at some point)
|
||||
*
|
||||
@@ -2139,45 +2137,73 @@ nsGridContainerFrame::PlaceGridItems(GridReflowState& aState,
|
||||
}
|
||||
}
|
||||
|
||||
// Count empty 'auto-fit' tracks at the end of the repeat() range.
|
||||
// Count empty 'auto-fit' tracks in the repeat() range.
|
||||
// |colAdjust| will have a count for each line in the grid of how many
|
||||
// tracks were empty between the start of the grid and that line.
|
||||
Maybe<nsTArray<uint32_t>> colAdjust;
|
||||
uint32_t numEmptyCols = 0;
|
||||
if (aState.mColFunctions.mHasRepeatAuto &&
|
||||
!gridStyle->mGridTemplateColumns.mIsAutoFill &&
|
||||
aState.mColFunctions.NumRepeatTracks() > 0) {
|
||||
for (int32_t start = aState.mColFunctions.mRepeatAutoStart,
|
||||
col = aState.mColFunctions.mRepeatAutoEnd - 1;
|
||||
col >= start && mCellMap.IsEmptyCol(col);
|
||||
--col) {
|
||||
++numEmptyCols;
|
||||
for (uint32_t col = aState.mColFunctions.mRepeatAutoStart,
|
||||
endRepeat = aState.mColFunctions.mRepeatAutoEnd,
|
||||
numColLines = mGridColEnd + 1;
|
||||
col < numColLines; ++col) {
|
||||
if (numEmptyCols) {
|
||||
(*colAdjust)[col] = numEmptyCols;
|
||||
}
|
||||
if (col < endRepeat && mCellMap.IsEmptyCol(col)) {
|
||||
++numEmptyCols;
|
||||
if (colAdjust.isNothing()) {
|
||||
colAdjust.emplace(numColLines);
|
||||
colAdjust->SetLength(numColLines);
|
||||
PodZero(colAdjust->Elements(), colAdjust->Length());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Maybe<nsTArray<uint32_t>> rowAdjust;
|
||||
uint32_t numEmptyRows = 0;
|
||||
if (aState.mRowFunctions.mHasRepeatAuto &&
|
||||
!gridStyle->mGridTemplateRows.mIsAutoFill &&
|
||||
aState.mRowFunctions.NumRepeatTracks() > 0) {
|
||||
for (int32_t start = aState.mRowFunctions.mRepeatAutoStart,
|
||||
row = aState.mRowFunctions.mRepeatAutoEnd - 1;
|
||||
row >= start && mCellMap.IsEmptyRow(row);
|
||||
--row) {
|
||||
++numEmptyRows;
|
||||
for (uint32_t row = aState.mRowFunctions.mRepeatAutoStart,
|
||||
endRepeat = aState.mRowFunctions.mRepeatAutoEnd,
|
||||
numRowLines = mGridRowEnd + 1;
|
||||
row < numRowLines; ++row) {
|
||||
if (numEmptyRows) {
|
||||
(*rowAdjust)[row] = numEmptyRows;
|
||||
}
|
||||
if (row < endRepeat && mCellMap.IsEmptyRow(row)) {
|
||||
++numEmptyRows;
|
||||
if (rowAdjust.isNothing()) {
|
||||
rowAdjust.emplace(numRowLines);
|
||||
rowAdjust->SetLength(numRowLines);
|
||||
PodZero(rowAdjust->Elements(), rowAdjust->Length());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove the empty 'auto-fit' tracks we found above, if any.
|
||||
if (numEmptyCols || numEmptyRows) {
|
||||
// Adjust the line numbers in the grid areas.
|
||||
const uint32_t firstRemovedCol =
|
||||
aState.mColFunctions.mRepeatAutoEnd - numEmptyCols;
|
||||
const uint32_t firstRemovedRow =
|
||||
aState.mRowFunctions.mRepeatAutoEnd - numEmptyRows;
|
||||
for (auto& item : mGridItems) {
|
||||
GridArea& area = item.mArea;
|
||||
area.mCols.AdjustForRemovedTracks(firstRemovedCol, numEmptyCols);
|
||||
area.mRows.AdjustForRemovedTracks(firstRemovedRow, numEmptyRows);
|
||||
if (numEmptyCols) {
|
||||
area.mCols.AdjustForRemovedTracks(*colAdjust);
|
||||
}
|
||||
if (numEmptyRows) {
|
||||
area.mRows.AdjustForRemovedTracks(*rowAdjust);
|
||||
}
|
||||
}
|
||||
for (auto& item : mAbsPosItems) {
|
||||
GridArea& area = item.mArea;
|
||||
area.mCols.AdjustAbsPosForRemovedTracks(firstRemovedCol, numEmptyCols);
|
||||
area.mRows.AdjustAbsPosForRemovedTracks(firstRemovedRow, numEmptyRows);
|
||||
if (numEmptyCols) {
|
||||
area.mCols.AdjustAbsPosForRemovedTracks(*colAdjust);
|
||||
}
|
||||
if (numEmptyRows) {
|
||||
area.mRows.AdjustAbsPosForRemovedTracks(*rowAdjust);
|
||||
}
|
||||
}
|
||||
// Adjust the grid size.
|
||||
mGridColEnd -= numEmptyCols;
|
||||
@@ -2257,6 +2283,7 @@ nsGridContainerFrame::Tracks::Initialize(
|
||||
aFunctions.MaxSizingFor(i));
|
||||
}
|
||||
mGridGap = aGridGap;
|
||||
mContentBoxSize = aContentBoxSize;
|
||||
MOZ_ASSERT(mGridGap >= nscoord(0), "negative grid gap");
|
||||
}
|
||||
|
||||
@@ -3062,7 +3089,7 @@ nsGridContainerFrame::LineRange::ToLength(
|
||||
|
||||
void
|
||||
nsGridContainerFrame::LineRange::ToPositionAndLengthForAbsPos(
|
||||
const nsTArray<TrackSize>& aTrackSizes, nscoord aGridOrigin,
|
||||
const Tracks& aTracks, nscoord aGridOrigin,
|
||||
nscoord* aPos, nscoord* aLength) const
|
||||
{
|
||||
// kAutoLine for abspos children contributes the corresponding edge
|
||||
@@ -3073,18 +3100,17 @@ nsGridContainerFrame::LineRange::ToPositionAndLengthForAbsPos(
|
||||
} else {
|
||||
const nscoord endPos = *aPos + *aLength;
|
||||
nscoord startPos =
|
||||
::GridLineEdge(mStart, aTrackSizes, GridLineSide::eAfterGridGap);
|
||||
aTracks.GridLineEdge(mStart, GridLineSide::eAfterGridGap);
|
||||
*aPos = aGridOrigin + startPos;
|
||||
*aLength = std::max(endPos - *aPos, 0);
|
||||
}
|
||||
} else {
|
||||
if (mStart == kAutoLine) {
|
||||
nscoord endPos =
|
||||
::GridLineEdge(mEnd, aTrackSizes, GridLineSide::eBeforeGridGap);
|
||||
nscoord endPos = aTracks.GridLineEdge(mEnd, GridLineSide::eBeforeGridGap);
|
||||
*aLength = std::max(aGridOrigin + endPos, 0);
|
||||
} else {
|
||||
nscoord pos;
|
||||
ToPositionAndLength(aTrackSizes, &pos, aLength);
|
||||
ToPositionAndLength(aTracks.mSizes, &pos, aLength);
|
||||
*aPos = aGridOrigin + pos;
|
||||
}
|
||||
}
|
||||
@@ -3113,11 +3139,9 @@ nsGridContainerFrame::ContainingBlockForAbsPos(const GridReflowState& aState,
|
||||
nscoord b = aGridCB.BStart(wm);
|
||||
nscoord iSize = aGridCB.ISize(wm);
|
||||
nscoord bSize = aGridCB.BSize(wm);
|
||||
aArea.mCols.ToPositionAndLengthForAbsPos(aState.mCols.mSizes,
|
||||
aGridOrigin.I(wm),
|
||||
aArea.mCols.ToPositionAndLengthForAbsPos(aState.mCols, aGridOrigin.I(wm),
|
||||
&i, &iSize);
|
||||
aArea.mRows.ToPositionAndLengthForAbsPos(aState.mRows.mSizes,
|
||||
aGridOrigin.B(wm),
|
||||
aArea.mRows.ToPositionAndLengthForAbsPos(aState.mRows, aGridOrigin.B(wm),
|
||||
&b, &bSize);
|
||||
return LogicalRect(wm, i, b, iSize, bSize);
|
||||
}
|
||||
@@ -3313,14 +3337,21 @@ nsGridContainerFrame::Reflow(nsPresContext* aPresContext,
|
||||
for (const TrackSize& sz : gridReflowState.mCols.mSizes) {
|
||||
colTrackSizes.AppendElement(sz.mBase);
|
||||
}
|
||||
Properties().Set(GridColTrackSizes(),
|
||||
new nsTArray<nscoord>(mozilla::Move(colTrackSizes)));
|
||||
ComputedGridTrackInfo* colInfo = new ComputedGridTrackInfo(
|
||||
gridReflowState.mColFunctions.mExplicitGridOffset,
|
||||
gridReflowState.mColFunctions.NumExplicitTracks(),
|
||||
Move(colTrackSizes));
|
||||
Properties().Set(GridColTrackInfo(), colInfo);
|
||||
|
||||
nsTArray<nscoord> rowTrackSizes(gridReflowState.mRows.mSizes.Length());
|
||||
for (const TrackSize& sz : gridReflowState.mRows.mSizes) {
|
||||
rowTrackSizes.AppendElement(sz.mBase);
|
||||
}
|
||||
Properties().Set(GridRowTrackSizes(),
|
||||
new nsTArray<nscoord>(mozilla::Move(rowTrackSizes)));
|
||||
ComputedGridTrackInfo* rowInfo = new ComputedGridTrackInfo(
|
||||
gridReflowState.mRowFunctions.mExplicitGridOffset,
|
||||
gridReflowState.mRowFunctions.NumExplicitTracks(),
|
||||
Move(rowTrackSizes));
|
||||
Properties().Set(GridRowTrackInfo(), rowInfo);
|
||||
|
||||
nscoord bSize = 0;
|
||||
if (computedBSize == NS_AUTOHEIGHT) {
|
||||
|
||||
@@ -21,6 +21,25 @@
|
||||
nsContainerFrame* NS_NewGridContainerFrame(nsIPresShell* aPresShell,
|
||||
nsStyleContext* aContext);
|
||||
|
||||
namespace mozilla {
|
||||
/**
|
||||
* The number of implicit / explicit tracks and their sizes.
|
||||
*/
|
||||
struct ComputedGridTrackInfo
|
||||
{
|
||||
ComputedGridTrackInfo(uint32_t aNumLeadingImplicitTracks,
|
||||
uint32_t aNumExplicitTracks,
|
||||
nsTArray<nscoord>&& aSizes)
|
||||
: mNumLeadingImplicitTracks(aNumLeadingImplicitTracks)
|
||||
, mNumExplicitTracks(aNumExplicitTracks)
|
||||
, mSizes(aSizes)
|
||||
{}
|
||||
uint32_t mNumLeadingImplicitTracks;
|
||||
uint32_t mNumExplicitTracks;
|
||||
nsTArray<nscoord> mSizes;
|
||||
};
|
||||
} // namespace mozilla
|
||||
|
||||
class nsGridContainerFrame final : public nsContainerFrame
|
||||
{
|
||||
public:
|
||||
@@ -88,18 +107,16 @@ public:
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY(GridItemContainingBlockRect, DeleteValue<nsRect>)
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY(GridColTrackSizes, DeleteValue<nsTArray<nscoord>>)
|
||||
|
||||
const nsTArray<nscoord>* GetComputedTemplateColumns()
|
||||
NS_DECLARE_FRAME_PROPERTY(GridColTrackInfo, DeleteValue<ComputedGridTrackInfo>)
|
||||
const ComputedGridTrackInfo* GetComputedTemplateColumns()
|
||||
{
|
||||
return static_cast<nsTArray<nscoord>*>(Properties().Get(GridColTrackSizes()));
|
||||
return static_cast<ComputedGridTrackInfo*>(Properties().Get(GridColTrackInfo()));
|
||||
}
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY(GridRowTrackSizes, DeleteValue<nsTArray<nscoord>>)
|
||||
|
||||
const nsTArray<nscoord>* GetComputedTemplateRows()
|
||||
NS_DECLARE_FRAME_PROPERTY(GridRowTrackInfo, DeleteValue<ComputedGridTrackInfo>)
|
||||
const ComputedGridTrackInfo* GetComputedTemplateRows()
|
||||
{
|
||||
return static_cast<nsTArray<nscoord>*>(Properties().Get(GridRowTrackSizes()));
|
||||
return static_cast<ComputedGridTrackInfo*>(Properties().Get(GridRowTrackInfo()));
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -192,47 +209,34 @@ protected:
|
||||
/**
|
||||
* Translate the lines to account for (empty) removed tracks. This method
|
||||
* is only for grid items and should only be called after placement.
|
||||
* aNumRemovedTracks contains a count for each line in the grid how many
|
||||
* tracks were removed between the start of the grid and that line.
|
||||
*/
|
||||
void AdjustForRemovedTracks(uint32_t aFirstRemovedTrack,
|
||||
uint32_t aNumRemovedTracks)
|
||||
void AdjustForRemovedTracks(const nsTArray<uint32_t>& aNumRemovedTracks)
|
||||
{
|
||||
MOZ_ASSERT(mStart != kAutoLine, "invalid resolved line for a grid item");
|
||||
MOZ_ASSERT(mEnd != kAutoLine, "invalid resolved line for a grid item");
|
||||
if (mStart >= aFirstRemovedTrack) {
|
||||
MOZ_ASSERT(mStart >= aFirstRemovedTrack + aNumRemovedTracks,
|
||||
"can't start in a removed range of tracks - those tracks "
|
||||
"are supposed to be empty");
|
||||
mStart -= aNumRemovedTracks;
|
||||
mEnd -= aNumRemovedTracks;
|
||||
} else {
|
||||
MOZ_ASSERT(mEnd <= aFirstRemovedTrack, "can't span into a removed "
|
||||
"range of tracks - those tracks are supposed to be empty");
|
||||
}
|
||||
uint32_t numRemovedTracks = aNumRemovedTracks[mStart];
|
||||
MOZ_ASSERT(numRemovedTracks == aNumRemovedTracks[mEnd],
|
||||
"tracks that a grid item spans can't be removed");
|
||||
mStart -= numRemovedTracks;
|
||||
mEnd -= numRemovedTracks;
|
||||
}
|
||||
/**
|
||||
* Translate the lines to account for (empty) removed tracks. This method
|
||||
* is only for abs.pos. children and should only be called after placement.
|
||||
* Same as for in-flow items, but we don't touch 'auto' lines here and we
|
||||
* also need to adjust areas that span into the removed range.
|
||||
* also need to adjust areas that span into the removed tracks.
|
||||
*/
|
||||
void AdjustAbsPosForRemovedTracks(uint32_t aFirstRemovedTrack,
|
||||
uint32_t aNumRemovedTracks)
|
||||
void AdjustAbsPosForRemovedTracks(const nsTArray<uint32_t>& aNumRemovedTracks)
|
||||
{
|
||||
if (mStart != nsGridContainerFrame::kAutoLine &&
|
||||
mStart > aFirstRemovedTrack) {
|
||||
if (mStart < aFirstRemovedTrack + aNumRemovedTracks) {
|
||||
mStart = aFirstRemovedTrack;
|
||||
} else {
|
||||
mStart -= aNumRemovedTracks;
|
||||
}
|
||||
if (mStart != nsGridContainerFrame::kAutoLine) {
|
||||
mStart -= aNumRemovedTracks[mStart];
|
||||
}
|
||||
if (mEnd != nsGridContainerFrame::kAutoLine &&
|
||||
mEnd > aFirstRemovedTrack) {
|
||||
if (mEnd < aFirstRemovedTrack + aNumRemovedTracks) {
|
||||
mEnd = aFirstRemovedTrack;
|
||||
} else {
|
||||
mEnd -= aNumRemovedTracks;
|
||||
}
|
||||
if (mEnd != nsGridContainerFrame::kAutoLine) {
|
||||
MOZ_ASSERT(mStart == nsGridContainerFrame::kAutoLine ||
|
||||
mEnd > mStart, "invalid line range");
|
||||
mEnd -= aNumRemovedTracks[mEnd];
|
||||
}
|
||||
if (mStart == mEnd) {
|
||||
mEnd = nsGridContainerFrame::kAutoLine;
|
||||
@@ -255,12 +259,12 @@ protected:
|
||||
*/
|
||||
nscoord ToLength(const nsTArray<TrackSize>& aTrackSizes) const;
|
||||
/**
|
||||
* Given an array of track sizes and a grid origin coordinate, adjust the
|
||||
* Given a set of tracks and a grid origin coordinate, adjust the
|
||||
* abs.pos. containing block along an axis given by aPos and aLength.
|
||||
* aPos and aLength should already be initialized to the grid container
|
||||
* containing block for this axis before calling this method.
|
||||
*/
|
||||
void ToPositionAndLengthForAbsPos(const nsTArray<TrackSize>& aTrackSizes,
|
||||
void ToPositionAndLengthForAbsPos(const Tracks& aTracks,
|
||||
nscoord aGridOrigin,
|
||||
nscoord* aPos, nscoord* aLength) const;
|
||||
|
||||
|
||||
@@ -6268,6 +6268,7 @@ void
|
||||
nsTextFrame::DrawEmphasisMarks(gfxContext* aContext, WritingMode aWM,
|
||||
const gfxPoint& aTextBaselinePt,
|
||||
uint32_t aOffset, uint32_t aLength,
|
||||
const nscolor* aDecorationOverrideColor,
|
||||
PropertyProvider& aProvider)
|
||||
{
|
||||
auto info = static_cast<const EmphasisMarkInfo*>(
|
||||
@@ -6276,8 +6277,8 @@ nsTextFrame::DrawEmphasisMarks(gfxContext* aContext, WritingMode aWM,
|
||||
return;
|
||||
}
|
||||
|
||||
nscolor color = nsLayoutUtils::
|
||||
GetColor(this, eCSSProperty_text_emphasis_color);
|
||||
nscolor color = aDecorationOverrideColor ? *aDecorationOverrideColor :
|
||||
nsLayoutUtils::GetColor(this, eCSSProperty_text_emphasis_color);
|
||||
aContext->SetColor(Color::FromABGR(color));
|
||||
gfxPoint pt(aTextBaselinePt);
|
||||
if (!aWM.IsVertical()) {
|
||||
@@ -6799,7 +6800,8 @@ nsTextFrame::DrawTextRunAndDecorations(
|
||||
aAdvanceWidth, aDrawSoftHyphen, aContextPaint, aCallbacks);
|
||||
|
||||
// Emphasis marks
|
||||
DrawEmphasisMarks(aCtx, wm, aTextBaselinePt, aOffset, aLength, aProvider);
|
||||
DrawEmphasisMarks(aCtx, wm, aTextBaselinePt, aOffset, aLength,
|
||||
aDecorationOverrideColor, aProvider);
|
||||
|
||||
// Line-throughs
|
||||
for (uint32_t i = aDecorations.mStrikes.Length(); i-- > 0; ) {
|
||||
|
||||
@@ -460,6 +460,7 @@ public:
|
||||
mozilla::WritingMode aWM,
|
||||
const gfxPoint& aTextBaselinePt,
|
||||
uint32_t aOffset, uint32_t aLength,
|
||||
const nscolor* aDecorationOverrideColor,
|
||||
PropertyProvider& aProvider);
|
||||
|
||||
virtual nscolor GetCaretColorAt(int32_t aOffset) override;
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html><head>
|
||||
<meta charset="utf-8">
|
||||
<title>Reference: grid abs.pos. child in grid with gutters</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1230695">
|
||||
<style type="text/css">
|
||||
body { width:800px; }
|
||||
|
||||
.grid {
|
||||
display: block;
|
||||
position: relative;
|
||||
grid-template-columns: repeat(5, 20px);
|
||||
grid-auto-rows: 10px;
|
||||
grid-gap: 100px 10px;
|
||||
border: 1px solid;
|
||||
padding: 0 3px 0 5px;
|
||||
height: 40px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.grid.r {
|
||||
grid-template-columns: 20px;
|
||||
grid-template-rows: repeat(5, 20px);
|
||||
height: 160px;
|
||||
padding: 2px 3px 4px 5px;
|
||||
float: left;
|
||||
min-width: 70px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
x {
|
||||
position: absolute;
|
||||
width: 20px;
|
||||
height: 10px;
|
||||
background: lime;
|
||||
}
|
||||
|
||||
a {
|
||||
position: absolute;
|
||||
left:0; right:0; bottom:20px; height: 3px;
|
||||
background: black;
|
||||
}
|
||||
b {
|
||||
position: absolute;
|
||||
left:0; right:0; bottom:10px; height: 3px;
|
||||
background: grey;
|
||||
}
|
||||
c {
|
||||
position: absolute;
|
||||
left:0; right:0; bottom:0; height: 3px;
|
||||
background: blue;
|
||||
}
|
||||
|
||||
.r a {
|
||||
left:50px; top:0; bottom:0; width: 3px; height:auto;
|
||||
}
|
||||
.r b {
|
||||
left:40px; top:0; bottom:0; width: 3px; height:auto;
|
||||
}
|
||||
.r c {
|
||||
left:30px; top:0; bottom:0; width: 3px; height:auto;
|
||||
}
|
||||
|
||||
x:nth-of-type(1) { left:5px; }
|
||||
x:nth-of-type(2) { left:125px; }
|
||||
x:nth-of-type(3) { left:245px; }
|
||||
x:nth-of-type(4) { left:365px; }
|
||||
|
||||
.r x { left:5px; height:20px; }
|
||||
.r x:nth-of-type(1) { top:2px; }
|
||||
.r x:nth-of-type(2) { top:32px; }
|
||||
.r x:nth-of-type(3) { top:62px; }
|
||||
.r x:nth-of-type(4) { top:92px; }
|
||||
|
||||
.s x:nth-of-type(1) { left:120px; }
|
||||
.s x:nth-of-type(2) { left:255px; }
|
||||
.s x:nth-of-type(3) { left:390px; }
|
||||
.s x:nth-of-type(4) { left:525px; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="grid">
|
||||
<x></x><x></x><x></x><x></x>
|
||||
<a style="left:125px; width:140px"></a><b style="width:265px"></b><c style="left:365px"></c>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
<x></x><x></x><x></x><x></x>
|
||||
<a style="left:5px; width:260px"></a><b style="width:5px"></b><c style="left:5px"></c>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
<x></x><x></x><x></x><x></x>
|
||||
<a style="left:795px"></a><b style="width:505px"></b><c style="left:795px"></c>
|
||||
</div>
|
||||
|
||||
<div class="grid s">
|
||||
<x></x><x></x><x></x><x></x>
|
||||
<a style="left:255px; width:155px"></a><b style="width:410px"></b><c style="left:525px"></c>
|
||||
</div>
|
||||
|
||||
<div class="grid s">
|
||||
<x></x><x></x><x></x><x></x>
|
||||
<a style="left:120px; width:290px"></a><b style="width:5px"></b><c style="left:120px"></c>
|
||||
</div>
|
||||
|
||||
<div class="grid s">
|
||||
<x></x><x></x><x></x><x></x>
|
||||
<a style="left:795px"></a><b style="width:680px"></b><c style="left:795px"></c>
|
||||
</div>
|
||||
|
||||
<div class="grid r">
|
||||
<x></x><x></x><x></x><x></x>
|
||||
<a style="top:32px; height:50px"></a><b style="height:82px"></b><c style="top:92px"></c>
|
||||
</div>
|
||||
|
||||
<div class="grid r">
|
||||
<x></x><x></x><x></x><x></x>
|
||||
<a style="top:2px; height:80px"></a><b style="height:2px"></b><c style="top:2px"></c>
|
||||
</div>
|
||||
|
||||
<div class="grid r">
|
||||
<x></x><x></x><x></x><x></x>
|
||||
<a style="top:162px"></a><b style="height:142px"></b><c style="top:162px"></c>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,120 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html><head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Grid Test: grid abs.pos. child in grid with gutters</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1230695">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-grid/#abspos">
|
||||
<link rel="match" href="grid-abspos-items-013-ref.html">
|
||||
<style type="text/css">
|
||||
body { width:800px; }
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
position: relative;
|
||||
grid-template-columns: repeat(5, 20px);
|
||||
grid-auto-rows: 10px;
|
||||
grid-gap: 100px 10px;
|
||||
border: 1px solid;
|
||||
padding: 0 3px 0 5px;
|
||||
height: 40px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.grid.r {
|
||||
grid-template-columns: 20px;
|
||||
grid-template-rows: repeat(5, 20px);
|
||||
height: 160px;
|
||||
padding: 2px 3px 4px 5px;
|
||||
float: left;
|
||||
min-width: 70px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
.c.s {
|
||||
justify-content: space-evenly;
|
||||
grid-gap: 0;
|
||||
}
|
||||
|
||||
x {
|
||||
background: lime;
|
||||
}
|
||||
|
||||
a {
|
||||
position: absolute;
|
||||
left:0; right:0; bottom:20px; height: 3px;
|
||||
background: black;
|
||||
}
|
||||
b {
|
||||
position: absolute;
|
||||
left:0; right:0; bottom:10px; height: 3px;
|
||||
background: grey;
|
||||
}
|
||||
c {
|
||||
position: absolute;
|
||||
left:0; right:0; bottom:0; height: 3px;
|
||||
background: blue;
|
||||
}
|
||||
|
||||
.r a {
|
||||
left:50px; top:0; bottom:0; width: 3px; height:auto;
|
||||
}
|
||||
.r b {
|
||||
left:40px; top:0; bottom:0; width: 3px; height:auto;
|
||||
}
|
||||
.r c {
|
||||
left:30px; top:0; bottom:0; width: 3px; height:auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="grid c">
|
||||
<x></x><x></x><x></x><x></x>
|
||||
<a style="grid-column:2/4"></a><b style="grid-column:auto/4"></b><c style="grid-column:4/auto"></c>
|
||||
</div>
|
||||
|
||||
<div class="grid c">
|
||||
<x></x><x></x><x></x><x></x>
|
||||
<a style="grid-column:1/4"></a><b style="grid-column:auto/1"></b><c style="grid-column:1/auto"></c>
|
||||
</div>
|
||||
|
||||
<div class="grid c">
|
||||
<x></x><x></x><x></x><x></x>
|
||||
<a style="grid-column:6/6"></a><b style="grid-column:auto/6"></b><c style="grid-column:6/auto"></c>
|
||||
</div>
|
||||
|
||||
<div class="grid c s">
|
||||
<x></x><x></x><x></x><x></x>
|
||||
<a style="grid-column:2/4"></a><b style="grid-column:auto/4"></b><c style="grid-column:4/auto"></c>
|
||||
</div>
|
||||
|
||||
<div class="grid c s">
|
||||
<x></x><x></x><x></x><x></x>
|
||||
<a style="grid-column:1/4"></a><b style="grid-column:auto/1"></b><c style="grid-column:1/auto"></c>
|
||||
</div>
|
||||
|
||||
<div class="grid c s">
|
||||
<x></x><x></x><x></x><x></x>
|
||||
<a style="grid-column:6/6"></a><b style="grid-column:auto/6"></b><c style="grid-column:6/auto"></c>
|
||||
</div>
|
||||
|
||||
<div class="grid r">
|
||||
<x></x><x></x><x></x><x></x>
|
||||
<a style="grid-row:2/4"></a><b style="grid-row:auto/4"></b><c style="grid-row:4/auto"></c>
|
||||
</div>
|
||||
|
||||
<div class="grid r">
|
||||
<x></x><x></x><x></x><x></x>
|
||||
<a style="grid-row:1/4"></a><b style="grid-row:auto/1"></b><c style="grid-row:1/auto"></c>
|
||||
</div>
|
||||
|
||||
<div class="grid r">
|
||||
<x></x><x></x><x></x><x></x>
|
||||
<a style="grid-row:6/6"></a><b style="grid-row:auto/6"></b><c style="grid-row:6/auto"></c>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -45,8 +45,8 @@ body,html { color:black; background:white; font-size:16px; padding:0; margin:0;
|
||||
width: 51px; height: 2px;
|
||||
}
|
||||
.d {
|
||||
left: 1px; top: 11px;
|
||||
width: 212px; height: 1px;
|
||||
left: 1px; top: 5px;
|
||||
width: 212px; height: 7px;
|
||||
}
|
||||
.e {
|
||||
right: 5px; bottom: 1px;
|
||||
@@ -98,7 +98,7 @@ span {
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
<span class="d abs" style="height:50px;top:11px">d</span>
|
||||
<span class="d abs" style="height:3px; top:58px"></span>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
|
||||
@@ -52,6 +52,7 @@ span.negative {
|
||||
.d {
|
||||
grid-column: auto / A -3;
|
||||
grid-row: 2 / 1;
|
||||
top: -3px;
|
||||
}
|
||||
.e {
|
||||
grid-column: A -3 / auto;
|
||||
@@ -111,7 +112,7 @@ span {
|
||||
|
||||
<div class="grid">
|
||||
<span class="negative"></span>
|
||||
<span class="d abs">d</span>
|
||||
<span class="d abs"></span>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
|
||||
@@ -28,7 +28,8 @@ html,body {
|
||||
|
||||
.r0 { grid-template-rows: [a] repeat(1, [b] 0 [c]) [d]; }
|
||||
.r10,.r1 { grid-template-rows: [a] repeat(1, [b] 20px [c]) [d]; }
|
||||
.r01 { grid-template-rows: [a] repeat(1, [b] 0 [c]) [d]; }
|
||||
.r01 { grid-template-rows: [a] repeat(1, [b] 0 [c]) 20px [d]; grid-gap:0;}
|
||||
.r01 a {grid-row-end:auto; }
|
||||
.r2 { grid-template-rows: [a] repeat(1, [b] 20px [c]) [d] 30px [e]; }
|
||||
.r20 { width:22px; grid-template-rows: [a] repeat(1, [b] 20px [c]) [d] 30px [e]; }
|
||||
.r02 { grid-template-rows: [a] repeat(1, [b] 0 [c]) [d] 30px [e]; }
|
||||
@@ -274,11 +275,11 @@ fill,fit {
|
||||
<div class="grid r0"><x></x><x></x><a></a><b></b><x></x></div>
|
||||
<div class="grid ra"><x></x><x></x><a></a><b></b><x></x></div>
|
||||
|
||||
<div class="grid w r01" style="min-height:0"><a></a><b></b></div>
|
||||
<div class="grid w r01" style="max-height:0"><a></a><b></b></div>
|
||||
<div class="grid w r01" style="height:0"><a></a><b></b></div>
|
||||
<div class="grid w r01" style="min-height:0; height:0"><a></a><b></b></div>
|
||||
<div class="grid w r01" style="max-height:0"><a></a><b></b></div>
|
||||
<div class="grid w r0"><a></a><b></b></div>
|
||||
<div class="grid w r01" style="max-height:0"><a></a><b></b></div>
|
||||
<div class="grid w r0a"><a></a><b></b></div>
|
||||
|
||||
<br clear="all">
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html><head>
|
||||
<meta charset="utf-8">
|
||||
<title>Reference: repeat(auto-fit) with grid-aligned abs.pos. with removed start/middle tracks</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1237805">
|
||||
<style type="text/css">
|
||||
html,body {
|
||||
color:black; background-color:white; font-size:16px; padding:0; margin:0;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
position: relative;
|
||||
border: 1px solid;
|
||||
grid-auto-rows: 30px;
|
||||
grid-template-columns: [a] repeat(auto-fit, [b] 20px [c]) [d] 20px;
|
||||
grid-gap: 2px;
|
||||
width: 160px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.c1 { width: 160px; }
|
||||
.c2 { width: 150px; }
|
||||
.c3 { width: 140px; }
|
||||
.p1 { padding-left:5px; }
|
||||
|
||||
.t2 { grid-template-columns: [a] repeat(auto-fit, [b] 20px [c]) [d]; }
|
||||
|
||||
x {
|
||||
width: 18px;
|
||||
border:1px solid;
|
||||
background: grey;
|
||||
}
|
||||
a {
|
||||
position: absolute;
|
||||
left:0; top:0; height:3px; right:0;
|
||||
background: cyan;
|
||||
grid-column: -1 / auto;
|
||||
}
|
||||
b {
|
||||
position: absolute;
|
||||
left:0; bottom:0; height:3px; right:0;
|
||||
background: brown;
|
||||
grid-column: auto / -1;
|
||||
}
|
||||
c {
|
||||
position: absolute;
|
||||
left:0; bottom:5px; height:3px; right:0;
|
||||
background: pink;
|
||||
grid-column: -2 / auto;
|
||||
}
|
||||
d {
|
||||
position: absolute;
|
||||
left:0; bottom:10px; height:3px; right:0;
|
||||
background: silver;
|
||||
grid-column: 2 / -3;
|
||||
}
|
||||
e {
|
||||
position: absolute;
|
||||
left:0; bottom:15px; height:3px; right:0;
|
||||
background: magenta;
|
||||
grid-column: 3 / -1;
|
||||
}
|
||||
f {
|
||||
position: absolute;
|
||||
left:0; bottom:20px; height:3px; right:0;
|
||||
background: orange;
|
||||
grid-column: auto / -2;
|
||||
}
|
||||
|
||||
x:first-child {
|
||||
background: lime;
|
||||
}
|
||||
x:last-child {
|
||||
background: blue;
|
||||
}
|
||||
|
||||
.t1 x:last-child {
|
||||
grid-column-end:-1;
|
||||
}
|
||||
|
||||
.x5 x:first-child , .x3 x:first-child , .x2 x:first-child {
|
||||
background: cyan;
|
||||
}
|
||||
|
||||
.x5.t1 x:nth-child(2) , .x4 x:nth-child(2) , .x3 x:nth-child(2) {
|
||||
background: purple;
|
||||
}
|
||||
|
||||
|
||||
float { float:left; margin-right:20px; }
|
||||
|
||||
.x5 { grid-template-columns: repeat(5,20px); }
|
||||
.x4 { grid-template-columns: repeat(4,20px); }
|
||||
.x3 { grid-template-columns: repeat(3,20px); }
|
||||
.x2 { grid-template-columns: repeat(2,20px); }
|
||||
|
||||
.t1.x5 a { grid-column:5/auto; }
|
||||
.c2.t1.x5 a , .c3.t1.x5 a { display:none; }
|
||||
.c1.t1.x4 a { grid-column:4/auto; }
|
||||
.c1.t1.x3 a { grid-column:3/auto; }
|
||||
.c1.t1.x2 a { grid-column:2/auto; }
|
||||
|
||||
.t1.x5 c { grid-column:-3/-2; }
|
||||
.t2.x5 c { grid-column:-2/-1; }
|
||||
|
||||
.c1.t1.x4 c { grid-column:-2/auto; }
|
||||
.x4 c { grid-column:-2/-1; }
|
||||
|
||||
.c1.t1.x3 c, .c1.t1.x2 c { grid-column:-2/auto; }
|
||||
.c2.t1.x3 c, .c3.t1.x3 c, .c2.t1.x2 c, .c3.t1.x2 c { grid-column:-2/-1; }
|
||||
.t2.x3 c, .t2.x2 c { grid-column:-1/auto; }
|
||||
|
||||
.t1.x5 f , .t2.x4 f { grid-column:auto/4; }
|
||||
.t2.x5 f { grid-column:auto/5; }
|
||||
.t2 f { grid-column:auto/-1; }
|
||||
|
||||
.t2.x5 e , .t2.x4 e , .x3 e { grid-column:2/-1; }
|
||||
.t1.x5 e , .c1.t1.x4 e, .c3.t1.x2 e { grid-column:2/-2; }
|
||||
.c2.t1.x4 e, .c3.t1.x4 e { grid-column:2/-1; }
|
||||
.c1.t1.x2 e { grid-column:2/auto; }
|
||||
.c1.t1.x3 e , .x2 e { grid-column:2/3; }
|
||||
|
||||
.t2.x5 d, .t2.x4 d , .t1.x4 d { grid-column:2/-2; }
|
||||
.t1.x3 d, .t1.x2 d { grid-column:2/3; }
|
||||
.t2.x3 d { grid-column:2/-1; }
|
||||
.t1.x2 d { grid-column:2/auto; }
|
||||
.t2.x2 d { grid-column:2/3; }
|
||||
|
||||
.c1.t1 b , .c2.t1.x5 b , .c3.t1.x5 b { grid-column:auto/-2; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<float>
|
||||
<div class="grid c1 t1 x5"><x></x><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t1 x5"><x></x><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f></div>
|
||||
<div class="grid c3 t1 x5"><x></x><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f></div>
|
||||
|
||||
<div class="grid c1 t2 x5"><x></x><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t2 x5"><x></x><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t2 x5"><x></x><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t1 x4"><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t1 x4"><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t1 x4"><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t2 x4"><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t2 x4"><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t2 x4"><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t1 x3"><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t1 x3"><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t1 x3"><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t2 x3"><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t2 x3"><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t2 x3"><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
</float>
|
||||
|
||||
<float>
|
||||
<div class="grid c1 t1 x2"><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t1 x2"><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t1 x2"><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t2 x2"><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t2 x2"><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t2 x2"><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
</float>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,195 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html class="reftest-wait"><head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Grid Test: repeat(auto-fit) with grid-aligned abs.pos. with removed start/middle tracks</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1237805">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-grid/#valdef-repeat-auto-fill">
|
||||
<link rel="match" href="grid-repeat-auto-fill-fit-007-ref.html">
|
||||
<style type="text/css">
|
||||
html,body {
|
||||
color:black; background-color:white; font-size:16px; padding:0; margin:0;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
position: relative;
|
||||
border: 1px solid;
|
||||
grid-auto-rows: 30px;
|
||||
grid-template-columns: [a] repeat(auto-fit, [b] 20px [c]) [d] 20px;
|
||||
grid-gap: 2px;
|
||||
width: 160px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.c1 { width: 160px; }
|
||||
.c2 { width: 150px; }
|
||||
.c3 { width: 140px; }
|
||||
.p1 { padding-left:5px; }
|
||||
|
||||
.t2 { grid-template-columns: [a] repeat(auto-fit, [b] 20px [c]) [d]; }
|
||||
|
||||
x {
|
||||
width: 18px;
|
||||
border:1px solid;
|
||||
background: grey;
|
||||
}
|
||||
a {
|
||||
position: absolute;
|
||||
left:0; top:0; height:3px; right:0;
|
||||
background: cyan;
|
||||
grid-column: 7 / auto;
|
||||
}
|
||||
b {
|
||||
position: absolute;
|
||||
left:0; bottom:0; height:3px; right:0;
|
||||
background: brown;
|
||||
grid-column: auto / 7;
|
||||
}
|
||||
c {
|
||||
position: absolute;
|
||||
left:0; bottom:5px; height:3px; right:0;
|
||||
background: pink;
|
||||
grid-column: 6 / 7;
|
||||
}
|
||||
d {
|
||||
position: absolute;
|
||||
left:0; bottom:10px; height:3px; right:0;
|
||||
background: silver;
|
||||
grid-column: 3 / 6;
|
||||
}
|
||||
e {
|
||||
position: absolute;
|
||||
left:0; bottom:15px; height:3px; right:0;
|
||||
background: magenta;
|
||||
grid-column: 3 / 7;
|
||||
}
|
||||
f {
|
||||
position: absolute;
|
||||
left:0; bottom:20px; height:3px; right:0;
|
||||
background: orange;
|
||||
grid-column: auto / 6;
|
||||
}
|
||||
|
||||
x:first-child {
|
||||
background: lime;
|
||||
}
|
||||
x:last-child {
|
||||
background: blue;
|
||||
}
|
||||
|
||||
.t1 x:last-child {
|
||||
grid-column-end:-1;
|
||||
}
|
||||
|
||||
float { float:left; margin-right:20px; }
|
||||
|
||||
.m x:first-child , .n x:first-child {
|
||||
background: cyan;
|
||||
grid-column:2;
|
||||
}
|
||||
|
||||
.n x:nth-child(2) , .o x:nth-child(2) {
|
||||
background: purple;
|
||||
grid-column:4;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<float>
|
||||
<div class="grid c1 t1 n"><x></x><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t1 n"><x></x><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t1 n"><x></x><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t2 m"><x></x><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t2 m"><x></x><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t2 m"><x></x><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t1 o"><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t1 o"><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t1 o"><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t2 o"><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t2 o"><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t2 o"><x></x><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t1 n"><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t1 n"><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t1 n"><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t2 n"><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t2 n"><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t2 n"><x></x><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
</float>
|
||||
|
||||
<float>
|
||||
<div class="grid c1 t1 n"><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t1 n"><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t1 n"><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t2 n"><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t2 n"><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t2 n"><x></x><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
</float>
|
||||
|
||||
<script>
|
||||
function testGridTemplateColumns(elem, expected) {
|
||||
var actual = window.getComputedStyle(elem).gridTemplateColumns;
|
||||
if (actual != expected) {
|
||||
var err = "FAIL: gridTemplateColumns " + elem.className +
|
||||
", GOT=" + actual +
|
||||
", EXPECTED=" + expected;
|
||||
document.body.appendChild(document.createTextNode(err));
|
||||
}
|
||||
}
|
||||
var a1 = [
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px",
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c d] 20px",
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c d] 20px",
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c d] 20px",
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c d] 20px",
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c d] 20px",
|
||||
"[a b] 20px [c b] 20px [c d] 20px",
|
||||
"[a b] 20px [c b] 20px [c d] 20px",
|
||||
"[a b] 20px [c b] 20px [c d] 20px",
|
||||
"[a b] 20px [c d] 20px",
|
||||
"[a b] 20px [c d] 20px",
|
||||
"[a b] 20px [c d] 20px"
|
||||
];
|
||||
var a2 = [
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c d]",
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c d]",
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c d]",
|
||||
"[a b] 20px [c b] 20px [c d]",
|
||||
"[a b] 20px [c b] 20px [c d]",
|
||||
"[a b] 20px [c b] 20px [c d]"
|
||||
];
|
||||
function runTest() {
|
||||
var t1 = document.querySelectorAll('.t1');
|
||||
for (var i = 0; i < t1.length; ++i) {
|
||||
testGridTemplateColumns(t1[i], a1[i]);
|
||||
}
|
||||
var t2 = document.querySelectorAll('.t2');
|
||||
for (var i = 0; i < t2.length; ++i) {
|
||||
testGridTemplateColumns(t2[i], a2[i]);
|
||||
}
|
||||
|
||||
document.documentElement.className='';
|
||||
}
|
||||
document.addEventListener('MozReftestInvalidate', runTest, false);
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,194 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html><head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Grid Test: repeat(auto-fit) with grid-aligned abs.pos. with removed start/middle tracks and implicit tracks on either/both sides</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1239036">
|
||||
<style type="text/css">
|
||||
html,body {
|
||||
color:black; background-color:white; font-size:16px; padding:0; margin:0;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
position: relative;
|
||||
border: 1px solid;
|
||||
grid-auto-rows: 30px;
|
||||
grid-auto-columns: 3px;
|
||||
grid-template-columns: [a] repeat(auto-fit, [b] 20px [c]) [d] 20px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.c1 { width: 165px; }
|
||||
.c2 { width: 155px; }
|
||||
.c3 { width: 150px; }
|
||||
.p1 { padding-left:5px; }
|
||||
|
||||
.t2 { grid-template-columns: [a] repeat(auto-fit, [b] 20px [c]) [d]; }
|
||||
|
||||
x {
|
||||
width: 18px;
|
||||
border:1px solid;
|
||||
background: grey;
|
||||
}
|
||||
a {
|
||||
position: absolute;
|
||||
top:0; height:3px; right:0;
|
||||
background: cyan;
|
||||
grid-column: auto / auto;
|
||||
}
|
||||
b {
|
||||
position: absolute;
|
||||
left:0; bottom:0; height:3px; width:103px;
|
||||
background: brown;
|
||||
grid-column: auto / auto;
|
||||
}
|
||||
.c2 b {width:100px;}
|
||||
c {
|
||||
position: absolute;
|
||||
left:0; bottom:5px; height:3px; right:0;
|
||||
background: pink;
|
||||
grid-column: auto / auto;
|
||||
}
|
||||
d {
|
||||
position: absolute;
|
||||
left:23px; bottom:10px; height:3px; width:60px;
|
||||
background: silver;
|
||||
grid-column: auto / auto;
|
||||
}
|
||||
e {
|
||||
position: absolute;
|
||||
left:0; bottom:15px; height:3px; right:0;
|
||||
background: magenta;
|
||||
grid-column: auto / auto;
|
||||
}
|
||||
f {
|
||||
position: absolute;
|
||||
left:0; bottom:20px; height:3px; width:83px;
|
||||
background: orange;
|
||||
grid-column: auto / auto;
|
||||
}
|
||||
.c2 f {width:80px;}
|
||||
|
||||
x:first-of-type {
|
||||
background: lime;
|
||||
}
|
||||
x:nth-of-type(1) { grid-area:1/1; }
|
||||
x:nth-of-type(2) { grid-area:1/2; }
|
||||
x:nth-of-type(3) { grid-area:1/3; }
|
||||
x:nth-of-type(4) { grid-area:1/4; }
|
||||
x:nth-of-type(5) { grid-area:1/5; }
|
||||
|
||||
x:last-of-type {
|
||||
background: blue;
|
||||
}
|
||||
|
||||
.t1 x:last-of-type {
|
||||
grid-column-end:-1;
|
||||
}
|
||||
|
||||
float { float:left; margin-right:20px; }
|
||||
|
||||
.m x:first-of-type , .n x:first-of-type {
|
||||
background: cyan;
|
||||
grid-area:1/2;
|
||||
}
|
||||
|
||||
.n x:nth-of-type(2) , .o x:nth-of-type(2) {
|
||||
background: purple;
|
||||
grid-area:1/4;
|
||||
}
|
||||
|
||||
.c1 y, .c3 y:first-of-type { grid-column: span X / 1; background:black; }
|
||||
.c2 y, .c3 y:last-of-type { grid-column: -1 / span X; background:black; }
|
||||
|
||||
.s2 { left: 23px; }
|
||||
.s2a { left: 20px; }
|
||||
.e5 { right: 82px; }
|
||||
.e5a { right: 75px; }
|
||||
.e5b { right: 67px; }
|
||||
.e6 { right: 62px; }
|
||||
.e6a { right: 55px; }
|
||||
.e6b { right: 47px; }
|
||||
.c2 d { left:20px; }
|
||||
.t2.x4 f, .t2.x3 f { width:63px; }
|
||||
.c2.t2.x4 f, .c2.t2.x3 f { width:60px; }
|
||||
.t2.x4 d, .t2.x3 d { width:40px; }
|
||||
.x2 d { width:20px; }
|
||||
.x2 f { width:43px; }
|
||||
.c2.x2 f { width:40px; }
|
||||
|
||||
.t2.x5 b { width:83px; }
|
||||
.c2.t2.x5 b { width:80px; }
|
||||
.t2.x4 b, .t2.x3 b { width:63px; }
|
||||
.c2.t2.x4 b, .c2.t2.x3 b { width:60px; }
|
||||
.x2 b { width:43px; }
|
||||
.c2.x2 b { width:40px; }
|
||||
|
||||
.t1.x5 c, .t1.x4 c, .t1.x3 c { left:83px; width:20px; right:auto; }
|
||||
.c2.x5 c , .c2.t1.x4 c , .c2.t1.x3 c { left:80px; }
|
||||
.t2.x5 c { left:83px; }
|
||||
.c2.t2.x5 c { left:80px; }
|
||||
.t2.x4 c , .t2.x3 c { left:63px; }
|
||||
.c2.t2.x4 c , .c2.t2.x3 c { left:60px; }
|
||||
.t1.x2 c , .t2.x2 c { left:43px; }
|
||||
.c2.t2.x2 c , .c2.t1.x2 c { left:40px;}
|
||||
|
||||
.x2 e { left:23px; width:20px; right:auto; }
|
||||
.c2.x2 e { left:20px; }
|
||||
.t1.c3.x2 e { width:40px; }
|
||||
.t1.c3.x2 b { width:63px; }
|
||||
.t1.c3.x2 c { width:20px; right:auto;}
|
||||
|
||||
.t2.x5 e { left:23px; width:60px; }
|
||||
.x4 e , .x3 e , .x2 e { left:23px; }
|
||||
.c2.x4 e , .c2.x3 e , .c2.x2 e { left:20px; }
|
||||
.c2.t2.x5 e { left:20px; }
|
||||
.t1.x4 e , .t1.x3 e { width:80px; }
|
||||
.t2.x4 e , .t2.x3 e { width:40px; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<float>
|
||||
<div class="grid c1 t1 n x5"><x></x><x></x><x></x><x></x><y></y><a style="width:62px"></a><b></b><c></c><d></d><e class="s2 e6"></e><f class="e5"></f><x></x></div>
|
||||
<div class="grid c2 t1 n x5"><x></x><x></x><x></x><x></x><y></y><a style="width:55px"></a><b></b><c></c><d></d><e class="s2a e6a"></e><f class="e5a"></f><x></x></div>
|
||||
<div class="grid c3 t1 n x5"><x></x><x></x><x></x><x></x><y></y><y></y><a style="width:47px"></a><b></b><c></c><d></d><e class="s2 e6b"></e><f class="e5b"></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t2 m x5"><x></x><x></x><x></x><x></x><y></y><a style="width:82px"></a><b></b><c></c><d></d><e class="s2"></e><f class="e5"></f><x></x></div>
|
||||
<div class="grid c2 t2 m x5"><x></x><x></x><x></x><x></x><y></y><a style="width:75px"></a><b></b><c></c><d></d><e class="s2e"></e><f class="e5"></f><x></x></div>
|
||||
<div class="grid c3 t2 m x5"><x></x><x></x><x></x><x></x><y></y><y></y><a style="width:67px"></a><b></b><c></c><d></d><e></e><f class="e5"></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t1 o x4"><x></x><x></x><x></x><y></y><a style="width:62px"></a><b></b><c></c><d></d><e></e><f class="e5"></f><x></x></div>
|
||||
<div class="grid c2 t1 o x4"><x></x><x></x><x></x><y></y><a style="width:55px"></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t1 o x4"><x></x><x></x><x></x><y></y><y></y><a style="width:47px"></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t2 o x4"><x></x><x></x><x></x><y></y><a style="width:102px"></a><b></b><c></c><d></d><e></e><f class="e5"></f><x></x></div>
|
||||
<div class="grid c2 t2 o x4"><x></x><x></x><x></x><y></y><a style="width:95px"></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t2 o x4"><x></x><x></x><x></x><y></y><y></y><a style="width:87px"></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t1 n x3"><x></x><x></x><y></y><a style="width:62px"></a><b></b><c></c><d></d><e></e><f class="e5"></f><x></x></div>
|
||||
<div class="grid c2 t1 n x3"><x></x><x></x><y></y><a style="width:55px"></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t1 n x3"><x></x><x></x><y></y><y></y><a style="width:47px"></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t2 n x3"><x></x><x></x><y></y><a style="width:102px"></a><b></b><c></c><d></d><e></e><f class="e5"></f><x></x></div>
|
||||
<div class="grid c2 t2 n x3"><x></x><x></x><y></y><a style="width:95px"></a><b></b><c></c><d></d><e></e><f class="e5"></f><x></x></div>
|
||||
<div class="grid c3 t2 n x3"><x></x><x></x><y></y><y></y><a style="width:87px"></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
</float>
|
||||
|
||||
<float>
|
||||
<div class="grid c1 t1 n x2"><x></x><y></y><a style="width:122px"></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t1 n x2"><x></x><y></y><a style="width:115px"></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t1 n x2"><x></x><y></y><y></y><a style="width:87px"></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t2 n x2"><x></x><y></y><a style="width:122px"></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t2 n x2"><x></x><y></y><a style="width:115px"></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t2 n x2"><x></x><y></y><y></y><a style="width:107px"></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
</float>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,204 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html class="reftest-wait"><head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Grid Test: repeat(auto-fit) with grid-aligned abs.pos. with removed start/middle tracks and implicit tracks on either/both sides</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1239036">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-grid/#valdef-repeat-auto-fill">
|
||||
<link rel="match" href="grid-repeat-auto-fill-fit-008-ref.html">
|
||||
<style type="text/css">
|
||||
html,body {
|
||||
color:black; background-color:white; font-size:16px; padding:0; margin:0;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
position: relative;
|
||||
border: 1px solid;
|
||||
grid-auto-rows: 30px;
|
||||
grid-auto-columns: 3px;
|
||||
grid-template-columns: [a] repeat(auto-fit, [b] 20px [c]) [d] 20px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.c1 { width: 165px; }
|
||||
.c2 { width: 155px; }
|
||||
.c3 { width: 150px; }
|
||||
.p1 { padding-left:5px; }
|
||||
|
||||
.t2 { grid-template-columns: [a] repeat(auto-fit, [b] 20px [c]) [d]; }
|
||||
|
||||
x {
|
||||
width: 18px;
|
||||
border:1px solid;
|
||||
background: grey;
|
||||
}
|
||||
a {
|
||||
position: absolute;
|
||||
left:0; top:0; height:3px; right:0;
|
||||
background: cyan;
|
||||
grid-column: 7 / auto;
|
||||
}
|
||||
b {
|
||||
position: absolute;
|
||||
left:0; bottom:0; height:3px; right:0;
|
||||
background: brown;
|
||||
grid-column: auto / 7;
|
||||
}
|
||||
c {
|
||||
position: absolute;
|
||||
left:0; bottom:5px; height:3px; right:0;
|
||||
background: pink;
|
||||
grid-column: 6 / 7;
|
||||
}
|
||||
d {
|
||||
position: absolute;
|
||||
left:0; bottom:10px; height:3px; right:0;
|
||||
background: silver;
|
||||
grid-column: 3 / 6;
|
||||
}
|
||||
e {
|
||||
position: absolute;
|
||||
left:0; bottom:15px; height:3px; right:0;
|
||||
background: magenta;
|
||||
grid-column: 3 / 7;
|
||||
}
|
||||
f {
|
||||
position: absolute;
|
||||
left:0; bottom:20px; height:3px; right:0;
|
||||
background: orange;
|
||||
grid-column: auto / 6;
|
||||
}
|
||||
|
||||
x:first-of-type {
|
||||
background: lime;
|
||||
}
|
||||
x:nth-of-type(1) { grid-area:1/1; }
|
||||
x:nth-of-type(2) { grid-area:1/2; }
|
||||
x:nth-of-type(3) { grid-area:1/3; }
|
||||
x:nth-of-type(4) { grid-area:1/4; }
|
||||
x:nth-of-type(5) { grid-area:1/5; }
|
||||
|
||||
x:last-of-type {
|
||||
background: blue;
|
||||
}
|
||||
|
||||
.t1 x:last-of-type {
|
||||
grid-column-end:-1;
|
||||
}
|
||||
|
||||
float { float:left; margin-right:20px; }
|
||||
|
||||
.m x:first-of-type , .n x:first-of-type {
|
||||
background: cyan;
|
||||
grid-area:1/2;
|
||||
}
|
||||
|
||||
.n x:nth-of-type(2) , .o x:nth-of-type(2) {
|
||||
background: purple;
|
||||
grid-area:1/4;
|
||||
}
|
||||
|
||||
.c1 y, .c3 y:first-of-type { grid-column: span X / 1; background:black; }
|
||||
.c2 y, .c3 y:last-of-type { grid-column: -1 / span X; background:black; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<float>
|
||||
<div class="grid c1 t1 n"><x></x><x></x><x></x><x></x><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t1 n"><x></x><x></x><x></x><x></x><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t1 n"><x></x><x></x><x></x><x></x><y></y><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t2 m"><x></x><x></x><x></x><x></x><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t2 m"><x></x><x></x><x></x><x></x><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t2 m"><x></x><x></x><x></x><x></x><y></y><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t1 o"><x></x><x></x><x></x><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t1 o"><x></x><x></x><x></x><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t1 o"><x></x><x></x><x></x><y></y><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t2 o"><x></x><x></x><x></x><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t2 o"><x></x><x></x><x></x><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t2 o"><x></x><x></x><x></x><y></y><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t1 n"><x></x><x></x><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t1 n"><x></x><x></x><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t1 n"><x></x><x></x><y></y><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t2 n"><x></x><x></x><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t2 n"><x></x><x></x><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t2 n"><x></x><x></x><y></y><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
</float>
|
||||
|
||||
<float>
|
||||
<div class="grid c1 t1 n"><x></x><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t1 n"><x></x><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t1 n"><x></x><y></y><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
|
||||
<div class="grid c1 t2 n"><x></x><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c2 t2 n"><x></x><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
<div class="grid c3 t2 n"><x></x><y></y><y></y><a></a><b></b><c></c><d></d><e></e><f></f><x></x></div>
|
||||
</float>
|
||||
|
||||
<script>
|
||||
function testGridTemplateColumns(elem, expected) {
|
||||
var actual = window.getComputedStyle(elem).gridTemplateColumns;
|
||||
if (actual != expected) {
|
||||
var err = "FAIL: gridTemplateColumns " + elem.className +
|
||||
", GOT=" + actual +
|
||||
", EXPECTED=" + expected;
|
||||
document.body.appendChild(document.createTextNode(err));
|
||||
}
|
||||
}
|
||||
var a1 = [
|
||||
"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px",
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px 3px",
|
||||
"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px 3px",
|
||||
"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px",
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px 3px",
|
||||
"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px 3px",
|
||||
"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px",
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px 3px",
|
||||
"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 20px 3px",
|
||||
"3px [a b] 20px [c b] 20px [c b] 20px [c d] 20px",
|
||||
"[a b] 20px [c b] 20px [c d] 20px 3px",
|
||||
"3px [a b] 20px [c b] 20px [c b] 20px [c d] 20px 3px"
|
||||
];
|
||||
var a2 = [
|
||||
"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 3px",
|
||||
"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 3px",
|
||||
"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c d] 3px",
|
||||
"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 3px",
|
||||
"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d]",
|
||||
"[a b] 20px [c b] 20px [c b] 20px [c d] 3px",
|
||||
"3px [a b] 20px [c b] 20px [c b] 20px [c b] 20px [c d] 3px",
|
||||
"3px [a b] 20px [c b] 20px [c b] 20px [c d]",
|
||||
"[a b] 20px [c b] 20px [c d] 3px",
|
||||
"3px [a b] 20px [c b] 20px [c b] 20px [c d] 3px"
|
||||
];
|
||||
function runTest() {
|
||||
var t1 = document.querySelectorAll('.t1');
|
||||
for (var i = 0; i < t1.length; ++i) {
|
||||
testGridTemplateColumns(t1[i], a1[i]);
|
||||
}
|
||||
var t2 = document.querySelectorAll('.t2');
|
||||
for (var i = 0; i < t2.length; ++i) {
|
||||
testGridTemplateColumns(t2[i], a2[i]);
|
||||
}
|
||||
|
||||
document.documentElement.className='';
|
||||
}
|
||||
document.addEventListener('MozReftestInvalidate', runTest, false);
|
||||
runTest()
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -24,6 +24,7 @@ fails == grid-whitespace-handling-1b.xhtml grid-whitespace-handling-1-ref.xhtml
|
||||
== grid-abspos-items-010.html grid-abspos-items-010-ref.html
|
||||
== grid-abspos-items-011.html grid-abspos-items-011-ref.html
|
||||
== grid-abspos-items-012.html grid-abspos-items-012-ref.html
|
||||
== grid-abspos-items-013.html grid-abspos-items-013-ref.html
|
||||
== grid-order-abspos-items-001.html grid-order-abspos-items-001-ref.html
|
||||
== grid-order-placement-auto-001.html grid-order-placement-auto-001-ref.html
|
||||
== grid-order-placement-definite-001.html grid-order-placement-definite-001-ref.html
|
||||
@@ -96,3 +97,5 @@ fuzzy-if(winWidget,1,36) == grid-auto-min-sizing-definite-001.html grid-auto-min
|
||||
== grid-repeat-auto-fill-fit-004.html grid-repeat-auto-fill-fit-004-ref.html
|
||||
== grid-repeat-auto-fill-fit-005.html grid-repeat-auto-fill-fit-005-ref.html
|
||||
== grid-repeat-auto-fill-fit-006.html grid-repeat-auto-fill-fit-006-ref.html
|
||||
== grid-repeat-auto-fill-fit-007.html grid-repeat-auto-fill-fit-007-ref.html
|
||||
== grid-repeat-auto-fill-fit-008.html grid-repeat-auto-fill-fit-008-ref.html
|
||||
|
||||
@@ -262,10 +262,9 @@ CSSAnimation::QueueEvents()
|
||||
StickyTimeDuration elapsedTime;
|
||||
|
||||
if (message == eAnimationStart || message == eAnimationIteration) {
|
||||
TimeDuration iterationStart = mEffect->Timing().mIterationDuration *
|
||||
computedTiming.mCurrentIteration;
|
||||
elapsedTime = StickyTimeDuration(std::max(iterationStart,
|
||||
InitialAdvance()));
|
||||
StickyTimeDuration iterationStart = computedTiming.mDuration *
|
||||
computedTiming.mCurrentIteration;
|
||||
elapsedTime = std::max(iterationStart, StickyTimeDuration(InitialAdvance()));
|
||||
} else {
|
||||
MOZ_ASSERT(message == eAnimationEnd);
|
||||
elapsedTime = computedTiming.mActiveDuration;
|
||||
@@ -309,7 +308,8 @@ CSSAnimation::ElapsedTimeToTimeStamp(const StickyTimeDuration&
|
||||
return result;
|
||||
}
|
||||
|
||||
result = AnimationTimeToTimeStamp(aElapsedTime + mEffect->Timing().mDelay);
|
||||
result = AnimationTimeToTimeStamp(aElapsedTime +
|
||||
mEffect->SpecifiedTiming().mDelay);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -442,9 +442,9 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext,
|
||||
KeyframeEffectReadOnly* oldEffect = oldAnim->GetEffect();
|
||||
KeyframeEffectReadOnly* newEffect = newAnim->GetEffect();
|
||||
animationChanged =
|
||||
oldEffect->Timing() != newEffect->Timing() ||
|
||||
oldEffect->SpecifiedTiming() != newEffect->SpecifiedTiming() ||
|
||||
oldEffect->Properties() != newEffect->Properties();
|
||||
oldEffect->SetTiming(newEffect->Timing());
|
||||
oldEffect->SetSpecifiedTiming(newEffect->SpecifiedTiming());
|
||||
oldEffect->CopyPropertiesFrom(*newEffect);
|
||||
}
|
||||
|
||||
@@ -644,13 +644,12 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext,
|
||||
dest->SetAnimationIndex(static_cast<uint64_t>(animIdx));
|
||||
aAnimations.AppendElement(dest);
|
||||
|
||||
AnimationTiming timing;
|
||||
timing.mIterationDuration =
|
||||
TimeDuration::FromMilliseconds(src.GetDuration());
|
||||
TimingParams timing;
|
||||
timing.mDuration.SetAsUnrestrictedDouble() = src.GetDuration();
|
||||
timing.mDelay = TimeDuration::FromMilliseconds(src.GetDelay());
|
||||
timing.mIterationCount = src.GetIterationCount();
|
||||
timing.mIterations = src.GetIterationCount();
|
||||
timing.mDirection = src.GetDirection();
|
||||
timing.mFillMode = src.GetFillMode();
|
||||
timing.mFill = src.GetFillMode();
|
||||
|
||||
RefPtr<KeyframeEffectReadOnly> destEffect =
|
||||
new KeyframeEffectReadOnly(mPresContext->Document(), aTarget,
|
||||
|
||||
@@ -169,11 +169,11 @@ protected:
|
||||
// Returns the duration from the start of the animation's source effect's
|
||||
// active interval to the point where the animation actually begins playback.
|
||||
// This is zero unless the animation's source effect has a negative delay in
|
||||
// which // case it is the absolute value of that delay.
|
||||
// which case it is the absolute value of that delay.
|
||||
// This is used for setting the elapsedTime member of CSS AnimationEvents.
|
||||
TimeDuration InitialAdvance() const {
|
||||
return mEffect ?
|
||||
std::max(TimeDuration(), mEffect->Timing().mDelay * -1) :
|
||||
std::max(TimeDuration(), mEffect->SpecifiedTiming().mDelay * -1) :
|
||||
TimeDuration();
|
||||
}
|
||||
// Converts an AnimationEvent's elapsedTime value to an equivalent TimeStamp
|
||||
|
||||
@@ -2454,8 +2454,9 @@ nsComputedDOMStyle::GetGridTrackSize(const nsStyleCoord& aMinValue,
|
||||
}
|
||||
|
||||
already_AddRefed<CSSValue>
|
||||
nsComputedDOMStyle::GetGridTemplateColumnsRows(const nsStyleGridTemplate& aTrackList,
|
||||
const nsTArray<nscoord>* aTrackSizes)
|
||||
nsComputedDOMStyle::GetGridTemplateColumnsRows(
|
||||
const nsStyleGridTemplate& aTrackList,
|
||||
const ComputedGridTrackInfo* aTrackInfo)
|
||||
{
|
||||
if (aTrackList.mIsSubgrid) {
|
||||
// XXX TODO: add support for repeat(auto-fill) for 'subgrid' (bug 1234311)
|
||||
@@ -2491,76 +2492,102 @@ nsComputedDOMStyle::GetGridTemplateColumnsRows(const nsStyleGridTemplate& aTrack
|
||||
uint32_t numSizes = aTrackList.mMinTrackSizingFunctions.Length();
|
||||
MOZ_ASSERT(aTrackList.mMaxTrackSizingFunctions.Length() == numSizes,
|
||||
"Different number of min and max track sizing functions");
|
||||
if (aTrackSizes) {
|
||||
numSizes = aTrackSizes->Length();
|
||||
MOZ_ASSERT(numSizes > 0 ||
|
||||
(aTrackList.HasRepeatAuto() && !aTrackList.mIsAutoFill),
|
||||
"only 'auto-fit' can result in zero tracks");
|
||||
if (aTrackInfo) {
|
||||
DebugOnly<bool> isAutoFill =
|
||||
aTrackList.HasRepeatAuto() && aTrackList.mIsAutoFill;
|
||||
DebugOnly<bool> isAutoFit =
|
||||
aTrackList.HasRepeatAuto() && !aTrackList.mIsAutoFill;
|
||||
DebugOnly<uint32_t> numExplicitTracks = aTrackInfo->mNumExplicitTracks;
|
||||
MOZ_ASSERT(numExplicitTracks == numSizes ||
|
||||
(isAutoFill && numExplicitTracks >= numSizes) ||
|
||||
(isAutoFit && numExplicitTracks + 1 >= numSizes),
|
||||
"expected all explicit tracks (or possibly one less, if there's "
|
||||
"an 'auto-fit' track, since that can collapse away)");
|
||||
numSizes = aTrackInfo->mSizes.Length();
|
||||
}
|
||||
|
||||
// An empty <track-list> is represented as "none" in syntax.
|
||||
if (numSizes == 0) {
|
||||
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
|
||||
val->SetIdent(eCSSKeyword_none);
|
||||
return val.forget();
|
||||
}
|
||||
// Delimiting N (specified) tracks requires N+1 lines:
|
||||
// one before each track, plus one at the very end.
|
||||
MOZ_ASSERT(aTrackList.mLineNameLists.Length() ==
|
||||
aTrackList.mMinTrackSizingFunctions.Length() + 1,
|
||||
"Unexpected number of line name lists");
|
||||
|
||||
RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
|
||||
if (aTrackSizes) {
|
||||
if (aTrackInfo) {
|
||||
// We've done layout on the grid and have resolved the sizes of its tracks,
|
||||
// so we'll return those sizes here. The grid spec says we MAY use
|
||||
// repeat(<positive-integer>, Npx) here for consecutive tracks with the same
|
||||
// size, but that doesn't seem worth doing since even for repeat(auto-*)
|
||||
// the resolved size might differ for the repeated tracks.
|
||||
int32_t endOfRepeat = 0; // first index after any repeat() tracks
|
||||
int32_t offsetToLastRepeat = 0;
|
||||
if (aTrackList.HasRepeatAuto()) {
|
||||
// offsetToLastRepeat is -1 if all repeat(auto-fit) tracks are empty
|
||||
offsetToLastRepeat = numSizes + 1 - aTrackList.mLineNameLists.Length();
|
||||
endOfRepeat = aTrackList.mRepeatAutoIndex + offsetToLastRepeat + 1;
|
||||
const nsTArray<nscoord>& trackSizes = aTrackInfo->mSizes;
|
||||
const uint32_t numExplicitTracks = aTrackInfo->mNumExplicitTracks;
|
||||
const uint32_t numLeadingImplicitTracks = aTrackInfo->mNumLeadingImplicitTracks;
|
||||
MOZ_ASSERT(numSizes > 0 &&
|
||||
numSizes >= numLeadingImplicitTracks + numExplicitTracks);
|
||||
|
||||
// Add any leading implicit tracks.
|
||||
for (uint32_t i = 0; i < numLeadingImplicitTracks; ++i) {
|
||||
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
|
||||
val->SetAppUnits(trackSizes[i]);
|
||||
valueList->AppendCSSValue(val.forget());
|
||||
}
|
||||
MOZ_ASSERT(numSizes > 0);
|
||||
for (int32_t i = 0;; i++) {
|
||||
|
||||
// Then add any explicit tracks.
|
||||
if (numExplicitTracks) {
|
||||
int32_t endOfRepeat = 0; // first index after any repeat() tracks
|
||||
int32_t offsetToLastRepeat = 0;
|
||||
if (aTrackList.HasRepeatAuto()) {
|
||||
if (i == aTrackList.mRepeatAutoIndex) {
|
||||
const nsTArray<nsString>& lineNames = aTrackList.mLineNameLists[i];
|
||||
if (i == endOfRepeat) {
|
||||
// all auto-fit tracks are empty, so "[a] repeat(...) [b]"
|
||||
// becomes "[a b]"
|
||||
AppendGridLineNames(valueList, lineNames,
|
||||
aTrackList.mLineNameLists[i + 1]);
|
||||
} else {
|
||||
AppendGridLineNames(valueList, lineNames,
|
||||
// offsetToLastRepeat is -1 if all repeat(auto-fit) tracks are empty
|
||||
offsetToLastRepeat = numExplicitTracks + 1 - aTrackList.mLineNameLists.Length();
|
||||
endOfRepeat = aTrackList.mRepeatAutoIndex + offsetToLastRepeat + 1;
|
||||
}
|
||||
for (int32_t i = 0;; i++) {
|
||||
if (aTrackList.HasRepeatAuto()) {
|
||||
if (i == aTrackList.mRepeatAutoIndex) {
|
||||
const nsTArray<nsString>& lineNames = aTrackList.mLineNameLists[i];
|
||||
if (i == endOfRepeat) {
|
||||
// all auto-fit tracks are empty, so "[a] repeat(...) [b]"
|
||||
// becomes "[a b]"
|
||||
AppendGridLineNames(valueList, lineNames,
|
||||
aTrackList.mLineNameLists[i + 1]);
|
||||
} else {
|
||||
AppendGridLineNames(valueList, lineNames,
|
||||
aTrackList.mRepeatAutoLineNameListBefore);
|
||||
}
|
||||
} else if (i == endOfRepeat) {
|
||||
const nsTArray<nsString>& lineNames =
|
||||
aTrackList.mLineNameLists[aTrackList.mRepeatAutoIndex + 1];
|
||||
AppendGridLineNames(valueList,
|
||||
aTrackList.mRepeatAutoLineNameListAfter,
|
||||
lineNames);
|
||||
} else if (i > aTrackList.mRepeatAutoIndex && i < endOfRepeat) {
|
||||
AppendGridLineNames(valueList,
|
||||
aTrackList.mRepeatAutoLineNameListAfter,
|
||||
aTrackList.mRepeatAutoLineNameListBefore);
|
||||
} else {
|
||||
uint32_t j = i > endOfRepeat ? i - offsetToLastRepeat : i;
|
||||
const nsTArray<nsString>& lineNames = aTrackList.mLineNameLists[j];
|
||||
AppendGridLineNames(valueList, lineNames);
|
||||
}
|
||||
} else if (i == endOfRepeat) {
|
||||
const nsTArray<nsString>& lineNames =
|
||||
aTrackList.mLineNameLists[aTrackList.mRepeatAutoIndex + 1];
|
||||
AppendGridLineNames(valueList,
|
||||
aTrackList.mRepeatAutoLineNameListAfter,
|
||||
lineNames);
|
||||
} else if (i > aTrackList.mRepeatAutoIndex && i < endOfRepeat) {
|
||||
AppendGridLineNames(valueList,
|
||||
aTrackList.mRepeatAutoLineNameListAfter,
|
||||
aTrackList.mRepeatAutoLineNameListBefore);
|
||||
} else {
|
||||
uint32_t j = i > endOfRepeat ? i - offsetToLastRepeat : i;
|
||||
const nsTArray<nsString>& lineNames = aTrackList.mLineNameLists[j];
|
||||
const nsTArray<nsString>& lineNames = aTrackList.mLineNameLists[i];
|
||||
AppendGridLineNames(valueList, lineNames);
|
||||
}
|
||||
} else {
|
||||
const nsTArray<nsString>& lineNames = aTrackList.mLineNameLists[i];
|
||||
AppendGridLineNames(valueList, lineNames);
|
||||
}
|
||||
if (uint32_t(i) == numSizes) {
|
||||
break;
|
||||
if (uint32_t(i) == numExplicitTracks) {
|
||||
break;
|
||||
}
|
||||
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
|
||||
val->SetAppUnits(trackSizes[i + numLeadingImplicitTracks]);
|
||||
valueList->AppendCSSValue(val.forget());
|
||||
}
|
||||
}
|
||||
|
||||
// Add any trailing implicit tracks.
|
||||
for (uint32_t i = numLeadingImplicitTracks + numExplicitTracks;
|
||||
i < numSizes; ++i) {
|
||||
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
|
||||
val->SetAppUnits((*aTrackSizes)[i]);
|
||||
val->SetAppUnits(trackSizes[i]);
|
||||
valueList->AppendCSSValue(val.forget());
|
||||
}
|
||||
} else {
|
||||
@@ -2634,31 +2661,31 @@ nsComputedDOMStyle::DoGetGridAutoRows()
|
||||
already_AddRefed<CSSValue>
|
||||
nsComputedDOMStyle::DoGetGridTemplateColumns()
|
||||
{
|
||||
const nsTArray<nscoord>* trackSizes = nullptr;
|
||||
const ComputedGridTrackInfo* info = nullptr;
|
||||
if (mInnerFrame) {
|
||||
nsIFrame* gridContainerCandidate = mInnerFrame->GetContentInsertionFrame();
|
||||
if (gridContainerCandidate &&
|
||||
gridContainerCandidate->GetType() == nsGkAtoms::gridContainerFrame) {
|
||||
auto gridContainer = static_cast<nsGridContainerFrame*>(gridContainerCandidate);
|
||||
trackSizes = gridContainer->GetComputedTemplateColumns();
|
||||
info = static_cast<nsGridContainerFrame*>(gridContainerCandidate)->
|
||||
GetComputedTemplateColumns();
|
||||
}
|
||||
}
|
||||
return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateColumns, trackSizes);
|
||||
return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateColumns, info);
|
||||
}
|
||||
|
||||
already_AddRefed<CSSValue>
|
||||
nsComputedDOMStyle::DoGetGridTemplateRows()
|
||||
{
|
||||
const nsTArray<nscoord>* trackSizes = nullptr;
|
||||
const ComputedGridTrackInfo* info = nullptr;
|
||||
if (mInnerFrame) {
|
||||
nsIFrame* gridContainerCandidate = mInnerFrame->GetContentInsertionFrame();
|
||||
if (gridContainerCandidate &&
|
||||
gridContainerCandidate->GetType() == nsGkAtoms::gridContainerFrame) {
|
||||
auto gridContainer = static_cast<nsGridContainerFrame*>(gridContainerCandidate);
|
||||
trackSizes = gridContainer->GetComputedTemplateRows();
|
||||
}
|
||||
info = static_cast<nsGridContainerFrame*>(gridContainerCandidate)->
|
||||
GetComputedTemplateRows();
|
||||
}
|
||||
}
|
||||
return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateRows, trackSizes);
|
||||
return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateRows, info);
|
||||
}
|
||||
|
||||
already_AddRefed<CSSValue>
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
class Element;
|
||||
} // namespace dom
|
||||
struct ComputedGridTrackInfo;
|
||||
} // namespace mozilla
|
||||
|
||||
struct nsComputedStyleMap;
|
||||
@@ -190,7 +191,7 @@ private:
|
||||
const nsStyleCoord& aMaxSize);
|
||||
already_AddRefed<CSSValue> GetGridTemplateColumnsRows(
|
||||
const nsStyleGridTemplate& aTrackList,
|
||||
const nsTArray<nscoord>* aTrackSizes);
|
||||
const mozilla::ComputedGridTrackInfo* aTrackInfo);
|
||||
already_AddRefed<CSSValue> GetGridLine(const nsStyleGridLine& aGridLine);
|
||||
|
||||
bool GetLineHeightCoord(nscoord& aCoord);
|
||||
|
||||
@@ -55,8 +55,8 @@ ElementPropertyTransition::CurrentValuePortion() const
|
||||
// causing us to get called *after* the animation interval. So, just in
|
||||
// case, we override the fill mode to 'both' to ensure the progress
|
||||
// is never null.
|
||||
AnimationTiming timingToUse = mTiming;
|
||||
timingToUse.mFillMode = dom::FillMode::Both;
|
||||
TimingParams timingToUse = SpecifiedTiming();
|
||||
timingToUse.mFill = dom::FillMode::Both;
|
||||
ComputedTiming computedTiming = GetComputedTiming(&timingToUse);
|
||||
|
||||
MOZ_ASSERT(!computedTiming.mProgress.IsNull(),
|
||||
@@ -150,7 +150,8 @@ CSSTransition::QueueEvents()
|
||||
nsTransitionManager* manager = presContext->TransitionManager();
|
||||
manager->QueueEvent(TransitionEventInfo(owningElement, owningPseudoType,
|
||||
property,
|
||||
mEffect->Timing().mIterationDuration,
|
||||
mEffect->GetComputedTiming()
|
||||
.mDuration,
|
||||
AnimationTimeToTimeStamp(EffectEnd()),
|
||||
this));
|
||||
}
|
||||
@@ -665,12 +666,12 @@ nsTransitionManager::ConsiderStartingTransition(
|
||||
reversePortion = valuePortion;
|
||||
}
|
||||
|
||||
AnimationTiming timing;
|
||||
timing.mIterationDuration = TimeDuration::FromMilliseconds(duration);
|
||||
TimingParams timing;
|
||||
timing.mDuration.SetAsUnrestrictedDouble() = duration;
|
||||
timing.mDelay = TimeDuration::FromMilliseconds(delay);
|
||||
timing.mIterationCount = 1;
|
||||
timing.mIterations = 1.0;
|
||||
timing.mDirection = dom::PlaybackDirection::Normal;
|
||||
timing.mFillMode = dom::FillMode::Backwards;
|
||||
timing.mFill = dom::FillMode::Backwards;
|
||||
|
||||
RefPtr<ElementPropertyTransition> pt =
|
||||
new ElementPropertyTransition(aElement->OwnerDoc(), aElement,
|
||||
|
||||
@@ -38,7 +38,7 @@ struct ElementPropertyTransition : public dom::KeyframeEffectReadOnly
|
||||
ElementPropertyTransition(nsIDocument* aDocument,
|
||||
dom::Element* aTarget,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
const AnimationTiming &aTiming)
|
||||
const TimingParams &aTiming)
|
||||
: dom::KeyframeEffectReadOnly(aDocument, aTarget, aPseudoType, aTiming)
|
||||
{ }
|
||||
|
||||
@@ -214,7 +214,7 @@ struct TransitionEventInfo {
|
||||
TransitionEventInfo(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
nsCSSProperty aProperty,
|
||||
TimeDuration aDuration,
|
||||
StickyTimeDuration aDuration,
|
||||
const TimeStamp& aTimeStamp,
|
||||
dom::Animation* aAnimation)
|
||||
: mElement(aElement)
|
||||
|
||||
@@ -26,6 +26,13 @@
|
||||
grid-auto-columns: 3fr;
|
||||
grid-auto-rows: 2fr;
|
||||
}
|
||||
#grid2 {
|
||||
display: grid;
|
||||
width: 500px;
|
||||
height: 400px;
|
||||
grid-auto-columns: 10px;
|
||||
grid-auto-rows: 2fr;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
@@ -36,6 +43,10 @@
|
||||
<div style="grid-column-start:1; width:50px"></div>
|
||||
<div style="grid-column-start:9; width:50px"></div>
|
||||
</div>
|
||||
<div id="grid2">
|
||||
<div style="grid-column: span X / 1"></div>
|
||||
<div style="grid-column: 1 / span X 2"></div>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<script>
|
||||
@@ -73,9 +84,21 @@
|
||||
test_grid_template(assert_not_equals, 420, 340,
|
||||
"test computed grid-template-{columns,rows} values, display: none on parent");
|
||||
|
||||
gridElement.parentNode.style.display = '';
|
||||
function test_grid2() {
|
||||
gridElement = document.getElementById("grid2");
|
||||
test(function() {
|
||||
assert_equals(getComputedStyle(gridElement).gridTemplateColumns,
|
||||
"10px 10px 10px");
|
||||
assert_equals(getComputedStyle(gridElement, "").gridTemplateRows,
|
||||
"400px");
|
||||
}, "test #grid2 computed grid-template-{columns,rows} values");
|
||||
}
|
||||
|
||||
test(function() {
|
||||
assert_equals(getComputedStyle(gridElement).gridAutoColumns, "3fr");
|
||||
assert_equals(getComputedStyle(gridElement).gridAutoRows, "2fr");
|
||||
test_grid2();
|
||||
}, "test computed grid-auto-{columns,rows} values");
|
||||
|
||||
</script>
|
||||
|
||||
@@ -2815,6 +2815,9 @@ pref("layout.float-fragments-inside-column.enabled", true);
|
||||
#endif
|
||||
|
||||
// Is support for the Web Animations API enabled?
|
||||
// Before enabling this by default, make sure also CSSPseudoElement interface
|
||||
// has been spec'ed properly, or we should add a separate pref for
|
||||
// CSSPseudoElement interface. See Bug 1174575 for further details.
|
||||
#ifdef RELEASE_BUILD
|
||||
pref("dom.animations-api.core.enabled", false);
|
||||
#else
|
||||
|
||||
@@ -18789,6 +18789,10 @@
|
||||
"path": "vibration/silent-ignore.html",
|
||||
"url": "/vibration/silent-ignore.html"
|
||||
},
|
||||
{
|
||||
"path": "web-animations/animatable/animate.html",
|
||||
"url": "/web-animations/animatable/animate.html"
|
||||
},
|
||||
{
|
||||
"path": "web-animations/animation-node/animation-node-after.html",
|
||||
"url": "/web-animations/animation-node/animation-node-after.html"
|
||||
@@ -21469,6 +21473,14 @@
|
||||
"path": "web-animations/keyframe-effect/constructor.html",
|
||||
"url": "/web-animations/keyframe-effect/constructor.html"
|
||||
},
|
||||
{
|
||||
"path": "web-animations/keyframe-effect/getComputedTiming.html",
|
||||
"url": "/web-animations/keyframe-effect/getComputedTiming.html"
|
||||
},
|
||||
{
|
||||
"path": "web-animations/animation/constructor.html",
|
||||
"url": "/web-animations/animation/constructor.html"
|
||||
},
|
||||
{
|
||||
"path": "webdriver/user_input/clear_test.py"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
[animate.html]
|
||||
type: testharness
|
||||
[Element.animate() creates an Animation object with a KeyframeEffect]
|
||||
expected: FAIL
|
||||
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1211783
|
||||
[Element.animate() accepts a single-valued keyframe specification]
|
||||
expected: FAIL
|
||||
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1216844
|
||||
@@ -0,0 +1,13 @@
|
||||
[constructor.html]
|
||||
type: testharness
|
||||
[Animation can be constructed with null effect and null timeline]
|
||||
expected: FAIL
|
||||
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1049975
|
||||
|
||||
[Animation can be constructed with null effect and non-null timeline]
|
||||
expected: FAIL
|
||||
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1049975
|
||||
|
||||
[Animation can be constructed with non-null effect and null timeline]
|
||||
expected: FAIL
|
||||
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1096776
|
||||
@@ -0,0 +1,126 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Animatable.animate tests</title>
|
||||
<link rel="help" href="http://w3c.github.io/web-animations/#dom-animatable-animate">
|
||||
<link rel="author" title="Brian Birtles" href="mailto:bbirtles@mozilla.com">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<iframe src="data:text/html;charset=utf-8," width="10" height="10"
|
||||
id="iframe"></iframe>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_class_string(anim, 'Animation', 'Returned object is an Animation');
|
||||
}, 'Element.animate() creates an Animation object');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_class_string(anim.effect, 'KeyframeEffect',
|
||||
'Returned Animation has a KeyframeEffect');
|
||||
}, 'Element.animate() creates an Animation object with a KeyframeEffect');
|
||||
|
||||
// Animatable.animate() passes its |frames| argument to the KeyframeEffect
|
||||
// constructor. As a result, detailed tests of the handling of that argument
|
||||
// are found in the tests for that constructor. Here we just check that the
|
||||
// different types of arguments are correctly passed along.
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_equals(anim.effect.getFrames().length, 2);
|
||||
assert_equals(anim.effect.getFrames()[0].opacity, '0');
|
||||
assert_equals(anim.effect.getFrames()[1].opacity, '1');
|
||||
}, 'Element.animate() accepts a property-indexed keyframe specification');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate([ { opacity: 0 }, { opacity: 1 } ], 2000);
|
||||
assert_equals(anim.effect.getFrames().length, 2);
|
||||
assert_equals(anim.effect.getFrames()[0].opacity, '0');
|
||||
assert_equals(anim.effect.getFrames()[1].opacity, '1');
|
||||
}, 'Element.animate() accepts a frame-indexed keyframe specification');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: 0 }, 2000);
|
||||
assert_equals(anim.effect.getFrames().length, 1);
|
||||
assert_equals(anim.effect.getFrames()[0].opacity, '0');
|
||||
}, 'Element.animate() accepts a single-valued keyframe specification');
|
||||
|
||||
// As with the |frames| argument, Animatable.animate() passes its |options|
|
||||
// argument to the KeyframeEffect constructor as well. As a result, detailed
|
||||
// tests of the handling of that argument are found in the tests for that
|
||||
// constructor. Here we just check that the different types of arguments are
|
||||
// correctly passed along.
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_equals(anim.effect.timing.duration, 2000);
|
||||
// Also check that unspecified parameters receive their default values
|
||||
assert_equals(anim.effect.timing.fill, 'auto');
|
||||
}, 'Element.animate() accepts a double as an options argument');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] },
|
||||
{ duration: Infinity, fill: 'forwards' });
|
||||
assert_equals(anim.effect.timing.duration, Infinity);
|
||||
assert_equals(anim.effect.timing.fill, 'forwards');
|
||||
// Also check that unspecified parameters receive their default values
|
||||
assert_equals(anim.effect.timing.direction, 'normal');
|
||||
}, 'Element.animate() accepts a KeyframeAnimationOptions argument');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] });
|
||||
assert_equals(anim.effect.timing.duration, 'auto');
|
||||
}, 'Element.animate() accepts an absent options argument');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_equals(anim.id, '');
|
||||
}, 'Element.animate() correctly sets the id attribute when no id is specified');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, { id: 'test' });
|
||||
assert_equals(anim.id, 'test');
|
||||
}, 'Element.animate() correctly sets the id attribute');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_equals(anim.timeline, document.timeline);
|
||||
}, 'Element.animate() correctly sets the Animation\'s timeline');
|
||||
|
||||
async_test(function(t) {
|
||||
var iframe = document.getElementById('iframe');
|
||||
iframe.addEventListener('load', t.step_func(function() {
|
||||
var div = createDiv(t, iframe.contentDocument);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_equals(anim.timeline, iframe.contentDocument.timeline);
|
||||
t.done();
|
||||
}));
|
||||
}, 'Element.animate() correctly sets the Animation\'s timeline when ' +
|
||||
'triggered on an element in a different document');
|
||||
|
||||
test(function(t) {
|
||||
var div = createDiv(t);
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
|
||||
assert_equals(anim.playState, 'pending');
|
||||
}, 'Element.animate() calls play on the Animation');
|
||||
|
||||
// TODO: Test the same on CSSPseudoElement
|
||||
|
||||
</script>
|
||||
</body>
|
||||
@@ -0,0 +1,60 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Animation constructor tests</title>
|
||||
<link rel="help" href="http://w3c.github.io/web-animations/#dom-animation-animation">
|
||||
<link rel="author" title="Hiroyuki Ikezoe" href="mailto:hiikezoe@mozilla-japan.org">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
var gTarget = document.getElementById("target");
|
||||
var gEffect = new KeyframeEffectReadOnly(gTarget, { opacity: [0, 1] });
|
||||
|
||||
var gTestArguments = [
|
||||
{
|
||||
effect: null,
|
||||
timeline: null,
|
||||
description: "with null effect and null timeline"
|
||||
},
|
||||
{
|
||||
effect: null,
|
||||
timeline: document.timeline,
|
||||
description: "with null effect and non-null timeline"
|
||||
},
|
||||
{
|
||||
effect: gEffect,
|
||||
timeline: null,
|
||||
description: "with non-null effect and null timeline"
|
||||
},
|
||||
{
|
||||
effect: gEffect,
|
||||
timeline: document.timeline,
|
||||
description: "with non-null effect and non-null timeline"
|
||||
},
|
||||
];
|
||||
|
||||
gTestArguments.forEach(function(args) {
|
||||
test(function(t) {
|
||||
var animation = new Animation(args.effect, args.timeline);
|
||||
|
||||
assert_not_equals(animation, null,
|
||||
"An animation sohuld be created");
|
||||
assert_equals(animation.effect, args.effect,
|
||||
"Animation returns the same effect passed to " +
|
||||
"the Constructor");
|
||||
assert_equals(animation.timeline, args.timeline,
|
||||
"Animation returns the same timeline passed to " +
|
||||
"the Constructor");
|
||||
assert_equals(animation.playState, "idle",
|
||||
"Animation.playState should be initially 'idle'");
|
||||
}, "Animation can be constructed " + args.description);
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
@@ -449,6 +449,186 @@ gKeyframeSequenceTests.forEach(function(subtest) {
|
||||
" roundtrips");
|
||||
});
|
||||
|
||||
|
||||
test(function(t) {
|
||||
var effect = new KeyframeEffectReadOnly(target,
|
||||
{left: ["10px", "20px"]});
|
||||
|
||||
var timing = effect.timing;
|
||||
assert_equals(timing.delay, 0, "default delay");
|
||||
assert_equals(timing.endDelay, 0, "default endDelay");
|
||||
assert_equals(timing.fill, "auto", "default fill");
|
||||
assert_equals(timing.iterations, 1.0, "default iterations");
|
||||
assert_equals(timing.iterationStart, 0.0, "default iterationStart");
|
||||
assert_equals(timing.duration, "auto", "default duration");
|
||||
assert_equals(timing.direction, "normal", "default direction");
|
||||
assert_equals(timing.easing, "linear", "default easing");
|
||||
|
||||
assert_equals(effect.composite, "replace", "default composite");
|
||||
assert_equals(effect.iterationComposite, "replace",
|
||||
"default iterationComposite");
|
||||
assert_equals(effect.spacing, "distribute",
|
||||
"default spacing");
|
||||
}, "a KeyframeEffectReadOnly constructed without any " +
|
||||
"KeyframeEffectOptions object");
|
||||
|
||||
var gKeyframeEffectOptionTests = [
|
||||
{ desc: "an empty KeyframeEffectOption",
|
||||
input: {},
|
||||
expected: {delay: 0,
|
||||
fill: "auto",
|
||||
iterations: 1,
|
||||
duration: "auto",
|
||||
direction: "normal"} },
|
||||
{ desc: "a normal KeyframeEffectOption",
|
||||
input: {delay: 1000,
|
||||
fill: "auto",
|
||||
iterations: 5.5,
|
||||
duration: "auto",
|
||||
direction: "alternate"},
|
||||
expected: {delay: 1000,
|
||||
fill: "auto",
|
||||
iterations: 5.5,
|
||||
duration: "auto",
|
||||
direction: "alternate"} },
|
||||
{ desc: "a double value",
|
||||
input: 3000,
|
||||
expected: {delay: 0,
|
||||
fill: "auto",
|
||||
iterations: 1,
|
||||
duration: 3000,
|
||||
direction: "normal"} },
|
||||
{ desc: "+Infinity",
|
||||
input: Infinity,
|
||||
expected: {delay: 0,
|
||||
fill: "auto",
|
||||
iterations: 1,
|
||||
duration: Infinity,
|
||||
direction: "normal"} },
|
||||
{ desc: "-Infinity",
|
||||
input: -Infinity,
|
||||
expected: {delay: 0,
|
||||
fill: "auto",
|
||||
iterations: 1,
|
||||
duration: -Infinity,
|
||||
direction: "normal"} },
|
||||
{ desc: "NaN",
|
||||
input: NaN,
|
||||
expected: {delay: 0,
|
||||
fill: "auto",
|
||||
iterations: 1,
|
||||
duration: NaN,
|
||||
direction: "normal"} },
|
||||
{ desc: "a negative value",
|
||||
input: -1,
|
||||
expected: {delay: 0,
|
||||
fill: "auto",
|
||||
iterations: 1,
|
||||
duration: -1,
|
||||
direction: "normal"} },
|
||||
{ desc: "an Infinity duration",
|
||||
input: {duration: Infinity},
|
||||
expected: {delay: 0,
|
||||
fill: "auto",
|
||||
iterations: 1,
|
||||
duration: Infinity,
|
||||
direction: "normal"} },
|
||||
{ desc: "a negative Infinity duration",
|
||||
input: {duration: -Infinity},
|
||||
expected: {delay: 0,
|
||||
fill: "auto",
|
||||
iterations: 1,
|
||||
duration: -Infinity,
|
||||
direction: "normal"} },
|
||||
{ desc: "a NaN duration",
|
||||
input: {duration: NaN},
|
||||
expected: {delay: 0,
|
||||
fill: "auto",
|
||||
iterations: 1,
|
||||
duration: NaN,
|
||||
direction: "normal"} },
|
||||
{ desc: "a negative duration",
|
||||
input: {duration: -1},
|
||||
expected: {delay: 0,
|
||||
fill: "auto",
|
||||
iterations: 1,
|
||||
duration: -1,
|
||||
direction: "normal"} },
|
||||
{ desc: "a string duration",
|
||||
input: {duration: "merrychristmas"},
|
||||
expected: {delay: 0,
|
||||
fill: "auto",
|
||||
iterations: 1,
|
||||
duration: "merrychristmas",
|
||||
direction: "normal"} },
|
||||
{ desc: "an auto duration",
|
||||
input: {duration: "auto"},
|
||||
expected: {delay: 0,
|
||||
fill: "auto",
|
||||
iterations: 1,
|
||||
duration: "auto",
|
||||
direction: "normal"} },
|
||||
{ desc: "an Infinity iterations",
|
||||
input: {iterations: Infinity},
|
||||
expected: {delay: 0,
|
||||
fill: "auto",
|
||||
iterations: Infinity,
|
||||
duration: "auto",
|
||||
direction: "normal"} },
|
||||
{ desc: "a negative Infinity iterations",
|
||||
input: {iterations: -Infinity},
|
||||
expected: {delay: 0,
|
||||
fill: "auto",
|
||||
iterations: -Infinity,
|
||||
duration: "auto",
|
||||
direction: "normal"} },
|
||||
{ desc: "a NaN iterations",
|
||||
input: {iterations: NaN},
|
||||
expected: {delay: 0,
|
||||
fill: "auto",
|
||||
iterations: NaN,
|
||||
duration: "auto",
|
||||
direction: "normal"} },
|
||||
{ desc: "a negative iterations",
|
||||
input: {iterations: -1},
|
||||
expected: {delay: 0,
|
||||
fill: "auto",
|
||||
iterations: -1,
|
||||
duration: "auto",
|
||||
direction: "normal"} },
|
||||
{ desc: "an auto fill",
|
||||
input: {fill: "auto"},
|
||||
expected: {delay: 0,
|
||||
fill: "auto",
|
||||
iterations: 1,
|
||||
duration: "auto",
|
||||
direction: "normal"} },
|
||||
{ desc: "a forwards fill",
|
||||
input: {fill: "forwards"},
|
||||
expected: {delay: 0,
|
||||
fill: "forwards",
|
||||
iterations: 1,
|
||||
duration: "auto",
|
||||
direction: "normal"} }
|
||||
];
|
||||
|
||||
gKeyframeEffectOptionTests.forEach(function(stest) {
|
||||
test(function(t) {
|
||||
var effect = new KeyframeEffectReadOnly(target,
|
||||
{left: ["10px", "20px"]},
|
||||
stest.input);
|
||||
|
||||
var timing = effect.timing;
|
||||
assert_equals(timing.delay, stest.expected.delay, "timing delay");
|
||||
assert_equals(timing.fill, stest.expected.fill, "timing fill");
|
||||
assert_equals(timing.iterations, stest.expected.iterations,
|
||||
"timing iterations");
|
||||
assert_equals(timing.duration, stest.expected.duration, "timing duration");
|
||||
assert_equals(timing.direction, stest.expected.direction,
|
||||
"timing direction");
|
||||
}, "a KeyframeEffectReadOnly constructed by " + stest.desc);
|
||||
});
|
||||
|
||||
done();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>KeyframeEffectReadOnly getComputedTiming() tests</title>
|
||||
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffectreadonly-getcomputedtiming">
|
||||
<link rel="author" title="Boris Chiou" href="mailto:boris.chiou@gmail.com">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
var target = document.getElementById("target");
|
||||
|
||||
test(function(t) {
|
||||
var effect = new KeyframeEffectReadOnly(target,
|
||||
{left: ["10px", "20px"]});
|
||||
|
||||
var ct = effect.getComputedTiming();
|
||||
assert_equals(ct.delay, 0, "computed delay");
|
||||
assert_equals(ct.fill, "none", "computed fill");
|
||||
assert_equals(ct.iterations, 1.0, "computed iterations");
|
||||
assert_equals(ct.duration, 0, "computed duration");
|
||||
assert_equals(ct.direction, "normal", "computed direction");
|
||||
}, "values of getComputedTiming() when a KeyframeEffectReadOnly is " +
|
||||
"constructed without any KeyframeEffectOptions object");
|
||||
|
||||
var gGetComputedTimingTests = [
|
||||
{ desc: "an empty KeyframeEffectOption",
|
||||
input: {},
|
||||
expected: {delay: 0,
|
||||
fill: "none",
|
||||
iterations: 1,
|
||||
duration: 0,
|
||||
direction: "normal"} },
|
||||
{ desc: "a normal KeyframeEffectOption",
|
||||
input: {delay: 1000,
|
||||
fill: "auto",
|
||||
iterations: 5.5,
|
||||
duration: "auto",
|
||||
direction: "alternate"},
|
||||
expected: {delay: 1000,
|
||||
fill: "none",
|
||||
iterations: 5.5,
|
||||
duration: 0,
|
||||
direction: "alternate"} },
|
||||
{ desc: "a double value",
|
||||
input: 3000,
|
||||
timing: {delay: 0,
|
||||
fill: "auto",
|
||||
iterations: 1,
|
||||
duration: 3000,
|
||||
direction: "normal"},
|
||||
expected: {delay: 0,
|
||||
fill: "none",
|
||||
iterations: 1,
|
||||
duration: 3000,
|
||||
direction: "normal"} },
|
||||
{ desc: "+Infinity",
|
||||
input: Infinity,
|
||||
expected: {delay: 0,
|
||||
fill: "none",
|
||||
iterations: 1,
|
||||
duration: Infinity,
|
||||
direction: "normal"} },
|
||||
{ desc: "-Infinity",
|
||||
input: -Infinity,
|
||||
expected: {delay: 0,
|
||||
fill: "none",
|
||||
iterations: 1,
|
||||
duration: 0,
|
||||
direction: "normal"} },
|
||||
{ desc: "NaN",
|
||||
input: NaN,
|
||||
expected: {delay: 0,
|
||||
fill: "none",
|
||||
iterations: 1,
|
||||
duration: 0,
|
||||
direction: "normal"} },
|
||||
{ desc: "a negative value",
|
||||
input: -1,
|
||||
expected: {delay: 0,
|
||||
fill: "none",
|
||||
iterations: 1,
|
||||
duration: 0,
|
||||
direction: "normal"} },
|
||||
{ desc: "an Infinity duration",
|
||||
input: {duration: Infinity},
|
||||
expected: {delay: 0,
|
||||
fill: "none",
|
||||
iterations: 1,
|
||||
duration: Infinity,
|
||||
direction: "normal"} },
|
||||
{ desc: "a negative Infinity duration",
|
||||
input: {duration: -Infinity},
|
||||
expected: {delay: 0,
|
||||
fill: "none",
|
||||
iterations: 1,
|
||||
duration: 0,
|
||||
direction: "normal"} },
|
||||
{ desc: "a NaN duration",
|
||||
input: {duration: NaN},
|
||||
expected: {delay: 0,
|
||||
fill: "none",
|
||||
iterations: 1,
|
||||
duration: 0,
|
||||
direction: "normal"} },
|
||||
{ desc: "a negative duration",
|
||||
input: {duration: -1},
|
||||
expected: {delay: 0,
|
||||
fill: "none",
|
||||
iterations: 1,
|
||||
duration: 0,
|
||||
direction: "normal"} },
|
||||
{ desc: "a string duration",
|
||||
input: {duration: "merrychristmas"},
|
||||
expected: {delay: 0,
|
||||
fill: "none",
|
||||
iterations: 1,
|
||||
duration: 0,
|
||||
direction: "normal"} },
|
||||
{ desc: "an auto duration",
|
||||
input: {duration: "auto"},
|
||||
expected: {delay: 0,
|
||||
fill: "none",
|
||||
iterations: 1,
|
||||
duration: 0,
|
||||
direction: "normal"} },
|
||||
{ desc: "an Infinity iterations",
|
||||
input: {iterations: Infinity},
|
||||
expected: {delay: 0,
|
||||
fill: "none",
|
||||
iterations: Infinity,
|
||||
duration: 0,
|
||||
direction: "normal"} },
|
||||
{ desc: "a negative Infinity iterations",
|
||||
input: {iterations: -Infinity},
|
||||
expected: {delay: 0,
|
||||
fill: "none",
|
||||
iterations: 1,
|
||||
duration: 0,
|
||||
direction: "normal"} },
|
||||
{ desc: "a NaN iterations",
|
||||
input: {iterations: NaN},
|
||||
expected: {delay: 0,
|
||||
fill: "none",
|
||||
iterations: 1,
|
||||
duration: 0,
|
||||
direction: "normal"} },
|
||||
{ desc: "a negative iterations",
|
||||
input: {iterations: -1},
|
||||
expected: {delay: 0,
|
||||
fill: "none",
|
||||
iterations: 1,
|
||||
duration: 0,
|
||||
direction: "normal"} },
|
||||
{ desc: "an auto fill",
|
||||
input: {fill: "auto"},
|
||||
expected: {delay: 0,
|
||||
fill: "none",
|
||||
iterations: 1,
|
||||
duration: 0,
|
||||
direction: "normal"} },
|
||||
{ desc: "a forwards fill",
|
||||
input: {fill: "forwards"},
|
||||
expected: {delay: 0,
|
||||
fill: "forwards",
|
||||
iterations: 1,
|
||||
duration: 0,
|
||||
direction: "normal"} }
|
||||
];
|
||||
|
||||
gGetComputedTimingTests.forEach(function(stest) {
|
||||
test(function(t) {
|
||||
var effect = new KeyframeEffectReadOnly(target,
|
||||
{left: ["10px", "20px"]},
|
||||
stest.input);
|
||||
|
||||
var ct = effect.getComputedTiming();
|
||||
assert_equals(ct.delay, stest.expected.delay, "computed delay");
|
||||
assert_equals(ct.fill, stest.expected.fill, "computed fill");
|
||||
assert_equals(ct.iterations, stest.expected.iterations,
|
||||
"computed iterations");
|
||||
assert_equals(ct.duration, stest.expected.duration, "computed duration");
|
||||
assert_equals(ct.direction, stest.expected.direction, "computed direction");
|
||||
}, "values of getComputedTiming() when a KeyframeEffectReadOnly is " +
|
||||
"constructed by " + stest.desc);
|
||||
});
|
||||
|
||||
done();
|
||||
</script>
|
||||
</body>
|
||||
@@ -34,7 +34,7 @@ function newAnimation(animationTarget) {
|
||||
}
|
||||
|
||||
// creates div element, appends it to the document body and
|
||||
// add removing of the created element to test cleanup
|
||||
// removes the created element during test cleanup
|
||||
function createDiv(test, doc) {
|
||||
if (!doc) {
|
||||
doc = document;
|
||||
|
||||
Reference in New Issue
Block a user