зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-inbound to mozilla-central a=merge
--HG-- extra : amend_source : bc1a2d4e4f8ba9197da4e0e72ab01990885ce2b4
This commit is contained in:
Коммит
5a3c5be60a
|
@ -20,14 +20,6 @@ INSTALL_TARGETS += UA_UPDATE
|
|||
# Make sure the standalone glue doesn't try to get libxpcom.so from b2g/app.
|
||||
NSDISTMODE = copy
|
||||
|
||||
# Copy the Firefox OS fonts if available
|
||||
ifdef MOZTTDIR
|
||||
include $(MOZTTDIR)/fonts.mk
|
||||
MOZTT_DEST = $(FINAL_TARGET)/fonts
|
||||
MOZTT_FILES = $(patsubst external/moztt/%,$(MOZTTDIR)/%,$(filter external/moztt/%,$(subst :, ,$(PRODUCT_COPY_FILES))))
|
||||
INSTALL_TARGETS += MOZTT
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
APP_ICON = b2g
|
||||
|
|
|
@ -73,6 +73,14 @@ CLANG_RT_ASAN_DEST = $(FINAL_TARGET)
|
|||
INSTALL_TARGETS += CLANG_RT_ASAN
|
||||
endif
|
||||
|
||||
ifdef MOZTTDIR
|
||||
# Install the Firefox OS fonts.
|
||||
include $(MOZTTDIR)/fonts.mk
|
||||
MOZTT_DEST = $(FINAL_TARGET)/fonts
|
||||
MOZTT_FILES = $(patsubst external/moztt/%,$(MOZTTDIR)/%,$(filter external/moztt/%,$(subst :, ,$(PRODUCT_COPY_FILES))))
|
||||
INSTALL_TARGETS += MOZTT
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
TARGET_DEPTH = ..
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
#include "AnimationPlayer.h"
|
||||
#include "AnimationUtils.h"
|
||||
#include "mozilla/dom/AnimationPlayerBinding.h"
|
||||
#include "AnimationCommon.h" // For AnimationPlayerCollection,
|
||||
// CommonAnimationManager
|
||||
#include "nsIDocument.h" // For nsIDocument
|
||||
#include "nsIPresShell.h" // For nsIPresShell
|
||||
#include "nsLayoutUtils.h" // For PostRestyleEvent (remove after bug 1073336)
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -63,50 +67,17 @@ AnimationPlayer::PlayState() const
|
|||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::Play(UpdateFlags aFlags)
|
||||
AnimationPlayer::Play()
|
||||
{
|
||||
// FIXME: When we implement finishing behavior (bug 1074630) we should
|
||||
// not return early if mIsPaused is false since we may still need to seek.
|
||||
// (However, we will need to pass a flag so that when we start playing due to
|
||||
// a change in animation-play-state we *don't* trigger finishing behavior.)
|
||||
if (!mIsPaused) {
|
||||
return;
|
||||
}
|
||||
mIsPaused = false;
|
||||
|
||||
Nullable<TimeDuration> timelineTime = mTimeline->GetCurrentTime();
|
||||
if (timelineTime.IsNull()) {
|
||||
// FIXME: We should just sit in the pending state in this case.
|
||||
// We will introduce the pending state in Bug 927349.
|
||||
return;
|
||||
}
|
||||
|
||||
// Update start time to an appropriate offset from the current timeline time
|
||||
MOZ_ASSERT(!mHoldTime.IsNull(), "Hold time should not be null when paused");
|
||||
mStartTime.SetValue(timelineTime.Value() - mHoldTime.Value());
|
||||
mHoldTime.SetNull();
|
||||
|
||||
if (aFlags == eUpdateStyle) {
|
||||
MaybePostRestyle();
|
||||
}
|
||||
DoPlay();
|
||||
PostUpdate();
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::Pause(UpdateFlags aFlags)
|
||||
AnimationPlayer::Pause()
|
||||
{
|
||||
if (mIsPaused) {
|
||||
return;
|
||||
}
|
||||
mIsPaused = true;
|
||||
mIsRunningOnCompositor = false;
|
||||
|
||||
// Bug 927349 - check for null result here and go to pending state
|
||||
mHoldTime = GetCurrentTime();
|
||||
mStartTime.SetNull();
|
||||
|
||||
if (aFlags == eUpdateStyle) {
|
||||
MaybePostRestyle();
|
||||
}
|
||||
DoPause();
|
||||
PostUpdate();
|
||||
}
|
||||
|
||||
Nullable<double>
|
||||
|
@ -115,40 +86,6 @@ AnimationPlayer::GetCurrentTimeAsDouble() const
|
|||
return AnimationUtils::TimeDurationToDouble(GetCurrentTime());
|
||||
}
|
||||
|
||||
AnimationPlayState
|
||||
AnimationPlayer::PlayStateFromJS() const
|
||||
{
|
||||
// FIXME: Once we introduce CSSTransitionPlayer, this should move to an
|
||||
// override of PlayStateFromJS in CSSAnimationPlayer and CSSTransitionPlayer
|
||||
// and we should skip it in the general case.
|
||||
FlushStyle();
|
||||
|
||||
return PlayState();
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::PlayFromJS()
|
||||
{
|
||||
// Flush style to ensure that any properties controlling animation state
|
||||
// (e.g. animation-play-state) are fully updated before we proceed.
|
||||
//
|
||||
// Note that this might trigger PlayFromStyle()/PauseFromStyle() on this
|
||||
// object.
|
||||
//
|
||||
// FIXME: Once we introduce CSSTransitionPlayer, this should move to an
|
||||
// override of PlayFromJS in CSSAnimationPlayer and CSSTransitionPlayer and
|
||||
// we should skip it in the general case.
|
||||
FlushStyle();
|
||||
|
||||
Play(eUpdateStyle);
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::PauseFromJS()
|
||||
{
|
||||
Pause(eUpdateStyle);
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::SetSource(Animation* aSource)
|
||||
{
|
||||
|
@ -224,45 +161,61 @@ AnimationPlayer::ComposeStyle(nsRefPtr<css::AnimValuesStyleRule>& aStyleRule,
|
|||
mIsPreviousStateFinished = (playState == AnimationPlayState::Finished);
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::DoPlay()
|
||||
{
|
||||
// FIXME: When we implement finishing behavior (bug 1074630) we should
|
||||
// not return early if mIsPaused is false since we may still need to seek.
|
||||
// (However, we will need to pass a flag so that when we start playing due to
|
||||
// a change in animation-play-state we *don't* trigger finishing behavior.)
|
||||
if (!mIsPaused) {
|
||||
return;
|
||||
}
|
||||
mIsPaused = false;
|
||||
|
||||
Nullable<TimeDuration> timelineTime = mTimeline->GetCurrentTime();
|
||||
if (timelineTime.IsNull()) {
|
||||
// FIXME: We should just sit in the pending state in this case.
|
||||
// We will introduce the pending state in Bug 927349.
|
||||
return;
|
||||
}
|
||||
|
||||
// Update start time to an appropriate offset from the current timeline time
|
||||
MOZ_ASSERT(!mHoldTime.IsNull(), "Hold time should not be null when paused");
|
||||
mStartTime.SetValue(timelineTime.Value() - mHoldTime.Value());
|
||||
mHoldTime.SetNull();
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::DoPause()
|
||||
{
|
||||
if (mIsPaused) {
|
||||
return;
|
||||
}
|
||||
mIsPaused = true;
|
||||
mIsRunningOnCompositor = false;
|
||||
|
||||
// Bug 927349 - check for null result here and go to pending state
|
||||
mHoldTime = GetCurrentTime();
|
||||
mStartTime.SetNull();
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::FlushStyle() const
|
||||
{
|
||||
if (!mSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
Element* targetElement;
|
||||
nsCSSPseudoElements::Type pseudoType;
|
||||
mSource->GetTarget(targetElement, pseudoType);
|
||||
if (!targetElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsIDocument* doc = targetElement->GetComposedDoc();
|
||||
nsIDocument* doc = GetRenderedDocument();
|
||||
if (doc) {
|
||||
doc->FlushPendingNotifications(Flush_Style);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::MaybePostRestyle() const
|
||||
AnimationPlayer::PostUpdate()
|
||||
{
|
||||
if (!mSource) {
|
||||
return;
|
||||
AnimationPlayerCollection* collection = GetCollection();
|
||||
if (collection) {
|
||||
collection->NotifyPlayerUpdated();
|
||||
}
|
||||
|
||||
Element* targetElement;
|
||||
nsCSSPseudoElements::Type pseudoType;
|
||||
mSource->GetTarget(targetElement, pseudoType);
|
||||
if (!targetElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: This is a bit heavy-handed but in bug 1073336 we hope to
|
||||
// introduce a better means for players to update style.
|
||||
nsLayoutUtils::PostRestyleEvent(targetElement,
|
||||
eRestyle_Self,
|
||||
nsChangeHint_AllReflowHints);
|
||||
}
|
||||
|
||||
StickyTimeDuration
|
||||
|
@ -276,5 +229,54 @@ AnimationPlayer::SourceContentEnd() const
|
|||
+ mSource->GetComputedTiming().mActiveDuration;
|
||||
}
|
||||
|
||||
nsIDocument*
|
||||
AnimationPlayer::GetRenderedDocument() const
|
||||
{
|
||||
if (!mSource) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Element* targetElement;
|
||||
nsCSSPseudoElements::Type pseudoType;
|
||||
mSource->GetTarget(targetElement, pseudoType);
|
||||
if (!targetElement) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return targetElement->GetComposedDoc();
|
||||
}
|
||||
|
||||
nsPresContext*
|
||||
AnimationPlayer::GetPresContext() const
|
||||
{
|
||||
nsIDocument* doc = GetRenderedDocument();
|
||||
if (!doc) {
|
||||
return nullptr;
|
||||
}
|
||||
nsIPresShell* shell = doc->GetShell();
|
||||
if (!shell) {
|
||||
return nullptr;
|
||||
}
|
||||
return shell->GetPresContext();
|
||||
}
|
||||
|
||||
AnimationPlayerCollection*
|
||||
AnimationPlayer::GetCollection() const
|
||||
{
|
||||
css::CommonAnimationManager* manager = GetAnimationManager();
|
||||
if (!manager) {
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_ASSERT(mSource, "A player with an animation manager must have a source");
|
||||
|
||||
Element* targetElement;
|
||||
nsCSSPseudoElements::Type targetPseudoType;
|
||||
mSource->GetTarget(targetElement, targetPseudoType);
|
||||
MOZ_ASSERT(targetElement,
|
||||
"A player with an animation manager must have a target");
|
||||
|
||||
return manager->GetAnimationPlayers(targetElement, targetPseudoType, false);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -22,13 +22,18 @@
|
|||
|
||||
struct JSContext;
|
||||
class nsCSSPropertySet;
|
||||
class nsIDocument;
|
||||
class nsPresContext;
|
||||
|
||||
namespace mozilla {
|
||||
struct AnimationPlayerCollection;
|
||||
namespace css {
|
||||
class AnimValuesStyleRule;
|
||||
class CommonAnimationManager;
|
||||
} // namespace css
|
||||
|
||||
class CSSAnimationPlayer;
|
||||
class CSSTransitionPlayer;
|
||||
|
||||
namespace dom {
|
||||
|
||||
|
@ -53,13 +58,7 @@ public:
|
|||
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
virtual CSSAnimationPlayer* AsCSSAnimationPlayer() { return nullptr; }
|
||||
|
||||
// Temporary flags to control restyle behavior until bug 1073336
|
||||
// provides a better solution.
|
||||
enum UpdateFlags {
|
||||
eNoUpdate,
|
||||
eUpdateStyle
|
||||
};
|
||||
virtual CSSTransitionPlayer* AsCSSTransitionPlayer() { return nullptr; }
|
||||
|
||||
// AnimationPlayer methods
|
||||
Animation* GetSource() const { return mSource; }
|
||||
|
@ -67,18 +66,21 @@ public:
|
|||
Nullable<double> GetStartTime() const;
|
||||
Nullable<TimeDuration> GetCurrentTime() const;
|
||||
AnimationPlayState PlayState() const;
|
||||
virtual void Play(UpdateFlags aUpdateFlags);
|
||||
virtual void Pause(UpdateFlags aUpdateFlags);
|
||||
virtual void Play();
|
||||
virtual void Pause();
|
||||
bool IsRunningOnCompositor() const { return mIsRunningOnCompositor; }
|
||||
|
||||
// Wrapper functions for AnimationPlayer DOM methods when called
|
||||
// from script. We often use the same methods internally and from
|
||||
// script but when called from script we perform extra steps such
|
||||
// as flushing style or converting the return type.
|
||||
// script but when called from script we (or one of our subclasses) perform
|
||||
// extra steps such as flushing style or converting the return type.
|
||||
Nullable<double> GetCurrentTimeAsDouble() const;
|
||||
AnimationPlayState PlayStateFromJS() const;
|
||||
void PlayFromJS();
|
||||
void PauseFromJS();
|
||||
virtual AnimationPlayState PlayStateFromJS() const { return PlayState(); }
|
||||
virtual void PlayFromJS() { Play(); }
|
||||
// PauseFromJS is currently only here for symmetry with PlayFromJS but
|
||||
// in future we will likely have to flush style in
|
||||
// CSSAnimationPlayer::PauseFromJS so we leave it for now.
|
||||
void PauseFromJS() { Pause(); }
|
||||
|
||||
void SetSource(Animation* aSource);
|
||||
void Tick();
|
||||
|
@ -120,10 +122,18 @@ public:
|
|||
Nullable<TimeDuration> mStartTime; // Timeline timescale
|
||||
|
||||
protected:
|
||||
void DoPlay();
|
||||
void DoPause();
|
||||
|
||||
void FlushStyle() const;
|
||||
void MaybePostRestyle() const;
|
||||
void PostUpdate();
|
||||
StickyTimeDuration SourceContentEnd() const;
|
||||
|
||||
nsIDocument* GetRenderedDocument() const;
|
||||
nsPresContext* GetPresContext() const;
|
||||
virtual css::CommonAnimationManager* GetAnimationManager() const = 0;
|
||||
AnimationPlayerCollection* GetCollection() const;
|
||||
|
||||
nsRefPtr<AnimationTimeline> mTimeline;
|
||||
nsRefPtr<Animation> mSource;
|
||||
Nullable<TimeDuration> mHoldTime; // Player timescale
|
||||
|
|
|
@ -42,17 +42,4 @@ test(function() {
|
|||
div.remove();
|
||||
}, 'Animation name with hex-escape');
|
||||
|
||||
test(function() {
|
||||
var div = addDiv();
|
||||
|
||||
// Add a transition
|
||||
div.style.left = '0px';
|
||||
window.getComputedStyle(div).transitionProperty;
|
||||
div.style.transition = 'all 100s';
|
||||
div.style.left = '100px';
|
||||
|
||||
assert_equals(div.getAnimationPlayers()[0].source.effect.name, '',
|
||||
'Animation effects for transitions have an empty name');
|
||||
div.remove();
|
||||
}, 'Effect name for transitions');
|
||||
</script>
|
|
@ -206,48 +206,4 @@ async_test(function(t) {
|
|||
}, 'pause() applies pending changes to animation-play-state first');
|
||||
// (Note that we can't actually test for this; see comment above, in test-body.)
|
||||
|
||||
/* Disabled until bug 1073336 lands */
|
||||
if (false) {
|
||||
async_test(function(t) {
|
||||
var div = addDiv();
|
||||
var cs = window.getComputedStyle(div);
|
||||
|
||||
div.style.marginLeft = '0px';
|
||||
cs.marginLeft; // Flush style to set up transition start point
|
||||
div.style.transition = 'margin-left 100s';
|
||||
div.style.marginLeft = '10000px';
|
||||
cs.marginLeft;
|
||||
|
||||
var player = div.getAnimationPlayers()[0];
|
||||
assert_equals(getMarginLeft(cs), 0,
|
||||
'Initial value of margin-left is zero');
|
||||
var previousAnimVal = getMarginLeft(cs);
|
||||
|
||||
waitForFrame().then(function() {
|
||||
t.step(function() {
|
||||
assert_true(getMarginLeft(cs) > previousAnimVal,
|
||||
'margin-left is initially increasing');
|
||||
previousAnimVal = getMarginLeft(cs);
|
||||
player.pause();
|
||||
});
|
||||
return waitForFrame();
|
||||
}).then(function() {
|
||||
t.step(function() {
|
||||
assert_equals(getMarginLeft(cs), previousAnimVal,
|
||||
'margin-left does not increase after calling pause()');
|
||||
previousAnimVal = getMarginLeft(cs);
|
||||
player.play();
|
||||
});
|
||||
return waitForFrame();
|
||||
}).then(function() {
|
||||
t.step(function() {
|
||||
assert_true(getMarginLeft(cs) > previousAnimVal,
|
||||
'margin-left increases after calling play()');
|
||||
});
|
||||
div.remove();
|
||||
t.done();
|
||||
});
|
||||
}, 'pause() and play() a transition');
|
||||
}
|
||||
|
||||
</script>
|
|
@ -0,0 +1,27 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="log"></div>
|
||||
<style>
|
||||
@keyframes anim { }
|
||||
</style>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
function addDiv() {
|
||||
var div = document.createElement('div');
|
||||
document.body.appendChild(div);
|
||||
return div;
|
||||
}
|
||||
|
||||
test(function() {
|
||||
var div = addDiv();
|
||||
div.style.animation = 'anim 100s';
|
||||
var players = div.getAnimationPlayers();
|
||||
assert_equals(players[0].source.target, div,
|
||||
'Animation.target is the animatable div');
|
||||
div.remove();
|
||||
}, 'Returned CSS animations have the correct Animation.target');
|
||||
|
||||
</script>
|
|
@ -73,41 +73,6 @@ test(function() {
|
|||
div.remove();
|
||||
}, 'getAnimationPlayers for multi-property animations');
|
||||
|
||||
async_test(function(t) {
|
||||
var div = addDiv();
|
||||
|
||||
// Add a couple of transitions
|
||||
div.style.left = '0px';
|
||||
div.style.top = '0px';
|
||||
window.getComputedStyle(div).transitionProperty;
|
||||
|
||||
div.style.transition = 'all 100s';
|
||||
div.style.left = '100px';
|
||||
div.style.top = '100px';
|
||||
|
||||
var players = div.getAnimationPlayers();
|
||||
assert_equals(players.length, 2,
|
||||
'getAnimationPlayers() returns one player per transitioning property');
|
||||
var startTime = players[0].startTime;
|
||||
assert_true(startTime > 0 && startTime <= document.timeline.currentTime,
|
||||
'CSS transitions have sensible start times');
|
||||
assert_equals(players[0].startTime, players[1].startTime,
|
||||
'CSS transitions started together have the same start time');
|
||||
|
||||
// Wait a moment then add a third transition
|
||||
window.requestAnimationFrame(t.step_func(function() {
|
||||
div.style.backgroundColor = 'green';
|
||||
players = div.getAnimationPlayers();
|
||||
assert_equals(players.length, 3,
|
||||
'getAnimationPlayers returns players for all running CSS Transitions');
|
||||
assert_true(players[1].startTime < players[2].startTime,
|
||||
'Player for additional CSS transition starts after the original'
|
||||
+ ' transitions and appears later in the list');
|
||||
div.remove();
|
||||
t.done();
|
||||
}));
|
||||
}, 'getAnimationPlayers for CSS Transitions');
|
||||
|
||||
async_test(function(t) {
|
||||
var div = addDiv();
|
||||
|
||||
|
@ -166,26 +131,6 @@ async_test(function(t) {
|
|||
}, 'getAnimationPlayers for CSS Animations that have finished but are'
|
||||
+ ' forwards filling');
|
||||
|
||||
async_test(function(t) {
|
||||
var div = addDiv();
|
||||
|
||||
// Set up event listener
|
||||
div.addEventListener('transitionend', t.step_func(function() {
|
||||
assert_equals(div.getAnimationPlayers().length, 0,
|
||||
'getAnimationPlayers does not return finished CSS Transitions');
|
||||
div.remove();
|
||||
t.done();
|
||||
}));
|
||||
|
||||
// Add a very short transition
|
||||
div.style.left = '0px';
|
||||
window.getComputedStyle(div).left;
|
||||
|
||||
div.style.transition = 'all 0.01s';
|
||||
div.style.left = '100px';
|
||||
window.getComputedStyle(div).left;
|
||||
}, 'getAnimationPlayers for CSS Transitions that have finished');
|
||||
|
||||
test(function() {
|
||||
var div = addDiv();
|
||||
div.style.animation = 'none 100s';
|
||||
|
@ -285,36 +230,6 @@ test(function() {
|
|||
div.remove();
|
||||
}, 'getAnimationPlayers for zero-duration CSS Animations');
|
||||
|
||||
test(function() {
|
||||
var div = addDiv();
|
||||
|
||||
// Try to transition non-animatable property animation-duration
|
||||
div.style.animationDuration = '10s';
|
||||
window.getComputedStyle(div).animationDuration;
|
||||
|
||||
div.style.transition = 'all 100s';
|
||||
div.style.animationDuration = '100s';
|
||||
|
||||
assert_equals(div.getAnimationPlayers().length, 0,
|
||||
'getAnimationPlayers returns an empty sequence for a transition'
|
||||
+ ' of a non-animatable property');
|
||||
div.remove();
|
||||
}, 'getAnimationPlayers for transition on non-animatable property');
|
||||
|
||||
test(function() {
|
||||
var div = addDiv();
|
||||
|
||||
div.style.setProperty('-vendor-unsupported', '0px', '');
|
||||
window.getComputedStyle(div).transitionProperty;
|
||||
div.style.transition = 'all 100s';
|
||||
div.style.setProperty('-vendor-unsupported', '100px', '');
|
||||
|
||||
assert_equals(div.getAnimationPlayers().length, 0,
|
||||
'getAnimationPlayers returns an empty sequence for a transition'
|
||||
+ ' of an unsupported property');
|
||||
div.remove();
|
||||
}, 'getAnimationPlayers for transition on unsupported property');
|
||||
|
||||
test(function() {
|
||||
var div = addDiv();
|
||||
div.style.animation = 'anim1 100s';
|
|
@ -0,0 +1,24 @@
|
|||
<!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';
|
||||
|
||||
test(function() {
|
||||
var div = document.createElement('div');
|
||||
document.body.appendChild(div);
|
||||
|
||||
// Add a transition
|
||||
div.style.left = '0px';
|
||||
window.getComputedStyle(div).transitionProperty;
|
||||
div.style.transition = 'all 100s';
|
||||
div.style.left = '100px';
|
||||
|
||||
assert_equals(div.getAnimationPlayers()[0].source.effect.name, '',
|
||||
'Animation effects for transitions have an empty name');
|
||||
div.remove();
|
||||
}, 'Effect name for transitions');
|
||||
|
||||
</script>
|
|
@ -0,0 +1,66 @@
|
|||
<!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';
|
||||
|
||||
function addDiv() {
|
||||
var div = document.createElement('div');
|
||||
document.body.appendChild(div);
|
||||
return div;
|
||||
}
|
||||
|
||||
function waitForFrame() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
window.requestAnimationFrame(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function getMarginLeft(cs) {
|
||||
return parseFloat(cs.marginLeft);
|
||||
}
|
||||
|
||||
async_test(function(t) {
|
||||
var div = addDiv();
|
||||
var cs = window.getComputedStyle(div);
|
||||
|
||||
div.style.marginLeft = '0px';
|
||||
cs.marginLeft; // Flush style to set up transition start point
|
||||
div.style.transition = 'margin-left 100s';
|
||||
div.style.marginLeft = '10000px';
|
||||
cs.marginLeft;
|
||||
|
||||
var player = div.getAnimationPlayers()[0];
|
||||
assert_equals(getMarginLeft(cs), 0,
|
||||
'Initial value of margin-left is zero');
|
||||
var previousAnimVal = getMarginLeft(cs);
|
||||
|
||||
waitForFrame().then(function() {
|
||||
t.step(function() {
|
||||
assert_true(getMarginLeft(cs) > previousAnimVal,
|
||||
'margin-left is initially increasing');
|
||||
previousAnimVal = getMarginLeft(cs);
|
||||
player.pause();
|
||||
});
|
||||
return waitForFrame();
|
||||
}).then(function() {
|
||||
t.step(function() {
|
||||
assert_equals(getMarginLeft(cs), previousAnimVal,
|
||||
'margin-left does not increase after calling pause()');
|
||||
previousAnimVal = getMarginLeft(cs);
|
||||
player.play();
|
||||
});
|
||||
return waitForFrame();
|
||||
}).then(function() {
|
||||
t.step(function() {
|
||||
assert_true(getMarginLeft(cs) > previousAnimVal,
|
||||
'margin-left increases after calling play()');
|
||||
});
|
||||
div.remove();
|
||||
t.done();
|
||||
});
|
||||
}, 'pause() and play() a transition');
|
||||
|
||||
</script>
|
|
@ -3,29 +3,12 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="log"></div>
|
||||
<style>
|
||||
@keyframes anim { }
|
||||
</style>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
function addDiv() {
|
||||
test(function() {
|
||||
var div = document.createElement('div');
|
||||
document.body.appendChild(div);
|
||||
return div;
|
||||
}
|
||||
|
||||
test(function() {
|
||||
var div = addDiv();
|
||||
div.style.animation = 'anim 100s';
|
||||
var players = div.getAnimationPlayers();
|
||||
assert_equals(players[0].source.target, div,
|
||||
'Animation.target is the animatable div');
|
||||
div.remove();
|
||||
}, 'Returned CSS animations have the correct Animation.target');
|
||||
|
||||
test(function() {
|
||||
var div = addDiv();
|
||||
|
||||
div.style.left = '0px';
|
||||
window.getComputedStyle(div).transitionProperty;
|
|
@ -0,0 +1,100 @@
|
|||
<!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';
|
||||
|
||||
function addDiv() {
|
||||
var div = document.createElement('div');
|
||||
document.body.appendChild(div);
|
||||
return div;
|
||||
}
|
||||
|
||||
async_test(function(t) {
|
||||
var div = addDiv();
|
||||
|
||||
// Add a couple of transitions
|
||||
div.style.left = '0px';
|
||||
div.style.top = '0px';
|
||||
window.getComputedStyle(div).transitionProperty;
|
||||
|
||||
div.style.transition = 'all 100s';
|
||||
div.style.left = '100px';
|
||||
div.style.top = '100px';
|
||||
|
||||
var players = div.getAnimationPlayers();
|
||||
assert_equals(players.length, 2,
|
||||
'getAnimationPlayers() returns one player per transitioning property');
|
||||
var startTime = players[0].startTime;
|
||||
assert_true(startTime > 0 && startTime <= document.timeline.currentTime,
|
||||
'CSS transitions have sensible start times');
|
||||
assert_equals(players[0].startTime, players[1].startTime,
|
||||
'CSS transitions started together have the same start time');
|
||||
|
||||
// Wait a moment then add a third transition
|
||||
window.requestAnimationFrame(t.step_func(function() {
|
||||
div.style.backgroundColor = 'green';
|
||||
players = div.getAnimationPlayers();
|
||||
assert_equals(players.length, 3,
|
||||
'getAnimationPlayers returns players for all running CSS Transitions');
|
||||
assert_true(players[1].startTime < players[2].startTime,
|
||||
'Player for additional CSS transition starts after the original'
|
||||
+ ' transitions and appears later in the list');
|
||||
div.remove();
|
||||
t.done();
|
||||
}));
|
||||
}, 'getAnimationPlayers for CSS Transitions');
|
||||
|
||||
async_test(function(t) {
|
||||
var div = addDiv();
|
||||
|
||||
// Set up event listener
|
||||
div.addEventListener('transitionend', t.step_func(function() {
|
||||
assert_equals(div.getAnimationPlayers().length, 0,
|
||||
'getAnimationPlayers does not return finished CSS Transitions');
|
||||
div.remove();
|
||||
t.done();
|
||||
}));
|
||||
|
||||
// Add a very short transition
|
||||
div.style.left = '0px';
|
||||
window.getComputedStyle(div).left;
|
||||
|
||||
div.style.transition = 'all 0.01s';
|
||||
div.style.left = '100px';
|
||||
window.getComputedStyle(div).left;
|
||||
}, 'getAnimationPlayers for CSS Transitions that have finished');
|
||||
|
||||
test(function() {
|
||||
var div = addDiv();
|
||||
|
||||
// Try to transition non-animatable property animation-duration
|
||||
div.style.animationDuration = '10s';
|
||||
window.getComputedStyle(div).animationDuration;
|
||||
|
||||
div.style.transition = 'all 100s';
|
||||
div.style.animationDuration = '100s';
|
||||
|
||||
assert_equals(div.getAnimationPlayers().length, 0,
|
||||
'getAnimationPlayers returns an empty sequence for a transition'
|
||||
+ ' of a non-animatable property');
|
||||
div.remove();
|
||||
}, 'getAnimationPlayers for transition on non-animatable property');
|
||||
|
||||
test(function() {
|
||||
var div = addDiv();
|
||||
|
||||
div.style.setProperty('-vendor-unsupported', '0px', '');
|
||||
window.getComputedStyle(div).transitionProperty;
|
||||
div.style.transition = 'all 100s';
|
||||
div.style.setProperty('-vendor-unsupported', '100px', '');
|
||||
|
||||
assert_equals(div.getAnimationPlayers().length, 0,
|
||||
'getAnimationPlayers returns an empty sequence for a transition'
|
||||
+ ' of an unsupported property');
|
||||
div.remove();
|
||||
}, 'getAnimationPlayers for transition on unsupported property');
|
||||
|
||||
</script>
|
|
@ -1,9 +1,14 @@
|
|||
[animation-timeline/test_animation-timeline.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[css-integration/test_element-get-animation-players.html]
|
||||
[css-animations/test_animations-dynamic-changes.html]
|
||||
[css-animations/test_animation-effect-name.html]
|
||||
[css-animations/test_animation-pausing.html]
|
||||
[css-animations/test_animation-player-playstate.html]
|
||||
[css-animations/test_animation-target.html]
|
||||
[css-animations/test_element-get-animation-players.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[css-transitions/test_animation-effect-name.html]
|
||||
[css-transitions/test_animation-pausing.html]
|
||||
[css-transitions/test_animation-target.html]
|
||||
[css-transitions/test_element-get-animation-players.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[css-integration/test_animations-dynamic-changes.html]
|
||||
[css-integration/test_animation-effect-name.html]
|
||||
[css-integration/test_animation-pausing.html]
|
||||
[css-integration/test_animation-player-playstate.html]
|
||||
[css-integration/test_animation-target.html]
|
||||
|
|
|
@ -3012,26 +3012,26 @@ class CGConstructorEnabled(CGAbstractMethod):
|
|||
if not iface.isExposedInWindow():
|
||||
exposedInWindowCheck = dedent(
|
||||
"""
|
||||
if (NS_IsMainThread()) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(!NS_IsMainThread(), "Why did we even get called?");
|
||||
""")
|
||||
body.append(CGGeneric(exposedInWindowCheck))
|
||||
|
||||
if iface.isExposedInAnyWorker() and iface.isExposedOnlyInSomeWorkers():
|
||||
if iface.isExposedInSomeButNotAllWorkers():
|
||||
workerGlobals = sorted(iface.getWorkerExposureSet())
|
||||
workerCondition = CGList((CGGeneric('strcmp(name, "%s")' % workerGlobal)
|
||||
for workerGlobal in workerGlobals), " && ")
|
||||
exposedInWorkerCheck = fill(
|
||||
"""
|
||||
if (!NS_IsMainThread()) {
|
||||
const char* name = js::GetObjectClass(aObj)->name;
|
||||
if (${workerCondition}) {
|
||||
return false;
|
||||
}
|
||||
const char* name = js::GetObjectClass(aObj)->name;
|
||||
if (${workerCondition}) {
|
||||
return false;
|
||||
}
|
||||
""", workerCondition=workerCondition.define())
|
||||
body.append(CGGeneric(exposedInWorkerCheck))
|
||||
exposedInWorkerCheck = CGGeneric(exposedInWorkerCheck)
|
||||
if iface.isExposedInWindow():
|
||||
exposedInWorkerCheck = CGIfWrapper(exposedInWorkerCheck,
|
||||
"!NS_IsMainThread()")
|
||||
body.append(exposedInWorkerCheck)
|
||||
|
||||
pref = iface.getExtendedAttribute("Pref")
|
||||
if pref:
|
||||
|
@ -11958,6 +11958,7 @@ class CGRegisterProtos(CGAbstractMethod):
|
|||
for desc in self.config.getDescriptors(hasInterfaceObject=True,
|
||||
isExternal=False,
|
||||
workers=False,
|
||||
isExposedInWindow=True,
|
||||
register=True):
|
||||
lines.append("REGISTER_PROTO(%s, %s);\n" % (desc.name, getCheck(desc)))
|
||||
lines.extend("REGISTER_CONSTRUCTOR(%s, %s, %s);\n" % (n.identifier.name, desc.name, getCheck(desc))
|
||||
|
@ -12226,10 +12227,6 @@ class CGBindingRoot(CGThing):
|
|||
workers=True)) != 0
|
||||
bindingHeaders["WorkerPrivate.h"] = hasWorkerStuff
|
||||
|
||||
def descriptorHasThreadChecks(desc):
|
||||
return ((not desc.workers and not desc.interface.isExposedInWindow()) or
|
||||
(desc.interface.isExposedInAnyWorker() and desc.interface.isExposedOnlyInSomeWorkers()))
|
||||
|
||||
hasThreadChecks = hasWorkerStuff or any(d.hasThreadChecks() for d in descriptors)
|
||||
bindingHeaders["nsThreadUtils.h"] = hasThreadChecks
|
||||
|
||||
|
@ -14400,6 +14397,7 @@ class GlobalGenRoots():
|
|||
defineIncludes = [CGHeaders.getDeclarationFilename(desc.interface)
|
||||
for desc in config.getDescriptors(hasInterfaceObject=True,
|
||||
workers=False,
|
||||
isExposedInWindow=True,
|
||||
register=True)]
|
||||
defineIncludes.append('nsScriptNameSpaceManager.h')
|
||||
defineIncludes.extend([CGHeaders.getDeclarationFilename(desc.interface)
|
||||
|
|
|
@ -210,6 +210,9 @@ class Configuration:
|
|||
elif key == 'isExposedInSystemGlobals':
|
||||
getter = lambda x: (not x.interface.isExternal() and
|
||||
x.interface.isExposedInSystemGlobals())
|
||||
elif key == 'isExposedInWindow':
|
||||
getter = lambda x: (not x.interface.isExternal() and
|
||||
x.interface.isExposedInWindow())
|
||||
else:
|
||||
# Have to watch out: just closing over "key" is not enough,
|
||||
# since we're about to mutate its value
|
||||
|
@ -654,12 +657,13 @@ class Descriptor(DescriptorProvider):
|
|||
in self.interface.members))
|
||||
|
||||
def hasThreadChecks(self):
|
||||
return ((not self.workers and not self.interface.isExposedInWindow()) or
|
||||
(self.interface.isExposedInAnyWorker() and
|
||||
self.interface.isExposedOnlyInSomeWorkers()))
|
||||
return ((self.isExposedConditionally() and
|
||||
not self.interface.isExposedInWindow()) or
|
||||
self.interface.isExposedInSomeButNotAllWorkers())
|
||||
|
||||
def isExposedConditionally(self):
|
||||
return self.interface.isExposedConditionally() or self.hasThreadChecks()
|
||||
return (self.interface.isExposedConditionally() or
|
||||
self.interface.isExposedInSomeButNotAllWorkers())
|
||||
|
||||
def needsXrayResolveHooks(self):
|
||||
"""
|
||||
|
|
|
@ -1072,8 +1072,15 @@ class IDLInterface(IDLObjectWithScope):
|
|||
def isExposedInSystemGlobals(self):
|
||||
return 'BackstagePass' in self.exposureSet
|
||||
|
||||
def isExposedOnlyInSomeWorkers(self):
|
||||
assert self.isExposedInAnyWorker()
|
||||
def isExposedInSomeButNotAllWorkers(self):
|
||||
"""
|
||||
Returns true if the Exposed extended attribute for this interface
|
||||
exposes it in some worker globals but not others. The return value does
|
||||
not depend on whether the interface is exposed in Window or System
|
||||
globals.
|
||||
"""
|
||||
if not self.isExposedInAnyWorker():
|
||||
return False
|
||||
workerScopes = self.parentScope.globalNameMapping["Worker"]
|
||||
return len(workerScopes.difference(self.exposureSet)) > 0
|
||||
|
||||
|
@ -5695,6 +5702,7 @@ class Parser(Tokenizer):
|
|||
# Builtin IDL defined by WebIDL
|
||||
_builtins = """
|
||||
typedef unsigned long long DOMTimeStamp;
|
||||
typedef (ArrayBufferView or ArrayBuffer) BufferSource;
|
||||
"""
|
||||
|
||||
def main():
|
||||
|
|
|
@ -14,20 +14,16 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
/** Represents a GL name that can be bound to a target.
|
||||
/** Represents a binding to a GL binding point
|
||||
*/
|
||||
template<typename T>
|
||||
class WebGLBindableName
|
||||
class WebGLBindable
|
||||
{
|
||||
public:
|
||||
WebGLBindable() : mTarget(LOCAL_GL_NONE) { }
|
||||
bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; }
|
||||
|
||||
WebGLBindableName()
|
||||
: mGLName(0)
|
||||
, mTarget(LOCAL_GL_NONE)
|
||||
{ }
|
||||
|
||||
void BindTo(T target)
|
||||
{
|
||||
void BindTo(T target) {
|
||||
MOZ_ASSERT(target != LOCAL_GL_NONE, "Can't bind to GL_NONE.");
|
||||
MOZ_ASSERT(!HasEverBeenBound() || mTarget == target, "Rebinding is illegal.");
|
||||
|
||||
|
@ -37,22 +33,38 @@ public:
|
|||
OnTargetChanged();
|
||||
}
|
||||
|
||||
bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; }
|
||||
GLuint GLName() const { return mGLName; }
|
||||
T Target() const {
|
||||
MOZ_ASSERT(HasEverBeenBound());
|
||||
return mTarget;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
//! Called after mTarget has been changed by BindTo(target).
|
||||
virtual void OnTargetChanged() {}
|
||||
|
||||
GLuint mGLName;
|
||||
T mTarget;
|
||||
};
|
||||
|
||||
|
||||
/** Represents a GL name that can be bound to a target.
|
||||
*/
|
||||
template<typename T>
|
||||
class WebGLBindableName
|
||||
: public WebGLBindable<T>
|
||||
{
|
||||
public:
|
||||
|
||||
WebGLBindableName(GLuint name)
|
||||
: WebGLBindable<T>()
|
||||
, mGLName(name)
|
||||
{ }
|
||||
GLuint GLName() const { return mGLName; }
|
||||
|
||||
protected:
|
||||
const GLuint mGLName;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // !WEBGLBINDABLENAME_H_
|
||||
|
|
|
@ -12,13 +12,11 @@
|
|||
|
||||
using namespace mozilla;
|
||||
|
||||
WebGLBuffer::WebGLBuffer(WebGLContext *context)
|
||||
: WebGLBindableName<BufferBinding>()
|
||||
WebGLBuffer::WebGLBuffer(WebGLContext* context, GLuint buf)
|
||||
: WebGLBindableName<BufferBinding>(buf)
|
||||
, WebGLContextBoundObject(context)
|
||||
, mByteLength(0)
|
||||
{
|
||||
mContext->MakeContextCurrent();
|
||||
mContext->gl->fGenBuffers(1, &mGLName);
|
||||
mContext->mBuffers.insertBack(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ class WebGLBuffer MOZ_FINAL
|
|||
, public WebGLContextBoundObject
|
||||
{
|
||||
public:
|
||||
explicit WebGLBuffer(WebGLContext* aContext);
|
||||
explicit WebGLBuffer(WebGLContext* context, GLuint buf);
|
||||
|
||||
void Delete();
|
||||
|
||||
|
|
|
@ -361,7 +361,11 @@ WebGLContext::CreateBuffer()
|
|||
if (IsContextLost())
|
||||
return nullptr;
|
||||
|
||||
nsRefPtr<WebGLBuffer> globj = new WebGLBuffer(this);
|
||||
GLuint buf = 0;
|
||||
MakeContextCurrent();
|
||||
gl->fGenBuffers(1, &buf);
|
||||
|
||||
nsRefPtr<WebGLBuffer> globj = new WebGLBuffer(this, buf);
|
||||
return globj.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -1372,7 +1372,12 @@ WebGLContext::CreateTexture()
|
|||
{
|
||||
if (IsContextLost())
|
||||
return nullptr;
|
||||
nsRefPtr<WebGLTexture> globj = new WebGLTexture(this);
|
||||
|
||||
GLuint tex = 0;
|
||||
MakeContextCurrent();
|
||||
gl->fGenTextures(1, &tex);
|
||||
|
||||
nsRefPtr<WebGLTexture> globj = new WebGLTexture(this, tex);
|
||||
return globj.forget();
|
||||
}
|
||||
|
||||
|
@ -3098,7 +3103,12 @@ WebGLContext::CreateFramebuffer()
|
|||
{
|
||||
if (IsContextLost())
|
||||
return nullptr;
|
||||
nsRefPtr<WebGLFramebuffer> globj = new WebGLFramebuffer(this);
|
||||
|
||||
GLuint fbo = 0;
|
||||
MakeContextCurrent();
|
||||
gl->fGenFramebuffers(1, &fbo);
|
||||
|
||||
nsRefPtr<WebGLFramebuffer> globj = new WebGLFramebuffer(this, fbo);
|
||||
return globj.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -26,16 +26,14 @@ WebGLFramebuffer::WrapObject(JSContext* cx)
|
|||
return dom::WebGLFramebufferBinding::Wrap(cx, this);
|
||||
}
|
||||
|
||||
WebGLFramebuffer::WebGLFramebuffer(WebGLContext* context)
|
||||
: WebGLBindableName<FBTarget>()
|
||||
WebGLFramebuffer::WebGLFramebuffer(WebGLContext* context, GLuint fbo)
|
||||
: WebGLBindableName<FBTarget>(fbo)
|
||||
, WebGLContextBoundObject(context)
|
||||
, mStatus(0)
|
||||
, mDepthAttachment(LOCAL_GL_DEPTH_ATTACHMENT)
|
||||
, mStencilAttachment(LOCAL_GL_STENCIL_ATTACHMENT)
|
||||
, mDepthStencilAttachment(LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
|
||||
{
|
||||
mContext->MakeContextCurrent();
|
||||
mContext->gl->fGenFramebuffers(1, &mGLName);
|
||||
mContext->mFramebuffers.insertBack(this);
|
||||
|
||||
mColorAttachments.SetLength(1);
|
||||
|
|
|
@ -34,7 +34,7 @@ class WebGLFramebuffer MOZ_FINAL
|
|||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_TYPENAME(WebGLFramebuffer)
|
||||
|
||||
explicit WebGLFramebuffer(WebGLContext* context);
|
||||
explicit WebGLFramebuffer(WebGLContext* context, GLuint fbo);
|
||||
|
||||
struct Attachment
|
||||
{
|
||||
|
|
|
@ -42,8 +42,8 @@ WebGLRenderbuffer::WrapObject(JSContext *cx) {
|
|||
return dom::WebGLRenderbufferBinding::Wrap(cx, this);
|
||||
}
|
||||
|
||||
WebGLRenderbuffer::WebGLRenderbuffer(WebGLContext *context)
|
||||
: WebGLBindableName<RBTarget>()
|
||||
WebGLRenderbuffer::WebGLRenderbuffer(WebGLContext* context)
|
||||
: WebGLBindable<RBTarget>()
|
||||
, WebGLContextBoundObject(context)
|
||||
, mPrimaryRB(0)
|
||||
, mSecondaryRB(0)
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace mozilla {
|
|||
|
||||
class WebGLRenderbuffer MOZ_FINAL
|
||||
: public nsWrapperCache
|
||||
, public WebGLBindableName<RBTarget>
|
||||
, public WebGLBindable<RBTarget>
|
||||
, public WebGLRefCountedObject<WebGLRenderbuffer>
|
||||
, public LinkedListElement<WebGLRenderbuffer>
|
||||
, public WebGLRectangleObject
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
using namespace mozilla;
|
||||
|
||||
WebGLSampler::WebGLSampler(WebGLContext* context)
|
||||
: WebGLContextBoundObject(context)
|
||||
: WebGLBindableName<GLenum>(0),
|
||||
WebGLContextBoundObject(context)
|
||||
{
|
||||
MOZ_CRASH("Not Implemented.");
|
||||
}
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
namespace mozilla {
|
||||
|
||||
class WebGLSampler MOZ_FINAL
|
||||
: public WebGLBindableName<GLenum>
|
||||
, public nsWrapperCache
|
||||
: public nsWrapperCache
|
||||
, public WebGLBindableName<GLenum>
|
||||
, public WebGLRefCountedObject<WebGLSampler>
|
||||
, public LinkedListElement<WebGLSampler>
|
||||
, public WebGLContextBoundObject
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
using namespace mozilla;
|
||||
|
||||
JSObject*
|
||||
WebGLTexture::WrapObject(JSContext *cx) {
|
||||
WebGLTexture::WrapObject(JSContext* cx) {
|
||||
return dom::WebGLTextureBinding::Wrap(cx, this);
|
||||
}
|
||||
|
||||
WebGLTexture::WebGLTexture(WebGLContext *context)
|
||||
: WebGLBindableName<TexTarget>()
|
||||
WebGLTexture::WebGLTexture(WebGLContext* context, GLuint tex)
|
||||
: WebGLBindableName<TexTarget>(tex)
|
||||
, WebGLContextBoundObject(context)
|
||||
, mMinFilter(LOCAL_GL_NEAREST_MIPMAP_LINEAR)
|
||||
, mMagFilter(LOCAL_GL_LINEAR)
|
||||
|
@ -38,8 +38,6 @@ WebGLTexture::WebGLTexture(WebGLContext *context)
|
|||
, mMaxMipmapLevel(1000)
|
||||
, mFakeBlackStatus(WebGLTextureFakeBlackStatus::IncompleteTexture)
|
||||
{
|
||||
mContext->MakeContextCurrent();
|
||||
mContext->gl->fGenTextures(1, &mGLName);
|
||||
mContext->mTextures.insertBack(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ class WebGLTexture MOZ_FINAL
|
|||
, public WebGLFramebufferAttachable
|
||||
{
|
||||
public:
|
||||
explicit WebGLTexture(WebGLContext* aContext);
|
||||
explicit WebGLTexture(WebGLContext* aContext, GLuint tex);
|
||||
|
||||
void Delete();
|
||||
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
using namespace mozilla;
|
||||
|
||||
WebGLTransformFeedback::WebGLTransformFeedback(WebGLContext* context)
|
||||
: WebGLContextBoundObject(context)
|
||||
: WebGLBindableName<GLenum>(0)
|
||||
, WebGLContextBoundObject(context)
|
||||
{
|
||||
MOZ_CRASH("Not Implemented.");
|
||||
}
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
namespace mozilla {
|
||||
|
||||
class WebGLTransformFeedback MOZ_FINAL
|
||||
: public WebGLBindableName<GLenum>
|
||||
, public nsWrapperCache
|
||||
: public nsWrapperCache
|
||||
, public WebGLBindableName<GLenum>
|
||||
, public WebGLRefCountedObject<WebGLTransformFeedback>
|
||||
, public LinkedListElement<WebGLTransformFeedback>
|
||||
, public WebGLContextBoundObject
|
||||
|
|
|
@ -20,8 +20,9 @@ WebGLVertexArray::WrapObject(JSContext *cx) {
|
|||
}
|
||||
|
||||
WebGLVertexArray::WebGLVertexArray(WebGLContext* context)
|
||||
: WebGLBindableName<VAOBinding>()
|
||||
: WebGLBindable<VAOBinding>()
|
||||
, WebGLContextBoundObject(context)
|
||||
, mGLName(0)
|
||||
{
|
||||
context->mVertexArrays.insertBack(this);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ class WebGLVertexArrayFake;
|
|||
|
||||
class WebGLVertexArray
|
||||
: public nsWrapperCache
|
||||
, public WebGLBindableName<VAOBinding>
|
||||
, public WebGLBindable<VAOBinding>
|
||||
, public WebGLRefCountedObject<WebGLVertexArray>
|
||||
, public LinkedListElement<WebGLVertexArray>
|
||||
, public WebGLContextBoundObject
|
||||
|
@ -61,6 +61,8 @@ public:
|
|||
// -------------------------------------------------------------------------
|
||||
// MEMBER FUNCTIONS
|
||||
|
||||
GLuint GLName() const { return mGLName; }
|
||||
|
||||
void EnsureAttrib(GLuint index);
|
||||
bool HasAttrib(GLuint index) {
|
||||
return index < mAttribs.Length();
|
||||
|
@ -82,6 +84,7 @@ protected:
|
|||
// -------------------------------------------------------------------------
|
||||
// MEMBERS
|
||||
|
||||
GLuint mGLName;
|
||||
nsTArray<WebGLVertexAttribData> mAttribs;
|
||||
WebGLRefPtr<WebGLBuffer> mElementArrayBuffer;
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=885996
|
|||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style> body { font-family: serif } </style>
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
/** Test the behaviour of the <input type='color'> when clicking on it from
|
||||
|
|
|
@ -9,6 +9,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=885996
|
|||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style> body { font-family: serif } </style>
|
||||
<script type="application/javascript;version=1.8">
|
||||
|
||||
/** Test that update() modifies the element value such as done() when it is
|
||||
|
|
|
@ -1024,6 +1024,7 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
|||
}
|
||||
nsRefPtr<TabParent> tp(new TabParent(constructorSender, tabId,
|
||||
aContext, chromeFlags));
|
||||
tp->SetInitedByParent();
|
||||
tp->SetOwnerElement(aFrameElement);
|
||||
|
||||
PBrowserParent* browser = constructorSender->SendPBrowserConstructor(
|
||||
|
@ -1135,6 +1136,7 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
|||
uint32_t chromeFlags = 0;
|
||||
|
||||
nsRefPtr<TabParent> tp = new TabParent(parent, tabId, aContext, chromeFlags);
|
||||
tp->SetInitedByParent();
|
||||
tp->SetOwnerElement(aFrameElement);
|
||||
PBrowserParent* browser = parent->SendPBrowserConstructor(
|
||||
// DeallocPBrowserParent() releases this ref.
|
||||
|
@ -1934,6 +1936,13 @@ ContentParent::ContentParent(mozIApplication* aApp,
|
|||
// PID along with the warning.
|
||||
nsDebugImpl::SetMultiprocessMode("Parent");
|
||||
|
||||
#if defined(XP_WIN) && !defined(MOZ_B2G)
|
||||
// Request Windows message deferral behavior on our side of the PContent
|
||||
// channel. Generally only applies to the situation where we get caught in
|
||||
// a deadlock with the plugin process when sending CPOWs.
|
||||
GetIPCChannel()->SetChannelFlags(MessageChannel::REQUIRE_DEFERRED_MESSAGE_PROTECTION);
|
||||
#endif
|
||||
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
ChildPrivileges privs = aIsNuwaProcess
|
||||
? base::PRIVILEGES_INHERIT
|
||||
|
|
|
@ -85,6 +85,12 @@ both:
|
|||
AsyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows,
|
||||
Principal aPrincipal);
|
||||
|
||||
/**
|
||||
* Create a layout frame (encapsulating a remote layer tree) for
|
||||
* the page that is currently loaded in the <browser>.
|
||||
*/
|
||||
PRenderFrame();
|
||||
|
||||
parent:
|
||||
/*
|
||||
* Creates a new remoted nsIWidget connection for windowed plugins
|
||||
|
@ -317,16 +323,6 @@ parent:
|
|||
*/
|
||||
PIndexedDBPermissionRequest(Principal principal);
|
||||
|
||||
/**
|
||||
* Create a layout frame (encapsulating a remote layer tree) for
|
||||
* the page that is currently loaded in the <browser>.
|
||||
*/
|
||||
sync PRenderFrame()
|
||||
returns (ScrollingBehavior scrolling,
|
||||
TextureFactoryIdentifier textureFactoryIdentifier, uint64_t layersId,
|
||||
bool success);
|
||||
|
||||
|
||||
/**
|
||||
* window.open from inside <iframe mozbrowser> is special. When the child
|
||||
* process calls window.open, it creates a new PBrowser (in its own
|
||||
|
@ -392,6 +388,11 @@ parent:
|
|||
*/
|
||||
async RemotePaintIsReady();
|
||||
|
||||
sync GetRenderFrameInfo(PRenderFrame aRenderFrame)
|
||||
returns (ScrollingBehavior scrolling,
|
||||
TextureFactoryIdentifier textureFactoryIdentifier,
|
||||
uint64_t layersId);
|
||||
|
||||
child:
|
||||
/**
|
||||
* Notify the remote browser that it has been Show()n on this
|
||||
|
@ -402,7 +403,11 @@ child:
|
|||
* content processes always render to a virtual <0, 0> top-left
|
||||
* point.
|
||||
*/
|
||||
Show(nsIntSize size);
|
||||
Show(nsIntSize size,
|
||||
ScrollingBehavior scrolling,
|
||||
TextureFactoryIdentifier textureFactoryIdentifier,
|
||||
uint64_t layersId,
|
||||
nullable PRenderFrame renderFrame);
|
||||
|
||||
LoadURL(nsCString uri);
|
||||
|
||||
|
|
|
@ -1511,9 +1511,22 @@ TabChild::BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
|
|||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
ScrollingBehavior scrolling = DEFAULT_SCROLLING;
|
||||
TextureFactoryIdentifier textureFactoryIdentifier;
|
||||
uint64_t layersId = 0;
|
||||
PRenderFrameChild* renderFrame = newChild->SendPRenderFrameConstructor();
|
||||
newChild->SendGetRenderFrameInfo(renderFrame,
|
||||
&scrolling,
|
||||
&textureFactoryIdentifier,
|
||||
&layersId);
|
||||
if (layersId == 0) { // if renderFrame is invalid.
|
||||
PRenderFrameChild::Send__delete__(renderFrame);
|
||||
renderFrame = nullptr;
|
||||
}
|
||||
|
||||
// Unfortunately we don't get a window unless we've shown the frame. That's
|
||||
// pretty bogus; see bug 763602.
|
||||
newChild->DoFakeShow();
|
||||
newChild->DoFakeShow(scrolling, textureFactoryIdentifier, layersId, renderFrame);
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> win = do_GetInterface(newChild->WebNavigation());
|
||||
win.forget(aReturn);
|
||||
|
@ -1828,9 +1841,12 @@ TabChild::CancelCachedFileDescriptorCallback(
|
|||
}
|
||||
|
||||
void
|
||||
TabChild::DoFakeShow()
|
||||
TabChild::DoFakeShow(const ScrollingBehavior& aScrolling,
|
||||
const TextureFactoryIdentifier& aTextureFactoryIdentifier,
|
||||
const uint64_t& aLayersId,
|
||||
PRenderFrameChild* aRenderFrame)
|
||||
{
|
||||
RecvShow(nsIntSize(0, 0));
|
||||
RecvShow(nsIntSize(0, 0), aScrolling, aTextureFactoryIdentifier, aLayersId, aRenderFrame);
|
||||
mDidFakeShow = true;
|
||||
}
|
||||
|
||||
|
@ -1893,8 +1909,13 @@ TabChild::MaybeRequestPreinitCamera()
|
|||
#endif
|
||||
|
||||
bool
|
||||
TabChild::RecvShow(const nsIntSize& size)
|
||||
TabChild::RecvShow(const nsIntSize& aSize,
|
||||
const ScrollingBehavior& aScrolling,
|
||||
const TextureFactoryIdentifier& aTextureFactoryIdentifier,
|
||||
const uint64_t& aLayersId,
|
||||
PRenderFrameChild* aRenderFrame)
|
||||
{
|
||||
MOZ_ASSERT((!mDidFakeShow && aRenderFrame) || (mDidFakeShow && !aRenderFrame));
|
||||
|
||||
if (mDidFakeShow) {
|
||||
return true;
|
||||
|
@ -1906,7 +1927,7 @@ TabChild::RecvShow(const nsIntSize& size)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!InitRenderingState()) {
|
||||
if (!InitRenderingState(aScrolling, aTextureFactoryIdentifier, aLayersId, aRenderFrame)) {
|
||||
// We can fail to initialize our widget if the <browser
|
||||
// remote> has already been destroyed, and we couldn't hook
|
||||
// into the parent-process's layer system. That's not a fatal
|
||||
|
@ -2748,10 +2769,7 @@ TabChild::RecvSetIsDocShellActive(const bool& aIsActive)
|
|||
}
|
||||
|
||||
PRenderFrameChild*
|
||||
TabChild::AllocPRenderFrameChild(ScrollingBehavior* aScrolling,
|
||||
TextureFactoryIdentifier* aTextureFactoryIdentifier,
|
||||
uint64_t* aLayersId,
|
||||
bool* aSuccess)
|
||||
TabChild::AllocPRenderFrameChild()
|
||||
{
|
||||
return new RenderFrameChild();
|
||||
}
|
||||
|
@ -2804,43 +2822,40 @@ TabChild::InitTabChildGlobal(FrameScriptLoading aScriptLoading)
|
|||
}
|
||||
|
||||
bool
|
||||
TabChild::InitRenderingState()
|
||||
TabChild::InitRenderingState(const ScrollingBehavior& aScrolling,
|
||||
const TextureFactoryIdentifier& aTextureFactoryIdentifier,
|
||||
const uint64_t& aLayersId,
|
||||
PRenderFrameChild* aRenderFrame)
|
||||
{
|
||||
static_cast<PuppetWidget*>(mWidget.get())->InitIMEState();
|
||||
|
||||
uint64_t id;
|
||||
bool success;
|
||||
RenderFrameChild* remoteFrame =
|
||||
static_cast<RenderFrameChild*>(SendPRenderFrameConstructor(
|
||||
&mScrolling,
|
||||
&mTextureFactoryIdentifier, &id,
|
||||
&success));
|
||||
RenderFrameChild* remoteFrame = static_cast<RenderFrameChild*>(aRenderFrame);
|
||||
if (!remoteFrame) {
|
||||
NS_WARNING("failed to construct RenderFrame");
|
||||
return false;
|
||||
}
|
||||
if (!success) {
|
||||
NS_WARNING("failed to construct RenderFrame");
|
||||
PRenderFrameChild::Send__delete__(remoteFrame);
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(id != 0);
|
||||
MOZ_ASSERT(aLayersId != 0);
|
||||
mScrolling = aScrolling;
|
||||
mTextureFactoryIdentifier = aTextureFactoryIdentifier;
|
||||
|
||||
// Pushing layers transactions directly to a separate
|
||||
// compositor context.
|
||||
PCompositorChild* compositorChild = CompositorChild::Get();
|
||||
if (!compositorChild) {
|
||||
NS_WARNING("failed to get CompositorChild instance");
|
||||
PRenderFrameChild::Send__delete__(remoteFrame);
|
||||
return false;
|
||||
}
|
||||
nsTArray<LayersBackend> backends;
|
||||
backends.AppendElement(mTextureFactoryIdentifier.mParentBackend);
|
||||
bool success;
|
||||
PLayerTransactionChild* shadowManager =
|
||||
compositorChild->SendPLayerTransactionConstructor(backends,
|
||||
id, &mTextureFactoryIdentifier, &success);
|
||||
aLayersId, &mTextureFactoryIdentifier, &success);
|
||||
if (!success) {
|
||||
NS_WARNING("failed to properly allocate layer transaction");
|
||||
PRenderFrameChild::Send__delete__(remoteFrame);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2860,13 +2875,13 @@ TabChild::InitRenderingState()
|
|||
ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier);
|
||||
|
||||
mRemoteFrame = remoteFrame;
|
||||
if (id != 0) {
|
||||
if (aLayersId != 0) {
|
||||
if (!sTabChildren) {
|
||||
sTabChildren = new TabChildMap;
|
||||
}
|
||||
MOZ_ASSERT(!sTabChildren->Get(id));
|
||||
sTabChildren->Put(id, this);
|
||||
mLayersId = id;
|
||||
MOZ_ASSERT(!sTabChildren->Get(aLayersId));
|
||||
sTabChildren->Put(aLayersId, this);
|
||||
mLayersId = aLayersId;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
|
|
|
@ -316,7 +316,11 @@ public:
|
|||
virtual bool RecvCacheFileDescriptor(const nsString& aPath,
|
||||
const FileDescriptor& aFileDescriptor)
|
||||
MOZ_OVERRIDE;
|
||||
virtual bool RecvShow(const nsIntSize& size) MOZ_OVERRIDE;
|
||||
virtual bool RecvShow(const nsIntSize& aSize,
|
||||
const ScrollingBehavior& aScrolling,
|
||||
const TextureFactoryIdentifier& aTextureFactoryIdentifier,
|
||||
const uint64_t& aLayersId,
|
||||
PRenderFrameChild* aRenderFrame) MOZ_OVERRIDE;
|
||||
virtual bool RecvUpdateDimensions(const nsIntRect& rect,
|
||||
const nsIntSize& size,
|
||||
const ScreenOrientation& orientation) MOZ_OVERRIDE;
|
||||
|
@ -491,10 +495,7 @@ public:
|
|||
protected:
|
||||
virtual ~TabChild();
|
||||
|
||||
virtual PRenderFrameChild* AllocPRenderFrameChild(ScrollingBehavior* aScrolling,
|
||||
TextureFactoryIdentifier* aTextureFactoryIdentifier,
|
||||
uint64_t* aLayersId,
|
||||
bool* aSuccess) MOZ_OVERRIDE;
|
||||
virtual PRenderFrameChild* AllocPRenderFrameChild() MOZ_OVERRIDE;
|
||||
virtual bool DeallocPRenderFrameChild(PRenderFrameChild* aFrame) MOZ_OVERRIDE;
|
||||
virtual bool RecvDestroy() MOZ_OVERRIDE;
|
||||
virtual bool RecvSetUpdateHitRegion(const bool& aEnabled) MOZ_OVERRIDE;
|
||||
|
@ -536,12 +537,18 @@ private:
|
|||
|
||||
enum FrameScriptLoading { DONT_LOAD_SCRIPTS, DEFAULT_LOAD_SCRIPTS };
|
||||
bool InitTabChildGlobal(FrameScriptLoading aScriptLoading = DEFAULT_LOAD_SCRIPTS);
|
||||
bool InitRenderingState();
|
||||
bool InitRenderingState(const ScrollingBehavior& aScrolling,
|
||||
const TextureFactoryIdentifier& aTextureFactoryIdentifier,
|
||||
const uint64_t& aLayersId,
|
||||
PRenderFrameChild* aRenderFrame);
|
||||
void DestroyWindow();
|
||||
void SetProcessNameToAppName();
|
||||
|
||||
// Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow().
|
||||
void DoFakeShow();
|
||||
void DoFakeShow(const ScrollingBehavior& aScrolling,
|
||||
const TextureFactoryIdentifier& aTextureFactoryIdentifier,
|
||||
const uint64_t& aLayersId,
|
||||
PRenderFrameChild* aRenderFrame);
|
||||
|
||||
// These methods are used for tracking synthetic mouse events
|
||||
// dispatched for compatibility. On each touch event, we
|
||||
|
|
|
@ -248,6 +248,7 @@ TabParent::TabParent(nsIContentParent* aManager,
|
|||
, mAppPackageFileDescriptorSent(false)
|
||||
, mSendOfflineStatus(true)
|
||||
, mChromeFlags(aChromeFlags)
|
||||
, mInitedByParent(false)
|
||||
, mTabId(aTabId)
|
||||
{
|
||||
MOZ_ASSERT(aManager);
|
||||
|
@ -573,9 +574,33 @@ TabParent::Show(const nsIntSize& size)
|
|||
// sigh
|
||||
mShown = true;
|
||||
mDimensions = size;
|
||||
if (!mIsDestroyed) {
|
||||
unused << SendShow(size);
|
||||
if (mIsDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
ScrollingBehavior scrolling = UseAsyncPanZoom() ? ASYNC_PAN_ZOOM : DEFAULT_SCROLLING;
|
||||
TextureFactoryIdentifier textureFactoryIdentifier;
|
||||
uint64_t layersId = 0;
|
||||
bool success = false;
|
||||
RenderFrameParent* renderFrame = nullptr;
|
||||
// If TabParent is initialized by parent side then the RenderFrame must also
|
||||
// be created here. If TabParent is initialized by child side,
|
||||
// child side will create RenderFrame.
|
||||
MOZ_ASSERT(!GetRenderFrame());
|
||||
if (IsInitedByParent()) {
|
||||
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
|
||||
if (frameLoader) {
|
||||
renderFrame =
|
||||
new RenderFrameParent(frameLoader,
|
||||
scrolling,
|
||||
&textureFactoryIdentifier,
|
||||
&layersId,
|
||||
&success);
|
||||
MOZ_ASSERT(success);
|
||||
unused << SendPRenderFrameConstructor(renderFrame);
|
||||
}
|
||||
}
|
||||
unused << SendShow(size, scrolling, textureFactoryIdentifier, layersId, renderFrame);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1911,18 +1936,26 @@ TabParent::DeallocPColorPickerParent(PColorPickerParent* actor)
|
|||
}
|
||||
|
||||
PRenderFrameParent*
|
||||
TabParent::AllocPRenderFrameParent(ScrollingBehavior* aScrolling,
|
||||
TextureFactoryIdentifier* aTextureFactoryIdentifier,
|
||||
uint64_t* aLayersId, bool* aSuccess)
|
||||
TabParent::AllocPRenderFrameParent()
|
||||
{
|
||||
MOZ_ASSERT(ManagedPRenderFrameParent().IsEmpty());
|
||||
|
||||
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
|
||||
*aScrolling = UseAsyncPanZoom() ? ASYNC_PAN_ZOOM : DEFAULT_SCROLLING;
|
||||
return new RenderFrameParent(frameLoader,
|
||||
*aScrolling,
|
||||
aTextureFactoryIdentifier, aLayersId,
|
||||
aSuccess);
|
||||
ScrollingBehavior scrolling = UseAsyncPanZoom() ? ASYNC_PAN_ZOOM : DEFAULT_SCROLLING;
|
||||
TextureFactoryIdentifier textureFactoryIdentifier;
|
||||
uint64_t layersId = 0;
|
||||
bool success = false;
|
||||
if(frameLoader) {
|
||||
PRenderFrameParent* renderFrame =
|
||||
new RenderFrameParent(frameLoader,
|
||||
scrolling,
|
||||
&textureFactoryIdentifier,
|
||||
&layersId,
|
||||
&success);
|
||||
MOZ_ASSERT(success);
|
||||
return renderFrame;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1932,6 +1965,19 @@ TabParent::DeallocPRenderFrameParent(PRenderFrameParent* aFrame)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvGetRenderFrameInfo(PRenderFrameParent* aRenderFrame,
|
||||
ScrollingBehavior* aScrolling,
|
||||
TextureFactoryIdentifier* aTextureFactoryIdentifier,
|
||||
uint64_t* aLayersId)
|
||||
{
|
||||
RenderFrameParent* renderFrame = static_cast<RenderFrameParent*>(aRenderFrame);
|
||||
*aScrolling = renderFrame->UseAsyncPanZoom() ? ASYNC_PAN_ZOOM : DEFAULT_SCROLLING;
|
||||
renderFrame->GetTextureFactoryIdentifier(aTextureFactoryIdentifier);
|
||||
*aLayersId = renderFrame->GetLayersId();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::AllowContentIME()
|
||||
{
|
||||
|
@ -2021,16 +2067,6 @@ TabParent::RecvBrowserFrameOpenWindow(PBrowserParent* aOpener,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvPRenderFrameConstructor(PRenderFrameParent* aActor,
|
||||
ScrollingBehavior* aScrolling,
|
||||
TextureFactoryIdentifier* aFactoryIdentifier,
|
||||
uint64_t* aLayersId,
|
||||
bool* aSuccess)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvZoomToRect(const uint32_t& aPresShellId,
|
||||
const ViewID& aViewId,
|
||||
|
|
|
@ -128,11 +128,6 @@ public:
|
|||
virtual bool RecvEvent(const RemoteDOMEvent& aEvent) MOZ_OVERRIDE;
|
||||
virtual bool RecvReplyKeyEvent(const WidgetKeyboardEvent& event);
|
||||
virtual bool RecvDispatchAfterKeyboardEvent(const WidgetKeyboardEvent& event);
|
||||
virtual bool RecvPRenderFrameConstructor(PRenderFrameParent* aActor,
|
||||
ScrollingBehavior* aScrolling,
|
||||
TextureFactoryIdentifier* aFactoryIdentifier,
|
||||
uint64_t* aLayersId,
|
||||
bool* aSuccess) MOZ_OVERRIDE;
|
||||
virtual bool RecvBrowserFrameOpenWindow(PBrowserParent* aOpener,
|
||||
const nsString& aURL,
|
||||
const nsString& aName,
|
||||
|
@ -341,6 +336,9 @@ public:
|
|||
virtual PPluginWidgetParent* AllocPPluginWidgetParent() MOZ_OVERRIDE;
|
||||
virtual bool DeallocPPluginWidgetParent(PPluginWidgetParent* aActor) MOZ_OVERRIDE;
|
||||
|
||||
void SetInitedByParent() { mInitedByParent = true; }
|
||||
bool IsInitedByParent() const { return mInitedByParent; }
|
||||
|
||||
protected:
|
||||
bool ReceiveMessage(const nsString& aMessage,
|
||||
bool aSync,
|
||||
|
@ -362,14 +360,16 @@ protected:
|
|||
|
||||
bool AllowContentIME();
|
||||
|
||||
virtual PRenderFrameParent* AllocPRenderFrameParent(ScrollingBehavior* aScrolling,
|
||||
TextureFactoryIdentifier* aTextureFactoryIdentifier,
|
||||
uint64_t* aLayersId,
|
||||
bool* aSuccess) MOZ_OVERRIDE;
|
||||
virtual PRenderFrameParent* AllocPRenderFrameParent() MOZ_OVERRIDE;
|
||||
virtual bool DeallocPRenderFrameParent(PRenderFrameParent* aFrame) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvRemotePaintIsReady() MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvGetRenderFrameInfo(PRenderFrameParent* aRenderFrame,
|
||||
ScrollingBehavior* aScrolling,
|
||||
TextureFactoryIdentifier* aTextureFactoryIdentifier,
|
||||
uint64_t* aLayersId) MOZ_OVERRIDE;
|
||||
|
||||
bool SendCompositionChangeEvent(mozilla::WidgetCompositionEvent& event);
|
||||
|
||||
// IME
|
||||
|
@ -445,6 +445,10 @@ private:
|
|||
|
||||
uint32_t mChromeFlags;
|
||||
|
||||
// When true, the TabParent is initialized without child side's request.
|
||||
// When false, the TabParent is initialized by window.open() from child side.
|
||||
bool mInitedByParent;
|
||||
|
||||
nsCOMPtr<nsILoadContext> mLoadContext;
|
||||
|
||||
TabId mTabId;
|
||||
|
|
|
@ -92,7 +92,6 @@ FFmpegAudioDecoder<LIBAV_VER>::DecodePacket(MP4Sample* aSample)
|
|||
aSample->Pad(FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
packet.data = aSample->data;
|
||||
packet.size = aSample->size;
|
||||
packet.pos = aSample->byte_offset;
|
||||
|
||||
if (!PrepareFrame()) {
|
||||
NS_WARNING("FFmpeg audio decoder failed to allocate frame.");
|
||||
|
@ -100,31 +99,50 @@ FFmpegAudioDecoder<LIBAV_VER>::DecodePacket(MP4Sample* aSample)
|
|||
return;
|
||||
}
|
||||
|
||||
int decoded;
|
||||
int bytesConsumed =
|
||||
avcodec_decode_audio4(mCodecContext, mFrame, &decoded, &packet);
|
||||
int64_t samplePosition = aSample->byte_offset;
|
||||
Microseconds pts = aSample->composition_timestamp;
|
||||
|
||||
if (bytesConsumed < 0 || !decoded) {
|
||||
NS_WARNING("FFmpeg audio decoder error.");
|
||||
mCallback->Error();
|
||||
return;
|
||||
while (packet.size > 0) {
|
||||
int decoded;
|
||||
int bytesConsumed =
|
||||
avcodec_decode_audio4(mCodecContext, mFrame, &decoded, &packet);
|
||||
|
||||
if (bytesConsumed < 0) {
|
||||
NS_WARNING("FFmpeg audio decoder error.");
|
||||
mCallback->Error();
|
||||
return;
|
||||
}
|
||||
|
||||
if (decoded) {
|
||||
uint32_t numChannels = mCodecContext->channels;
|
||||
uint32_t samplingRate = mCodecContext->sample_rate;
|
||||
|
||||
nsAutoArrayPtr<AudioDataValue> audio(
|
||||
CopyAndPackAudio(mFrame, numChannels, mFrame->nb_samples));
|
||||
|
||||
CheckedInt<Microseconds> duration =
|
||||
FramesToUsecs(mFrame->nb_samples, samplingRate);
|
||||
if (!duration.isValid()) {
|
||||
NS_WARNING("Invalid count of accumulated audio samples");
|
||||
mCallback->Error();
|
||||
return;
|
||||
}
|
||||
|
||||
AudioData* data = new AudioData(samplePosition,
|
||||
pts,
|
||||
duration.value(),
|
||||
mFrame->nb_samples,
|
||||
audio.forget(),
|
||||
numChannels,
|
||||
samplingRate);
|
||||
mCallback->Output(data);
|
||||
pts += duration.value();
|
||||
}
|
||||
packet.data += bytesConsumed;
|
||||
packet.size -= bytesConsumed;
|
||||
samplePosition += bytesConsumed;
|
||||
}
|
||||
|
||||
NS_ASSERTION(bytesConsumed == (int)aSample->size,
|
||||
"Only one audio packet should be received at a time.");
|
||||
|
||||
uint32_t numChannels = mCodecContext->channels;
|
||||
uint32_t samplingRate = mCodecContext->sample_rate;
|
||||
|
||||
nsAutoArrayPtr<AudioDataValue> audio(
|
||||
CopyAndPackAudio(mFrame, numChannels, mFrame->nb_samples));
|
||||
|
||||
nsAutoPtr<AudioData> data(
|
||||
new AudioData(packet.pos, aSample->composition_timestamp, aSample->duration,
|
||||
mFrame->nb_samples, audio.forget(), numChannels, samplingRate));
|
||||
|
||||
mCallback->Output(data.forget());
|
||||
|
||||
if (mTaskQueue->IsEmpty()) {
|
||||
mCallback->InputExhausted();
|
||||
}
|
||||
|
@ -142,8 +160,9 @@ FFmpegAudioDecoder<LIBAV_VER>::Input(MP4Sample* aSample)
|
|||
nsresult
|
||||
FFmpegAudioDecoder<LIBAV_VER>::Drain()
|
||||
{
|
||||
mTaskQueue->AwaitIdle();
|
||||
mCallback->DrainComplete();
|
||||
return NS_OK;
|
||||
return Flush();
|
||||
}
|
||||
|
||||
AVCodecID
|
||||
|
|
|
@ -329,15 +329,20 @@ GonkVideoDecoderManager::Output(int64_t aStreamOffset,
|
|||
return NS_OK;
|
||||
}
|
||||
case android::INFO_FORMAT_CHANGED:
|
||||
case android::INFO_OUTPUT_BUFFERS_CHANGED:
|
||||
{
|
||||
// If the format changed, update our cached info.
|
||||
ALOG("Decoder format changed");
|
||||
if (!SetVideoFormat()) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
else
|
||||
return Output(aStreamOffset, aOutData);
|
||||
}
|
||||
case android::INFO_OUTPUT_BUFFERS_CHANGED:
|
||||
{
|
||||
if (mDecoder->UpdateOutputBuffers()) {
|
||||
return Output(aStreamOffset, aOutData);
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
case -EAGAIN:
|
||||
{
|
||||
|
@ -420,7 +425,6 @@ GonkVideoDecoderManager::codecReserved()
|
|||
}
|
||||
status_t err = mDecoder->configure(format, surface, nullptr, 0);
|
||||
mDecoder->Prepare();
|
||||
SetVideoFormat();
|
||||
|
||||
if (mHandler != nullptr) {
|
||||
// post kNotifyCodecReserved to Looper thread.
|
||||
|
|
|
@ -22,3 +22,5 @@ USE_STATIC_LIBS = True
|
|||
NO_VISIBILITY_FLAGS = True
|
||||
# Don't use STL wrappers; this isn't Gecko code
|
||||
DISABLE_STL_WRAPPING = True
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
|
|
@ -39,6 +39,8 @@ public:
|
|||
virtual const uint16_t* ClearBytes() const = 0;
|
||||
|
||||
virtual const uint32_t* CipherBytes() const = 0;
|
||||
|
||||
virtual ~GMPEncryptedBufferMetadata() {}
|
||||
};
|
||||
|
||||
class GMPBuffer {
|
||||
|
@ -177,6 +179,8 @@ public:
|
|||
|
||||
// Returns decrypted buffer to Gecko, or reports failure.
|
||||
virtual void Decrypted(GMPBuffer* aBuffer, GMPErr aResult) = 0;
|
||||
|
||||
virtual ~GMPDecryptorCallback() {}
|
||||
};
|
||||
|
||||
// Host interface, passed to GetAPIFunc(), with "decrypt".
|
||||
|
@ -187,6 +191,8 @@ public:
|
|||
|
||||
virtual void GetPluginVoucher(const uint8_t** aVoucher,
|
||||
uint32_t* aVoucherLength) = 0;
|
||||
|
||||
virtual ~GMPDecryptorHost() {}
|
||||
};
|
||||
|
||||
enum GMPSessionType {
|
||||
|
@ -265,6 +271,7 @@ public:
|
|||
// Do not call the GMPDecryptorCallback's functions after this is called.
|
||||
virtual void DecryptingComplete() = 0;
|
||||
|
||||
virtual ~GMPDecryptor() {}
|
||||
};
|
||||
|
||||
#endif // GMP_DECRYPTION_h_
|
||||
|
|
|
@ -504,6 +504,21 @@ bool MediaCodecProxy::Prepare()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MediaCodecProxy::UpdateOutputBuffers()
|
||||
{
|
||||
if (mCodec == nullptr) {
|
||||
ALOG("MediaCodec has not been inited from input!");
|
||||
return false;
|
||||
}
|
||||
|
||||
status_t err = getOutputBuffers(&mOutputBuffers);
|
||||
if (err != OK){
|
||||
ALOG("Couldn't update output buffers from MediaCodec");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
status_t MediaCodecProxy::Input(const uint8_t* aData, uint32_t aDataSize,
|
||||
int64_t aTimestampUsecs, uint64_t aflags)
|
||||
{
|
||||
|
@ -540,7 +555,6 @@ status_t MediaCodecProxy::Input(const uint8_t* aData, uint32_t aDataSize,
|
|||
|
||||
status_t MediaCodecProxy::Output(MediaBuffer** aBuffer, int64_t aTimeoutUs)
|
||||
{
|
||||
|
||||
if (mCodec == nullptr) {
|
||||
ALOG("MediaCodec has not been inited from output!");
|
||||
return NO_INIT;
|
||||
|
|
|
@ -132,6 +132,8 @@ public:
|
|||
bool IsWaitingResources();
|
||||
bool IsDormantNeeded();
|
||||
void ReleaseMediaResources();
|
||||
// This updates mOutputBuffer when receiving INFO_OUTPUT_BUFFERS_CHANGED event.
|
||||
bool UpdateOutputBuffers();
|
||||
|
||||
void ReleaseMediaBuffer(MediaBuffer* abuffer);
|
||||
|
||||
|
|
|
@ -424,7 +424,7 @@ txCompileObserver::loadURI(const nsAString& aUri,
|
|||
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET,
|
||||
uri,
|
||||
referrerPrincipal,
|
||||
nullptr,
|
||||
mLoaderDocument,
|
||||
NS_LITERAL_CSTRING("application/xml"),
|
||||
nullptr,
|
||||
&shouldLoad);
|
||||
|
@ -460,12 +460,14 @@ txCompileObserver::startLoad(nsIURI* aUri, txStylesheetCompiler* aCompiler,
|
|||
}
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsresult rv = NS_NewChannel(getter_AddRefs(channel),
|
||||
aUri,
|
||||
aReferrerPrincipal,
|
||||
nsILoadInfo::SEC_NORMAL,
|
||||
nsIContentPolicy::TYPE_STYLESHEET,
|
||||
loadGroup);
|
||||
nsresult rv = NS_NewChannelWithTriggeringPrincipal(
|
||||
getter_AddRefs(channel),
|
||||
aUri,
|
||||
mLoaderDocument,
|
||||
aReferrerPrincipal, // triggeringPrincipal
|
||||
nsILoadInfo::SEC_NORMAL,
|
||||
nsIContentPolicy::TYPE_XSLT,
|
||||
loadGroup);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
@ -521,7 +523,7 @@ TX_LoadSheet(nsIURI* aUri, txMozillaXSLTProcessor* aProcessor,
|
|||
NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET,
|
||||
aUri,
|
||||
principal,
|
||||
aProcessor->GetSourceContentModel(),
|
||||
aLoaderDocument,
|
||||
NS_LITERAL_CSTRING("application/xml"),
|
||||
nullptr,
|
||||
&shouldLoad);
|
||||
|
|
|
@ -1003,6 +1003,7 @@ public:
|
|||
|
||||
virtual bool IsDualDrawTarget() const { return false; }
|
||||
virtual bool IsTiledDrawTarget() const { return false; }
|
||||
virtual bool SupportsRegionClipping() const { return true; }
|
||||
|
||||
void AddUserData(UserDataKey *key, void *userData, void (*destroy)(void*)) {
|
||||
mUserData.Add(key, userData, destroy);
|
||||
|
|
|
@ -131,6 +131,8 @@ public:
|
|||
|
||||
virtual TemporaryRef<FilterNode> CreateFilter(FilterType aType);
|
||||
|
||||
virtual bool SupportsRegionClipping() const { return false; }
|
||||
|
||||
virtual void *GetNativeSurface(NativeSurfaceType aType);
|
||||
|
||||
bool Init(const IntSize &aSize, SurfaceFormat aFormat);
|
||||
|
|
|
@ -122,6 +122,8 @@ public:
|
|||
|
||||
virtual TemporaryRef<FilterNode> CreateFilter(FilterType aType);
|
||||
|
||||
virtual bool SupportsRegionClipping() const { return false; }
|
||||
|
||||
virtual void *GetNativeSurface(NativeSurfaceType aType) { return nullptr; }
|
||||
|
||||
bool Init(const IntSize &aSize, SurfaceFormat aFormat);
|
||||
|
|
|
@ -174,52 +174,6 @@ gfxFT2Font::~gfxFT2Font()
|
|||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the font in the gfxFont cache. If we don't find it, create one.
|
||||
* In either case, add a ref, append it to the aFonts array, and return it ---
|
||||
* except for OOM in which case we do nothing and return null.
|
||||
*/
|
||||
already_AddRefed<gfxFT2Font>
|
||||
gfxFT2Font::GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle,
|
||||
bool aNeedsBold)
|
||||
{
|
||||
#ifdef ANDROID
|
||||
FT2FontEntry *fe = static_cast<FT2FontEntry*>
|
||||
(gfxPlatformFontList::PlatformFontList()->
|
||||
FindFontForFamily(aName, aStyle, aNeedsBold));
|
||||
#else
|
||||
FT2FontEntry *fe = static_cast<FT2FontEntry*>
|
||||
(gfxToolkitPlatform::GetPlatform()->FindFontEntry(aName, *aStyle));
|
||||
#endif
|
||||
if (!fe) {
|
||||
NS_WARNING("Failed to find font entry for font!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxFT2Font> font = GetOrMakeFont(fe, aStyle, aNeedsBold);
|
||||
return font.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<gfxFT2Font>
|
||||
gfxFT2Font::GetOrMakeFont(FT2FontEntry *aFontEntry, const gfxFontStyle *aStyle,
|
||||
bool aNeedsBold)
|
||||
{
|
||||
nsRefPtr<gfxFont> font = gfxFontCache::GetCache()->Lookup(aFontEntry, aStyle);
|
||||
if (!font) {
|
||||
cairo_scaled_font_t *scaledFont = aFontEntry->CreateScaledFont(aStyle);
|
||||
if (!scaledFont) {
|
||||
return nullptr;
|
||||
}
|
||||
font = new gfxFT2Font(scaledFont, aFontEntry, aStyle, aNeedsBold);
|
||||
cairo_scaled_font_destroy(scaledFont);
|
||||
if (!font) {
|
||||
return nullptr;
|
||||
}
|
||||
gfxFontCache::GetCache()->AddNew(font);
|
||||
}
|
||||
return font.forget().downcast<gfxFT2Font>();
|
||||
}
|
||||
|
||||
void
|
||||
gfxFT2Font::FillGlyphDataForChar(uint32_t ch, CachedGlyphData *gd)
|
||||
{
|
||||
|
|
|
@ -27,14 +27,6 @@ public: // new functions
|
|||
|
||||
FT2FontEntry *GetFontEntry();
|
||||
|
||||
static already_AddRefed<gfxFT2Font>
|
||||
GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle,
|
||||
bool aNeedsBold = false);
|
||||
|
||||
static already_AddRefed<gfxFT2Font>
|
||||
GetOrMakeFont(FT2FontEntry *aFontEntry, const gfxFontStyle *aStyle,
|
||||
bool aNeedsBold = false);
|
||||
|
||||
struct CachedGlyphData {
|
||||
CachedGlyphData()
|
||||
: glyphIndex(0xffffffffU) { }
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "base/process.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
#if defined(OS_POSIX)
|
||||
#if defined(OS_LINUX) || defined(OS_MACOSX)
|
||||
#include <pthread.h>
|
||||
#include "SharedMemoryBasic.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
|
@ -34,7 +34,7 @@ struct ParamTraits;
|
|||
namespace mozilla {
|
||||
#if defined(OS_WIN)
|
||||
typedef HANDLE CrossProcessMutexHandle;
|
||||
#elif defined(OS_POSIX)
|
||||
#elif defined(OS_LINUX) || defined(OS_MACOSX)
|
||||
typedef mozilla::ipc::SharedMemoryBasic::Handle CrossProcessMutexHandle;
|
||||
#else
|
||||
// Stub for other platforms. We can't use uintptr_t here since different
|
||||
|
@ -100,7 +100,7 @@ private:
|
|||
|
||||
#if defined(OS_WIN)
|
||||
HANDLE mMutex;
|
||||
#elif defined(OS_POSIX)
|
||||
#elif defined(OS_LINUX) || defined(OS_MACOSX)
|
||||
nsRefPtr<mozilla::ipc::SharedMemoryBasic> mSharedBuffer;
|
||||
pthread_mutex_t* mMutex;
|
||||
mozilla::Atomic<int32_t>* mCount;
|
||||
|
|
|
@ -321,7 +321,11 @@ enum { REG_EIP = 14 };
|
|||
static uint8_t **
|
||||
ContextToPC(CONTEXT *context)
|
||||
{
|
||||
return reinterpret_cast<uint8_t**>(&PC_sig(context));
|
||||
#ifdef JS_CODEGEN_NONE
|
||||
MOZ_CRASH();
|
||||
#else
|
||||
return reinterpret_cast<uint8_t**>(&PC_sig(context));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(JS_CODEGEN_X64)
|
||||
|
|
|
@ -3358,7 +3358,7 @@ class FunctionCompiler
|
|||
private:
|
||||
void noteBasicBlockPosition(MBasicBlock *blk, ParseNode *pn)
|
||||
{
|
||||
#if defined(JS_ION_PERF)
|
||||
#if defined(JS_ION_PERF) || defined(DEBUG)
|
||||
if (pn) {
|
||||
unsigned line = 0U, column = 0U;
|
||||
m().tokenStream().srcCoords.lineNumAndColumnIndex(pn->pn_pos.begin, &line, &column);
|
||||
|
|
|
@ -139,13 +139,14 @@ JS_TraceIncomingCCWs(JSTracer *trc, const JS::ZoneSet &zones)
|
|||
// zones multiple times, and don't hold a strong reference.
|
||||
if (key.kind == CrossCompartmentKey::StringWrapper)
|
||||
continue;
|
||||
JSObject *obj = static_cast<JSObject *>(key.wrapped);
|
||||
// Ignore CCWs whose wrapped value doesn't live in our given set
|
||||
// of zones.
|
||||
if (!zones.has(static_cast<JSObject *>(key.wrapped)->zone()))
|
||||
if (!zones.has(obj->zone()))
|
||||
continue;
|
||||
|
||||
void *thing = key.wrapped;
|
||||
trc->callback(trc, &thing, GetGCThingTraceKind(key.wrapped));
|
||||
MarkObjectUnbarriered(trc, &obj, "cross-compartment wrapper");
|
||||
MOZ_ASSERT(obj == key.wrapped);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
if (typeof TypedObject === "undefined")
|
||||
quit();
|
||||
|
||||
var T = TypedObject;
|
||||
var ObjectStruct = new T.StructType({f: T.Object});
|
||||
var o = new ObjectStruct();
|
||||
function testGC(o, p) {
|
||||
for (var i = 0; i < 5; i++) {
|
||||
minorgc();
|
||||
o.f >>= p;
|
||||
}
|
||||
}
|
||||
testGC(o, {});
|
|
@ -4103,8 +4103,22 @@ CodeGenerator::generateBody()
|
|||
if (current->isTrivial())
|
||||
continue;
|
||||
|
||||
JitSpew(JitSpew_Codegen, "# block%lu%s:", i,
|
||||
#ifdef DEBUG
|
||||
const char *filename = nullptr;
|
||||
unsigned lineNumber = 0, columnNumber = 0;
|
||||
if (current->mir()->info().script()) {
|
||||
filename = current->mir()->info().script()->filename();
|
||||
if (current->mir()->pc())
|
||||
lineNumber = PCToLineNumber(current->mir()->info().script(), current->mir()->pc(),
|
||||
&columnNumber);
|
||||
} else {
|
||||
lineNumber = current->mir()->lineno();
|
||||
columnNumber = current->mir()->columnIndex();
|
||||
}
|
||||
JitSpew(JitSpew_Codegen, "# block%lu %s:%u:%u%s:", i,
|
||||
filename ? filename : "?", lineNumber, columnNumber,
|
||||
current->mir()->isLoopHeader() ? " (loop header)" : "");
|
||||
#endif
|
||||
|
||||
masm.bind(current->label());
|
||||
|
||||
|
|
|
@ -11321,9 +11321,6 @@ IonBuilder::storeReferenceTypedObjectValue(MDefinition *typedObj,
|
|||
ReferenceTypeDescr::Type type,
|
||||
MDefinition *value)
|
||||
{
|
||||
if (NeedsPostBarrier(info(), value))
|
||||
current->add(MPostWriteBarrier::New(alloc(), typedObj, value));
|
||||
|
||||
// Find location within the owner object.
|
||||
MDefinition *elements, *scaledOffset;
|
||||
size_t alignment = ReferenceTypeDescr::alignment(type);
|
||||
|
@ -11332,12 +11329,20 @@ IonBuilder::storeReferenceTypedObjectValue(MDefinition *typedObj,
|
|||
MInstruction *store;
|
||||
switch (type) {
|
||||
case ReferenceTypeDescr::TYPE_ANY:
|
||||
if (NeedsPostBarrier(info(), value))
|
||||
current->add(MPostWriteBarrier::New(alloc(), typedObj, value));
|
||||
store = MStoreElement::New(alloc(), elements, scaledOffset, value, false);
|
||||
break;
|
||||
case ReferenceTypeDescr::TYPE_OBJECT:
|
||||
store = MStoreUnboxedObjectOrNull::New(alloc(), elements, scaledOffset, value);
|
||||
// Note: We cannot necessarily tell at this point whether a post
|
||||
// barrier is needed, because the type policy may insert ToObjectOrNull
|
||||
// instructions later, and those may require a post barrier. Therefore,
|
||||
// defer the insertion of post barriers to the type policy.
|
||||
store = MStoreUnboxedObjectOrNull::New(alloc(), elements, scaledOffset, value, typedObj);
|
||||
break;
|
||||
case ReferenceTypeDescr::TYPE_STRING:
|
||||
// Strings are not nursery allocated, so these writes do not need post
|
||||
// barriers.
|
||||
store = MStoreUnboxedString::New(alloc(), elements, scaledOffset, value);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -2456,7 +2456,8 @@ LIRGenerator::visitPostWriteBarrier(MPostWriteBarrier *ins)
|
|||
{
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
switch (ins->value()->type()) {
|
||||
case MIRType_Object: {
|
||||
case MIRType_Object:
|
||||
case MIRType_ObjectOrNull: {
|
||||
LDefinition tmp = needTempForPostBarrier() ? temp() : LDefinition::BogusTemp();
|
||||
LPostWriteBarrierO *lir =
|
||||
new(alloc()) LPostWriteBarrierO(useRegisterOrConstant(ins->object()),
|
||||
|
|
|
@ -8004,15 +8004,18 @@ class MStoreElementHole
|
|||
|
||||
// Store an unboxed object or null pointer to a vector.
|
||||
class MStoreUnboxedObjectOrNull
|
||||
: public MAryInstruction<3>,
|
||||
public ConvertToObjectOrNullPolicy<2>::Data
|
||||
: public MAryInstruction<4>,
|
||||
public StoreUnboxedObjectOrNullPolicy::Data
|
||||
{
|
||||
MStoreUnboxedObjectOrNull(MDefinition *elements, MDefinition *index, MDefinition *value) {
|
||||
MStoreUnboxedObjectOrNull(MDefinition *elements, MDefinition *index,
|
||||
MDefinition *value, MDefinition *typedObj) {
|
||||
initOperand(0, elements);
|
||||
initOperand(1, index);
|
||||
initOperand(2, value);
|
||||
initOperand(3, typedObj);
|
||||
MOZ_ASSERT(elements->type() == MIRType_Elements);
|
||||
MOZ_ASSERT(index->type() == MIRType_Int32);
|
||||
MOZ_ASSERT(typedObj->type() == MIRType_Object);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -8020,8 +8023,8 @@ class MStoreUnboxedObjectOrNull
|
|||
|
||||
static MStoreUnboxedObjectOrNull *New(TempAllocator &alloc,
|
||||
MDefinition *elements, MDefinition *index,
|
||||
MDefinition *value) {
|
||||
return new(alloc) MStoreUnboxedObjectOrNull(elements, index, value);
|
||||
MDefinition *value, MDefinition *typedObj) {
|
||||
return new(alloc) MStoreUnboxedObjectOrNull(elements, index, value, typedObj);
|
||||
}
|
||||
MDefinition *elements() const {
|
||||
return getOperand(0);
|
||||
|
@ -8032,11 +8035,19 @@ class MStoreUnboxedObjectOrNull
|
|||
MDefinition *value() const {
|
||||
return getOperand(2);
|
||||
}
|
||||
MDefinition *typedObj() const {
|
||||
return getOperand(3);
|
||||
}
|
||||
AliasSet getAliasSet() const {
|
||||
// Use AliasSet::Element for reference typed object fields.
|
||||
return AliasSet::Store(AliasSet::Element);
|
||||
}
|
||||
|
||||
// For StoreUnboxedObjectOrNullPolicy.
|
||||
void setValue(MDefinition *def) {
|
||||
replaceOperand(2, def);
|
||||
}
|
||||
|
||||
ALLOW_CLONE(MStoreUnboxedObjectOrNull)
|
||||
};
|
||||
|
||||
|
|
|
@ -651,7 +651,7 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
|
|||
|
||||
const BytecodeSite *trackedSite_;
|
||||
|
||||
#if defined (JS_ION_PERF)
|
||||
#if defined(JS_ION_PERF) || defined(DEBUG)
|
||||
unsigned lineno_;
|
||||
unsigned columnIndex_;
|
||||
|
||||
|
|
|
@ -192,7 +192,8 @@ RValueAllocation::layoutFromMode(Mode mode)
|
|||
case UNTYPED_STACK_REG: {
|
||||
static const RValueAllocation::Layout layout = {
|
||||
PAYLOAD_STACK_OFFSET,
|
||||
PAYLOAD_GPR
|
||||
PAYLOAD_GPR,
|
||||
"value"
|
||||
};
|
||||
return layout;
|
||||
}
|
||||
|
|
|
@ -407,31 +407,6 @@ template bool ConvertToStringPolicy<0>::staticAdjustInputs(TempAllocator &alloc,
|
|||
template bool ConvertToStringPolicy<1>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins);
|
||||
template bool ConvertToStringPolicy<2>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins);
|
||||
|
||||
template <unsigned Op>
|
||||
bool
|
||||
ConvertToObjectOrNullPolicy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins)
|
||||
{
|
||||
MDefinition *in = ins->getOperand(Op);
|
||||
if (in->type() == MIRType_Object ||
|
||||
in->type() == MIRType_Null ||
|
||||
in->type() == MIRType_ObjectOrNull)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
MToObjectOrNull *replace = MToObjectOrNull::New(alloc, in);
|
||||
ins->block()->insertBefore(ins, replace);
|
||||
ins->replaceOperand(Op, replace);
|
||||
|
||||
if (!BoxPolicy<0>::staticAdjustInputs(alloc, replace))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template bool ConvertToObjectOrNullPolicy<2>::staticAdjustInputs(TempAllocator &alloc,
|
||||
MInstruction *ins);
|
||||
|
||||
template <unsigned Op>
|
||||
bool
|
||||
IntPolicy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def)
|
||||
|
@ -869,6 +844,39 @@ StoreTypedArrayElementStaticPolicy::adjustInputs(TempAllocator &alloc, MInstruct
|
|||
adjustValueInput(alloc, ins, store->viewType(), store->value(), 1);
|
||||
}
|
||||
|
||||
bool
|
||||
StoreUnboxedObjectOrNullPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
|
||||
{
|
||||
// Change the value input to a ToObjectOrNull instruction if it might be
|
||||
// a non-null primitive. Insert a post barrier for the instruction's object
|
||||
// and whatever its new value is, unless the value is definitely null.
|
||||
MStoreUnboxedObjectOrNull *store = ins->toStoreUnboxedObjectOrNull();
|
||||
|
||||
MDefinition *value = store->value();
|
||||
if (value->type() == MIRType_Object ||
|
||||
value->type() == MIRType_Null ||
|
||||
value->type() == MIRType_ObjectOrNull)
|
||||
{
|
||||
if (value->type() != MIRType_Null) {
|
||||
MInstruction *barrier = MPostWriteBarrier::New(alloc, store->typedObj(), value);
|
||||
store->block()->insertBefore(store, barrier);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MToObjectOrNull *replace = MToObjectOrNull::New(alloc, value);
|
||||
store->block()->insertBefore(store, replace);
|
||||
store->setValue(replace);
|
||||
|
||||
if (!BoxPolicy<0>::staticAdjustInputs(alloc, replace))
|
||||
return false;
|
||||
|
||||
MInstruction *barrier = MPostWriteBarrier::New(alloc, store->typedObj(), replace);
|
||||
store->block()->insertBefore(store, barrier);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ClampPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
|
||||
{
|
||||
|
@ -956,6 +964,7 @@ FilterTypeSetPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
|
|||
_(StoreTypedArrayElementStaticPolicy) \
|
||||
_(StoreTypedArrayHolePolicy) \
|
||||
_(StoreTypedArrayPolicy) \
|
||||
_(StoreUnboxedObjectOrNullPolicy) \
|
||||
_(TestPolicy) \
|
||||
_(ToDoublePolicy) \
|
||||
_(ToInt32Policy) \
|
||||
|
@ -968,7 +977,6 @@ FilterTypeSetPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
|
|||
_(ConvertToInt32Policy<0>) \
|
||||
_(ConvertToStringPolicy<0>) \
|
||||
_(ConvertToStringPolicy<2>) \
|
||||
_(ConvertToObjectOrNullPolicy<2>) \
|
||||
_(DoublePolicy<0>) \
|
||||
_(FloatingPointPolicy<0>) \
|
||||
_(IntPolicy<0>) \
|
||||
|
|
|
@ -148,19 +148,6 @@ class ConvertToStringPolicy : public TypePolicy
|
|||
}
|
||||
};
|
||||
|
||||
// Expect an object or null value for operand Op. Else a ToObjectOrNull
|
||||
// instruction is inserted.
|
||||
template <unsigned Op>
|
||||
class ConvertToObjectOrNullPolicy : public TypePolicy
|
||||
{
|
||||
public:
|
||||
EMPTY_DATA_;
|
||||
static bool staticAdjustInputs(TempAllocator &alloc, MInstruction *def);
|
||||
bool adjustInputs(TempAllocator &alloc, MInstruction *def) {
|
||||
return staticAdjustInputs(alloc, def);
|
||||
}
|
||||
};
|
||||
|
||||
// Expect an Int for operand Op. If the input is a Value, it is unboxed.
|
||||
template <unsigned Op>
|
||||
class IntPolicy : public BoxInputsPolicy
|
||||
|
@ -397,6 +384,13 @@ class StoreTypedArrayElementStaticPolicy : public StoreTypedArrayPolicy
|
|||
bool adjustInputs(TempAllocator &alloc, MInstruction *ins);
|
||||
};
|
||||
|
||||
class StoreUnboxedObjectOrNullPolicy : public TypePolicy
|
||||
{
|
||||
public:
|
||||
EMPTY_DATA_;
|
||||
bool adjustInputs(TempAllocator &alloc, MInstruction *def);
|
||||
};
|
||||
|
||||
// Accepts integers and doubles. Everything else is boxed.
|
||||
class ClampPolicy : public BoxInputsPolicy
|
||||
{
|
||||
|
|
|
@ -4407,7 +4407,7 @@ static bool ShouldDrawRectsSeparately(gfxContext* aContext, DrawRegionClip aClip
|
|||
}
|
||||
|
||||
DrawTarget *dt = aContext->GetDrawTarget();
|
||||
return dt->GetBackendType() == BackendType::DIRECT2D;
|
||||
return !dt->SupportsRegionClipping();
|
||||
}
|
||||
|
||||
static void DrawForcedBackgroundColor(gfxContext* aContext, Layer* aLayer, nscolor aBackgroundColor)
|
||||
|
|
|
@ -8,9 +8,12 @@
|
|||
* changes need to happen, scheduling them, and doing them.
|
||||
*/
|
||||
|
||||
#include <algorithm> // For std::max
|
||||
#include "RestyleManager.h"
|
||||
#include "mozilla/EventStates.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "AnimationCommon.h" // For GetLayerAnimationInfo
|
||||
#include "FrameLayerBuilder.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "nsStyleChangeList.h"
|
||||
#include "nsRuleProcessorData.h"
|
||||
|
@ -1149,6 +1152,27 @@ RestyleManager::AttributeChanged(Element* aElement,
|
|||
PostRestyleEvent(aElement, rshint, hint);
|
||||
}
|
||||
|
||||
/* static */ uint64_t
|
||||
RestyleManager::GetMaxAnimationGenerationForFrame(nsIFrame* aFrame)
|
||||
{
|
||||
nsIContent* content = aFrame->GetContent();
|
||||
if (!content || !content->IsElement()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsCSSPseudoElements::Type pseudoType =
|
||||
aFrame->StyleContext()->GetPseudoType();
|
||||
AnimationPlayerCollection* transitions =
|
||||
aFrame->PresContext()->TransitionManager()->GetAnimationPlayers(
|
||||
content->AsElement(), pseudoType, false /* don't create */);
|
||||
AnimationPlayerCollection* animations =
|
||||
aFrame->PresContext()->AnimationManager()->GetAnimationPlayers(
|
||||
content->AsElement(), pseudoType, false /* don't create */);
|
||||
|
||||
return std::max(transitions ? transitions->mAnimationGeneration : 0,
|
||||
animations ? animations->mAnimationGeneration : 0);
|
||||
}
|
||||
|
||||
void
|
||||
RestyleManager::RestyleForEmptyChange(Element* aContainer)
|
||||
{
|
||||
|
@ -1560,7 +1584,7 @@ RestyleManager::ProcessPendingRestyles()
|
|||
// correct old style for starting the transition.
|
||||
if (nsLayoutUtils::AreAsyncAnimationsEnabled() &&
|
||||
mPendingRestyles.Count() > 0) {
|
||||
++mAnimationGeneration;
|
||||
IncrementAnimationGeneration();
|
||||
UpdateOnlyAnimationStyles();
|
||||
}
|
||||
|
||||
|
@ -2408,6 +2432,40 @@ ElementRestyler::ElementRestyler(ParentContextFromChildFrame,
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
ElementRestyler::AddLayerChangesForAnimation()
|
||||
{
|
||||
// Bug 847286 - We should have separate animation generation counters
|
||||
// on layers for transitions and animations and use != comparison below
|
||||
// rather than a > comparison.
|
||||
uint64_t frameGeneration =
|
||||
RestyleManager::GetMaxAnimationGenerationForFrame(mFrame);
|
||||
|
||||
nsChangeHint hint = nsChangeHint(0);
|
||||
const auto& layerInfo = css::CommonAnimationManager::sLayerAnimationInfo;
|
||||
for (size_t i = 0; i < ArrayLength(layerInfo); i++) {
|
||||
Layer* layer =
|
||||
FrameLayerBuilder::GetDedicatedLayer(mFrame, layerInfo[i].mLayerType);
|
||||
if (layer && frameGeneration > layer->GetAnimationGeneration()) {
|
||||
// If we have a transform layer but don't have any transform style, we
|
||||
// probably just removed the transform but haven't destroyed the layer
|
||||
// yet. In this case we will add the appropriate change hint
|
||||
// (nsChangeHint_AddOrRemoveTransform) when we compare style contexts
|
||||
// so we can skip adding any change hint here. (If we *were* to add
|
||||
// nsChangeHint_UpdateTransformLayer, ApplyRenderingChangeToTree would
|
||||
// complain that we're updating a transform layer without a transform).
|
||||
if (layerInfo[i].mLayerType == nsDisplayItem::TYPE_TRANSFORM &&
|
||||
!mFrame->StyleDisplay()->HasTransformStyle()) {
|
||||
continue;
|
||||
}
|
||||
NS_UpdateHint(hint, layerInfo[i].mChangeHint);
|
||||
}
|
||||
}
|
||||
if (hint) {
|
||||
mChangeList->AppendChange(mFrame, mContent, hint);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ElementRestyler::CaptureChange(nsStyleContext* aOldContext,
|
||||
nsStyleContext* aNewContext,
|
||||
|
@ -2522,6 +2580,12 @@ ElementRestyler::Restyle(nsRestyleHint aRestyleHint)
|
|||
}
|
||||
}
|
||||
|
||||
// Some changes to animations don't affect the computed style and yet still
|
||||
// require the layer to be updated. For example, pausing an animation via
|
||||
// the Web Animations API won't affect an element's style but still
|
||||
// requires us to pull the animation off the layer.
|
||||
AddLayerChangesForAnimation();
|
||||
|
||||
// If we are restyling this frame with eRestyle_Self or weaker hints,
|
||||
// we restyle children with nsRestyleHint(0). But we pass the
|
||||
// eRestyle_ChangeAnimationPhaseDescendants and eRestyle_ForceDescendants
|
||||
|
|
|
@ -92,6 +92,19 @@ public:
|
|||
// track whether off-main-thread animations are up-to-date.
|
||||
uint64_t GetAnimationGeneration() const { return mAnimationGeneration; }
|
||||
|
||||
// A workaround until bug 847286 lands that gets the maximum of the animation
|
||||
// generation counters stored on the set of animations and transitions
|
||||
// respectively for |aFrame|.
|
||||
static uint64_t GetMaxAnimationGenerationForFrame(nsIFrame* aFrame);
|
||||
|
||||
// Update the animation generation count to mark that animation state
|
||||
// has changed.
|
||||
//
|
||||
// This is normally performed automatically by ProcessPendingRestyles
|
||||
// but it is also called when we have out-of-band changes to animations
|
||||
// such as changes made through the Web Animations API.
|
||||
void IncrementAnimationGeneration() { ++mAnimationGeneration; }
|
||||
|
||||
// Whether rule matching should skip styles associated with animation
|
||||
bool SkipAnimationRules() const {
|
||||
MOZ_ASSERT(mSkipAnimationRules || !mPostAnimationRestyles,
|
||||
|
@ -593,6 +606,11 @@ private:
|
|||
*/
|
||||
void RestyleChildren(nsRestyleHint aChildRestyleHint);
|
||||
|
||||
/**
|
||||
* Helpers for Restyle().
|
||||
*/
|
||||
void AddLayerChangesForAnimation();
|
||||
|
||||
/**
|
||||
* Helpers for RestyleSelf().
|
||||
*/
|
||||
|
|
|
@ -1444,7 +1444,7 @@ nsCSSBorderRenderer::DrawBorders()
|
|||
strokeOptions.mDashOffset = 0.5f;
|
||||
DrawOptions drawOptions;
|
||||
drawOptions.mAntialiasMode = AntialiasMode::NONE;
|
||||
mDrawTarget->StrokeRect(rect, color, strokeOptions);
|
||||
mDrawTarget->StrokeRect(rect, color, strokeOptions, drawOptions);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
#include "UnitTransforms.h"
|
||||
#include "LayersLogging.h"
|
||||
#include "FrameLayerBuilder.h"
|
||||
#include "RestyleManager.h"
|
||||
#include "nsCaret.h"
|
||||
#include "nsISelection.h"
|
||||
|
||||
|
@ -440,6 +441,15 @@ nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(Layer* aLayer,
|
|||
aLayer->ClearAnimations();
|
||||
}
|
||||
|
||||
// Update the animation generation on the layer. We need to do this before
|
||||
// any early returns since even if we don't add any animations to the
|
||||
// layer, we still need to mark it as up-to-date with regards to animations.
|
||||
// Otherwise, in RestyleManager we'll notice the discrepancy between the
|
||||
// animation generation numbers and update the layer indefinitely.
|
||||
uint64_t animationGeneration =
|
||||
RestyleManager::GetMaxAnimationGenerationForFrame(aFrame);
|
||||
aLayer->SetAnimationGeneration(animationGeneration);
|
||||
|
||||
nsIContent* content = aFrame->GetContent();
|
||||
if (!content) {
|
||||
return;
|
||||
|
@ -507,13 +517,11 @@ nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(Layer* aLayer,
|
|||
if (transitions) {
|
||||
AddAnimationsForProperty(aFrame, aProperty, transitions->mPlayers,
|
||||
aLayer, data, pending);
|
||||
aLayer->SetAnimationGeneration(transitions->mAnimationGeneration);
|
||||
}
|
||||
|
||||
if (animations) {
|
||||
AddAnimationsForProperty(aFrame, aProperty, animations->mPlayers,
|
||||
aLayer, data, pending);
|
||||
aLayer->SetAnimationGeneration(animations->mAnimationGeneration);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1558,7 +1558,7 @@ nsPresContext::Detach()
|
|||
}
|
||||
|
||||
bool
|
||||
nsPresContext::StyleUpdateForAllAnimationsIsUpToDate()
|
||||
nsPresContext::StyleUpdateForAllAnimationsIsUpToDate() const
|
||||
{
|
||||
return mLastStyleUpdateForAllAnimations == mRefreshDriver->MostRecentRefresh();
|
||||
}
|
||||
|
@ -1569,6 +1569,12 @@ nsPresContext::TickLastStyleUpdateForAllAnimations()
|
|||
mLastStyleUpdateForAllAnimations = mRefreshDriver->MostRecentRefresh();
|
||||
}
|
||||
|
||||
void
|
||||
nsPresContext::ClearLastStyleUpdateForAllAnimations()
|
||||
{
|
||||
mLastStyleUpdateForAllAnimations = TimeStamp();
|
||||
}
|
||||
|
||||
bool
|
||||
nsPresContext::BidiEnabledExternal() const
|
||||
{
|
||||
|
|
|
@ -705,10 +705,11 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Getter and setter for OMTA time counters
|
||||
* Getter and setters for OMTA time counters
|
||||
*/
|
||||
bool StyleUpdateForAllAnimationsIsUpToDate();
|
||||
bool StyleUpdateForAllAnimationsIsUpToDate() const;
|
||||
void TickLastStyleUpdateForAllAnimations();
|
||||
void ClearLastStyleUpdateForAllAnimations();
|
||||
|
||||
/**
|
||||
* Check if bidi enabled (set depending on the presence of RTL
|
||||
|
|
|
@ -296,7 +296,7 @@ NS_DECLARE_FRAME_PROPERTY_FRAMELIST(OverflowOutOfFlowsProperty)
|
|||
NS_DECLARE_FRAME_PROPERTY_FRAMELIST(PushedFloatProperty)
|
||||
NS_DECLARE_FRAME_PROPERTY_FRAMELIST(OutsideBulletProperty)
|
||||
NS_DECLARE_FRAME_PROPERTY(InsideBulletProperty, nullptr)
|
||||
NS_DECLARE_FRAME_PROPERTY(BottomEdgeOfChildrenProperty, nullptr)
|
||||
NS_DECLARE_FRAME_PROPERTY(BlockEndEdgeOfChildrenProperty, nullptr)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
@ -1048,7 +1048,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
if (GetLogicalSkipSides().BStart()) {
|
||||
blockDirExtras.BStart(wm) = 0;
|
||||
} else {
|
||||
// Bottom margin never causes us to create continuations, so we
|
||||
// Block-end margin never causes us to create continuations, so we
|
||||
// don't need to worry about whether it fits in its entirety.
|
||||
blockDirExtras.BStart(wm) +=
|
||||
aReflowState.ComputedLogicalMargin().BStart(wm);
|
||||
|
@ -1206,11 +1206,11 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
WritingMode wm = aReflowState.GetWritingMode();
|
||||
bool havePosition = nsLayoutUtils::GetFirstLinePosition(wm, this,
|
||||
&position);
|
||||
nscoord lineTop = havePosition ?
|
||||
nscoord lineBStart = havePosition ?
|
||||
position.mBStart :
|
||||
reflowState->ComputedLogicalBorderPadding().BStart(wm);
|
||||
nsIFrame* bullet = GetOutsideBullet();
|
||||
ReflowBullet(bullet, state, metrics, lineTop);
|
||||
ReflowBullet(bullet, state, metrics, lineBStart);
|
||||
NS_ASSERTION(!BulletIsEmpty() || metrics.BSize(wm) == 0,
|
||||
"empty bullet took up space");
|
||||
|
||||
|
@ -1225,7 +1225,8 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
bbox.BStart(wm) = position.mBaseline - metrics.BlockStartAscent();
|
||||
bullet->SetRect(wm, bbox, metrics.Width());
|
||||
}
|
||||
// Otherwise just leave the bullet where it is, up against our top padding.
|
||||
// Otherwise just leave the bullet where it is, up against our
|
||||
// block-start padding.
|
||||
}
|
||||
|
||||
CheckFloats(state);
|
||||
|
@ -1369,7 +1370,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
|
|||
printf(": status=%x (%scomplete) metrics=%d,%d carriedMargin=%d",
|
||||
aStatus, NS_FRAME_IS_COMPLETE(aStatus) ? "" : "not ",
|
||||
aMetrics.ISize(parentWM), aMetrics.BSize(parentWM),
|
||||
aMetrics.mCarriedOutBottomMargin.get());
|
||||
aMetrics.mCarriedOutBEndMargin.get());
|
||||
if (HasOverflowAreas()) {
|
||||
printf(" overflow-vis={%d,%d,%d,%d}",
|
||||
aMetrics.VisualOverflow().x,
|
||||
|
@ -1452,42 +1453,42 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
|||
aReflowState.ComputedISize()),
|
||||
borderPadding.IEnd(wm));
|
||||
|
||||
// Return bottom margin information
|
||||
// Return block-end margin information
|
||||
// rbs says he hit this assertion occasionally (see bug 86947), so
|
||||
// just set the margin to zero and we'll figure out why later
|
||||
//NS_ASSERTION(aMetrics.mCarriedOutBottomMargin.IsZero(),
|
||||
//NS_ASSERTION(aMetrics.mCarriedOutBEndMargin.IsZero(),
|
||||
// "someone else set the margin");
|
||||
nscoord nonCarriedOutBDirMargin = 0;
|
||||
if (!aState.GetFlag(BRS_ISBENDMARGINROOT)) {
|
||||
// Apply rule from CSS 2.1 section 8.3.1. If we have some empty
|
||||
// line with clearance and a non-zero top margin and all
|
||||
// line with clearance and a non-zero block-start margin and all
|
||||
// subsequent lines are empty, then we do not allow our children's
|
||||
// carried out bottom margin to be carried out of us and collapse
|
||||
// with our own bottom margin.
|
||||
// carried out block-end margin to be carried out of us and collapse
|
||||
// with our own block-end margin.
|
||||
if (CheckForCollapsedBEndMarginFromClearanceLine()) {
|
||||
// Convert the children's carried out margin to something that
|
||||
// we will include in our height
|
||||
nonCarriedOutBDirMargin = aState.mPrevBEndMargin.get();
|
||||
aState.mPrevBEndMargin.Zero();
|
||||
}
|
||||
aMetrics.mCarriedOutBottomMargin = aState.mPrevBEndMargin;
|
||||
aMetrics.mCarriedOutBEndMargin = aState.mPrevBEndMargin;
|
||||
} else {
|
||||
aMetrics.mCarriedOutBottomMargin.Zero();
|
||||
aMetrics.mCarriedOutBEndMargin.Zero();
|
||||
}
|
||||
|
||||
nscoord blockEndEdgeOfChildren = aState.mBCoord + nonCarriedOutBDirMargin;
|
||||
// Shrink wrap our height around our contents.
|
||||
if (aState.GetFlag(BRS_ISBENDMARGINROOT) ||
|
||||
NS_UNCONSTRAINEDSIZE != aReflowState.ComputedBSize()) {
|
||||
// When we are a bottom-margin root make sure that our last
|
||||
// childs bottom margin is fully applied. We also do this when
|
||||
// When we are a block-end-margin root make sure that our last
|
||||
// childs block-end margin is fully applied. We also do this when
|
||||
// we have a computed height, since in that case the carried out
|
||||
// margin is not going to be applied anywhere, so we should note it
|
||||
// here to be included in the overflow area.
|
||||
// Apply the margin only if there's space for it.
|
||||
if (blockEndEdgeOfChildren < aState.mReflowState.AvailableBSize())
|
||||
{
|
||||
// Truncate bottom margin if it doesn't fit to our available height.
|
||||
// Truncate block-end margin if it doesn't fit to our available BSize.
|
||||
blockEndEdgeOfChildren =
|
||||
std::min(blockEndEdgeOfChildren + aState.mPrevBEndMargin.get(),
|
||||
aState.mReflowState.AvailableBSize());
|
||||
|
@ -1495,7 +1496,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
|||
}
|
||||
if (aState.GetFlag(BRS_FLOAT_MGR)) {
|
||||
// Include the float manager's state to properly account for the
|
||||
// bottom margin of any floated elements; e.g., inside a table cell.
|
||||
// block-end margin of any floated elements; e.g., inside a table cell.
|
||||
nscoord floatHeight =
|
||||
aState.ClearFloats(blockEndEdgeOfChildren, NS_STYLE_CLEAR_BOTH,
|
||||
nullptr, nsFloatManager::DONT_CLEAR_PUSHED_FLOATS);
|
||||
|
@ -1527,16 +1528,16 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
|||
// height in the current frame, not whether it's last-in-flow.
|
||||
}
|
||||
|
||||
// Don't carry out a bottom margin when our height is fixed.
|
||||
aMetrics.mCarriedOutBottomMargin.Zero();
|
||||
// Don't carry out a block-end margin when our BSize is fixed.
|
||||
aMetrics.mCarriedOutBEndMargin.Zero();
|
||||
}
|
||||
else if (NS_FRAME_IS_COMPLETE(aState.mReflowStatus)) {
|
||||
nscoord contentBSize = blockEndEdgeOfChildren - borderPadding.BStart(wm);
|
||||
nscoord autoBSize = aReflowState.ApplyMinMaxHeight(contentBSize);
|
||||
if (autoBSize != contentBSize) {
|
||||
// Our min-height or max-height made our height change. Don't carry out
|
||||
// our kids' bottom margins.
|
||||
aMetrics.mCarriedOutBottomMargin.Zero();
|
||||
// our kids' block-end margins.
|
||||
aMetrics.mCarriedOutBEndMargin.Zero();
|
||||
}
|
||||
autoBSize += borderPadding.BStart(wm) + borderPadding.BEnd(wm);
|
||||
finalSize.BSize(wm) = autoBSize;
|
||||
|
@ -1566,10 +1567,10 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
|||
|
||||
FrameProperties properties = Properties();
|
||||
if (blockEndEdgeOfChildren != finalSize.BSize(wm) - borderPadding.BEnd(wm)) {
|
||||
properties.Set(BottomEdgeOfChildrenProperty(),
|
||||
properties.Set(BlockEndEdgeOfChildrenProperty(),
|
||||
NS_INT32_TO_PTR(blockEndEdgeOfChildren));
|
||||
} else {
|
||||
properties.Delete(BottomEdgeOfChildrenProperty());
|
||||
properties.Delete(BlockEndEdgeOfChildrenProperty());
|
||||
}
|
||||
|
||||
aMetrics.SetSize(wm, finalSize);
|
||||
|
@ -1583,25 +1584,45 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
|||
}
|
||||
|
||||
static void
|
||||
ConsiderBottomEdgeOfChildren(nscoord aBottomEdgeOfChildren,
|
||||
nsOverflowAreas& aOverflowAreas)
|
||||
ConsiderBlockEndEdgeOfChildren(const WritingMode aWritingMode,
|
||||
nscoord aBEndEdgeOfChildren,
|
||||
nsOverflowAreas& aOverflowAreas)
|
||||
{
|
||||
// Factor in the bottom edge of the children. Child frames will be added
|
||||
// Factor in the block-end edge of the children. Child frames will be added
|
||||
// to the overflow area as we iterate through the lines, but their margins
|
||||
// won't, so we need to account for bottom margins here.
|
||||
// won't, so we need to account for block-end margins here.
|
||||
// REVIEW: For now, we do this for both visual and scrollable area,
|
||||
// although when we make scrollable overflow area not be a subset of
|
||||
// visual, we can change this.
|
||||
NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
|
||||
nsRect& o = aOverflowAreas.Overflow(otype);
|
||||
o.height = std::max(o.YMost(), aBottomEdgeOfChildren) - o.y;
|
||||
// XXX Currently, overflow areas are stored as physical rects, so we have
|
||||
// to handle writing modes explicitly here. If we change overflow rects
|
||||
// to be stored logically, this can be simplified again.
|
||||
if (aWritingMode.IsVertical()) {
|
||||
if (aWritingMode.IsVerticalLR()) {
|
||||
NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
|
||||
nsRect& o = aOverflowAreas.Overflow(otype);
|
||||
o.width = std::max(o.XMost(), aBEndEdgeOfChildren) - o.x;
|
||||
}
|
||||
} else {
|
||||
NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
|
||||
nsRect& o = aOverflowAreas.Overflow(otype);
|
||||
nscoord xmost = o.XMost();
|
||||
o.x = std::min(o.x, xmost - aBEndEdgeOfChildren);
|
||||
o.width = xmost - o.x;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
|
||||
nsRect& o = aOverflowAreas.Overflow(otype);
|
||||
o.height = std::max(o.YMost(), aBEndEdgeOfChildren) - o.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsBlockFrame::ComputeOverflowAreas(const nsRect& aBounds,
|
||||
const nsStyleDisplay* aDisplay,
|
||||
nscoord aBottomEdgeOfChildren,
|
||||
nscoord aBEndEdgeOfChildren,
|
||||
nsOverflowAreas& aOverflowAreas)
|
||||
{
|
||||
// Compute the overflow areas of our children
|
||||
|
@ -1625,7 +1646,8 @@ nsBlockFrame::ComputeOverflowAreas(const nsRect& aBounds,
|
|||
areas.UnionAllWith(outsideBullet->GetRect());
|
||||
}
|
||||
|
||||
ConsiderBottomEdgeOfChildren(aBottomEdgeOfChildren, areas);
|
||||
ConsiderBlockEndEdgeOfChildren(GetWritingMode(),
|
||||
aBEndEdgeOfChildren, areas);
|
||||
}
|
||||
|
||||
#ifdef NOISY_COMBINED_AREA
|
||||
|
@ -1679,10 +1701,11 @@ nsBlockFrame::UpdateOverflow()
|
|||
kPrincipalList | kFloatList);
|
||||
|
||||
bool found;
|
||||
nscoord bottomEdgeOfChildren = NS_PTR_TO_INT32(
|
||||
Properties().Get(BottomEdgeOfChildrenProperty(), &found));
|
||||
nscoord blockEndEdgeOfChildren = NS_PTR_TO_INT32(
|
||||
Properties().Get(BlockEndEdgeOfChildrenProperty(), &found));
|
||||
if (found) {
|
||||
ConsiderBottomEdgeOfChildren(bottomEdgeOfChildren, overflowAreas);
|
||||
ConsiderBlockEndEdgeOfChildren(GetWritingMode(),
|
||||
blockEndEdgeOfChildren, overflowAreas);
|
||||
}
|
||||
|
||||
return FinishAndStoreOverflow(overflowAreas, GetSize());
|
||||
|
@ -2077,7 +2100,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
|||
// Reflow the line if it might not have clearance anymore.
|
||||
if (newBCoord == curBCoord
|
||||
// aState.mBCoord is the clearance point which should be the
|
||||
// top border-edge of the block frame. If sliding the
|
||||
// block-start border-edge of the block frame. If sliding the
|
||||
// block by deltaBCoord isn't going to put it in the predicted
|
||||
// position, then we'd better reflow the line.
|
||||
|| newBCoord != line->BStart() + deltaBCoord) {
|
||||
|
@ -2156,9 +2179,9 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
|||
}
|
||||
|
||||
if (needToRecoverState && line->IsDirty()) {
|
||||
// We need to reconstruct the bottom margin only if we didn't
|
||||
// We need to reconstruct the block-end margin only if we didn't
|
||||
// reflow the previous line and we do need to reflow (or repair
|
||||
// the top position of) the next line.
|
||||
// the block-start position of) the next line.
|
||||
aState.ReconstructMarginBefore(line);
|
||||
}
|
||||
|
||||
|
@ -2227,22 +2250,22 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
|||
// Test to see whether the margin that should be carried out
|
||||
// to the next line (NL) might have changed. In ReflowBlockFrame
|
||||
// we call nextLine->MarkPreviousMarginDirty if the block's
|
||||
// actual carried-out bottom margin changed. So here we only
|
||||
// actual carried-out block-end margin changed. So here we only
|
||||
// need to worry about the following effects:
|
||||
// 1) the line was just created, and it might now be blocking
|
||||
// a carried-out bottom margin from previous lines that
|
||||
// a carried-out block-end margin from previous lines that
|
||||
// used to reach NL from reaching NL
|
||||
// 2) the line used to be empty, and is now not empty,
|
||||
// thus blocking a carried-out bottom margin from previous lines
|
||||
// thus blocking a carried-out block-end margin from previous lines
|
||||
// that used to reach NL from reaching NL
|
||||
// 3) the line wasn't empty, but now is, so a carried-out
|
||||
// bottom margin from previous lines that didn't used to reach NL
|
||||
// block-end margin from previous lines that didn't used to reach NL
|
||||
// now does
|
||||
// 4) the line might have changed in a way that affects NL's
|
||||
// ShouldApplyBStartMargin decision. The three things that matter
|
||||
// are the line's emptiness, its adjacency to the top of the block,
|
||||
// and whether it has clearance (the latter only matters if the block
|
||||
// was and is adjacent to the top and empty).
|
||||
// are the line's emptiness, its adjacency to the block-start edge of the
|
||||
// block, and whether it has clearance (the latter only matters if the
|
||||
// block was and is adjacent to the block-start and empty).
|
||||
//
|
||||
// If the line is empty now, we can't reliably tell if the line was empty
|
||||
// before, so we just assume it was and do nextLine->MarkPreviousMarginDirty.
|
||||
|
@ -2956,8 +2979,8 @@ nsBlockFrame::ShouldApplyBStartMargin(nsBlockReflowState& aState,
|
|||
if (!aState.IsAdjacentWithTop() ||
|
||||
aChildFrame->StyleBorder()->mBoxDecorationBreak ==
|
||||
NS_STYLE_BOX_DECORATION_BREAK_CLONE) {
|
||||
// If we aren't at the top Y coordinate then something of non-zero
|
||||
// height must have been placed. Therefore the childs top-margin
|
||||
// If we aren't at the start block-coordinate then something of non-zero
|
||||
// height must have been placed. Therefore the childs block-start margin
|
||||
// applies.
|
||||
aState.SetFlag(BRS_APPLYBSTARTMARGIN, true);
|
||||
return true;
|
||||
|
@ -2971,11 +2994,11 @@ nsBlockFrame::ShouldApplyBStartMargin(nsBlockReflowState& aState,
|
|||
while (line != aLine) {
|
||||
if (!line->CachedIsEmpty() || line->HasClearance()) {
|
||||
// A line which precedes aLine is non-empty, or has clearance,
|
||||
// so therefore the top margin applies.
|
||||
// so therefore the block-start margin applies.
|
||||
aState.SetFlag(BRS_APPLYBSTARTMARGIN, true);
|
||||
return true;
|
||||
}
|
||||
// No need to apply the top margin if the line has floats. We
|
||||
// No need to apply the block-start margin if the line has floats. We
|
||||
// should collapse anyway (bug 44419)
|
||||
++line;
|
||||
aState.SetFlag(BRS_HAVELINEADJACENTTOTOP, true);
|
||||
|
@ -2983,7 +3006,7 @@ nsBlockFrame::ShouldApplyBStartMargin(nsBlockReflowState& aState,
|
|||
}
|
||||
|
||||
// The line being reflowed is "essentially" the first line in the
|
||||
// block. Therefore its top-margin will be collapsed by the
|
||||
// block. Therefore its block-start margin will be collapsed by the
|
||||
// generational collapsing logic with its parent (us).
|
||||
return false;
|
||||
}
|
||||
|
@ -3015,9 +3038,9 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
|||
// Clear past floats before the block if the clear style is not none
|
||||
aLine->SetBreakTypeBefore(breakType);
|
||||
|
||||
// See if we should apply the top margin. If the block frame being
|
||||
// See if we should apply the block-start margin. If the block frame being
|
||||
// reflowed is a continuation (non-null prev-in-flow) then we don't
|
||||
// apply its top margin because it's not significant unless it has
|
||||
// apply its block-start margin because it's not significant unless it has
|
||||
// 'box-decoration-break:clone'. Otherwise, dig deeper.
|
||||
bool applyBStartMargin = (frame->StyleBorder()->mBoxDecorationBreak ==
|
||||
NS_STYLE_BOX_DECORATION_BREAK_CLONE ||
|
||||
|
@ -3025,7 +3048,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
|||
ShouldApplyBStartMargin(aState, aLine, frame);
|
||||
if (applyBStartMargin) {
|
||||
// The HasClearance setting is only valid if ShouldApplyBStartMargin
|
||||
// returned false (in which case the top-margin-root set our
|
||||
// returned false (in which case the block-start margin-root set our
|
||||
// clearance flag). Otherwise clear it now. We'll set it later on
|
||||
// ourselves if necessary.
|
||||
aLine->ClearHasClearance();
|
||||
|
@ -3039,8 +3062,8 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
|||
replacedBlock = frame;
|
||||
}
|
||||
|
||||
// If our top margin was counted as part of some parents top-margin
|
||||
// collapse and we are being speculatively reflowed assuming this
|
||||
// If our block-start margin was counted as part of some parent's block-start
|
||||
// margin collapse, and we are being speculatively reflowed assuming this
|
||||
// frame DID NOT need clearance, then we need to check that
|
||||
// assumption.
|
||||
if (!treatWithClearance && !applyBStartMargin && mightClearFloats &&
|
||||
|
@ -3080,19 +3103,19 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
|||
bool mayNeedRetry = false;
|
||||
bool clearedFloats = false;
|
||||
if (applyBStartMargin) {
|
||||
// Precompute the blocks top margin value so that we can get the
|
||||
// Precompute the blocks block-start margin value so that we can get the
|
||||
// correct available space (there might be a float that's
|
||||
// already been placed below the aState.mPrevBEndMargin
|
||||
|
||||
// Setup a reflowState to get the style computed margin-top
|
||||
// Setup a reflowState to get the style computed block-start margin
|
||||
// value. We'll use a reason of `resize' so that we don't fudge
|
||||
// any incremental reflow state.
|
||||
|
||||
// The availSpace here is irrelevant to our needs - all we want
|
||||
// out if this setup is the margin-top value which doesn't depend
|
||||
// out if this setup is the block-start margin value which doesn't depend
|
||||
// on the childs available space.
|
||||
// XXX building a complete nsHTMLReflowState just to get the margin-top
|
||||
// seems like a waste. And we do this for almost every block!
|
||||
// XXX building a complete nsHTMLReflowState just to get the block-start
|
||||
// margin seems like a waste. And we do this for almost every block!
|
||||
WritingMode wm = frame->GetWritingMode();
|
||||
LogicalSize availSpace = aState.ContentSize(wm);
|
||||
availSpace.BSize(wm) = NS_UNCONSTRAINEDSIZE;
|
||||
|
@ -3117,7 +3140,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
|||
|
||||
if (clearanceFrame) {
|
||||
// Don't allow retries on the second pass. The clearance decisions for the
|
||||
// blocks whose top-margins collapse with ours are now fixed.
|
||||
// blocks whose block-start margins collapse with ours are now fixed.
|
||||
mayNeedRetry = false;
|
||||
}
|
||||
|
||||
|
@ -3173,7 +3196,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
|||
// Note that negative clearance is possible
|
||||
clearance = aState.mBCoord - (currentBCoord + bStartMargin);
|
||||
|
||||
// Add clearance to our top margin while we compute available
|
||||
// Add clearance to our block-start margin while we compute available
|
||||
// space for the frame
|
||||
bStartMargin += clearance;
|
||||
|
||||
|
@ -3200,14 +3223,14 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
|||
|
||||
// The check for
|
||||
// (!aState.mReflowState.mFlags.mIsTopOfPage || clearedFloats)
|
||||
// is to some degree out of paranoia: if we reliably eat up top
|
||||
// is to some degree out of paranoia: if we reliably eat up block-start
|
||||
// margins at the top of the page as we ought to, it wouldn't be
|
||||
// needed.
|
||||
if ((!aState.mReflowState.mFlags.mIsTopOfPage || clearedFloats) &&
|
||||
availSpace.BSize(wm) < 0) {
|
||||
// We know already that this child block won't fit on this
|
||||
// page/column due to the top margin or the clearance. So we need
|
||||
// to get out of here now. (If we don't, most blocks will handle
|
||||
// page/column due to the block-start margin or the clearance. So we
|
||||
// need to get out of here now. (If we don't, most blocks will handle
|
||||
// things fine, and report break-before, but zero-height blocks
|
||||
// won't, and will thus make their parent overly-large and force
|
||||
// *it* to be pushed in its entirety.)
|
||||
|
@ -3393,7 +3416,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
|||
}
|
||||
*aKeepReflowGoing = false;
|
||||
|
||||
// The bottom margin for a block is only applied on the last
|
||||
// The block-end margin for a block is only applied on the last
|
||||
// flow block. Since we just continued the child block frame,
|
||||
// we know that line->mFirstChild is not the last flow block
|
||||
// therefore zero out the running margin value.
|
||||
|
@ -3494,7 +3517,7 @@ nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState,
|
|||
aLine->SetLineIsImpactedByFloat(false);
|
||||
|
||||
// Setup initial coordinate system for reflowing the inline frames
|
||||
// into. Apply a previous block frame's bottom margin first.
|
||||
// into. Apply a previous block frame's block-end margin first.
|
||||
if (ShouldApplyBStartMargin(aState, aLine, aLine->mFirstChild)) {
|
||||
aState.mBCoord += aState.mPrevBEndMargin.get();
|
||||
}
|
||||
|
@ -4286,9 +4309,9 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
|||
|
||||
// Inline lines do not have margins themselves; however they are
|
||||
// impacted by prior block margins. If this line ends up having some
|
||||
// height then we zero out the previous bottom margin value that was
|
||||
// height then we zero out the previous block-end margin value that was
|
||||
// already applied to the line's starting Y coordinate. Otherwise we
|
||||
// leave it be so that the previous blocks bottom margin can be
|
||||
// leave it be so that the previous blocks block-end margin can be
|
||||
// collapsed with a block that follows.
|
||||
nscoord newBCoord;
|
||||
|
||||
|
@ -5898,7 +5921,7 @@ nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
|
|||
nsCollapsingMargin margin;
|
||||
bool mayNeedRetry = false;
|
||||
floatRS.mDiscoveredClearance = nullptr;
|
||||
// Only first in flow gets a top margin.
|
||||
// Only first in flow gets a block-start margin.
|
||||
if (!aFloat->GetPrevInFlow()) {
|
||||
brc.ComputeCollapsedBStartMargin(floatRS, &margin,
|
||||
clearanceFrame,
|
||||
|
|
|
@ -351,7 +351,7 @@ nsBlockReflowContext::PlaceBlock(const nsHTMLReflowState& aReflowState,
|
|||
WritingMode wm = aReflowState.GetWritingMode();
|
||||
WritingMode parentWM = mMetrics.GetWritingMode();
|
||||
if (NS_FRAME_IS_COMPLETE(aReflowStatus)) {
|
||||
aBEndMarginResult = mMetrics.mCarriedOutBottomMargin;
|
||||
aBEndMarginResult = mMetrics.mCarriedOutBEndMargin;
|
||||
aBEndMarginResult.Include(aReflowState.ComputedLogicalMargin().BEnd(wm));
|
||||
} else {
|
||||
// The used bottom-margin is set to zero above a break.
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
nsReflowStatus aReflowStatus);
|
||||
|
||||
nsCollapsingMargin& GetCarriedOutBEndMargin() {
|
||||
return mMetrics.mCarriedOutBottomMargin;
|
||||
return mMetrics.mCarriedOutBEndMargin;
|
||||
}
|
||||
|
||||
const nsHTMLReflowMetrics& GetMetrics() const {
|
||||
|
|
|
@ -572,12 +572,12 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
|
|||
#ifdef DEBUG_roc
|
||||
printf("*** Reflowed child #%d %p: status = %d, desiredSize=%d,%d CarriedOutBottomMargin=%d\n",
|
||||
columnCount, (void*)child, aStatus, kidDesiredSize.Width(), kidDesiredSize.Height(),
|
||||
kidDesiredSize.mCarriedOutBottomMargin.get());
|
||||
kidDesiredSize.mCarriedOutBEndMargin.get());
|
||||
#endif
|
||||
|
||||
NS_FRAME_TRACE_REFLOW_OUT("Column::Reflow", aStatus);
|
||||
|
||||
*aBottomMarginCarriedOut = kidDesiredSize.mCarriedOutBottomMargin;
|
||||
*aBottomMarginCarriedOut = kidDesiredSize.mCarriedOutBEndMargin;
|
||||
|
||||
FinishReflowChild(child, PresContext(), kidDesiredSize,
|
||||
&kidReflowState, childOrigin.x, childOrigin.y, 0);
|
||||
|
@ -1030,7 +1030,7 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
|
|||
|
||||
FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus, false);
|
||||
|
||||
aDesiredSize.mCarriedOutBottomMargin = carriedOutBottomMargin;
|
||||
aDesiredSize.mCarriedOutBEndMargin = carriedOutBottomMargin;
|
||||
|
||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
|
||||
}
|
||||
|
|
|
@ -5405,7 +5405,7 @@ nsFrame::IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState,
|
|||
ClearOverflowRects();
|
||||
aMetrics.ClearSize();
|
||||
aMetrics.SetBlockStartAscent(0);
|
||||
aMetrics.mCarriedOutBottomMargin.Zero();
|
||||
aMetrics.mCarriedOutBEndMargin.Zero();
|
||||
aMetrics.mOverflowAreas.Clear();
|
||||
|
||||
if (GetNextInFlow()) {
|
||||
|
|
|
@ -419,37 +419,63 @@ nsHTMLScrollFrame::ReflowScrolledFrame(ScrollReflowState* aState,
|
|||
nsHTMLReflowMetrics* aMetrics,
|
||||
bool aFirstPass)
|
||||
{
|
||||
WritingMode wm = mHelper.mScrolledFrame->GetWritingMode();
|
||||
|
||||
// these could be NS_UNCONSTRAINEDSIZE ... std::min arithmetic should
|
||||
// be OK
|
||||
const nsMargin& padding = aState->mReflowState.ComputedPhysicalPadding();
|
||||
nscoord availWidth = aState->mReflowState.ComputedWidth() + padding.LeftRight();
|
||||
LogicalMargin padding = aState->mReflowState.ComputedLogicalPadding();
|
||||
nscoord availISize =
|
||||
aState->mReflowState.ComputedISize() + padding.IStartEnd(wm);
|
||||
|
||||
nscoord computedHeight = aState->mReflowState.ComputedHeight();
|
||||
nscoord computedMinHeight = aState->mReflowState.ComputedMinHeight();
|
||||
nscoord computedMaxHeight = aState->mReflowState.ComputedMaxHeight();
|
||||
nscoord computedBSize = aState->mReflowState.ComputedBSize();
|
||||
nscoord computedMinBSize = aState->mReflowState.ComputedMinBSize();
|
||||
nscoord computedMaxBSize = aState->mReflowState.ComputedMaxBSize();
|
||||
if (!ShouldPropagateComputedHeightToScrolledContent()) {
|
||||
computedHeight = NS_UNCONSTRAINEDSIZE;
|
||||
computedMinHeight = 0;
|
||||
computedMaxHeight = NS_UNCONSTRAINEDSIZE;
|
||||
}
|
||||
if (aAssumeHScroll) {
|
||||
nsSize hScrollbarPrefSize;
|
||||
GetScrollbarMetrics(aState->mBoxState, mHelper.mHScrollbarBox,
|
||||
nullptr, &hScrollbarPrefSize, false);
|
||||
if (computedHeight != NS_UNCONSTRAINEDSIZE) {
|
||||
computedHeight = std::max(0, computedHeight - hScrollbarPrefSize.height);
|
||||
}
|
||||
computedMinHeight = std::max(0, computedMinHeight - hScrollbarPrefSize.height);
|
||||
if (computedMaxHeight != NS_UNCONSTRAINEDSIZE) {
|
||||
computedMaxHeight = std::max(0, computedMaxHeight - hScrollbarPrefSize.height);
|
||||
}
|
||||
computedBSize = NS_UNCONSTRAINEDSIZE;
|
||||
computedMinBSize = 0;
|
||||
computedMaxBSize = NS_UNCONSTRAINEDSIZE;
|
||||
}
|
||||
|
||||
if (aAssumeVScroll) {
|
||||
nsSize vScrollbarPrefSize;
|
||||
GetScrollbarMetrics(aState->mBoxState, mHelper.mVScrollbarBox,
|
||||
nullptr, &vScrollbarPrefSize, true);
|
||||
availWidth = std::max(0, availWidth - vScrollbarPrefSize.width);
|
||||
if (wm.IsVertical()) {
|
||||
if (aAssumeVScroll) {
|
||||
nsSize vScrollbarPrefSize;
|
||||
GetScrollbarMetrics(aState->mBoxState, mHelper.mVScrollbarBox,
|
||||
nullptr, &vScrollbarPrefSize, false);
|
||||
if (computedBSize != NS_UNCONSTRAINEDSIZE) {
|
||||
computedBSize = std::max(0, computedBSize - vScrollbarPrefSize.width);
|
||||
}
|
||||
computedMinBSize = std::max(0, computedMinBSize - vScrollbarPrefSize.width);
|
||||
if (computedMaxBSize != NS_UNCONSTRAINEDSIZE) {
|
||||
computedMaxBSize = std::max(0, computedMaxBSize - vScrollbarPrefSize.width);
|
||||
}
|
||||
}
|
||||
|
||||
if (aAssumeHScroll) {
|
||||
nsSize hScrollbarPrefSize;
|
||||
GetScrollbarMetrics(aState->mBoxState, mHelper.mHScrollbarBox,
|
||||
nullptr, &hScrollbarPrefSize, true);
|
||||
availISize = std::max(0, availISize - hScrollbarPrefSize.height);
|
||||
}
|
||||
} else {
|
||||
if (aAssumeHScroll) {
|
||||
nsSize hScrollbarPrefSize;
|
||||
GetScrollbarMetrics(aState->mBoxState, mHelper.mHScrollbarBox,
|
||||
nullptr, &hScrollbarPrefSize, false);
|
||||
if (computedBSize != NS_UNCONSTRAINEDSIZE) {
|
||||
computedBSize = std::max(0, computedBSize - hScrollbarPrefSize.height);
|
||||
}
|
||||
computedMinBSize = std::max(0, computedMinBSize - hScrollbarPrefSize.height);
|
||||
if (computedMaxBSize != NS_UNCONSTRAINEDSIZE) {
|
||||
computedMaxBSize = std::max(0, computedMaxBSize - hScrollbarPrefSize.height);
|
||||
}
|
||||
}
|
||||
|
||||
if (aAssumeVScroll) {
|
||||
nsSize vScrollbarPrefSize;
|
||||
GetScrollbarMetrics(aState->mBoxState, mHelper.mVScrollbarBox,
|
||||
nullptr, &vScrollbarPrefSize, true);
|
||||
availISize = std::max(0, availISize - vScrollbarPrefSize.width);
|
||||
}
|
||||
}
|
||||
|
||||
nsPresContext* presContext = PresContext();
|
||||
|
@ -458,16 +484,16 @@ nsHTMLScrollFrame::ReflowScrolledFrame(ScrollReflowState* aState,
|
|||
nsHTMLReflowState
|
||||
kidReflowState(presContext, aState->mReflowState,
|
||||
mHelper.mScrolledFrame,
|
||||
LogicalSize(mHelper.mScrolledFrame->GetWritingMode(),
|
||||
nsSize(availWidth, NS_UNCONSTRAINEDSIZE)),
|
||||
LogicalSize(wm, availISize, NS_UNCONSTRAINEDSIZE),
|
||||
-1, -1, nsHTMLReflowState::CALLER_WILL_INIT);
|
||||
const nsMargin physicalPadding = padding.GetPhysicalMargin(wm);
|
||||
kidReflowState.Init(presContext, -1, -1, nullptr,
|
||||
&padding);
|
||||
&physicalPadding);
|
||||
kidReflowState.mFlags.mAssumingHScrollbar = aAssumeHScroll;
|
||||
kidReflowState.mFlags.mAssumingVScrollbar = aAssumeVScroll;
|
||||
kidReflowState.SetComputedHeight(computedHeight);
|
||||
kidReflowState.ComputedMinHeight() = computedMinHeight;
|
||||
kidReflowState.ComputedMaxHeight() = computedMaxHeight;
|
||||
kidReflowState.SetComputedBSize(computedBSize);
|
||||
kidReflowState.ComputedMinBSize() = computedMinBSize;
|
||||
kidReflowState.ComputedMaxBSize() = computedMaxBSize;
|
||||
|
||||
// Temporarily set mHasHorizontalScrollbar/mHasVerticalScrollbar to
|
||||
// reflect our assumptions while we reflow the child.
|
||||
|
@ -507,8 +533,10 @@ nsHTMLScrollFrame::ReflowScrolledFrame(ScrollReflowState* aState,
|
|||
nsOverflowAreas childOverflow;
|
||||
nsLayoutUtils::UnionChildOverflow(mHelper.mScrolledFrame, childOverflow);
|
||||
nsRect childScrollableOverflow = childOverflow.ScrollableOverflow();
|
||||
childScrollableOverflow.Inflate(padding);
|
||||
nsRect contentArea = nsRect(0, 0, availWidth, computedHeight);
|
||||
childScrollableOverflow.Inflate(padding.GetPhysicalMargin(wm));
|
||||
nsRect contentArea =
|
||||
wm.IsVertical() ? nsRect(0, 0, computedBSize, availISize)
|
||||
: nsRect(0, 0, availISize, computedBSize);
|
||||
if (!contentArea.Contains(childScrollableOverflow)) {
|
||||
aMetrics->mOverflowAreas.ScrollableOverflow() = childScrollableOverflow;
|
||||
}
|
||||
|
@ -4128,7 +4156,8 @@ ScrollFrameHelper::IsLTR() const
|
|||
}
|
||||
}
|
||||
|
||||
return frame->StyleVisibility()->mDirection != NS_STYLE_DIRECTION_RTL;
|
||||
WritingMode wm = frame->GetWritingMode();
|
||||
return wm.IsVertical() ? wm.IsVerticalLR() : wm.IsBidiLTR();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -4584,13 +4613,21 @@ ScrollFrameHelper::AdjustScrollbarRectForResizer(
|
|||
aPresContext->DevPixelsToAppUnits(widgetRect.height));
|
||||
}
|
||||
|
||||
if (!resizerRect.Contains(aRect.BottomRight() - nsPoint(1, 1)))
|
||||
return;
|
||||
|
||||
if (aVertical)
|
||||
aRect.height = std::max(0, resizerRect.y - aRect.y);
|
||||
else
|
||||
aRect.width = std::max(0, resizerRect.x - aRect.x);
|
||||
if (resizerRect.Contains(aRect.BottomRight() - nsPoint(1, 1))) {
|
||||
if (aVertical) {
|
||||
aRect.height = std::max(0, resizerRect.y - aRect.y);
|
||||
} else {
|
||||
aRect.width = std::max(0, resizerRect.x - aRect.x);
|
||||
}
|
||||
} else if (resizerRect.Contains(aRect.BottomLeft() + nsPoint(1, -1))) {
|
||||
if (aVertical) {
|
||||
aRect.height = std::max(0, resizerRect.y - aRect.y);
|
||||
} else {
|
||||
nscoord xmost = aRect.XMost();
|
||||
aRect.x = std::max(aRect.x, resizerRect.XMost());
|
||||
aRect.width = xmost - aRect.x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -287,9 +287,9 @@ public:
|
|||
// of the base and the text of the superscript.
|
||||
nsBoundingMetrics mBoundingMetrics; // [OUT]
|
||||
|
||||
// Carried out bottom margin values. This is the collapsed
|
||||
// (generational) bottom margin value.
|
||||
nsCollapsingMargin mCarriedOutBottomMargin;
|
||||
// Carried out block-end margin values. This is the collapsed
|
||||
// (generational) block-end margin value.
|
||||
nsCollapsingMargin mCarriedOutBEndMargin;
|
||||
|
||||
// For frames that have content that overflow their content area
|
||||
// (HasOverflowAreas() is true) these rectangles represent the total
|
||||
|
|
|
@ -565,6 +565,19 @@ RenderFrameParent::HitTest(const nsRect& aRect)
|
|||
return mTouchRegion.Contains(aRect);
|
||||
}
|
||||
|
||||
void
|
||||
RenderFrameParent::GetTextureFactoryIdentifier(TextureFactoryIdentifier* aTextureFactoryIdentifier)
|
||||
{
|
||||
nsRefPtr<LayerManager> lm = GetFrom(mFrameLoader);
|
||||
// Perhaps the document containing this frame currently has no presentation?
|
||||
if (lm && lm->GetBackendType() == LayersBackend::LAYERS_CLIENT) {
|
||||
*aTextureFactoryIdentifier =
|
||||
static_cast<ClientLayerManager*>(lm.get())->GetTextureFactoryIdentifier();
|
||||
} else {
|
||||
*aTextureFactoryIdentifier = TextureFactoryIdentifier();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace layout
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -109,6 +109,11 @@ public:
|
|||
|
||||
bool HitTest(const nsRect& aRect);
|
||||
|
||||
bool UseAsyncPanZoom() { return !!mContentController; }
|
||||
|
||||
void GetTextureFactoryIdentifier(TextureFactoryIdentifier* aTextureFactoryIdentifier);
|
||||
|
||||
inline uint64_t GetLayersId() { return mLayersId; }
|
||||
protected:
|
||||
void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
/**************************************************************************/
|
||||
|
||||
math {
|
||||
writing-mode: horizontal-tb !important;
|
||||
direction: ltr;
|
||||
unicode-bidi: embed;
|
||||
display: inline;
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
|
||||
# more serious tests, using SVG reference
|
||||
== border-circle-2.html border-circle-2-ref.xhtml
|
||||
fails == curved-stripe-border.html curved-stripe-border-ref.svg # bug 459945
|
||||
fuzzy-if(gtk2Widget,7,437) fuzzy-if(azureQuartz,4,582) fuzzy-if(Android||B2G,36,264) fuzzy-if(d2d,51,323) fuzzy-if(winWidget&&!d2d,16,377) == curved-stripe-border.html curved-stripe-border-ref.svg # bug 459945
|
||||
|
||||
# Corners
|
||||
== corner-1.html corner-1-ref.svg # bottom corners different radius than top corners
|
||||
random == corner-2.html corner-2-ref.svg # right corners different radius than left corners; see bug 500804
|
||||
fuzzy-if(winWidget&&!d2d,23,5) fuzzy-if(d2d,32,8) fuzzy-if(Android||B2G,10,8) == corner-2.html corner-2-ref.svg # right corners different radius than left corners; see bug 500804
|
||||
fuzzy-if(winWidget&&!d2d,3,10) fuzzy-if(d2d,15,32) fuzzy-if(Android||B2G,3,15) == corner-3.html corner-3-ref.svg
|
||||
== corner-4.html corner-4-ref.svg
|
||||
|
||||
|
@ -39,7 +39,7 @@ fuzzy-if(winWidget&&!d2d,3,10) fuzzy-if(d2d,15,32) fuzzy-if(Android||B2G,3,15) =
|
|||
fails == clipping-1.html clipping-1-ref.html # background color should completely fill box; bug 466572
|
||||
!= clipping-2.html about:blank # background color clipped to inner/outer border, can't get
|
||||
# great tests for this due to antialiasing problems described in bug 466572
|
||||
fuzzy-if(Android&&AndroidVersion<15,9,73) fuzzy-if(Android&&AndroidVersion>=15,9,200) == clipping-3.html clipping-3-ref.xhtml # edge of border-radius clips an underlying object's background
|
||||
== clipping-3.html clipping-3-ref.xhtml # edge of border-radius clips an underlying object's background
|
||||
|
||||
# Tests for clipping the contents of replaced elements and overflow!=visible
|
||||
!= clipping-4-ref.html clipping-4-notref.html
|
||||
|
@ -87,6 +87,6 @@ skip-if(B2G) fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,20) fuzzy-if(A
|
|||
== iframe-1.html iframe-1-ref.html
|
||||
|
||||
# Test for antialiasing gaps between background and border
|
||||
skip-if(B2G) fails-if(d2d) fuzzy-if(winWidget&&!d2d,1,9) fuzzy-if(Android,1,5) == curved-border-background-nogap.html curved-border-background-nogap-ref.html
|
||||
fuzzy-if(winWidget&&!d2d,1,9) fuzzy-if(d2d,5,40) fuzzy-if(Android||B2G,1,5) == curved-border-background-nogap.html curved-border-background-nogap-ref.html
|
||||
|
||||
== color-layer-1a.html color-layer-1-ref.html
|
||||
|
|
|
@ -1195,9 +1195,9 @@ test-pref(dom.use_xbl_scopes_for_remote_xul,true) != 449149-1b.html about:blank
|
|||
== 455280-1.xhtml 455280-1-ref.xhtml
|
||||
skip-if(B2G) fails-if(Android) == 455826-1.html 455826-1-ref.html
|
||||
skip-if(B2G) fails-if(cocoaWidget) fails-if(Android) == 456147.xul 456147-ref.html # bug 458047
|
||||
skip-if(B2G) fails-if(Android) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu),1,1) fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,69) == 456219-1a.html 456219-1-ref.html # bug 853273
|
||||
skip-if(B2G) fails-if(Android) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu),1,1) fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,69) == 456219-1b.html 456219-1-ref.html # bug 853273
|
||||
skip-if(B2G) fails-if(Android) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu),1,1) fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,69) == 456219-1c.html 456219-1-ref.html # bug 853273
|
||||
fuzzy-if(Android,11,40) fuzzy-if(B2G,11,35) fuzzy-if(d2d&&/^Windows\x20NT\x206\.2/.test(http.oscpu),1,69) == 456219-1a.html 456219-1-ref.html # bug 853273
|
||||
fuzzy-if(Android,11,40) fuzzy-if(B2G,11,35) fuzzy-if(d2d&&/^Windows\x20NT\x206\.2/.test(http.oscpu),1,69) == 456219-1b.html 456219-1-ref.html # bug 853273
|
||||
fuzzy-if(Android,11,40) fuzzy-if(B2G,11,35) fuzzy-if(d2d&&/^Windows\x20NT\x206\.2/.test(http.oscpu),1,69) == 456219-1c.html 456219-1-ref.html # bug 853273
|
||||
== 456219-2.html 456219-2-ref.html
|
||||
== 456330-1.gif 456330-1-ref.png
|
||||
== 456484-1.html 456484-1-ref.html
|
||||
|
|
|
@ -17,7 +17,7 @@ fuzzy-if(d2d&&/^Windows\x20NT\x206\.1/.test(http.oscpu),16,90) == element-paint-
|
|||
== element-paint-background-size-02.html element-paint-background-size-02-ref.html
|
||||
== element-paint-transform-repeated.html element-paint-transform-repeated-ref.html
|
||||
fuzzy-if(d2d,255,24) == element-paint-transform-03.html element-paint-transform-03-ref.html
|
||||
fuzzy-if(B2G,1,5) fuzzy-if(gtk2Widget,1,32) fuzzy-if(cocoaWidget,1,106) == element-paint-native-widget.html element-paint-native-widget-ref.html
|
||||
== element-paint-native-widget.html element-paint-native-widget-ref.html
|
||||
== element-paint-subimage-sampling-restriction.html about:blank
|
||||
== element-paint-clippath.html element-paint-clippath-ref.html
|
||||
== element-paint-sharpness-01a.html element-paint-sharpness-01b.html
|
||||
|
|
|
@ -52,6 +52,7 @@ namespace css {
|
|||
|
||||
CommonAnimationManager::CommonAnimationManager(nsPresContext *aPresContext)
|
||||
: mPresContext(aPresContext)
|
||||
, mIsObservingRefreshDriver(false)
|
||||
{
|
||||
PR_INIT_CLIST(&mElementCollections);
|
||||
}
|
||||
|
@ -70,6 +71,21 @@ CommonAnimationManager::Disconnect()
|
|||
mPresContext = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
CommonAnimationManager::AddElementCollection(AnimationPlayerCollection*
|
||||
aCollection)
|
||||
{
|
||||
if (!mIsObservingRefreshDriver) {
|
||||
NS_ASSERTION(aCollection->mNeedsRefreshes,
|
||||
"Added data which doesn't need refreshing?");
|
||||
// We need to observe the refresh driver.
|
||||
mPresContext->RefreshDriver()->AddRefreshObserver(this, Flush_Style);
|
||||
mIsObservingRefreshDriver = true;
|
||||
}
|
||||
|
||||
PR_INSERT_BEFORE(aCollection, &mElementCollections);
|
||||
}
|
||||
|
||||
void
|
||||
CommonAnimationManager::RemoveAllElementCollections()
|
||||
{
|
||||
|
@ -81,6 +97,26 @@ CommonAnimationManager::RemoveAllElementCollections()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
CommonAnimationManager::CheckNeedsRefresh()
|
||||
{
|
||||
for (PRCList *l = PR_LIST_HEAD(&mElementCollections);
|
||||
l != &mElementCollections;
|
||||
l = PR_NEXT_LINK(l)) {
|
||||
if (static_cast<AnimationPlayerCollection*>(l)->mNeedsRefreshes) {
|
||||
if (!mIsObservingRefreshDriver) {
|
||||
mPresContext->RefreshDriver()->AddRefreshObserver(this, Flush_Style);
|
||||
mIsObservingRefreshDriver = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (mIsObservingRefreshDriver) {
|
||||
mIsObservingRefreshDriver = false;
|
||||
mPresContext->RefreshDriver()->RemoveRefreshObserver(this, Flush_Style);
|
||||
}
|
||||
}
|
||||
|
||||
AnimationPlayerCollection*
|
||||
CommonAnimationManager::GetAnimationsForCompositor(nsIContent* aContent,
|
||||
nsIAtom* aElementProperty,
|
||||
|
@ -102,10 +138,12 @@ CommonAnimationManager::GetAnimationsForCompositor(nsIContent* aContent,
|
|||
// Mark the frame as active, in case we are able to throttle this animation.
|
||||
nsIFrame* frame = nsLayoutUtils::GetStyleFrame(collection->mElement);
|
||||
if (frame) {
|
||||
if (aProperty == eCSSProperty_opacity) {
|
||||
ActiveLayerTracker::NotifyAnimated(frame, eCSSProperty_opacity);
|
||||
} else if (aProperty == eCSSProperty_transform) {
|
||||
ActiveLayerTracker::NotifyAnimated(frame, eCSSProperty_transform);
|
||||
const auto& info = sLayerAnimationInfo;
|
||||
for (size_t i = 0; i < ArrayLength(info); i++) {
|
||||
if (aProperty == info[i].mProperty) {
|
||||
ActiveLayerTracker::NotifyAnimated(frame, aProperty);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,6 +227,17 @@ CommonAnimationManager::AddStyleUpdatesTo(RestyleTracker& aTracker)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
CommonAnimationManager::NotifyCollectionUpdated(AnimationPlayerCollection&
|
||||
aCollection)
|
||||
{
|
||||
CheckNeedsRefresh();
|
||||
mPresContext->ClearLastStyleUpdateForAllAnimations();
|
||||
mPresContext->RestyleManager()->IncrementAnimationGeneration();
|
||||
aCollection.UpdateAnimationGeneration(mPresContext);
|
||||
aCollection.PostRestyleForAnimation(mPresContext);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
CommonAnimationManager::ExtractComputedValueForTransition(
|
||||
nsCSSProperty aProperty,
|
||||
|
@ -208,6 +257,15 @@ CommonAnimationManager::ExtractComputedValueForTransition(
|
|||
return result;
|
||||
}
|
||||
|
||||
/* static */ const CommonAnimationManager::LayerAnimationRecord
|
||||
CommonAnimationManager::sLayerAnimationInfo[] =
|
||||
{ { eCSSProperty_transform,
|
||||
nsDisplayItem::TYPE_TRANSFORM,
|
||||
nsChangeHint_UpdateTransformLayer },
|
||||
{ eCSSProperty_opacity,
|
||||
nsDisplayItem::TYPE_OPACITY,
|
||||
nsChangeHint_UpdateOpacityLayer } };
|
||||
|
||||
NS_IMPL_ISUPPORTS(AnimValuesStyleRule, nsIStyleRule)
|
||||
|
||||
/* virtual */ void
|
||||
|
@ -438,6 +496,16 @@ AnimationPlayerCollection::GetElementToRestyle() const
|
|||
return pseudoFrame->GetContent()->AsElement();
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayerCollection::NotifyPlayerUpdated()
|
||||
{
|
||||
// On the next flush, force us to update the style rule
|
||||
mNeedsRefreshes = true;
|
||||
mStyleRuleRefreshTime = TimeStamp();
|
||||
|
||||
mManager->NotifyCollectionUpdated(*this);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
AnimationPlayerCollection::LogAsyncAnimationFailure(nsCString& aMessage,
|
||||
const nsIContent* aContent)
|
||||
|
@ -527,8 +595,9 @@ AnimationPlayerCollection::EnsureStyleRuleFor(TimeStamp aRefreshTime,
|
|||
mNeedsRefreshes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mManager->CheckNeedsRefresh();
|
||||
}
|
||||
|
||||
bool
|
||||
AnimationPlayerCollection::CanThrottleTransformChanges(TimeStamp aTime)
|
||||
|
@ -546,7 +615,8 @@ AnimationPlayerCollection::CanThrottleTransformChanges(TimeStamp aTime)
|
|||
}
|
||||
|
||||
// If this animation can cause overflow, we can throttle some of the ticks.
|
||||
if ((aTime - mStyleRuleRefreshTime) < TimeDuration::FromMilliseconds(200)) {
|
||||
if (!mStyleRuleRefreshTime.IsNull() &&
|
||||
(aTime - mStyleRuleRefreshTime) < TimeDuration::FromMilliseconds(200)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -576,27 +646,27 @@ AnimationPlayerCollection::CanThrottleAnimation(TimeStamp aTime)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool hasTransform = HasAnimationOfProperty(eCSSProperty_transform);
|
||||
bool hasOpacity = HasAnimationOfProperty(eCSSProperty_opacity);
|
||||
if (hasOpacity) {
|
||||
|
||||
const auto& info = css::CommonAnimationManager::sLayerAnimationInfo;
|
||||
for (size_t i = 0; i < ArrayLength(info); i++) {
|
||||
auto record = info[i];
|
||||
if (!HasAnimationOfProperty(record.mProperty)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Layer* layer = FrameLayerBuilder::GetDedicatedLayer(
|
||||
frame, nsDisplayItem::TYPE_OPACITY);
|
||||
frame, record.mLayerType);
|
||||
if (!layer || mAnimationGeneration > layer->GetAnimationGeneration()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (record.mProperty == eCSSProperty_transform &&
|
||||
!CanThrottleTransformChanges(aTime)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasTransform) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Layer* layer = FrameLayerBuilder::GetDedicatedLayer(
|
||||
frame, nsDisplayItem::TYPE_TRANSFORM);
|
||||
if (!layer || mAnimationGeneration > layer->GetAnimationGeneration()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return CanThrottleTransformChanges(aTime);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
#include "nsIStyleRule.h"
|
||||
#include "nsRefreshDriver.h"
|
||||
#include "prclist.h"
|
||||
#include "nsChangeHint.h"
|
||||
#include "nsCSSProperty.h"
|
||||
#include "nsDisplayList.h" // For nsDisplayItem::Type
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/StyleAnimationValue.h"
|
||||
#include "mozilla/dom/AnimationPlayer.h"
|
||||
|
@ -66,6 +68,15 @@ public:
|
|||
// elements.
|
||||
void AddStyleUpdatesTo(mozilla::RestyleTracker& aTracker);
|
||||
|
||||
virtual AnimationPlayerCollection*
|
||||
GetAnimationPlayers(dom::Element *aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
bool aCreateIfNeeded) = 0;
|
||||
|
||||
// Notify this manager that one of its collections of animation players,
|
||||
// has been updated.
|
||||
void NotifyCollectionUpdated(AnimationPlayerCollection& aCollection);
|
||||
|
||||
enum FlushFlags {
|
||||
Can_Throttle,
|
||||
Cannot_Throttle
|
||||
|
@ -75,17 +86,34 @@ public:
|
|||
nsCSSProperty aProperty,
|
||||
nsStyleContext* aStyleContext,
|
||||
mozilla::StyleAnimationValue& aComputedValue);
|
||||
|
||||
// For CSS properties that may be animated on a separate layer, represents
|
||||
// a record of the corresponding layer type and change hint.
|
||||
struct LayerAnimationRecord {
|
||||
nsCSSProperty mProperty;
|
||||
nsDisplayItem::Type mLayerType;
|
||||
nsChangeHint mChangeHint;
|
||||
};
|
||||
|
||||
protected:
|
||||
static const size_t kLayerRecords = 2;
|
||||
|
||||
public:
|
||||
static const LayerAnimationRecord sLayerAnimationInfo[kLayerRecords];
|
||||
|
||||
protected:
|
||||
virtual ~CommonAnimationManager();
|
||||
|
||||
// For ElementCollectionRemoved
|
||||
friend struct mozilla::AnimationPlayerCollection;
|
||||
|
||||
virtual void
|
||||
AddElementCollection(AnimationPlayerCollection* aCollection) = 0;
|
||||
virtual void ElementCollectionRemoved() = 0;
|
||||
void AddElementCollection(AnimationPlayerCollection* aCollection);
|
||||
void ElementCollectionRemoved() { CheckNeedsRefresh(); }
|
||||
void RemoveAllElementCollections();
|
||||
|
||||
// Check to see if we should stop or start observing the refresh driver
|
||||
void CheckNeedsRefresh();
|
||||
|
||||
// When this returns a value other than nullptr, it also,
|
||||
// as a side-effect, notifies the ActiveLayerTracker.
|
||||
static AnimationPlayerCollection*
|
||||
|
@ -95,6 +123,7 @@ protected:
|
|||
|
||||
PRCList mElementCollections;
|
||||
nsPresContext *mPresContext; // weak (non-null from ctor to Disconnect)
|
||||
bool mIsObservingRefreshDriver;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -184,10 +213,6 @@ struct AnimationPlayerCollection : public PRCList
|
|||
|
||||
void Tick();
|
||||
|
||||
// This updates mNeedsRefreshes so the caller may need to check
|
||||
// for changes to values (for example, nsAnimationManager provides
|
||||
// CheckNeedsRefresh to register or unregister from observing the refresh
|
||||
// driver when this value changes).
|
||||
void EnsureStyleRuleFor(TimeStamp aRefreshTime, EnsureStyleRuleFlags aFlags);
|
||||
|
||||
bool CanThrottleTransformChanges(mozilla::TimeStamp aTime);
|
||||
|
@ -274,6 +299,8 @@ struct AnimationPlayerCollection : public PRCList
|
|||
}
|
||||
}
|
||||
|
||||
void NotifyPlayerUpdated();
|
||||
|
||||
static void LogAsyncAnimationFailure(nsCString& aMessage,
|
||||
const nsIContent* aContent = nullptr);
|
||||
|
||||
|
|
|
@ -28,17 +28,35 @@ using mozilla::dom::AnimationPlayer;
|
|||
using mozilla::CSSAnimationPlayer;
|
||||
|
||||
void
|
||||
CSSAnimationPlayer::Play(UpdateFlags aUpdateFlags)
|
||||
CSSAnimationPlayer::Play()
|
||||
{
|
||||
mPauseShouldStick = false;
|
||||
AnimationPlayer::Play(aUpdateFlags);
|
||||
AnimationPlayer::Play();
|
||||
}
|
||||
|
||||
void
|
||||
CSSAnimationPlayer::Pause(UpdateFlags aUpdateFlags)
|
||||
CSSAnimationPlayer::Pause()
|
||||
{
|
||||
mPauseShouldStick = true;
|
||||
AnimationPlayer::Pause(aUpdateFlags);
|
||||
AnimationPlayer::Pause();
|
||||
}
|
||||
|
||||
mozilla::dom::AnimationPlayState
|
||||
CSSAnimationPlayer::PlayStateFromJS() const
|
||||
{
|
||||
// Flush style to ensure that any properties controlling animation state
|
||||
// (e.g. animation-play-state) are fully updated.
|
||||
FlushStyle();
|
||||
return AnimationPlayer::PlayStateFromJS();
|
||||
}
|
||||
|
||||
void
|
||||
CSSAnimationPlayer::PlayFromJS()
|
||||
{
|
||||
// Note that flushing style below might trigger calls to
|
||||
// PlayFromStyle()/PauseFromStyle() on this object.
|
||||
FlushStyle();
|
||||
AnimationPlayer::PlayFromJS();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -46,7 +64,7 @@ CSSAnimationPlayer::PlayFromStyle()
|
|||
{
|
||||
mIsStylePaused = false;
|
||||
if (!mPauseShouldStick) {
|
||||
AnimationPlayer::Play(eNoUpdate);
|
||||
DoPlay();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,7 +77,7 @@ CSSAnimationPlayer::PauseFromStyle()
|
|||
}
|
||||
|
||||
mIsStylePaused = true;
|
||||
AnimationPlayer::Pause(eNoUpdate);
|
||||
DoPause();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -134,6 +152,17 @@ CSSAnimationPlayer::QueueEvents(EventArray& aEventsToDispatch)
|
|||
}
|
||||
}
|
||||
|
||||
CommonAnimationManager*
|
||||
CSSAnimationPlayer::GetAnimationManager() const
|
||||
{
|
||||
nsPresContext* context = GetPresContext();
|
||||
if (!context) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return context->AnimationManager();
|
||||
}
|
||||
|
||||
/* static */ nsString
|
||||
CSSAnimationPlayer::PseudoTypeAsString(nsCSSPseudoElements::Type aPseudoType)
|
||||
{
|
||||
|
@ -155,7 +184,6 @@ nsAnimationManager::UpdateStyleAndEvents(AnimationPlayerCollection*
|
|||
{
|
||||
aCollection->EnsureStyleRuleFor(aRefreshTime, aFlags);
|
||||
QueueEvents(aCollection, mPendingEvents);
|
||||
CheckNeedsRefresh();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -760,42 +788,6 @@ nsAnimationManager::WillRefresh(mozilla::TimeStamp aTime)
|
|||
FlushAnimations(Can_Throttle);
|
||||
}
|
||||
|
||||
void
|
||||
nsAnimationManager::AddElementCollection(
|
||||
AnimationPlayerCollection* aCollection)
|
||||
{
|
||||
if (!mObservingRefreshDriver) {
|
||||
NS_ASSERTION(
|
||||
static_cast<AnimationPlayerCollection*>(aCollection)->mNeedsRefreshes,
|
||||
"Added data which doesn't need refreshing?");
|
||||
// We need to observe the refresh driver.
|
||||
mPresContext->RefreshDriver()->AddRefreshObserver(this, Flush_Style);
|
||||
mObservingRefreshDriver = true;
|
||||
}
|
||||
|
||||
PR_INSERT_BEFORE(aCollection, &mElementCollections);
|
||||
}
|
||||
|
||||
void
|
||||
nsAnimationManager::CheckNeedsRefresh()
|
||||
{
|
||||
for (PRCList *l = PR_LIST_HEAD(&mElementCollections);
|
||||
l != &mElementCollections;
|
||||
l = PR_NEXT_LINK(l)) {
|
||||
if (static_cast<AnimationPlayerCollection*>(l)->mNeedsRefreshes) {
|
||||
if (!mObservingRefreshDriver) {
|
||||
mPresContext->RefreshDriver()->AddRefreshObserver(this, Flush_Style);
|
||||
mObservingRefreshDriver = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (mObservingRefreshDriver) {
|
||||
mObservingRefreshDriver = false;
|
||||
mPresContext->RefreshDriver()->RemoveRefreshObserver(this, Flush_Style);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAnimationManager::FlushAnimations(FlushFlags aFlags)
|
||||
{
|
||||
|
|
|
@ -63,8 +63,11 @@ public:
|
|||
virtual CSSAnimationPlayer*
|
||||
AsCSSAnimationPlayer() MOZ_OVERRIDE { return this; }
|
||||
|
||||
virtual void Play(UpdateFlags aUpdateFlags) MOZ_OVERRIDE;
|
||||
virtual void Pause(UpdateFlags aUpdateFlags) MOZ_OVERRIDE;
|
||||
virtual void Play() MOZ_OVERRIDE;
|
||||
virtual void Pause() MOZ_OVERRIDE;
|
||||
|
||||
virtual dom::AnimationPlayState PlayStateFromJS() const MOZ_OVERRIDE;
|
||||
virtual void PlayFromJS() MOZ_OVERRIDE;
|
||||
|
||||
void PlayFromStyle();
|
||||
void PauseFromStyle();
|
||||
|
@ -75,6 +78,7 @@ public:
|
|||
|
||||
protected:
|
||||
virtual ~CSSAnimationPlayer() { }
|
||||
virtual css::CommonAnimationManager* GetAnimationManager() const MOZ_OVERRIDE;
|
||||
|
||||
static nsString PseudoTypeAsString(nsCSSPseudoElements::Type aPseudoType);
|
||||
|
||||
|
@ -147,7 +151,6 @@ class nsAnimationManager MOZ_FINAL
|
|||
public:
|
||||
explicit nsAnimationManager(nsPresContext *aPresContext)
|
||||
: mozilla::css::CommonAnimationManager(aPresContext)
|
||||
, mObservingRefreshDriver(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -220,26 +223,13 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
mozilla::AnimationPlayerCollection*
|
||||
virtual mozilla::AnimationPlayerCollection*
|
||||
GetAnimationPlayers(mozilla::dom::Element *aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
bool aCreateIfNeeded);
|
||||
bool aCreateIfNeeded) MOZ_OVERRIDE;
|
||||
nsIStyleRule* GetAnimationRule(mozilla::dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType);
|
||||
|
||||
protected:
|
||||
virtual void ElementCollectionRemoved() MOZ_OVERRIDE
|
||||
{
|
||||
CheckNeedsRefresh();
|
||||
}
|
||||
virtual void
|
||||
AddElementCollection(mozilla::AnimationPlayerCollection* aData) MOZ_OVERRIDE;
|
||||
|
||||
/**
|
||||
* Check to see if we should stop or start observing the refresh driver
|
||||
*/
|
||||
void CheckNeedsRefresh();
|
||||
|
||||
private:
|
||||
void BuildAnimations(nsStyleContext* aStyleContext,
|
||||
mozilla::dom::Element* aTarget,
|
||||
|
@ -257,8 +247,6 @@ private:
|
|||
void DoDispatchEvents();
|
||||
|
||||
mozilla::EventArray mPendingEvents;
|
||||
|
||||
bool mObservingRefreshDriver;
|
||||
};
|
||||
|
||||
#endif /* !defined(nsAnimationManager_h_) */
|
||||
|
|
|
@ -71,32 +71,38 @@ ElementPropertyTransition::CurrentValuePortion() const
|
|||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* nsTransitionManager *
|
||||
* CSSTransitionPlayer *
|
||||
*****************************************************************************/
|
||||
|
||||
void
|
||||
nsTransitionManager::ElementCollectionRemoved()
|
||||
mozilla::dom::AnimationPlayState
|
||||
CSSTransitionPlayer::PlayStateFromJS() const
|
||||
{
|
||||
// If we have no transitions or animations left, remove ourselves from
|
||||
// the refresh driver.
|
||||
if (PR_CLIST_IS_EMPTY(&mElementCollections)) {
|
||||
mPresContext->RefreshDriver()->RemoveRefreshObserver(this, Flush_Style);
|
||||
}
|
||||
FlushStyle();
|
||||
return AnimationPlayer::PlayStateFromJS();
|
||||
}
|
||||
|
||||
void
|
||||
nsTransitionManager::AddElementCollection(
|
||||
AnimationPlayerCollection* aCollection)
|
||||
CSSTransitionPlayer::PlayFromJS()
|
||||
{
|
||||
if (PR_CLIST_IS_EMPTY(&mElementCollections)) {
|
||||
// We need to observe the refresh driver.
|
||||
nsRefreshDriver *rd = mPresContext->RefreshDriver();
|
||||
rd->AddRefreshObserver(this, Flush_Style);
|
||||
FlushStyle();
|
||||
AnimationPlayer::PlayFromJS();
|
||||
}
|
||||
|
||||
CommonAnimationManager*
|
||||
CSSTransitionPlayer::GetAnimationManager() const
|
||||
{
|
||||
nsPresContext* context = GetPresContext();
|
||||
if (!context) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PR_INSERT_BEFORE(aCollection, &mElementCollections);
|
||||
return context->TransitionManager();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* nsTransitionManager *
|
||||
*****************************************************************************/
|
||||
|
||||
already_AddRefed<nsIStyleRule>
|
||||
nsTransitionManager::StyleContextChanged(dom::Element *aElement,
|
||||
nsStyleContext *aOldStyleContext,
|
||||
|
@ -166,7 +172,7 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement,
|
|||
}
|
||||
|
||||
AnimationPlayerCollection* collection =
|
||||
GetElementTransitions(aElement, pseudoType, false);
|
||||
GetAnimationPlayers(aElement, pseudoType, false);
|
||||
if (!collection &&
|
||||
disp->mTransitionPropertyCount == 1 &&
|
||||
disp->mTransitions[0].GetDelay() == 0.0f &&
|
||||
|
@ -532,14 +538,13 @@ nsTransitionManager::ConsiderStartingTransition(
|
|||
segment.mToKey = 1;
|
||||
segment.mTimingFunction.Init(tf);
|
||||
|
||||
nsRefPtr<dom::AnimationPlayer> player = new dom::AnimationPlayer(timeline);
|
||||
nsRefPtr<CSSTransitionPlayer> player = new CSSTransitionPlayer(timeline);
|
||||
player->mStartTime = timeline->GetCurrentTime();
|
||||
player->SetSource(pt);
|
||||
|
||||
if (!aElementTransitions) {
|
||||
aElementTransitions =
|
||||
GetElementTransitions(aElement, aNewStyleContext->GetPseudoType(),
|
||||
true);
|
||||
GetAnimationPlayers(aElement, aNewStyleContext->GetPseudoType(), true);
|
||||
if (!aElementTransitions) {
|
||||
NS_WARNING("allocating CommonAnimationManager failed");
|
||||
return;
|
||||
|
@ -575,7 +580,7 @@ nsTransitionManager::ConsiderStartingTransition(
|
|||
}
|
||||
|
||||
AnimationPlayerCollection*
|
||||
nsTransitionManager::GetElementTransitions(
|
||||
nsTransitionManager::GetAnimationPlayers(
|
||||
dom::Element *aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
bool aCreateIfNeeded)
|
||||
|
@ -631,7 +636,7 @@ nsTransitionManager::WalkTransitionRule(dom::Element* aElement,
|
|||
nsRuleWalker* aRuleWalker)
|
||||
{
|
||||
AnimationPlayerCollection* collection =
|
||||
GetElementTransitions(aElement, aPseudoType, false);
|
||||
GetAnimationPlayers(aElement, aPseudoType, false);
|
||||
if (!collection) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/dom/Animation.h"
|
||||
#include "mozilla/dom/AnimationPlayer.h"
|
||||
#include "AnimationCommon.h"
|
||||
#include "nsCSSPseudoElements.h"
|
||||
|
||||
|
@ -64,6 +65,26 @@ struct ElementPropertyTransition : public dom::Animation
|
|||
double CurrentValuePortion() const;
|
||||
};
|
||||
|
||||
class CSSTransitionPlayer MOZ_FINAL : public dom::AnimationPlayer
|
||||
{
|
||||
public:
|
||||
explicit CSSTransitionPlayer(dom::AnimationTimeline* aTimeline)
|
||||
: dom::AnimationPlayer(aTimeline)
|
||||
{
|
||||
}
|
||||
|
||||
virtual CSSTransitionPlayer*
|
||||
AsCSSTransitionPlayer() MOZ_OVERRIDE { return this; }
|
||||
|
||||
virtual dom::AnimationPlayState PlayStateFromJS() const MOZ_OVERRIDE;
|
||||
virtual void PlayFromJS() MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
virtual ~CSSTransitionPlayer() { }
|
||||
|
||||
virtual css::CommonAnimationManager* GetAnimationManager() const MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
class nsTransitionManager MOZ_FINAL
|
||||
|
@ -144,19 +165,14 @@ public:
|
|||
|
||||
void FlushTransitions(FlushFlags aFlags);
|
||||
|
||||
AnimationPlayerCollection* GetElementTransitions(
|
||||
mozilla::dom::Element *aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
bool aCreateIfNeeded);
|
||||
virtual AnimationPlayerCollection*
|
||||
GetAnimationPlayers(mozilla::dom::Element *aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
bool aCreateIfNeeded) MOZ_OVERRIDE;
|
||||
void WalkTransitionRule(mozilla::dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
nsRuleWalker* aRuleWalker);
|
||||
|
||||
protected:
|
||||
virtual void ElementCollectionRemoved() MOZ_OVERRIDE;
|
||||
virtual void
|
||||
AddElementCollection(AnimationPlayerCollection* aCollection) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
void
|
||||
ConsiderStartingTransition(nsCSSProperty aProperty,
|
||||
|
|
|
@ -25,3 +25,20 @@ USE_STATIC_LIBS = True
|
|||
|
||||
DISABLE_STL_WRAPPING = True
|
||||
DEFINES['MOZ_NO_MOZALLOC'] = True
|
||||
|
||||
# Suppress warnings in third-party code.
|
||||
if CONFIG['GNU_CXX']:
|
||||
CFLAGS += [
|
||||
'-Wno-missing-braces',
|
||||
'-Wno-pointer-to-int-cast',
|
||||
'-Wno-sign-compare',
|
||||
'-include stdio.h', # for sprintf() prototype
|
||||
'-include unistd.h', # for getpid() prototype
|
||||
]
|
||||
elif CONFIG['_MSC_VER']:
|
||||
CFLAGS += [
|
||||
'-FI stdio.h', # for sprintf() prototype
|
||||
'-wd4090', # '=' : different 'const' qualifiers
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
|
|
@ -174,6 +174,7 @@ Moof::ParseTrun(Box& aBox, Tfhd& aTfhd, Tfdt& aTfdt, Mdhd& aMdhd)
|
|||
reader->DiscardRemaining();
|
||||
return;
|
||||
}
|
||||
uint8_t version = flags >> 24;
|
||||
|
||||
uint32_t sampleCount = reader->ReadU32();
|
||||
if (sampleCount == 0) {
|
||||
|
@ -194,7 +195,14 @@ Moof::ParseTrun(Box& aBox, Tfhd& aTfhd, Tfdt& aTfdt, Mdhd& aMdhd)
|
|||
flags & 0x400 ? reader->ReadU32() : hasFirstSampleFlags && i == 0
|
||||
? firstSampleFlags
|
||||
: aTfhd.mDefaultSampleFlags;
|
||||
uint32_t ctsOffset = flags & 0x800 ? reader->ReadU32() : 0;
|
||||
int64_t ctsOffset = 0;
|
||||
if (flags & 0x800) {
|
||||
if (version == 0) {
|
||||
ctsOffset = reader->ReadU32();
|
||||
} else {
|
||||
ctsOffset = reader->Read32();
|
||||
}
|
||||
}
|
||||
|
||||
Sample sample;
|
||||
sample.mByteRange = MediaByteRange(offset, offset + sampleSize);
|
||||
|
|
|
@ -76,6 +76,16 @@ public:
|
|||
return mozilla::BigEndian::readUint32(ptr);
|
||||
}
|
||||
|
||||
int64_t Read32()
|
||||
{
|
||||
auto ptr = Read(4);
|
||||
if (!ptr) {
|
||||
MOZ_ASSERT(false);
|
||||
return 0;
|
||||
}
|
||||
return mozilla::BigEndian::readInt32(ptr);
|
||||
}
|
||||
|
||||
uint64_t ReadU64()
|
||||
{
|
||||
auto ptr = Read(8);
|
||||
|
|
|
@ -139,7 +139,7 @@ private:
|
|||
off64_t offset;
|
||||
uint32_t size;
|
||||
uint32_t duration;
|
||||
uint32_t ctsOffset;
|
||||
int64_t ctsOffset;
|
||||
uint32_t flags;
|
||||
uint8_t iv[16];
|
||||
Vector<uint16_t> clearsizes;
|
||||
|
@ -2993,12 +2993,10 @@ status_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) {
|
|||
if (!mDataSource->getUInt32(offset, &flags)) {
|
||||
return ERROR_MALFORMED;
|
||||
}
|
||||
uint8_t version = flags >> 24;
|
||||
ALOGV("fragment run flags: %08x", flags);
|
||||
|
||||
// Some videos have the 0x01000000 flag (unknown) present, and ignoring
|
||||
// it doesn't appear to affect playerback. Assume other flags in the high
|
||||
// byte are invalid.
|
||||
if (flags & 0xfe000000) {
|
||||
if (version > 1) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -3127,7 +3125,11 @@ status_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) {
|
|||
tmp.offset = dataOffset;
|
||||
tmp.size = sampleSize;
|
||||
tmp.duration = sampleDuration;
|
||||
tmp.ctsOffset = sampleCtsOffset;
|
||||
if (version == 0) {
|
||||
tmp.ctsOffset = sampleCtsOffset;
|
||||
} else {
|
||||
tmp.ctsOffset = (int32_t)sampleCtsOffset;
|
||||
}
|
||||
mCurrentSamples.add(tmp);
|
||||
|
||||
dataOffset += sampleSize;
|
||||
|
@ -3609,7 +3611,7 @@ status_t MPEG4Source::fragmentedRead(
|
|||
|
||||
// If we're pointing to a segment type or sidx box then we skip them.
|
||||
if (chunk_type != FOURCC('m', 'o', 'o', 'f')) {
|
||||
moofOffset += chunk_size;
|
||||
mNextMoofOffset += chunk_size;
|
||||
continue;
|
||||
}
|
||||
mCurrentMoofOffset = moofOffset;
|
||||
|
@ -3652,7 +3654,7 @@ status_t MPEG4Source::fragmentedRead(
|
|||
off64_t offset = 0;
|
||||
size_t size = 0;
|
||||
uint32_t dts = 0;
|
||||
uint32_t cts = 0;
|
||||
int64_t cts = 0;
|
||||
uint32_t duration = 0;
|
||||
bool isSyncSample = false;
|
||||
bool newBuffer = false;
|
||||
|
@ -3743,7 +3745,7 @@ status_t MPEG4Source::fragmentedRead(
|
|||
mBuffer->meta_data()->setInt64(
|
||||
kKeyDecodingTime, ((int64_t)dts * 1000000) / mTimescale);
|
||||
mBuffer->meta_data()->setInt64(
|
||||
kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
|
||||
kKeyTime, (cts * 1000000) / mTimescale);
|
||||
mBuffer->meta_data()->setInt64(
|
||||
kKeyDuration, ((int64_t)duration * 1000000) / mTimescale);
|
||||
|
||||
|
@ -3872,7 +3874,7 @@ status_t MPEG4Source::fragmentedRead(
|
|||
mBuffer->meta_data()->setInt64(
|
||||
kKeyDecodingTime, ((int64_t)dts * 1000000) / mTimescale);
|
||||
mBuffer->meta_data()->setInt64(
|
||||
kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
|
||||
kKeyTime, (cts * 1000000) / mTimescale);
|
||||
mBuffer->meta_data()->setInt64(
|
||||
kKeyDuration, ((int64_t)duration * 1000000) / mTimescale);
|
||||
|
||||
|
|
|
@ -1771,7 +1771,7 @@ pref("font.mathfont-family", "Latin Modern Math, XITS Math, STIX Math, Cambria M
|
|||
// These fonts are ignored the underline offset, instead of it, the underline is lowered to bottom of its em descent.
|
||||
pref("font.blacklist.underline_offset", "FangSong,Gulim,GulimChe,MingLiU,MingLiU-ExtB,MingLiU_HKSCS,MingLiU-HKSCS-ExtB,MS Gothic,MS Mincho,MS PGothic,MS PMincho,MS UI Gothic,PMingLiU,PMingLiU-ExtB,SimHei,SimSun,SimSun-ExtB,Hei,Kai,Apple LiGothic,Apple LiSung,Osaka");
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#ifdef MOZ_B2G
|
||||
// Whitelist of fonts that ship with B2G that do not include space lookups in
|
||||
// default features. This allows us to skip analyzing the GSUB/GPOS tables
|
||||
// unless features are explicitly enabled.
|
||||
|
@ -3345,166 +3345,6 @@ pref("print.print_extra_margin", 0); // twips
|
|||
pref("layout.css.scroll-behavior.enabled", false);
|
||||
pref("layout.css.scroll-behavior.property-enabled", false);
|
||||
|
||||
# ANDROID
|
||||
#endif
|
||||
|
||||
#if defined(ANDROID) || defined(FXOS_SIMULATOR)
|
||||
// font names
|
||||
|
||||
// Gonk (along with FxOS Simulator) and Android ship different sets of fonts
|
||||
#if defined(MOZ_WIDGET_GONK) || defined(FXOS_SIMULATOR)
|
||||
|
||||
// TODO: some entries could probably be cleaned up.
|
||||
|
||||
// ar
|
||||
|
||||
pref("font.name.serif.el", "Droid Serif"); // not Charis SIL Compact, only has a few Greek chars
|
||||
pref("font.name.sans-serif.el", "Fira Sans");
|
||||
pref("font.name.monospace.el", "Fira Mono");
|
||||
|
||||
pref("font.name.serif.he", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.he", "Fira Sans");
|
||||
pref("font.name.monospace.he", "Fira Mono");
|
||||
pref("font.name-list.sans-serif.he", "Droid Sans Hebrew, Fira Sans");
|
||||
|
||||
pref("font.name.serif.ja", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.ja", "Fira Sans");
|
||||
pref("font.name.monospace.ja", "MotoyaLMaru");
|
||||
pref("font.name-list.sans-serif.ja", "Fira Sans, MotoyaLMaru, MotoyaLCedar, Droid Sans Japanese");
|
||||
pref("font.name-list.monospace.ja", "MotoyaLMaru, MotoyaLCedar, Fira Mono");
|
||||
|
||||
pref("font.name.serif.ko", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.ko", "Fira Sans");
|
||||
pref("font.name.monospace.ko", "Fira Mono");
|
||||
|
||||
pref("font.name.serif.th", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.th", "Fira Sans");
|
||||
pref("font.name.monospace.th", "Fira Mono");
|
||||
pref("font.name-list.sans-serif.th", "Fira Sans, Noto Sans Thai, Droid Sans Thai");
|
||||
|
||||
pref("font.name.serif.x-cyrillic", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.x-cyrillic", "Fira Sans");
|
||||
pref("font.name.monospace.x-cyrillic", "Fira Mono");
|
||||
|
||||
pref("font.name.serif.x-unicode", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.x-unicode", "Fira Sans");
|
||||
pref("font.name.monospace.x-unicode", "Fira Mono");
|
||||
|
||||
pref("font.name.serif.x-western", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.x-western", "Fira Sans");
|
||||
pref("font.name.monospace.x-western", "Fira Mono");
|
||||
|
||||
pref("font.name.serif.zh-CN", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.zh-CN", "Fira Sans");
|
||||
pref("font.name.monospace.zh-CN", "Fira Mono");
|
||||
|
||||
pref("font.name.serif.zh-HK", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.zh-HK", "Fira Sans");
|
||||
pref("font.name.monospace.zh-HK", "Fira Mono");
|
||||
|
||||
pref("font.name.serif.zh-TW", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.zh-TW", "Fira Sans");
|
||||
pref("font.name.monospace.zh-TW", "Fira Mono");
|
||||
|
||||
#else
|
||||
|
||||
// not MOZ_WIDGET_GONK / FXOS_SIMULATOR
|
||||
// (i.e. this is Firefox for Android) - here, we use the bundled fonts
|
||||
|
||||
// ar
|
||||
|
||||
pref("font.name.serif.el", "Droid Serif"); // not Charis SIL Compact, only has a few Greek chars
|
||||
pref("font.name.sans-serif.el", "Clear Sans");
|
||||
pref("font.name.monospace.el", "Droid Sans Mono");
|
||||
pref("font.name-list.sans-serif.el", "Clear Sans, Roboto, Droid Sans");
|
||||
|
||||
pref("font.name.serif.he", "Droid Serif");
|
||||
pref("font.name.sans-serif.he", "Clear Sans");
|
||||
pref("font.name.monospace.he", "Droid Sans Mono");
|
||||
pref("font.name-list.sans-serif.he", "Droid Sans Hebrew, Clear Sans, Droid Sans");
|
||||
|
||||
pref("font.name.serif.ja", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.ja", "Clear Sans");
|
||||
pref("font.name.monospace.ja", "MotoyaLMaru");
|
||||
pref("font.name-list.serif.ja", "Droid Serif");
|
||||
pref("font.name-list.sans-serif.ja", "Clear Sans, Roboto, Droid Sans, MotoyaLMaru, MotoyaLCedar, Droid Sans Japanese");
|
||||
pref("font.name-list.monospace.ja", "MotoyaLMaru, MotoyaLCedar, Droid Sans Mono");
|
||||
|
||||
pref("font.name.serif.ko", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.ko", "Clear Sans");
|
||||
pref("font.name.monospace.ko", "Droid Sans Mono");
|
||||
pref("font.name-list.serif.ko", "Droid Serif, HYSerif");
|
||||
pref("font.name-list.sans-serif.ko", "SmartGothic, NanumGothic, DroidSansFallback, Droid Sans Fallback");
|
||||
|
||||
pref("font.name.serif.th", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.th", "Clear Sans");
|
||||
pref("font.name.monospace.th", "Droid Sans Mono");
|
||||
pref("font.name-list.serif.th", "Droid Serif");
|
||||
pref("font.name-list.sans-serif.th", "Droid Sans Thai, Clear Sans, Droid Sans");
|
||||
|
||||
pref("font.name.serif.x-cyrillic", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.x-cyrillic", "Clear Sans");
|
||||
pref("font.name.monospace.x-cyrillic", "Droid Sans Mono");
|
||||
pref("font.name-list.serif.x-cyrillic", "Droid Serif");
|
||||
pref("font.name-list.sans-serif.x-cyrillic", "Clear Sans, Roboto, Droid Sans");
|
||||
|
||||
pref("font.name.serif.x-unicode", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.x-unicode", "Clear Sans");
|
||||
pref("font.name.monospace.x-unicode", "Droid Sans Mono");
|
||||
pref("font.name-list.serif.x-unicode", "Droid Serif");
|
||||
pref("font.name-list.sans-serif.x-unicode", "Clear Sans, Roboto, Droid Sans");
|
||||
|
||||
pref("font.name.serif.x-western", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.x-western", "Clear Sans");
|
||||
pref("font.name.monospace.x-western", "Droid Sans Mono");
|
||||
pref("font.name-list.serif.x-western", "Droid Serif");
|
||||
pref("font.name-list.sans-serif.x-western", "Clear Sans, Roboto, Droid Sans");
|
||||
|
||||
pref("font.name.serif.zh-CN", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.zh-CN", "Clear Sans");
|
||||
pref("font.name.monospace.zh-CN", "Droid Sans Mono");
|
||||
pref("font.name-list.serif.zh-CN", "Droid Serif, Droid Sans Fallback");
|
||||
pref("font.name-list.sans-serif.zh-CN", "Roboto, Droid Sans, Droid Sans Fallback");
|
||||
pref("font.name-list.monospace.zh-CN", "Droid Sans Fallback");
|
||||
|
||||
pref("font.name.serif.zh-HK", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.zh-HK", "Clear Sans");
|
||||
pref("font.name.monospace.zh-HK", "Droid Sans Mono");
|
||||
pref("font.name-list.serif.zh-HK", "Droid Serif, Droid Sans Fallback");
|
||||
pref("font.name-list.sans-serif.zh-HK", "Roboto, Droid Sans, Droid Sans Fallback");
|
||||
pref("font.name-list.monospace.zh-HK", "Droid Sans Fallback");
|
||||
|
||||
pref("font.name.serif.zh-TW", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.zh-TW", "Clear Sans");
|
||||
pref("font.name.monospace.zh-TW", "Droid Sans Mono");
|
||||
pref("font.name-list.serif.zh-TW", "Droid Serif, Droid Sans Fallback");
|
||||
pref("font.name-list.sans-serif.zh-TW", "Roboto, Droid Sans, Droid Sans Fallback");
|
||||
pref("font.name-list.monospace.zh-TW", "Droid Sans Fallback");
|
||||
|
||||
// end ! (MOZ_WIDGET_GONK || FXOS_SIMULATOR)
|
||||
|
||||
#endif
|
||||
|
||||
pref("font.size.fixed.ar", 12);
|
||||
|
||||
pref("font.default.el", "sans-serif");
|
||||
pref("font.size.fixed.el", 12);
|
||||
|
||||
pref("font.size.fixed.he", 12);
|
||||
|
||||
pref("font.default.x-cyrillic", "sans-serif");
|
||||
pref("font.size.fixed.x-cyrillic", 12);
|
||||
|
||||
pref("font.default.x-unicode", "sans-serif");
|
||||
pref("font.size.fixed.x-unicode", 12);
|
||||
|
||||
pref("font.default.x-western", "sans-serif");
|
||||
pref("font.size.fixed.x-western", 12);
|
||||
|
||||
# ANDROID || FXOS_SIMUALTOR
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
/* PostScript print module prefs */
|
||||
// pref("print.postscript.enabled", true);
|
||||
pref("print.postscript.paper_size", "letter");
|
||||
|
@ -3655,6 +3495,157 @@ pref("intl.ime.use_simple_context_on_password_field", false);
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(ANDROID) || defined(MOZ_B2G)
|
||||
|
||||
pref("font.size.fixed.ar", 12);
|
||||
|
||||
pref("font.default.el", "sans-serif");
|
||||
pref("font.size.fixed.el", 12);
|
||||
|
||||
pref("font.size.fixed.he", 12);
|
||||
|
||||
pref("font.default.x-cyrillic", "sans-serif");
|
||||
pref("font.size.fixed.x-cyrillic", 12);
|
||||
|
||||
pref("font.default.x-unicode", "sans-serif");
|
||||
pref("font.size.fixed.x-unicode", 12);
|
||||
|
||||
pref("font.default.x-western", "sans-serif");
|
||||
pref("font.size.fixed.x-western", 12);
|
||||
|
||||
# ANDROID || MOZ_B2G
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_B2G)
|
||||
// Gonk, FxOS Simulator, B2G Desktop and Mulet.
|
||||
|
||||
// TODO: some entries could probably be cleaned up.
|
||||
|
||||
// ar
|
||||
|
||||
pref("font.name.serif.el", "Droid Serif"); // not Charis SIL Compact, only has a few Greek chars
|
||||
pref("font.name.sans-serif.el", "Fira Sans");
|
||||
pref("font.name.monospace.el", "Fira Mono");
|
||||
|
||||
pref("font.name.serif.he", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.he", "Fira Sans");
|
||||
pref("font.name.monospace.he", "Fira Mono");
|
||||
pref("font.name-list.sans-serif.he", "Droid Sans Hebrew, Fira Sans");
|
||||
|
||||
pref("font.name.serif.ja", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.ja", "Fira Sans");
|
||||
pref("font.name.monospace.ja", "MotoyaLMaru");
|
||||
pref("font.name-list.sans-serif.ja", "Fira Sans, MotoyaLMaru, MotoyaLCedar, Droid Sans Japanese");
|
||||
pref("font.name-list.monospace.ja", "MotoyaLMaru, MotoyaLCedar, Fira Mono");
|
||||
|
||||
pref("font.name.serif.ko", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.ko", "Fira Sans");
|
||||
pref("font.name.monospace.ko", "Fira Mono");
|
||||
|
||||
pref("font.name.serif.th", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.th", "Fira Sans");
|
||||
pref("font.name.monospace.th", "Fira Mono");
|
||||
pref("font.name-list.sans-serif.th", "Fira Sans, Noto Sans Thai, Droid Sans Thai");
|
||||
|
||||
pref("font.name.serif.x-cyrillic", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.x-cyrillic", "Fira Sans");
|
||||
pref("font.name.monospace.x-cyrillic", "Fira Mono");
|
||||
|
||||
pref("font.name.serif.x-unicode", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.x-unicode", "Fira Sans");
|
||||
pref("font.name.monospace.x-unicode", "Fira Mono");
|
||||
|
||||
pref("font.name.serif.x-western", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.x-western", "Fira Sans");
|
||||
pref("font.name.monospace.x-western", "Fira Mono");
|
||||
|
||||
pref("font.name.serif.zh-CN", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.zh-CN", "Fira Sans");
|
||||
pref("font.name.monospace.zh-CN", "Fira Mono");
|
||||
|
||||
pref("font.name.serif.zh-HK", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.zh-HK", "Fira Sans");
|
||||
pref("font.name.monospace.zh-HK", "Fira Mono");
|
||||
|
||||
pref("font.name.serif.zh-TW", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.zh-TW", "Fira Sans");
|
||||
pref("font.name.monospace.zh-TW", "Fira Mono");
|
||||
|
||||
#elif defined(ANDROID)
|
||||
// We use the bundled fonts for Firefox for Android
|
||||
|
||||
// ar
|
||||
|
||||
pref("font.name.serif.el", "Droid Serif"); // not Charis SIL Compact, only has a few Greek chars
|
||||
pref("font.name.sans-serif.el", "Clear Sans");
|
||||
pref("font.name.monospace.el", "Droid Sans Mono");
|
||||
pref("font.name-list.sans-serif.el", "Clear Sans, Roboto, Droid Sans");
|
||||
|
||||
pref("font.name.serif.he", "Droid Serif");
|
||||
pref("font.name.sans-serif.he", "Clear Sans");
|
||||
pref("font.name.monospace.he", "Droid Sans Mono");
|
||||
pref("font.name-list.sans-serif.he", "Droid Sans Hebrew, Clear Sans, Droid Sans");
|
||||
|
||||
pref("font.name.serif.ja", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.ja", "Clear Sans");
|
||||
pref("font.name.monospace.ja", "MotoyaLMaru");
|
||||
pref("font.name-list.serif.ja", "Droid Serif");
|
||||
pref("font.name-list.sans-serif.ja", "Clear Sans, Roboto, Droid Sans, MotoyaLMaru, MotoyaLCedar, Droid Sans Japanese");
|
||||
pref("font.name-list.monospace.ja", "MotoyaLMaru, MotoyaLCedar, Droid Sans Mono");
|
||||
|
||||
pref("font.name.serif.ko", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.ko", "Clear Sans");
|
||||
pref("font.name.monospace.ko", "Droid Sans Mono");
|
||||
pref("font.name-list.serif.ko", "Droid Serif, HYSerif");
|
||||
pref("font.name-list.sans-serif.ko", "SmartGothic, NanumGothic, DroidSansFallback, Droid Sans Fallback");
|
||||
|
||||
pref("font.name.serif.th", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.th", "Clear Sans");
|
||||
pref("font.name.monospace.th", "Droid Sans Mono");
|
||||
pref("font.name-list.serif.th", "Droid Serif");
|
||||
pref("font.name-list.sans-serif.th", "Droid Sans Thai, Clear Sans, Droid Sans");
|
||||
|
||||
pref("font.name.serif.x-cyrillic", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.x-cyrillic", "Clear Sans");
|
||||
pref("font.name.monospace.x-cyrillic", "Droid Sans Mono");
|
||||
pref("font.name-list.serif.x-cyrillic", "Droid Serif");
|
||||
pref("font.name-list.sans-serif.x-cyrillic", "Clear Sans, Roboto, Droid Sans");
|
||||
|
||||
pref("font.name.serif.x-unicode", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.x-unicode", "Clear Sans");
|
||||
pref("font.name.monospace.x-unicode", "Droid Sans Mono");
|
||||
pref("font.name-list.serif.x-unicode", "Droid Serif");
|
||||
pref("font.name-list.sans-serif.x-unicode", "Clear Sans, Roboto, Droid Sans");
|
||||
|
||||
pref("font.name.serif.x-western", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.x-western", "Clear Sans");
|
||||
pref("font.name.monospace.x-western", "Droid Sans Mono");
|
||||
pref("font.name-list.serif.x-western", "Droid Serif");
|
||||
pref("font.name-list.sans-serif.x-western", "Clear Sans, Roboto, Droid Sans");
|
||||
|
||||
pref("font.name.serif.zh-CN", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.zh-CN", "Clear Sans");
|
||||
pref("font.name.monospace.zh-CN", "Droid Sans Mono");
|
||||
pref("font.name-list.serif.zh-CN", "Droid Serif, Droid Sans Fallback");
|
||||
pref("font.name-list.sans-serif.zh-CN", "Roboto, Droid Sans, Droid Sans Fallback");
|
||||
pref("font.name-list.monospace.zh-CN", "Droid Sans Fallback");
|
||||
|
||||
pref("font.name.serif.zh-HK", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.zh-HK", "Clear Sans");
|
||||
pref("font.name.monospace.zh-HK", "Droid Sans Mono");
|
||||
pref("font.name-list.serif.zh-HK", "Droid Serif, Droid Sans Fallback");
|
||||
pref("font.name-list.sans-serif.zh-HK", "Roboto, Droid Sans, Droid Sans Fallback");
|
||||
pref("font.name-list.monospace.zh-HK", "Droid Sans Fallback");
|
||||
|
||||
pref("font.name.serif.zh-TW", "Charis SIL Compact");
|
||||
pref("font.name.sans-serif.zh-TW", "Clear Sans");
|
||||
pref("font.name.monospace.zh-TW", "Droid Sans Mono");
|
||||
pref("font.name-list.serif.zh-TW", "Droid Serif, Droid Sans Fallback");
|
||||
pref("font.name-list.sans-serif.zh-TW", "Roboto, Droid Sans, Droid Sans Fallback");
|
||||
pref("font.name-list.monospace.zh-TW", "Droid Sans Fallback");
|
||||
|
||||
#endif
|
||||
|
||||
#if OS_ARCH==AIX
|
||||
|
||||
// Override default Japanese fonts
|
||||
|
|
|
@ -991,6 +991,10 @@ VARIABLES = {
|
|||
"""List of manifest files defining mochitest tests.
|
||||
""", None),
|
||||
|
||||
'MOCHITEST_WEBAPPRT_CONTENT_MANIFESTS': (StrictOrderingOnAppendList, list,
|
||||
"""List of manifest files defining webapprt mochitest content tests.
|
||||
""", None),
|
||||
|
||||
'MOCHITEST_WEBAPPRT_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list,
|
||||
"""List of manifest files defining webapprt mochitest chrome tests.
|
||||
""", None),
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче