зеркало из https://github.com/mozilla/gecko-dev.git
merge the last green changeset on fx-team to m-c
This commit is contained in:
Коммит
22a09be64a
|
@ -254,7 +254,7 @@ pref("browser.warnOnRestart", false);
|
|||
pref("browser.showQuitWarning", false);
|
||||
pref("browser.fullscreen.autohide", true);
|
||||
pref("browser.fullscreen.animateUp", 1);
|
||||
pref("browser.overlink-delay", 70);
|
||||
pref("browser.overlink-delay", 80);
|
||||
|
||||
#ifdef UNIX_BUT_NOT_MAC
|
||||
pref("browser.urlbar.clickSelectsAll", false);
|
||||
|
|
|
@ -511,16 +511,20 @@ statuspanel[type=status] {
|
|||
}
|
||||
|
||||
statuspanel[type=overLink] {
|
||||
-moz-transition: opacity 100ms ease-out;
|
||||
-moz-transition: opacity 120ms ease-out;
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
statuspanel[label=""] {
|
||||
statuspanel[inactive] {
|
||||
-moz-transition: none;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
statuspanel[inactive][previoustype=overLink] {
|
||||
-moz-transition: opacity 200ms ease-out;
|
||||
}
|
||||
|
||||
.statuspanel-inner {
|
||||
height: 3em;
|
||||
width: 100%;
|
||||
|
|
|
@ -4683,7 +4683,7 @@ var LinkTargetDisplay = {
|
|||
return this.DELAY_SHOW = Services.prefs.getIntPref("browser.overlink-delay");
|
||||
},
|
||||
|
||||
DELAY_HIDE: 150,
|
||||
DELAY_HIDE: 250,
|
||||
_timer: 0,
|
||||
|
||||
get _isVisible () XULBrowserWindow.statusTextField.label != "",
|
||||
|
|
|
@ -956,7 +956,7 @@
|
|||
contentcontextmenu="contentAreaContextMenu"
|
||||
autocompletepopup="PopupAutoComplete"
|
||||
onclick="return contentAreaClick(event, false);"/>
|
||||
<statuspanel id="statusbar-display" label=""/>
|
||||
<statuspanel id="statusbar-display" inactive="true"/>
|
||||
</vbox>
|
||||
<vbox id="browser-border-end" hidden="true" layer="true"/>
|
||||
</hbox>
|
||||
|
|
|
@ -4274,11 +4274,17 @@
|
|||
this.getAttribute("previoustype") == "status"
|
||||
? getComputedStyle(this).width : "";
|
||||
|
||||
this.setAttribute("label", val);
|
||||
if (val) {
|
||||
this.setAttribute("label", val);
|
||||
this.removeAttribute("inactive");
|
||||
} else {
|
||||
this.setAttribute("inactive", "true");
|
||||
}
|
||||
|
||||
return val;
|
||||
]]></setter>
|
||||
<getter>
|
||||
return this.getAttribute("label");
|
||||
return this.hasAttribute("inactive") ? "" : this.getAttribute("label");
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
|
|
|
@ -782,7 +782,7 @@ BrowserGlue.prototype = {
|
|||
|
||||
var productName = brandBundle.GetStringFromName("brandFullName");
|
||||
var serverOwner = Services.prefs.getCharPref(PREF_TELEMETRY_SERVER_OWNER);
|
||||
var telemetryText = browserBundle.formatStringFromName("telemetryText", [productName, serverOwner], 2);
|
||||
var telemetryPrompt = browserBundle.formatStringFromName("telemetryPrompt", [productName, serverOwner], 2);
|
||||
|
||||
var buttons = [
|
||||
{
|
||||
|
@ -804,8 +804,8 @@ BrowserGlue.prototype = {
|
|||
// Set pref to indicate we've shown the notification.
|
||||
Services.prefs.setBoolPref(PREF_TELEMETRY_PROMPTED, true);
|
||||
|
||||
var notification = notifyBox.appendNotification(telemetryText, "telemetry", null, notifyBox.PRIORITY_INFO_LOW, buttons);
|
||||
notification.persistence = 3; // arbitrary number, just so bar sticks around for a bit
|
||||
var notification = notifyBox.appendNotification(telemetryPrompt, "telemetry", null, notifyBox.PRIORITY_INFO_LOW, buttons);
|
||||
notification.persistence = 6; // arbitrary number, just so bar sticks around for a bit
|
||||
|
||||
let XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
let link = notification.ownerDocument.createElementNS(XULNS, "label");
|
||||
|
@ -818,7 +818,7 @@ BrowserGlue.prototype = {
|
|||
notification.parentNode.removeNotification(notification, true);
|
||||
// Add a new notification to that tab, with no "Learn more" link
|
||||
var notifyBox = browser.getNotificationBox();
|
||||
notifyBox.appendNotification(telemetryText, "telemetry", null, notifyBox.PRIORITY_INFO_LOW, buttons);
|
||||
notifyBox.appendNotification(telemetryPrompt, "telemetry", null, notifyBox.PRIORITY_INFO_LOW, buttons);
|
||||
}, false);
|
||||
let description = notification.ownerDocument.getAnonymousElementByAttribute(notification, "anonid", "messageText");
|
||||
description.appendChild(link);
|
||||
|
|
|
@ -244,10 +244,8 @@ Site.prototype = {
|
|||
* @return An array of the logins stored for the site.
|
||||
*/
|
||||
get logins() {
|
||||
// There could be more logins for different schemes/ports, but this covers
|
||||
// the vast majority of cases.
|
||||
let httpLogins = Services.logins.findLogins({}, this.httpURI.prePath, "", null);
|
||||
let httpsLogins = Services.logins.findLogins({}, this.httpsURI.prePath, "", null);
|
||||
let httpLogins = Services.logins.findLogins({}, this.httpURI.prePath, "", "");
|
||||
let httpsLogins = Services.logins.findLogins({}, this.httpsURI.prePath, "", "");
|
||||
return httpLogins.concat(httpsLogins);
|
||||
},
|
||||
|
||||
|
|
|
@ -327,9 +327,9 @@ syncPromoNotification.passwords.description=You can access your passwords on all
|
|||
syncPromoNotification.learnMoreLinkText=Learn More
|
||||
|
||||
# Telemetry prompt
|
||||
# LOCALIZATION NOTE (telemetryText): %1$S will be replaced by brandFullName,
|
||||
# LOCALIZATION NOTE (telemetryPrompt): %1$S will be replaced by brandFullName,
|
||||
# and %2$S by the value of the toolkit.telemetry.server_owner preference.
|
||||
telemetryText = Would you like to help improve %1$S by automatically reporting memory usage, performance, and responsiveness to %2$S?
|
||||
telemetryPrompt = Will you help improve %1$S by sending anonymous information about performance, hardware characteristics, feature usage, and browser customizations to %2$S?
|
||||
telemetryLinkLabel = Learn More
|
||||
telemetryYesButtonLabel = Yes
|
||||
telemetryYesButtonAccessKey = Y
|
||||
|
|
|
@ -603,37 +603,18 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
|
|||
|
||||
#forward-button {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=toolbar");
|
||||
-moz-transition: 250ms ease-out;
|
||||
}
|
||||
#forward-button[disabled="true"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=toolbar&state=disabled");
|
||||
}
|
||||
|
||||
#forward-button:-moz-locale-dir(rtl) {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=toolbar");
|
||||
}
|
||||
|
||||
toolbar:not([mode=icons]) #forward-button[disabled="true"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=toolbar&state=disabled");
|
||||
}
|
||||
toolbar:not([mode=icons]) #forward-button[disabled="true"]:-moz-locale-dir(rtl) {
|
||||
#forward-button[disabled="true"]:-moz-locale-dir(rtl) {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=toolbar&state=disabled");
|
||||
}
|
||||
|
||||
toolbar[mode=icons] #forward-button[disabled="true"] {
|
||||
-moz-transform: scale(0);
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
toolbar[mode=icons] #forward-button[disabled="true"]:-moz-locale-dir(ltr) {
|
||||
margin-left: -36px;
|
||||
}
|
||||
toolbar[mode=icons] #forward-button[disabled="true"]:-moz-locale-dir(rtl) {
|
||||
margin-right: -36px;
|
||||
}
|
||||
toolbar[mode=icons][iconsize=small] #forward-button[disabled="true"]:-moz-locale-dir(ltr) {
|
||||
margin-left: -28px;
|
||||
}
|
||||
toolbar[mode=icons][iconsize=small] #forward-button[disabled="true"]:-moz-locale-dir(rtl) {
|
||||
margin-right: -28px;
|
||||
}
|
||||
|
||||
#reload-button {
|
||||
list-style-image: url("moz-icon://stock/gtk-refresh?size=toolbar");
|
||||
}
|
||||
|
@ -805,7 +786,7 @@ toolbar[iconsize="small"] #forward-button {
|
|||
.unified-nav-forward[_moz-menuactive] {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=menu") !important;
|
||||
}
|
||||
toolbar[iconsize="small"]:not([mode=icons]) #forward-button[disabled="true"] {
|
||||
toolbar[iconsize="small"] #forward-button[disabled="true"] {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
|
@ -815,7 +796,7 @@ toolbar[iconsize="small"] #forward-button:-moz-locale-dir(rtl) {
|
|||
.unified-nav-forward[_moz-menuactive]:-moz-locale-dir(rtl) {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu") !important;
|
||||
}
|
||||
toolbar[iconsize="small"]:not([mode=icons]) #forward-button[disabled="true"]:-moz-locale-dir(rtl) {
|
||||
toolbar[iconsize="small"] #forward-button[disabled="true"]:-moz-locale-dir(rtl) {
|
||||
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu&state=disabled");
|
||||
}
|
||||
|
||||
|
|
|
@ -4357,7 +4357,7 @@ MOZ_DISABLE_DOMCRYPTO=
|
|||
NSS_DISABLE_DBM=
|
||||
NECKO_WIFI=1
|
||||
NECKO_COOKIES=1
|
||||
NECKO_PROTOCOLS_DEFAULT="about data file ftp http res viewsource websocket wyciwyg"
|
||||
NECKO_PROTOCOLS_DEFAULT="about data file ftp http res viewsource websocket wyciwyg device"
|
||||
USE_ARM_KUSER=
|
||||
BUILD_CTYPES=1
|
||||
MOZ_USE_NATIVE_POPUP_WINDOWS=
|
||||
|
|
|
@ -287,8 +287,12 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument *aOldDocument,
|
|||
aObserver, &doneLoading, &isAlternate);
|
||||
}
|
||||
else {
|
||||
// XXXbz clone the URI here to work around content policies modifying URIs.
|
||||
nsCOMPtr<nsIURI> clonedURI;
|
||||
uri->Clone(getter_AddRefs(clonedURI));
|
||||
NS_ENSURE_TRUE(clonedURI, NS_ERROR_OUT_OF_MEMORY);
|
||||
rv = doc->CSSLoader()->
|
||||
LoadStyleLink(thisContent, uri, title, media, isAlternate, aObserver,
|
||||
LoadStyleLink(thisContent, clonedURI, title, media, isAlternate, aObserver,
|
||||
&isAlternate);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Don't propagate LoadStyleLink() errors further than this, since some
|
||||
|
|
|
@ -12,7 +12,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=364413
|
|||
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
|
||||
<script type="text/javascript" src="/MochiKit/Style.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=364413">Mozilla Bug 364413</a>
|
||||
|
|
|
@ -24,7 +24,7 @@ include autofocus/reftest.list
|
|||
== 649134-1.html 649134-ref.html
|
||||
skip-if(Android) == 649134-2.html 649134-2-ref.html
|
||||
|
||||
== hidden-1a.html hidden-1-ref.html
|
||||
skip-if(Android&&layersOpenGL) == hidden-1a.html hidden-1-ref.html
|
||||
== hidden-1b.html hidden-1-ref.html
|
||||
== hidden-1c.html hidden-1-ref.html
|
||||
== hidden-1d.html hidden-1-ref.html
|
||||
|
|
|
@ -353,12 +353,11 @@ nsresult nsBuiltinDecoder::Seek(double aTime)
|
|||
// above will result in the new seek occurring when the current seek
|
||||
// completes.
|
||||
if (mPlayState != PLAY_STATE_SEEKING) {
|
||||
if (mPlayState == PLAY_STATE_ENDED) {
|
||||
mNextState = PLAY_STATE_PLAYING;
|
||||
}
|
||||
else {
|
||||
mNextState = mPlayState;
|
||||
PRBool paused = PR_FALSE;
|
||||
if (mElement) {
|
||||
mElement->GetPaused(&paused);
|
||||
}
|
||||
mNextState = paused ? PLAY_STATE_PAUSED : PLAY_STATE_PLAYING;
|
||||
PinForSeek();
|
||||
ChangeState(PLAY_STATE_SEEKING);
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "mozilla/mozalloc.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "nsTimeRanges.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::layers;
|
||||
|
@ -56,17 +57,10 @@ extern PRLogModuleInfo* gBuiltinDecoderLog;
|
|||
#define LOG(type, msg)
|
||||
#endif
|
||||
|
||||
// Wait this number of seconds when buffering, then leave and play
|
||||
// Wait this number of milliseconds when buffering, then leave and play
|
||||
// as best as we can if the required amount of data hasn't been
|
||||
// retrieved.
|
||||
static const PRUint32 BUFFERING_WAIT = 30;
|
||||
|
||||
// The amount of data to retrieve during buffering is computed based
|
||||
// on the download rate. BUFFERING_MIN_RATE is the minimum download
|
||||
// rate to be used in that calculation to help avoid constant buffering
|
||||
// attempts at a time when the average download rate has not stabilised.
|
||||
#define BUFFERING_MIN_RATE 50000
|
||||
#define BUFFERING_RATE(x) ((x)< BUFFERING_MIN_RATE ? BUFFERING_MIN_RATE : (x))
|
||||
static const PRUint32 BUFFERING_WAIT = 30000;
|
||||
|
||||
// If audio queue has less than this many usecs of decoded audio, we won't risk
|
||||
// trying to decode the video, we'll skip decoding video up to the next
|
||||
|
@ -194,7 +188,8 @@ private:
|
|||
};
|
||||
|
||||
nsBuiltinDecoderStateMachine::nsBuiltinDecoderStateMachine(nsBuiltinDecoder* aDecoder,
|
||||
nsBuiltinDecoderReader* aReader) :
|
||||
nsBuiltinDecoderReader* aReader,
|
||||
PRPackedBool aRealTime) :
|
||||
mDecoder(aDecoder),
|
||||
mState(DECODER_STATE_DECODING_METADATA),
|
||||
mCbCrSize(0),
|
||||
|
@ -221,7 +216,8 @@ nsBuiltinDecoderStateMachine::nsBuiltinDecoderStateMachine(nsBuiltinDecoder* aDe
|
|||
mRunAgain(PR_FALSE),
|
||||
mDispatchedRunEvent(PR_FALSE),
|
||||
mDecodeThreadWaiting(PR_FALSE),
|
||||
mEventManager(aDecoder)
|
||||
mEventManager(aDecoder),
|
||||
mRealTime(aRealTime)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsBuiltinDecoderStateMachine);
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
|
@ -233,6 +229,13 @@ nsBuiltinDecoderStateMachine::nsBuiltinDecoderStateMachine(nsBuiltinDecoder* aDe
|
|||
NS_ABORT_IF_FALSE(NS_SUCCEEDED(res), "Can't create media state machine thread");
|
||||
}
|
||||
gStateMachineCount++;
|
||||
|
||||
// only enable realtime mode when "media.realtime_decoder.enabled" is true.
|
||||
if (Preferences::GetBool("media.realtime_decoder.enabled", PR_FALSE) == PR_FALSE)
|
||||
mRealTime = PR_FALSE;
|
||||
|
||||
mBufferingWait = mRealTime ? 0 : BUFFERING_WAIT;
|
||||
mLowDataThresholdUsecs = mRealTime ? 0 : LOW_DATA_THRESHOLD_USECS;
|
||||
}
|
||||
|
||||
nsBuiltinDecoderStateMachine::~nsBuiltinDecoderStateMachine()
|
||||
|
@ -332,12 +335,12 @@ void nsBuiltinDecoderStateMachine::DecodeLoop()
|
|||
|
||||
// Once we've decoded more than videoPumpThreshold video frames, we'll
|
||||
// no longer be considered to be "pumping video".
|
||||
const unsigned videoPumpThreshold = AMPLE_VIDEO_FRAMES / 2;
|
||||
const unsigned videoPumpThreshold = mRealTime ? 0 : AMPLE_VIDEO_FRAMES / 2;
|
||||
|
||||
// After the audio decode fills with more than audioPumpThreshold usecs
|
||||
// of decoded audio, we'll start to check whether the audio or video decode
|
||||
// is falling behind.
|
||||
const unsigned audioPumpThreshold = LOW_AUDIO_USECS * 2;
|
||||
const unsigned audioPumpThreshold = mRealTime ? 0 : LOW_AUDIO_USECS * 2;
|
||||
|
||||
// Our local low audio threshold. We may increase this if we're slow to
|
||||
// decode video frames, in order to reduce the chance of audio underruns.
|
||||
|
@ -429,7 +432,7 @@ void nsBuiltinDecoderStateMachine::DecodeLoop()
|
|||
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
|
||||
audioPlaying = mReader->DecodeAudioData();
|
||||
}
|
||||
|
||||
|
||||
// Notify to ensure that the AudioLoop() is not waiting, in case it was
|
||||
// waiting for more audio to be decoded.
|
||||
mDecoder->GetReentrantMonitor().NotifyAll();
|
||||
|
@ -1146,7 +1149,7 @@ PRBool nsBuiltinDecoderStateMachine::HasLowDecodedData(PRInt64 aAudioUsecs) cons
|
|||
|
||||
PRBool nsBuiltinDecoderStateMachine::HasLowUndecodedData() const
|
||||
{
|
||||
return GetUndecodedData() < LOW_DATA_THRESHOLD_USECS;
|
||||
return GetUndecodedData() < mLowDataThresholdUsecs;
|
||||
}
|
||||
|
||||
PRInt64 nsBuiltinDecoderStateMachine::GetUndecodedData() const
|
||||
|
@ -1511,9 +1514,9 @@ nsresult nsBuiltinDecoderStateMachine::RunStateMachine()
|
|||
TimeDuration elapsed = now - mBufferingStart;
|
||||
PRBool isLiveStream = mDecoder->GetCurrentStream()->GetLength() == -1;
|
||||
if ((isLiveStream || !mDecoder->CanPlayThrough()) &&
|
||||
elapsed < TimeDuration::FromSeconds(BUFFERING_WAIT) &&
|
||||
elapsed < TimeDuration::FromSeconds(mBufferingWait) &&
|
||||
(mQuickBuffering ? HasLowDecodedData(QUICK_BUFFERING_LOW_DATA_USECS)
|
||||
: (GetUndecodedData() < BUFFERING_WAIT * USECS_PER_S)) &&
|
||||
: (GetUndecodedData() < mBufferingWait * USECS_PER_S / 1000)) &&
|
||||
!stream->IsDataCachedToEndOfStream(mDecoder->mDecoderPosition) &&
|
||||
!stream->IsSuspended())
|
||||
{
|
||||
|
@ -1521,8 +1524,8 @@ nsresult nsBuiltinDecoderStateMachine::RunStateMachine()
|
|||
("%p Buffering: %.3lfs/%ds, timeout in %.3lfs %s",
|
||||
mDecoder.get(),
|
||||
GetUndecodedData() / static_cast<double>(USECS_PER_S),
|
||||
BUFFERING_WAIT,
|
||||
BUFFERING_WAIT - elapsed.ToSeconds(),
|
||||
mBufferingWait,
|
||||
mBufferingWait - elapsed.ToSeconds(),
|
||||
(mQuickBuffering ? "(quick exit)" : "")));
|
||||
ScheduleStateMachine(USECS_PER_S);
|
||||
return NS_OK;
|
||||
|
@ -1683,7 +1686,7 @@ void nsBuiltinDecoderStateMachine::AdvanceFrame()
|
|||
nsAutoPtr<VideoData> currentFrame;
|
||||
if (mReader->mVideoQueue.GetSize() > 0) {
|
||||
VideoData* frame = mReader->mVideoQueue.PeekFront();
|
||||
while (clock_time >= frame->mTime) {
|
||||
while (mRealTime || clock_time >= frame->mTime) {
|
||||
mVideoFrameEndTime = frame->mEndTime;
|
||||
currentFrame = frame;
|
||||
mReader->mVideoQueue.PopFront();
|
||||
|
@ -1908,7 +1911,7 @@ nsresult nsBuiltinDecoderStateMachine::Run()
|
|||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread.");
|
||||
|
||||
return CallRunStateMachine();
|
||||
return CallRunStateMachine();
|
||||
}
|
||||
|
||||
nsresult nsBuiltinDecoderStateMachine::CallRunStateMachine()
|
||||
|
@ -1951,9 +1954,9 @@ void nsBuiltinDecoderStateMachine::TimeoutExpired()
|
|||
if (mIsRunning) {
|
||||
mRunAgain = PR_TRUE;
|
||||
} else if (!mDispatchedRunEvent) {
|
||||
// We don't have an event dispatched to run the state machine, so we
|
||||
// can just run it from here.
|
||||
CallRunStateMachine();
|
||||
// We don't have an event dispatched to run the state machine, so we
|
||||
// can just run it from here.
|
||||
CallRunStateMachine();
|
||||
}
|
||||
// Otherwise, an event has already been dispatched to run the state machine
|
||||
// as soon as possible. Nothing else needed to do, the state machine is
|
||||
|
@ -1989,6 +1992,8 @@ nsresult nsBuiltinDecoderStateMachine::ScheduleStateMachine(PRInt64 aUsecs) {
|
|||
}
|
||||
|
||||
PRUint32 ms = static_cast<PRUint32>((aUsecs / USECS_PER_MS) & 0xFFFFFFFF);
|
||||
if (mRealTime && ms > 40)
|
||||
ms = 40;
|
||||
if (ms == 0) {
|
||||
if (mIsRunning) {
|
||||
// We're currently running this state machine on the state machine
|
||||
|
|
|
@ -137,7 +137,7 @@ public:
|
|||
typedef mozilla::TimeStamp TimeStamp;
|
||||
typedef mozilla::TimeDuration TimeDuration;
|
||||
|
||||
nsBuiltinDecoderStateMachine(nsBuiltinDecoder* aDecoder, nsBuiltinDecoderReader* aReader);
|
||||
nsBuiltinDecoderStateMachine(nsBuiltinDecoder* aDecoder, nsBuiltinDecoderReader* aReader, PRPackedBool aRealTime = PR_FALSE);
|
||||
~nsBuiltinDecoderStateMachine();
|
||||
|
||||
// nsDecoderStateMachine interface
|
||||
|
@ -624,6 +624,12 @@ protected:
|
|||
// by the decoder monitor.
|
||||
PRPackedBool mDecodeThreadWaiting;
|
||||
|
||||
// true is we are decoding a realtime stream, like a camera stream
|
||||
PRPackedBool mRealTime;
|
||||
|
||||
PRUint32 mBufferingWait;
|
||||
PRInt64 mLowDataThresholdUsecs;
|
||||
|
||||
private:
|
||||
// Manager for queuing and dispatching MozAudioAvailable events. The
|
||||
// event manager is accessed from the state machine and audio threads,
|
||||
|
|
|
@ -50,6 +50,7 @@ LIBXUL_LIBRARY = 1
|
|||
EXPORTS += \
|
||||
nsRawDecoder.h \
|
||||
nsRawReader.h \
|
||||
nsRawStructs.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS += \
|
||||
|
|
|
@ -40,5 +40,5 @@
|
|||
|
||||
nsDecoderStateMachine* nsRawDecoder::CreateStateMachine()
|
||||
{
|
||||
return new nsBuiltinDecoderStateMachine(this, new nsRawReader(this));
|
||||
return new nsBuiltinDecoderStateMachine(this, new nsRawReader(this), PR_TRUE);
|
||||
}
|
||||
|
|
|
@ -43,8 +43,6 @@
|
|||
#include "nsRawDecoder.h"
|
||||
#include "VideoUtils.h"
|
||||
|
||||
static const PRUint24 RAW_ID = 0x595556;
|
||||
|
||||
nsRawReader::nsRawReader(nsBuiltinDecoder* aDecoder)
|
||||
: nsBuiltinDecoderReader(aDecoder),
|
||||
mCurrentFrame(0), mFrameSize(0)
|
||||
|
|
|
@ -41,51 +41,7 @@
|
|||
#define nsRawReader_h_
|
||||
|
||||
#include "nsBuiltinDecoderReader.h"
|
||||
|
||||
struct nsRawVideo_PRUint24 {
|
||||
operator PRUint32() const { return value[2] << 16 | value[1] << 8 | value[0]; }
|
||||
private:
|
||||
PRUint8 value[3];
|
||||
};
|
||||
|
||||
struct nsRawPacketHeader {
|
||||
typedef nsRawVideo_PRUint24 PRUint24;
|
||||
PRUint8 packetID;
|
||||
PRUint24 codecID;
|
||||
};
|
||||
|
||||
// This is Arc's draft from wiki.xiph.org/OggYUV
|
||||
struct nsRawVideoHeader {
|
||||
typedef nsRawVideo_PRUint24 PRUint24;
|
||||
PRUint8 headerPacketID; // Header Packet ID (always 0)
|
||||
PRUint24 codecID; // Codec identifier (always "YUV")
|
||||
PRUint8 majorVersion; // Version Major (breaks backwards compat)
|
||||
PRUint8 minorVersion; // Version Minor (preserves backwards compat)
|
||||
PRUint16 options; // Bit 1: Color (false = B/W)
|
||||
// Bits 2-4: Chroma Pixel Shape
|
||||
// Bit 5: 50% horizontal offset for Cr samples
|
||||
// Bit 6: 50% vertical ...
|
||||
// Bits 7-8: Chroma Blending
|
||||
// Bit 9: Packed (false = Planar)
|
||||
// Bit 10: Cr Staggered Horizontally
|
||||
// Bit 11: Cr Staggered Vertically
|
||||
// Bit 12: Unused (format is always little endian)
|
||||
// Bit 13: Interlaced (false = Progressive)
|
||||
// Bits 14-16: Interlace options (undefined)
|
||||
|
||||
PRUint8 alphaChannelBpp;
|
||||
PRUint8 lumaChannelBpp;
|
||||
PRUint8 chromaChannelBpp;
|
||||
PRUint8 colorspace;
|
||||
|
||||
PRUint24 frameWidth;
|
||||
PRUint24 frameHeight;
|
||||
PRUint24 aspectNumerator;
|
||||
PRUint24 aspectDenominator;
|
||||
|
||||
PRUint32 framerateNumerator;
|
||||
PRUint32 framerateDenominator;
|
||||
};
|
||||
#include "nsRawStructs.h"
|
||||
|
||||
class nsRawReader : public nsBuiltinDecoderReader
|
||||
{
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brad Lassey
|
||||
* Kyle Huey <me@kylehuey.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#if !defined(nsRawStructs_h_)
|
||||
#define nsRawStructs_h_
|
||||
|
||||
static const PRUint32 RAW_ID = 0x595556;
|
||||
|
||||
struct nsRawVideo_PRUint24 {
|
||||
operator PRUint32() const { return value[2] << 16 | value[1] << 8 | value[0]; }
|
||||
nsRawVideo_PRUint24& operator= (const PRUint32& rhs)
|
||||
{ value[2] = (rhs & 0x00FF0000) >> 16;
|
||||
value[1] = (rhs & 0x0000FF00) >> 8;
|
||||
value[0] = (rhs & 0x000000FF);
|
||||
return *this; }
|
||||
private:
|
||||
PRUint8 value[3];
|
||||
};
|
||||
|
||||
struct nsRawPacketHeader {
|
||||
typedef nsRawVideo_PRUint24 PRUint24;
|
||||
PRUint8 packetID;
|
||||
PRUint24 codecID;
|
||||
};
|
||||
|
||||
// This is Arc's draft from wiki.xiph.org/OggYUV
|
||||
struct nsRawVideoHeader {
|
||||
typedef nsRawVideo_PRUint24 PRUint24;
|
||||
PRUint8 headerPacketID; // Header Packet ID (always 0)
|
||||
PRUint24 codecID; // Codec identifier (always "YUV")
|
||||
PRUint8 majorVersion; // Version Major (breaks backwards compat)
|
||||
PRUint8 minorVersion; // Version Minor (preserves backwards compat)
|
||||
PRUint16 options; // Bit 1: Color (false = B/W)
|
||||
// Bits 2-4: Chroma Pixel Shape
|
||||
// Bit 5: 50% horizontal offset for Cr samples
|
||||
// Bit 6: 50% vertical ...
|
||||
// Bits 7-8: Chroma Blending
|
||||
// Bit 9: Packed (false = Planar)
|
||||
// Bit 10: Cr Staggered Horizontally
|
||||
// Bit 11: Cr Staggered Vertically
|
||||
// Bit 12: Unused (format is always little endian)
|
||||
// Bit 13: Interlaced (false = Progressive)
|
||||
// Bits 14-16: Interlace options (undefined)
|
||||
|
||||
PRUint8 alphaChannelBpp;
|
||||
PRUint8 lumaChannelBpp;
|
||||
PRUint8 chromaChannelBpp;
|
||||
PRUint8 colorspace;
|
||||
|
||||
PRUint24 frameWidth;
|
||||
PRUint24 frameHeight;
|
||||
PRUint24 aspectNumerator;
|
||||
PRUint24 aspectDenominator;
|
||||
|
||||
PRUint32 framerateNumerator;
|
||||
PRUint32 framerateDenominator;
|
||||
};
|
||||
|
||||
#endif // nsRawStructs_h_
|
|
@ -11567,8 +11567,17 @@ nsDocShell::OnLinkClickSync(nsIContent *aContent,
|
|||
NS_ParseContentType(utf8Hint, type, dummy);
|
||||
CopyUTF8toUTF16(type, typeHint);
|
||||
}
|
||||
|
||||
// Clone the URI now, in case a content policy or something messes
|
||||
// with it under InternalLoad; we do _not_ want to change the URI
|
||||
// our caller passed in.
|
||||
nsCOMPtr<nsIURI> clonedURI;
|
||||
aURI->Clone(getter_AddRefs(clonedURI));
|
||||
if (!clonedURI) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsresult rv = InternalLoad(aURI, // New URI
|
||||
nsresult rv = InternalLoad(clonedURI, // New URI
|
||||
referer, // Referer URI
|
||||
aContent->NodePrincipal(), // Owner is our node's
|
||||
// principal
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
#include "nsIPresShell.h"
|
||||
#include "nsStyleAnimation.h"
|
||||
#include "nsCSSProps.h"
|
||||
#include "nsDOMFile.h"
|
||||
|
||||
#if defined(MOZ_X11) && defined(MOZ_WIDGET_GTK2)
|
||||
#include <gdk/gdk.h>
|
||||
|
@ -1841,6 +1842,13 @@ nsDOMWindowUtils::GetOuterWindowWithId(PRUint64 aWindowID,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::WrapDOMFile(nsIFile *aFile,
|
||||
nsIDOMFile **aDOMFile) {
|
||||
NS_ADDREF(*aDOMFile = new nsDOMFileFile(aFile));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static PRBool
|
||||
CheckLeafLayers(Layer* aLayer, const nsIntPoint& aOffset, nsIntRegion* aCoveredRegion)
|
||||
|
|
|
@ -65,8 +65,10 @@ interface nsIDOMEvent;
|
|||
interface nsITransferable;
|
||||
interface nsIQueryContentEventResult;
|
||||
interface nsIDOMWindow;
|
||||
interface nsIDOMFile;
|
||||
interface nsIFile;
|
||||
|
||||
[scriptable, uuid(748746a7-a6f4-41d6-bc82-1788981b2623)]
|
||||
[scriptable, uuid(bc6c156a-c41f-43dd-ace3-e3bca9894ed1)]
|
||||
interface nsIDOMWindowUtils : nsISupports {
|
||||
|
||||
/**
|
||||
|
@ -888,6 +890,11 @@ interface nsIDOMWindowUtils : nsISupports {
|
|||
in AString value1,
|
||||
in AString value2);
|
||||
|
||||
/**
|
||||
* Wrap an nsIFile in an nsIDOMFile
|
||||
*/
|
||||
nsIDOMFile wrapDOMFile(in nsIFile aFile);
|
||||
|
||||
/**
|
||||
* Get the type of the currently focused html input, if any.
|
||||
*/
|
||||
|
|
|
@ -38,6 +38,7 @@ Reset=Reset
|
|||
Submit=Submit Query
|
||||
Browse=Browse…
|
||||
FileUpload=File Upload
|
||||
MediaUpload=Media Upload
|
||||
# LOCALIZATION NOTE (IsIndexPromptWithSpace): The last character of the string
|
||||
# should be a space (U+0020) in most locales. The prompt is followed by an
|
||||
# input field. The space needs be escaped in the property file to avoid
|
||||
|
|
|
@ -9,9 +9,9 @@ random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) =
|
|||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) skip-if(Android) == border-padding-3.html border-padding-3-ref.html # bug 629430
|
||||
random-if(cocoaWidget||d2d) fails-if(!haveTestPlugin&&!Android) skip-if(!testPluginIsOOP()) == pluginproblemui-direction-1.html pluginproblemui-direction-1-ref.html
|
||||
random-if(cocoaWidget) fails-if(!haveTestPlugin&&!Android) skip-if(!testPluginIsOOP()) == pluginproblemui-direction-2.html pluginproblemui-direction-2-ref.html
|
||||
fails-if(!haveTestPlugin) == plugin-canvas-alpha-zindex.html div-alpha-zindex.html
|
||||
fails-if(!haveTestPlugin) == plugin-transform-alpha-zindex.html div-alpha-zindex.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-busy-alpha-zindex.html div-alpha-zindex.html
|
||||
fails-if(!haveTestPlugin) skip-if(Android&&layersOpenGL) == plugin-canvas-alpha-zindex.html div-alpha-zindex.html
|
||||
fails-if(!haveTestPlugin) skip-if(Android&&layersOpenGL) == plugin-transform-alpha-zindex.html div-alpha-zindex.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) skip-if(Android&&layersOpenGL) == plugin-busy-alpha-zindex.html div-alpha-zindex.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-background.html plugin-background-ref.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-background-1-step.html plugin-background-ref.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-background-2-step.html plugin-background-ref.html
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
#include "nsISelectionPrivate.h"
|
||||
#include "nsFrameSelection.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
NS_IMETHODIMP nsPlaintextEditor::PrepareTransferable(nsITransferable **transferable)
|
||||
{
|
||||
|
@ -136,6 +137,10 @@ NS_IMETHODIMP nsPlaintextEditor::InsertTextFromTransferable(nsITransferable *aTr
|
|||
nsAutoString stuffToPaste;
|
||||
textDataObj->GetData(stuffToPaste);
|
||||
NS_ASSERTION(stuffToPaste.Length() <= (len/2), "Invalid length!");
|
||||
|
||||
// Sanitize possible carriage returns in the string to be inserted
|
||||
nsContentUtils::PlatformToDOMLineBreaks(stuffToPaste);
|
||||
|
||||
nsAutoEditBatch beginBatching(this);
|
||||
rv = InsertTextAt(stuffToPaste, aDestinationNode, aDestOffset, aDoDeleteSelection);
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ _TEST_FILES = \
|
|||
test_bug638596.html \
|
||||
test_bug641466.html \
|
||||
test_bug645914.html \
|
||||
test_bug681229.html \
|
||||
$(NULL)
|
||||
|
||||
# disables the key handling test on gtk2 because gtk2 overrides some key events
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=681229
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 681229</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=681229">Mozilla Bug 681229</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<textarea spellcheck="false"></textarea>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 681229 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
var t = document.querySelector("textarea");
|
||||
t.focus();
|
||||
|
||||
const kValue = "a\r\nb";
|
||||
const kExpectedValue = (navigator.platform.indexOf("Win") == 0) ?
|
||||
"a\nb" : kValue;
|
||||
|
||||
SimpleTest.waitForClipboard(kExpectedValue,
|
||||
function() {
|
||||
SpecialPowers.copyString(kValue);
|
||||
},
|
||||
function() {
|
||||
synthesizeKey("V", {accelKey: true});
|
||||
is(t.value, "a\nb", "The carriage return has been correctly sanitized");
|
||||
SimpleTest.finish();
|
||||
},
|
||||
function() {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -30,6 +30,10 @@
|
|||
<uses-feature android:name="android.hardware.location.gps" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.touchscreen"/>
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-feature android:name="android.hardware.camera" />
|
||||
<uses-feature android:name="android.hardware.camera.autofocus" />
|
||||
|
||||
<application android:label="@MOZ_APP_DISPLAYNAME@"
|
||||
android:icon="@drawable/icon"
|
||||
#if MOZILLA_OFFICIAL
|
||||
|
|
|
@ -863,10 +863,25 @@ public class GeckoAppShell
|
|||
getHandler().post(new Runnable() {
|
||||
public void run() {
|
||||
Context context = GeckoApp.surfaceView.getContext();
|
||||
android.text.ClipboardManager cm = (android.text.ClipboardManager)
|
||||
context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
String text = null;
|
||||
if (android.os.Build.VERSION.SDK_INT >= 11) {
|
||||
android.content.ClipboardManager cm = (android.content.ClipboardManager)
|
||||
context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
if (cm.hasPrimaryClip()) {
|
||||
ClipData clip = cm.getPrimaryClip();
|
||||
if (clip != null) {
|
||||
ClipData.Item item = clip.getItemAt(0);
|
||||
text = item.coerceToText(context).toString();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
android.text.ClipboardManager cm = (android.text.ClipboardManager)
|
||||
context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
if (cm.hasText())
|
||||
text = cm.getText().toString();
|
||||
}
|
||||
try {
|
||||
sClipboardQueue.put(cm.hasText() ? cm.getText().toString() : "");
|
||||
sClipboardQueue.put(text != null ? text : "");
|
||||
} catch (InterruptedException ie) {}
|
||||
}});
|
||||
try {
|
||||
|
@ -880,9 +895,15 @@ public class GeckoAppShell
|
|||
getHandler().post(new Runnable() {
|
||||
public void run() {
|
||||
Context context = GeckoApp.surfaceView.getContext();
|
||||
android.text.ClipboardManager cm = (android.text.ClipboardManager)
|
||||
context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cm.setText(text);
|
||||
if (android.os.Build.VERSION.SDK_INT >= 11) {
|
||||
android.content.ClipboardManager cm = (android.content.ClipboardManager)
|
||||
context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cm.setPrimaryClip(ClipData.newPlainText("Text", text));
|
||||
} else {
|
||||
android.text.ClipboardManager cm = (android.text.ClipboardManager)
|
||||
context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cm.setText(text);
|
||||
}
|
||||
}});
|
||||
}
|
||||
|
||||
|
@ -1583,4 +1604,95 @@ public class GeckoAppShell
|
|||
Log.i("GeckoShell", "post to " + (mainThread ? "main " : "") + "java thread");
|
||||
getMainHandler().post(new GeckoRunnableCallback());
|
||||
}
|
||||
|
||||
public static android.hardware.Camera sCamera = null;
|
||||
|
||||
static native void cameraCallbackBridge(byte[] data);
|
||||
|
||||
static int kPreferedFps = 25;
|
||||
static byte[] sCameraBuffer = null;
|
||||
|
||||
static int[] initCamera(String aContentType, int aCamera, int aWidth, int aHeight) {
|
||||
Log.i("GeckoAppJava", "initCamera(" + aContentType + ", " + aWidth + "x" + aHeight + ") on thread " + Thread.currentThread().getId());
|
||||
|
||||
// [0] = 0|1 (failure/success)
|
||||
// [1] = width
|
||||
// [2] = height
|
||||
// [3] = fps
|
||||
int[] result = new int[4];
|
||||
result[0] = 0;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 9) {
|
||||
if (android.hardware.Camera.getNumberOfCameras() == 0)
|
||||
return result;
|
||||
}
|
||||
|
||||
try {
|
||||
sCamera = android.hardware.Camera.open(aCamera);
|
||||
android.hardware.Camera.Parameters params = sCamera.getParameters();
|
||||
params.setPreviewFormat(ImageFormat.NV21);
|
||||
|
||||
// use the preview fps closest to 25 fps.
|
||||
int fpsDelta = 1000;
|
||||
try {
|
||||
Iterator<Integer> it = params.getSupportedPreviewFrameRates().iterator();
|
||||
while (it.hasNext()) {
|
||||
int nFps = it.next();
|
||||
if (Math.abs(nFps - kPreferedFps) < fpsDelta) {
|
||||
fpsDelta = Math.abs(nFps - kPreferedFps);
|
||||
params.setPreviewFrameRate(nFps);
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
params.setPreviewFrameRate(kPreferedFps);
|
||||
}
|
||||
|
||||
// set up the closest preview size available
|
||||
Iterator<android.hardware.Camera.Size> sit = params.getSupportedPreviewSizes().iterator();
|
||||
int sizeDelta = 10000000;
|
||||
int bufferSize = 0;
|
||||
while (sit.hasNext()) {
|
||||
android.hardware.Camera.Size size = sit.next();
|
||||
if (Math.abs(size.width * size.height - aWidth * aHeight) < sizeDelta) {
|
||||
sizeDelta = Math.abs(size.width * size.height - aWidth * aHeight);
|
||||
params.setPreviewSize(size.width, size.height);
|
||||
bufferSize = size.width * size.height;
|
||||
}
|
||||
}
|
||||
|
||||
sCamera.setParameters(params);
|
||||
sCameraBuffer = new byte[(bufferSize * 12) / 8];
|
||||
sCamera.addCallbackBuffer(sCameraBuffer);
|
||||
sCamera.setPreviewCallbackWithBuffer(new android.hardware.Camera.PreviewCallback() {
|
||||
public void onPreviewFrame(byte[] data, android.hardware.Camera camera) {
|
||||
cameraCallbackBridge(data);
|
||||
sCamera.addCallbackBuffer(sCameraBuffer);
|
||||
}
|
||||
});
|
||||
sCamera.startPreview();
|
||||
params = sCamera.getParameters();
|
||||
Log.i("GeckoAppJava", "Camera: " + params.getPreviewSize().width + "x" + params.getPreviewSize().height +
|
||||
" @ " + params.getPreviewFrameRate() + "fps. format is " + params.getPreviewFormat());
|
||||
result[0] = 1;
|
||||
result[1] = params.getPreviewSize().width;
|
||||
result[2] = params.getPreviewSize().height;
|
||||
result[3] = params.getPreviewFrameRate();
|
||||
|
||||
Log.i("GeckoAppJava", "Camera preview started");
|
||||
} catch(RuntimeException e) {
|
||||
Log.e("GeckoAppJava", "initCamera RuntimeException : ", e);
|
||||
result[0] = result[1] = result[2] = result[3] = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static synchronized void closeCamera() {
|
||||
Log.i("GeckoAppJava", "closeCamera() on thread " + Thread.currentThread().getId());
|
||||
if (sCamera != null) {
|
||||
sCamera.stopPreview();
|
||||
sCamera.release();
|
||||
sCamera = null;
|
||||
sCameraBuffer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,6 @@ struct {
|
|||
{ HB_TAG('c','a','l','t'), DEFAULT_PRIORITY },
|
||||
{ HB_TAG('c','c','m','p'), FIRST_PRIORITY },
|
||||
{ HB_TAG('c','l','i','g'), DEFAULT_PRIORITY },
|
||||
{ HB_TAG('c','s','w','h'), DEFAULT_PRIORITY },
|
||||
{ HB_TAG('c','u','r','s'), DEFAULT_PRIORITY },
|
||||
{ HB_TAG('k','e','r','n'), DEFAULT_PRIORITY },
|
||||
{ HB_TAG('l','i','g','a'), DEFAULT_PRIORITY },
|
||||
|
|
|
@ -42,6 +42,40 @@
|
|||
#include <algorithm>
|
||||
using namespace std;
|
||||
|
||||
/* Force small values to zero. We do this to avoid having sin(360deg)
|
||||
* evaluate to a tiny but nonzero value.
|
||||
*/
|
||||
static double FlushToZero(double aVal)
|
||||
{
|
||||
if (-FLT_EPSILON < aVal && aVal < FLT_EPSILON)
|
||||
return 0.0f;
|
||||
else
|
||||
return aVal;
|
||||
}
|
||||
|
||||
/* Computes tan(aTheta). For values of aTheta such that tan(aTheta) is
|
||||
* undefined or very large, SafeTangent returns a manageably large value
|
||||
* of the correct sign.
|
||||
*/
|
||||
static double SafeTangent(double aTheta)
|
||||
{
|
||||
const double kEpsilon = 0.0001;
|
||||
|
||||
/* tan(theta) = sin(theta)/cos(theta); problems arise when
|
||||
* cos(theta) is too close to zero. Limit cos(theta) to the
|
||||
* range [-1, -epsilon] U [epsilon, 1].
|
||||
*/
|
||||
double sinTheta = sin(aTheta);
|
||||
double cosTheta = cos(aTheta);
|
||||
|
||||
if (cosTheta >= 0 && cosTheta < kEpsilon)
|
||||
cosTheta = kEpsilon;
|
||||
else if (cosTheta < 0 && cosTheta >= -kEpsilon)
|
||||
cosTheta = -kEpsilon;
|
||||
|
||||
return FlushToZero(sinTheta / cosTheta);
|
||||
}
|
||||
|
||||
gfx3DMatrix::gfx3DMatrix(void)
|
||||
{
|
||||
_11 = _22 = _33 = _44 = 1.0f;
|
||||
|
@ -182,19 +216,19 @@ gfx3DMatrix::TranslatePost(const gfxPoint3D& aPoint)
|
|||
}
|
||||
|
||||
void
|
||||
gfx3DMatrix::SkewXY(float aSkew)
|
||||
gfx3DMatrix::SkewXY(double aSkew)
|
||||
{
|
||||
(*this)[1] += (*this)[0] * aSkew;
|
||||
}
|
||||
|
||||
void
|
||||
gfx3DMatrix::SkewXZ(float aSkew)
|
||||
gfx3DMatrix::SkewXZ(double aSkew)
|
||||
{
|
||||
(*this)[2] += (*this)[0] * aSkew;
|
||||
}
|
||||
|
||||
void
|
||||
gfx3DMatrix::SkewYZ(float aSkew)
|
||||
gfx3DMatrix::SkewYZ(double aSkew)
|
||||
{
|
||||
(*this)[2] += (*this)[1] * aSkew;
|
||||
}
|
||||
|
@ -207,6 +241,144 @@ gfx3DMatrix::Scale(float aX, float aY, float aZ)
|
|||
(*this)[2] *= aZ;
|
||||
}
|
||||
|
||||
void
|
||||
gfx3DMatrix::Perspective(float aDepth)
|
||||
{
|
||||
NS_ASSERTION(aDepth > 0.0f, "Perspective must be positive!");
|
||||
_31 += -1.0/aDepth * _41;
|
||||
_32 += -1.0/aDepth * _42;
|
||||
_33 += -1.0/aDepth * _43;
|
||||
_34 += -1.0/aDepth * _44;
|
||||
}
|
||||
|
||||
void gfx3DMatrix::SkewXY(double aXSkew, double aYSkew)
|
||||
{
|
||||
float tanX = SafeTangent(aXSkew);
|
||||
float tanY = SafeTangent(aYSkew);
|
||||
float temp;
|
||||
|
||||
temp = _11;
|
||||
_11 += tanY * _21;
|
||||
_21 += tanX * temp;
|
||||
|
||||
temp = _12;
|
||||
_12 += tanY * _22;
|
||||
_22 += tanX * temp;
|
||||
|
||||
temp = _13;
|
||||
_13 += tanY * _23;
|
||||
_23 += tanX * temp;
|
||||
|
||||
temp = _14;
|
||||
_14 += tanY * _24;
|
||||
_24 += tanX * temp;
|
||||
}
|
||||
|
||||
void
|
||||
gfx3DMatrix::RotateX(double aTheta)
|
||||
{
|
||||
double cosTheta = FlushToZero(cos(aTheta));
|
||||
double sinTheta = FlushToZero(sin(aTheta));
|
||||
|
||||
float temp;
|
||||
|
||||
temp = _21;
|
||||
_21 = cosTheta * _21 + sinTheta * _31;
|
||||
_31 = -sinTheta * temp + cosTheta * _31;
|
||||
|
||||
temp = _22;
|
||||
_22 = cosTheta * _22 + sinTheta * _32;
|
||||
_32 = -sinTheta * temp + cosTheta * _32;
|
||||
|
||||
temp = _23;
|
||||
_23 = cosTheta * _23 + sinTheta * _33;
|
||||
_33 = -sinTheta * temp + cosTheta * _33;
|
||||
|
||||
temp = _24;
|
||||
_24 = cosTheta * _24 + sinTheta * _34;
|
||||
_34 = -sinTheta * temp + cosTheta * _34;
|
||||
}
|
||||
|
||||
void
|
||||
gfx3DMatrix::RotateY(double aTheta)
|
||||
{
|
||||
double cosTheta = FlushToZero(cos(aTheta));
|
||||
double sinTheta = FlushToZero(sin(aTheta));
|
||||
|
||||
float temp;
|
||||
|
||||
temp = _11;
|
||||
_11 = cosTheta * _11 + -sinTheta * _31;
|
||||
_31 = sinTheta * temp + cosTheta * _31;
|
||||
|
||||
temp = _12;
|
||||
_12 = cosTheta * _12 + -sinTheta * _32;
|
||||
_32 = sinTheta * temp + cosTheta * _32;
|
||||
|
||||
temp = _13;
|
||||
_13 = cosTheta * _13 + -sinTheta * _33;
|
||||
_33 = sinTheta * temp + cosTheta * _33;
|
||||
|
||||
temp = _14;
|
||||
_14 = cosTheta * _14 + -sinTheta * _34;
|
||||
_34 = sinTheta * temp + cosTheta * _34;
|
||||
}
|
||||
|
||||
void
|
||||
gfx3DMatrix::RotateZ(double aTheta)
|
||||
{
|
||||
double cosTheta = FlushToZero(cos(aTheta));
|
||||
double sinTheta = FlushToZero(sin(aTheta));
|
||||
|
||||
float temp;
|
||||
|
||||
temp = _11;
|
||||
_11 = cosTheta * _11 + sinTheta * _21;
|
||||
_21 = -sinTheta * temp + cosTheta * _21;
|
||||
|
||||
temp = _12;
|
||||
_12 = cosTheta * _12 + sinTheta * _22;
|
||||
_22 = -sinTheta * temp + cosTheta * _22;
|
||||
|
||||
temp = _13;
|
||||
_13 = cosTheta * _13 + sinTheta * _23;
|
||||
_23 = -sinTheta * temp + cosTheta * _23;
|
||||
|
||||
temp = _14;
|
||||
_14 = cosTheta * _14 + sinTheta * _24;
|
||||
_24 = -sinTheta * temp + cosTheta * _24;
|
||||
}
|
||||
|
||||
void
|
||||
gfx3DMatrix::PreMultiply(const gfx3DMatrix& aOther)
|
||||
{
|
||||
*this = aOther * (*this);
|
||||
}
|
||||
|
||||
void
|
||||
gfx3DMatrix::PreMultiply(const gfxMatrix& aOther)
|
||||
{
|
||||
gfx3DMatrix temp;
|
||||
temp._11 = aOther.xx * _11 + aOther.yx * _21;
|
||||
temp._21 = aOther.xy * _11 + aOther.yy * _21;
|
||||
temp._31 = _31;
|
||||
temp._41 = aOther.x0 * _11 + aOther.y0 * _21 + _41;
|
||||
temp._12 = aOther.xx * _12 + aOther.yx * _22;
|
||||
temp._22 = aOther.xy * _12 + aOther.yy * _22;
|
||||
temp._32 = _32;
|
||||
temp._42 = aOther.x0 * _12 + aOther.y0 * _22 + _42;
|
||||
temp._13 = aOther.xx * _13 + aOther.yx * _23;
|
||||
temp._23 = aOther.xy * _13 + aOther.yy * _23;
|
||||
temp._33 = _33;
|
||||
temp._43 = aOther.x0 * _13 + aOther.y0 * _23 + _43;
|
||||
temp._14 = aOther.xx * _14 + aOther.yx * _24;
|
||||
temp._24 = aOther.xy * _14 + aOther.yy * _24;
|
||||
temp._34 = _34;
|
||||
temp._44 = aOther.x0 * _14 + aOther.y0 * _24 + _44;
|
||||
|
||||
*this = temp;
|
||||
}
|
||||
|
||||
gfx3DMatrix
|
||||
gfx3DMatrix::Translation(float aX, float aY, float aZ)
|
||||
{
|
||||
|
|
|
@ -126,26 +126,117 @@ public:
|
|||
*/
|
||||
PRBool IsIdentity() const;
|
||||
|
||||
/**
|
||||
* Pre-multiplication transformation functions:
|
||||
*
|
||||
* These functions construct a temporary matrix containing
|
||||
* a single transformation and pre-multiply it onto the current
|
||||
* matrix.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Add a translation by aPoint to the matrix.
|
||||
* This is functionally equivalent to:
|
||||
* gfx3DMatrix::Translation(aPoint) * matrix
|
||||
*
|
||||
* This creates this temporary matrix:
|
||||
* | 1 0 0 0 |
|
||||
* | 0 1 0 0 |
|
||||
* | 0 0 1 0 |
|
||||
* | aPoint.x aPoint.y aPoint.z 1 |
|
||||
*/
|
||||
void Translate(const gfxPoint3D& aPoint);
|
||||
|
||||
/**
|
||||
* Skew the matrix.
|
||||
*
|
||||
* This creates this temporary matrix:
|
||||
* | 1 tan(aYSkew) 0 0 |
|
||||
* | tan(aXSkew) 1 0 0 |
|
||||
* | 0 0 1 0 |
|
||||
* | 0 0 0 1 |
|
||||
*/
|
||||
void SkewXY(double aXSkew, double aYSkew);
|
||||
|
||||
void SkewXY(double aSkew);
|
||||
void SkewXZ(double aSkew);
|
||||
void SkewYZ(double aSkew);
|
||||
|
||||
/**
|
||||
* Scale the matrix
|
||||
*
|
||||
* This creates this temporary matrix:
|
||||
* | aX 0 0 0 |
|
||||
* | 0 aY 0 0 |
|
||||
* | 0 0 aZ 0 |
|
||||
* | 0 0 0 1 |
|
||||
*/
|
||||
void Scale(float aX, float aY, float aZ);
|
||||
|
||||
/**
|
||||
* Rotate around the X axis..
|
||||
*
|
||||
* This creates this temporary matrix:
|
||||
* | 1 0 0 0 |
|
||||
* | 0 cos(aTheta) sin(aTheta) 0 |
|
||||
* | 0 -sin(aTheta) cos(aTheta) 0 |
|
||||
* | 0 0 0 1 |
|
||||
*/
|
||||
void RotateX(double aTheta);
|
||||
|
||||
/**
|
||||
* Rotate around the Y axis..
|
||||
*
|
||||
* This creates this temporary matrix:
|
||||
* | cos(aTheta) 0 -sin(aTheta) 0 |
|
||||
* | 0 1 0 0 |
|
||||
* | sin(aTheta) 0 cos(aTheta) 0 |
|
||||
* | 0 0 0 1 |
|
||||
*/
|
||||
void RotateY(double aTheta);
|
||||
|
||||
/**
|
||||
* Rotate around the Z axis..
|
||||
*
|
||||
* This creates this temporary matrix:
|
||||
* | cos(aTheta) sin(aTheta) 0 0 |
|
||||
* | -sin(aTheta) cos(aTheta) 0 0 |
|
||||
* | 0 0 1 0 |
|
||||
* | 0 0 0 1 |
|
||||
*/
|
||||
void RotateZ(double aTheta);
|
||||
|
||||
/**
|
||||
* Apply perspective to the matrix.
|
||||
*
|
||||
* This creates this temporary matrix:
|
||||
* | 1 0 0 0 |
|
||||
* | 0 1 0 0 |
|
||||
* | 0 0 1 -1/aDepth |
|
||||
* | 0 0 0 1 |
|
||||
*/
|
||||
void Perspective(float aDepth);
|
||||
|
||||
/**
|
||||
* Pre multiply an existing matrix onto the current
|
||||
* matrix
|
||||
*/
|
||||
void PreMultiply(const gfx3DMatrix& aOther);
|
||||
void PreMultiply(const gfxMatrix& aOther);
|
||||
|
||||
/**
|
||||
* Post-multiplication transformation functions:
|
||||
*
|
||||
* These functions construct a temporary matrix containing
|
||||
* a single transformation and post-multiply it onto the current
|
||||
* matrix.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Add a translation by aPoint after the matrix.
|
||||
* This is functionally equivalent to:
|
||||
* matrix *gfx3DMatrix::Translation(aPoint)
|
||||
* matrix * gfx3DMatrix::Translation(aPoint)
|
||||
*/
|
||||
void TranslatePost(const gfxPoint3D& aPoint);
|
||||
|
||||
void SkewXY(float aSkew);
|
||||
void SkewXZ(float aSkew);
|
||||
void SkewYZ(float aSkew);
|
||||
|
||||
void Scale(float aX, float aY, float aZ);
|
||||
|
||||
/**
|
||||
* Transforms a point according to this matrix.
|
||||
*/
|
||||
|
|
|
@ -55,6 +55,8 @@
|
|||
#include "jsstr.h"
|
||||
#include "jsvector.h"
|
||||
|
||||
#include "vm/GlobalObject.h"
|
||||
|
||||
#include "jsinferinlines.h"
|
||||
#include "jsinterpinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
|
@ -65,9 +67,7 @@ using namespace js::types;
|
|||
|
||||
Class js::BooleanClass = {
|
||||
"Boolean",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(1) |
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean),
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean), JS_PropertyStub, /* addProperty */
|
||||
JS_PropertyStub, /* delProperty */
|
||||
JS_PropertyStub, /* getProperty */
|
||||
JS_StrictPropertyStub, /* setProperty */
|
||||
|
@ -152,12 +152,30 @@ Boolean(JSContext *cx, uintN argc, Value *vp)
|
|||
JSObject *
|
||||
js_InitBooleanClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSObject *proto = js_InitClass(cx, obj, NULL, &BooleanClass, Boolean, 1,
|
||||
NULL, boolean_methods, NULL, NULL);
|
||||
if (!proto)
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
GlobalObject *global = obj->asGlobal();
|
||||
|
||||
JSObject *booleanProto = global->createBlankPrototype(cx, &BooleanClass);
|
||||
if (!booleanProto)
|
||||
return NULL;
|
||||
proto->setPrimitiveThis(BooleanValue(false));
|
||||
return proto;
|
||||
booleanProto->setPrimitiveThis(BooleanValue(false));
|
||||
|
||||
JSFunction *ctor = global->createConstructor(cx, Boolean, &BooleanClass,
|
||||
CLASS_ATOM(cx, Boolean), 1);
|
||||
if (!ctor)
|
||||
return NULL;
|
||||
|
||||
if (!LinkConstructorAndPrototype(cx, ctor, booleanProto))
|
||||
return NULL;
|
||||
|
||||
if (!DefinePropertiesAndBrand(cx, booleanProto, NULL, boolean_methods))
|
||||
return NULL;
|
||||
|
||||
if (!DefineConstructorAndPrototype(cx, global, JSProto_Boolean, ctor, booleanProto))
|
||||
return NULL;
|
||||
|
||||
return booleanProto;
|
||||
}
|
||||
|
||||
JSString *
|
||||
|
|
|
@ -72,6 +72,8 @@
|
|||
#include "jsstr.h"
|
||||
#include "jslibmath.h"
|
||||
|
||||
#include "vm/GlobalObject.h"
|
||||
|
||||
#include "jsinferinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
|
@ -2605,34 +2607,52 @@ js_Date(JSContext *cx, uintN argc, Value *vp)
|
|||
JSObject *
|
||||
js_InitDateClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
/* set static LocalTZA */
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
/* Set the static LocalTZA. */
|
||||
LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond);
|
||||
JSObject *proto = js_InitClass(cx, obj, NULL, &DateClass, js_Date, MAXARGS,
|
||||
NULL, date_methods, NULL, date_static_methods);
|
||||
if (!proto)
|
||||
|
||||
GlobalObject *global = obj->asGlobal();
|
||||
|
||||
JSObject *dateProto = global->createBlankPrototype(cx, &DateClass);
|
||||
if (!dateProto)
|
||||
return NULL;
|
||||
SetDateToNaN(cx, dateProto);
|
||||
|
||||
JSFunction *ctor = global->createConstructor(cx, js_Date, &DateClass,
|
||||
CLASS_ATOM(cx, Date), MAXARGS);
|
||||
if (!ctor)
|
||||
return NULL;
|
||||
|
||||
AutoObjectRooter tvr(cx, proto);
|
||||
if (!LinkConstructorAndPrototype(cx, ctor, dateProto))
|
||||
return NULL;
|
||||
|
||||
SetDateToNaN(cx, proto);
|
||||
if (!DefinePropertiesAndBrand(cx, ctor, NULL, date_static_methods))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* ES5 B.2.6:
|
||||
* The Function object that is the initial value of
|
||||
* Date.prototype.toGMTString is the same Function
|
||||
* object that is the initial value of
|
||||
* Date.prototype.toUTCString.
|
||||
* Define all Date.prototype.* functions, then brand for trace-jitted code.
|
||||
* Date.prototype.toGMTString has the same initial value as
|
||||
* Date.prototype.toUTCString.
|
||||
*/
|
||||
AutoValueRooter toUTCStringFun(cx);
|
||||
if (!JS_DefineFunctions(cx, dateProto, date_methods))
|
||||
return NULL;
|
||||
Value toUTCStringFun;
|
||||
jsid toUTCStringId = ATOM_TO_JSID(cx->runtime->atomState.toUTCStringAtom);
|
||||
jsid toGMTStringId = ATOM_TO_JSID(cx->runtime->atomState.toGMTStringAtom);
|
||||
if (!js_GetProperty(cx, proto, toUTCStringId, toUTCStringFun.addr()) ||
|
||||
!js_DefineProperty(cx, proto, toGMTStringId, toUTCStringFun.addr(),
|
||||
JS_PropertyStub, JS_StrictPropertyStub, 0)) {
|
||||
if (!js_GetProperty(cx, dateProto, toUTCStringId, &toUTCStringFun) ||
|
||||
!js_DefineProperty(cx, dateProto, toGMTStringId, &toUTCStringFun,
|
||||
JS_PropertyStub, JS_StrictPropertyStub, 0))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (!cx->typeInferenceEnabled())
|
||||
dateProto->brand(cx);
|
||||
|
||||
return proto;
|
||||
if (!DefineConstructorAndPrototype(cx, global, JSProto_Date, ctor, dateProto))
|
||||
return NULL;
|
||||
|
||||
return dateProto;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
|
|
|
@ -75,6 +75,8 @@
|
|||
#include "jsvector.h"
|
||||
#include "jslibmath.h"
|
||||
|
||||
#include "vm/GlobalObject.h"
|
||||
|
||||
#include "jsatominlines.h"
|
||||
#include "jsinferinlines.h"
|
||||
#include "jsinterpinlines.h"
|
||||
|
@ -82,6 +84,7 @@
|
|||
#include "jsobjinlines.h"
|
||||
#include "jsstrinlines.h"
|
||||
|
||||
#include "vm/NumberObject-inl.h"
|
||||
#include "vm/String-inl.h"
|
||||
|
||||
using namespace js;
|
||||
|
@ -1099,39 +1102,52 @@ FinishRuntimeNumberState(JSRuntime *rt)
|
|||
JSObject *
|
||||
js_InitNumberClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSObject *proto, *ctor;
|
||||
JSRuntime *rt;
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
/* XXX must do at least once per new thread, so do it per JSContext... */
|
||||
FIX_FPU();
|
||||
|
||||
proto = js_InitClass(cx, obj, NULL, &NumberClass, Number, 1,
|
||||
NULL, number_methods, NULL, NULL);
|
||||
if (!proto || !(ctor = JS_GetConstructor(cx, proto)))
|
||||
return NULL;
|
||||
proto->setPrimitiveThis(Int32Value(0));
|
||||
GlobalObject *global = obj->asGlobal();
|
||||
|
||||
if (!JS_DefineFunctions(cx, obj, number_functions))
|
||||
JSObject *numberProto = global->createBlankPrototype(cx, &NumberClass);
|
||||
if (!numberProto)
|
||||
return NULL;
|
||||
numberProto->asNumber()->setPrimitiveValue(0);
|
||||
|
||||
JSFunction *ctor = global->createConstructor(cx, Number, &NumberClass,
|
||||
CLASS_ATOM(cx, Number), 1);
|
||||
if (!ctor)
|
||||
return NULL;
|
||||
|
||||
if (!LinkConstructorAndPrototype(cx, ctor, numberProto))
|
||||
return NULL;
|
||||
|
||||
/* Add numeric constants (MAX_VALUE, NaN, &c.) to the Number constructor. */
|
||||
if (!JS_DefineConstDoubles(cx, ctor, number_constants))
|
||||
return NULL;
|
||||
|
||||
/* ECMA 15.1.1.1 */
|
||||
rt = cx->runtime;
|
||||
if (!JS_DefineProperty(cx, obj, js_NaN_str, rt->NaNValue,
|
||||
JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JSPROP_PERMANENT | JSPROP_READONLY)) {
|
||||
if (!DefinePropertiesAndBrand(cx, numberProto, NULL, number_methods))
|
||||
return NULL;
|
||||
|
||||
if (!JS_DefineFunctions(cx, global, number_functions))
|
||||
return NULL;
|
||||
|
||||
/* ES5 15.1.1.1, 15.1.1.2 */
|
||||
if (!DefineNativeProperty(cx, global, ATOM_TO_JSID(cx->runtime->atomState.NaNAtom),
|
||||
cx->runtime->NaNValue, JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JSPROP_PERMANENT | JSPROP_READONLY, 0, 0) ||
|
||||
!DefineNativeProperty(cx, global, ATOM_TO_JSID(cx->runtime->atomState.InfinityAtom),
|
||||
cx->runtime->positiveInfinityValue,
|
||||
JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JSPROP_PERMANENT | JSPROP_READONLY, 0, 0))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ECMA 15.1.1.2 */
|
||||
if (!JS_DefineProperty(cx, obj, js_Infinity_str, rt->positiveInfinityValue,
|
||||
JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JSPROP_PERMANENT | JSPROP_READONLY)) {
|
||||
if (!DefineConstructorAndPrototype(cx, global, JSProto_Number, ctor, numberProto))
|
||||
return NULL;
|
||||
}
|
||||
return proto;
|
||||
|
||||
return numberProto;
|
||||
}
|
||||
|
||||
namespace v8 {
|
||||
|
|
|
@ -89,6 +89,7 @@
|
|||
#include "jsscriptinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "vm/NumberObject-inl.h"
|
||||
#include "vm/StringObject-inl.h"
|
||||
|
||||
#if JS_HAS_GENERATORS
|
||||
|
@ -6763,10 +6764,11 @@ PrimitiveToObject(JSContext *cx, const Value &v)
|
|||
{
|
||||
if (v.isString())
|
||||
return StringObject::create(cx, v.toString());
|
||||
if (v.isNumber())
|
||||
return NumberObject::create(cx, v.toNumber());
|
||||
|
||||
JS_ASSERT(v.isNumber() || v.isBoolean());
|
||||
Class *clasp = v.isNumber() ? &NumberClass : &BooleanClass;
|
||||
JSObject *obj = NewBuiltinClassInstance(cx, clasp);
|
||||
JS_ASSERT(v.isBoolean());
|
||||
JSObject *obj = NewBuiltinClassInstance(cx, &BooleanClass);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
|
|
|
@ -380,6 +380,7 @@ extern Class XMLFilterClass;
|
|||
class ArgumentsObject;
|
||||
class GlobalObject;
|
||||
class NormalArgumentsObject;
|
||||
class NumberObject;
|
||||
class StrictArgumentsObject;
|
||||
class StringObject;
|
||||
|
||||
|
@ -1052,6 +1053,7 @@ struct JSObject : js::gc::Cell {
|
|||
}
|
||||
|
||||
public:
|
||||
inline js::NumberObject *asNumber();
|
||||
inline js::StringObject *asString();
|
||||
|
||||
/*
|
||||
|
|
|
@ -49,6 +49,8 @@
|
|||
#include "jsgcmark.h"
|
||||
#include "jsweakmap.h"
|
||||
|
||||
#include "vm/GlobalObject.h"
|
||||
|
||||
#include "jsgcinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
|
@ -290,12 +292,27 @@ static JSFunctionSpec weak_map_methods[] = {
|
|||
JSObject *
|
||||
js_InitWeakMapClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSObject *proto = js_InitClass(cx, obj, NULL, &WeakMapClass, WeakMap_construct, 0,
|
||||
NULL, weak_map_methods, NULL, NULL);
|
||||
if (!proto)
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
GlobalObject *global = obj->asGlobal();
|
||||
|
||||
JSObject *weakMapProto = global->createBlankPrototype(cx, &WeakMapClass);
|
||||
if (!weakMapProto)
|
||||
return NULL;
|
||||
weakMapProto->setPrivate(NULL);
|
||||
|
||||
JSFunction *ctor = global->createConstructor(cx, WeakMap_construct, &WeakMapClass,
|
||||
CLASS_ATOM(cx, WeakMap), 0);
|
||||
if (!ctor)
|
||||
return NULL;
|
||||
|
||||
proto->setPrivate(NULL);
|
||||
if (!LinkConstructorAndPrototype(cx, ctor, weakMapProto))
|
||||
return NULL;
|
||||
|
||||
return proto;
|
||||
if (!DefinePropertiesAndBrand(cx, weakMapProto, NULL, weak_map_methods))
|
||||
return NULL;
|
||||
|
||||
if (!DefineConstructorAndPrototype(cx, global, JSProto_WeakMap, ctor, weakMapProto))
|
||||
return NULL;
|
||||
return weakMapProto;
|
||||
}
|
||||
|
|
|
@ -4632,58 +4632,6 @@ static JSPropertySpec its_props[] = {
|
|||
{NULL,0,0,NULL,NULL}
|
||||
};
|
||||
|
||||
static JSBool
|
||||
its_bindMethod(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSString *name;
|
||||
JSObject *method;
|
||||
|
||||
JSObject *thisobj = JS_THIS_OBJECT(cx, vp);
|
||||
|
||||
if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "So", &name, &method))
|
||||
return JS_FALSE;
|
||||
|
||||
*vp = OBJECT_TO_JSVAL(method);
|
||||
|
||||
if (JS_TypeOfValue(cx, *vp) != JSTYPE_FUNCTION) {
|
||||
JSAutoByteString nameBytes(cx, name);
|
||||
if (!!nameBytes) {
|
||||
JSString *valstr = JS_ValueToString(cx, *vp);
|
||||
if (valstr) {
|
||||
JSAutoByteString valBytes(cx, valstr);
|
||||
if (!!valBytes) {
|
||||
JS_ReportError(cx, "can't bind method %s to non-callable object %s",
|
||||
nameBytes.ptr(), valBytes.ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (method->getFunctionPrivate()->isInterpreted() &&
|
||||
method->getFunctionPrivate()->script()->compileAndGo) {
|
||||
/* Can't reparent compileAndGo scripts. */
|
||||
JSAutoByteString nameBytes(cx, name);
|
||||
if (!!nameBytes)
|
||||
JS_ReportError(cx, "can't bind method %s to compileAndGo script", nameBytes.ptr());
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
jsid id;
|
||||
if (!JS_ValueToId(cx, STRING_TO_JSVAL(name), &id))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!JS_DefinePropertyById(cx, thisobj, id, *vp, NULL, NULL, JSPROP_ENUMERATE))
|
||||
return JS_FALSE;
|
||||
|
||||
return JS_SetParent(cx, method, thisobj);
|
||||
}
|
||||
|
||||
static JSFunctionSpec its_methods[] = {
|
||||
{"bindMethod", its_bindMethod, 2,0},
|
||||
{NULL,NULL,0,0}
|
||||
};
|
||||
|
||||
#ifdef JSD_LOWLEVEL_SOURCE
|
||||
/*
|
||||
* This facilitates sending source to JSD (the debugger system) in the shell
|
||||
|
@ -5336,8 +5284,6 @@ NewGlobalObject(JSContext *cx, CompartmentKind compartment)
|
|||
return NULL;
|
||||
if (!JS_DefineProperties(cx, it, its_props))
|
||||
return NULL;
|
||||
if (!JS_DefineFunctions(cx, it, its_methods))
|
||||
return NULL;
|
||||
|
||||
if (!JS_DefineProperty(cx, glob, "custom", JSVAL_VOID, its_getter,
|
||||
its_setter, 0))
|
||||
|
|
|
@ -152,6 +152,17 @@ actual = F2.call(null);
|
|||
expect = F2.call();
|
||||
addThis();
|
||||
|
||||
if (typeof newGlobal === "function")
|
||||
{
|
||||
/*
|
||||
* Function.prototype.call gets lexical globals, not caller globals
|
||||
*/
|
||||
status = inSection(11);
|
||||
actual = g2 = newGlobal('new-compartment');
|
||||
g2.eval("boundMethod = Function('return this');");
|
||||
expect = g2.boundMethod.call();
|
||||
addThis();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -68,6 +68,17 @@ assertEq(bazArguments.get, canonicalTTE);
|
|||
assertEq(bazArguments.set, canonicalTTE);
|
||||
|
||||
|
||||
// [[ThrowTypeError]] characteristics
|
||||
|
||||
assertEq(Object.prototype.toString.call(canonicalTTE), "[object Function]");
|
||||
assertEq(Object.getPrototypeOf(canonicalTTE), Function.prototype);
|
||||
assertEq(canonicalTTE.length, 0);
|
||||
assertEq(Object.isExtensible(canonicalTTE), false);
|
||||
canonicalTTE.lumpy = 17;
|
||||
assertEq(canonicalTTE.hasOwnProperty("lumpy"), false);
|
||||
assertEq("lumpy" in canonicalTTE, false);
|
||||
expectTypeError(function setTTEProp() { "use strict"; canonicalTTE.x = 42; });
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
url-prefix ../../jsreftest.html?test=js1_5/Function/
|
||||
script 10.1.6-01.js
|
||||
script 10.1.6.js
|
||||
script 15.3.4.4.js
|
||||
script regress-123371.js
|
||||
script regress-178389.js
|
||||
script regress-222029-001.js
|
||||
|
|
|
@ -225,6 +225,9 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
|
|||
JSFunction *throwTypeError = js_NewFunction(cx, NULL, ThrowTypeError, 0, 0, this, NULL);
|
||||
if (!throwTypeError)
|
||||
return NULL;
|
||||
AutoIdVector ids(cx);
|
||||
if (!throwTypeError->preventExtensions(cx, &ids))
|
||||
return NULL;
|
||||
setThrowTypeError(throwTypeError);
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
|
@ -12,18 +14,19 @@
|
|||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is JavaScript Engine testing utilities.
|
||||
* The Original Code is SpiderMonkey string object code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Brendan Eich
|
||||
* Contributor(s):
|
||||
* Jeff Walden <jwalden+code@mit.edu> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
|
@ -35,39 +38,43 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
var BUGNUMBER = 290488;
|
||||
var summary = '15.3.4.4 - Function.prototype.call() Scope';
|
||||
var actual = '';
|
||||
var expect = '';
|
||||
var description = '';
|
||||
var GLOBAL = this;
|
||||
#ifndef NumberObject_inl_h___
|
||||
#define NumberObject_inl_h___
|
||||
|
||||
printBugNumber(BUGNUMBER);
|
||||
printStatus (summary);
|
||||
#include "NumberObject.h"
|
||||
|
||||
printStatus(inSection(1));
|
||||
|
||||
function func() { return this; }
|
||||
|
||||
description = 'top-level function: this == GLOBAL';
|
||||
expect = GLOBAL;
|
||||
actual = func.call();
|
||||
reportCompare(expect, actual, description);
|
||||
|
||||
printStatus(inSection(2));
|
||||
|
||||
function getBoundMethod()
|
||||
inline js::NumberObject *
|
||||
JSObject::asNumber()
|
||||
{
|
||||
return it.bindMethod("boundMethod", Function("return this"));
|
||||
JS_ASSERT(isNumber());
|
||||
return static_cast<js::NumberObject *>(const_cast<JSObject *>(this));
|
||||
}
|
||||
|
||||
// it is a js shell only construction
|
||||
if (typeof it != 'undefined')
|
||||
namespace js {
|
||||
|
||||
inline NumberObject *
|
||||
NumberObject::create(JSContext *cx, jsdouble d)
|
||||
{
|
||||
description = 'bound method: this == GLOBAL';
|
||||
var func = getBoundMethod();
|
||||
expect = GLOBAL;
|
||||
actual = func.call();
|
||||
reportCompare(expect, actual, description);
|
||||
JSObject *obj = NewBuiltinClassInstance(cx, &NumberClass);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
NumberObject *numobj = obj->asNumber();
|
||||
numobj->setPrimitiveValue(d);
|
||||
return numobj;
|
||||
}
|
||||
|
||||
inline NumberObject *
|
||||
NumberObject::createWithProto(JSContext *cx, jsdouble d, JSObject &proto)
|
||||
{
|
||||
JSObject *obj = NewObjectWithClassProto(cx, &NumberClass, &proto,
|
||||
gc::GetGCObjectKind(RESERVED_SLOTS));
|
||||
if (!obj)
|
||||
return NULL;
|
||||
NumberObject *numobj = obj->asNumber();
|
||||
numobj->setPrimitiveValue(d);
|
||||
return numobj;
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif /* NumberObject_inl_h__ */
|
|
@ -0,0 +1,89 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is SpiderMonkey string object code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jeff Walden <jwalden+code@mit.edu> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef NumberObject_h___
|
||||
#define NumberObject_h___
|
||||
|
||||
#include "jsnum.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
class NumberObject : public ::JSObject
|
||||
{
|
||||
/* Stores this Number object's [[PrimitiveValue]]. */
|
||||
static const uintN PRIMITIVE_VALUE_SLOT = 0;
|
||||
|
||||
public:
|
||||
static const uintN RESERVED_SLOTS = 1;
|
||||
|
||||
/*
|
||||
* Creates a new Number object boxing the given number. The object's
|
||||
* [[Prototype]] is determined from context.
|
||||
*/
|
||||
static inline NumberObject *create(JSContext *cx, jsdouble d);
|
||||
|
||||
/*
|
||||
* Identical to create(), but uses |proto| as [[Prototype]]. This method
|
||||
* must not be used to create |Number.prototype|.
|
||||
*/
|
||||
static inline NumberObject *createWithProto(JSContext *cx, jsdouble d, JSObject &proto);
|
||||
|
||||
Value unbox() const {
|
||||
JS_ASSERT(getSlot(PRIMITIVE_VALUE_SLOT).isNumber());
|
||||
return getSlot(PRIMITIVE_VALUE_SLOT);
|
||||
}
|
||||
|
||||
private:
|
||||
inline void setPrimitiveValue(jsdouble d) {
|
||||
setSlot(PRIMITIVE_VALUE_SLOT, NumberValue(d));
|
||||
}
|
||||
|
||||
/* For access to init, as Number.prototype is special. */
|
||||
friend JSObject *
|
||||
::js_InitNumberClass(JSContext *cx, JSObject *global);
|
||||
|
||||
private:
|
||||
NumberObject();
|
||||
NumberObject &operator=(const NumberObject &so);
|
||||
};
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif /* NumberObject_h__ */
|
|
@ -726,10 +726,10 @@ XPCConvert::JSData2Native(XPCCallContext& ccx, void* d, jsval s,
|
|||
static const PRUnichar EMPTY_STRING[] = { '\0' };
|
||||
static const PRUnichar VOID_STRING[] = { 'u', 'n', 'd', 'e', 'f', 'i', 'n', 'e', 'd', '\0' };
|
||||
|
||||
const PRUnichar* chars;
|
||||
const PRUnichar* chars = nsnull;
|
||||
JSString* str = nsnull;
|
||||
JSBool isNewString = JS_FALSE;
|
||||
PRUint32 length;
|
||||
PRUint32 length = 0;
|
||||
|
||||
if(JSVAL_IS_VOID(s))
|
||||
{
|
||||
|
|
|
@ -438,7 +438,7 @@ nsFileControlFrame::CaptureMouseListener::HandleEvent(nsIDOMEvent* aMouseEvent)
|
|||
// Get Loc title
|
||||
nsXPIDLString title;
|
||||
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
|
||||
"FileUpload", title);
|
||||
"MediaUpload", title);
|
||||
|
||||
nsPIDOMWindow* win = doc->GetWindow();
|
||||
if (!win) {
|
||||
|
|
|
@ -242,7 +242,7 @@ mtable[frame="dashed"] {
|
|||
border: dashed thin;
|
||||
}
|
||||
|
||||
mtr {
|
||||
mtr, mlabeledtr {
|
||||
display: table-row;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
@ -254,12 +254,19 @@ mtd {
|
|||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Don't support mtr without mtable, nor mtd without mtr */
|
||||
/* Don't support m(labeled)tr without mtable, nor mtd without m(labeled)tr */
|
||||
:not(mtable) > mtr,
|
||||
:not(mtr) > mtd {
|
||||
:not(mtable) > mlabeledtr,
|
||||
:not(mtr):not(mlabeledtr) > mtd {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Hide the label because mlabeledtr is not supported yet (bug 356870). This
|
||||
rule can be overriden by users. */
|
||||
mlabeledtr > mtd:first-child {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/***********************/
|
||||
/* -- mtd: columnalign */
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ random == corner-2.html corner-2-ref.svg # right corners different radius than l
|
|||
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
|
||||
== clipping-3.html clipping-3-ref.xhtml # edge of border-radius clips an underlying object's background
|
||||
fails-if(Android&&layersOpenGL) == 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
|
||||
|
@ -63,8 +63,8 @@ fails-if(cocoaWidget) == intersecting-clipping-1-refc.html intersecting-clipping
|
|||
== table-collapse-1.html table-collapse-1-ref.html # border-radius is ignored on internal table elements
|
||||
# when border-collapse: collapse
|
||||
|
||||
== invalidate-1a.html invalidate-1-ref.html
|
||||
== invalidate-1b.html invalidate-1-ref.html
|
||||
fails-if(Android&&layersOpenGL) == invalidate-1a.html invalidate-1-ref.html
|
||||
fails-if(Android&&layersOpenGL) == invalidate-1b.html invalidate-1-ref.html
|
||||
|
||||
# test that border-radius is reduced for scrollbars
|
||||
fails-if(Android) == scrollbar-clamping-1.html scrollbar-clamping-1-ref.html
|
||||
|
@ -74,7 +74,7 @@ fails-if(Android) == scrollbar-clamping-2.html scrollbar-clamping-2-ref.html
|
|||
== corner-joins-1.xhtml corner-joins-1-ref.xhtml
|
||||
random-if(winWidget) HTTP(..) == corner-joins-2.xhtml corner-joins-2-ref.xhtml
|
||||
|
||||
== scroll-1.html scroll-1-ref.html # see bug 602892
|
||||
fails-if(Android&&layersOpenGL) == scroll-1.html scroll-1-ref.html # see bug 602892
|
||||
|
||||
== zero-radius-clip-1.html zero-radius-clip-ref.html
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
== default-size.html default-size-ref.html
|
||||
== size-1.html size-1-ref.html
|
||||
fails-if(Android&&layersOpenGL) == size-1.html size-1-ref.html
|
||||
|
||||
== image-rendering-test.html image-rendering-ref.html
|
||||
== image-shadow.html image-shadow-ref.html
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
!= inline-horizontal-2.html inline-horizontal-2-noref.html
|
||||
== inline-horizontal-1-dyn.html inline-horizontal-1-ref.html
|
||||
!= inline-horizontal-1-dyn.html inline-horizontal-1-noref.html
|
||||
== inline-horizontal-2-dyn.html inline-horizontal-2-ref.html
|
||||
fails-if(Android&&layersOpenGL) == inline-horizontal-2-dyn.html inline-horizontal-2-ref.html
|
||||
!= inline-horizontal-2-dyn.html inline-horizontal-2-noref.html
|
||||
== block-horizontal-1.html block-horizontal-1-ref.html
|
||||
!= block-horizontal-1.html block-horizontal-1-noref.html
|
||||
|
@ -18,9 +18,9 @@
|
|||
!= block-horizontal-1-dyn.html block-horizontal-1-noref.html
|
||||
== block-horizontal-2-dyn.html block-horizontal-2-ref.html
|
||||
!= block-horizontal-2-dyn.html block-horizontal-2-noref.html
|
||||
== block-horizontal-3-dyn.html block-horizontal-3-ref.html
|
||||
fails-if(Android&&layersOpenGL) == block-horizontal-3-dyn.html block-horizontal-3-ref.html
|
||||
!= block-horizontal-3-dyn.html block-horizontal-3-noref.html
|
||||
== block-horizontal-4-dyn.html block-horizontal-4-ref.html
|
||||
fails-if(Android&&layersOpenGL) == block-horizontal-4-dyn.html block-horizontal-4-ref.html
|
||||
!= block-horizontal-4-dyn.html block-horizontal-4-noref.html
|
||||
== inline-block-horizontal-1.html inline-block-horizontal-1-ref.html
|
||||
!= inline-block-horizontal-1.html inline-block-horizontal-1-noref.html
|
||||
|
@ -28,7 +28,7 @@
|
|||
!= inline-block-horizontal-2.html inline-block-horizontal-2-noref.html
|
||||
== inline-block-horizontal-1-dyn.html inline-block-horizontal-1-ref.html
|
||||
!= inline-block-horizontal-1-dyn.html inline-block-horizontal-1-noref.html
|
||||
== inline-block-horizontal-2-dyn.html inline-block-horizontal-2-ref.html
|
||||
fails-if(Android&&layersOpenGL) == inline-block-horizontal-2-dyn.html inline-block-horizontal-2-ref.html
|
||||
!= inline-block-horizontal-2-dyn.html inline-block-horizontal-2-noref.html
|
||||
== inline-table-horizontal-1.html inline-table-horizontal-1-ref.html
|
||||
!= inline-table-horizontal-1.html inline-table-horizontal-1-noref.html
|
||||
|
@ -58,8 +58,8 @@
|
|||
== block-sibling-1c-dyn.html block-sibling-1-ref.html
|
||||
== block-sibling-1c-dyn.html block-sibling-1-ref2.html
|
||||
!= block-sibling-1c-dyn.html block-sibling-1-noref2.html
|
||||
== block-sibling-2-dyn.html block-sibling-2-ref.html
|
||||
== block-sibling-2-dyn.html block-sibling-2-ref2.html
|
||||
fails-if(Android&&layersOpenGL) == block-sibling-2-dyn.html block-sibling-2-ref.html
|
||||
fails-if(Android&&layersOpenGL) == block-sibling-2-dyn.html block-sibling-2-ref2.html
|
||||
!= block-sibling-2-dyn.html block-sibling-2-noref.html
|
||||
== block-sibling-3-dyn.html block-sibling-1-ref.html
|
||||
== block-sibling-3-dyn.html block-sibling-1-ref2.html
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
== 166591-dynamic-1.html 166591-dynamic-1-ref.html
|
||||
== 336736-1a.html 336736-1-ref.html
|
||||
== 336736-1b.html 336736-1-ref.html
|
||||
fails-if(Android&&layersOpenGL) == 336736-1a.html 336736-1-ref.html
|
||||
fails-if(Android&&layersOpenGL) == 336736-1b.html 336736-1-ref.html
|
||||
== 406073-1.html 406073-1-ref.html
|
||||
== 407016-2.html 407016-2-ref.html
|
||||
== 413027-4.html 413027-4-ref.html
|
||||
fails-if(Android&&layersOpenGL) == 413027-4.html 413027-4-ref.html
|
||||
== 425247-1.html 425247-1-ref.html
|
||||
== 425247-2.html 425247-2-ref.html
|
||||
random == 429849-1.html 429849-1-ref.html # bug 432288
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<p>
|
||||
<math>
|
||||
<mrow>
|
||||
<mi>x</mi> <mspace width="0.0555555556em"></mspace> <mi>y</mi>
|
||||
</mrow>
|
||||
</math>
|
||||
</p>
|
||||
<p>
|
||||
<math>
|
||||
<mrow>
|
||||
<mi>x</mi> <mspace width="0.111111111em"></mspace> <mi>y</mi>
|
||||
</mrow>
|
||||
</math>
|
||||
<p>
|
||||
<math>
|
||||
<mrow>
|
||||
<mi>x</mi> <mspace width="0.166666667em"></mspace> <mi>y</mi>
|
||||
</mrow>
|
||||
</math>
|
||||
</p>
|
||||
<p>
|
||||
<math>
|
||||
<mrow>
|
||||
<mi>x</mi> <mspace width="0.222222222em"></mspace> <mi>y</mi>
|
||||
</mrow>
|
||||
</math>
|
||||
</p>
|
||||
<p>
|
||||
<math>
|
||||
<mrow>
|
||||
<mi>x</mi> <mspace width="0.277777778em"></mspace> <mi>y</mi>
|
||||
</mrow>
|
||||
</math>
|
||||
</p>
|
||||
<p>
|
||||
<math>
|
||||
<mrow>
|
||||
<mi>x</mi> <mspace width="0.333333333em"></mspace> <mi>y</mi>
|
||||
</mrow>
|
||||
</math>
|
||||
</p>
|
||||
<p>
|
||||
<math>
|
||||
<mrow>
|
||||
<mi>x</mi> <mspace width="0.388888889em"></mspace> <mi>y</mi>
|
||||
</mrow>
|
||||
</math>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,54 @@
|
|||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<p>
|
||||
<math>
|
||||
<mrow>
|
||||
<mi>x</mi> <mspace width="veryverythinmathspace"></mspace> <mi>y</mi>
|
||||
</mrow>
|
||||
</math>
|
||||
</p>
|
||||
<p>
|
||||
<math>
|
||||
<mrow>
|
||||
<mi>x</mi> <mspace width="verythinmathspace"></mspace> <mi>y</mi>
|
||||
</mrow>
|
||||
</math>
|
||||
</p>
|
||||
<p>
|
||||
<math>
|
||||
<mrow>
|
||||
<mi>x</mi> <mspace width="thinmathspace"></mspace> <mi>y</mi>
|
||||
</mrow>
|
||||
</math>
|
||||
</p>
|
||||
<p>
|
||||
<math>
|
||||
<mrow>
|
||||
<mi>x</mi> <mspace width="mediummathspace"></mspace> <mi>y</mi>
|
||||
</mrow>
|
||||
</math>
|
||||
</p>
|
||||
<p>
|
||||
<math>
|
||||
<mrow>
|
||||
<mi>x</mi> <mspace width="thickmathspace"></mspace> <mi>y</mi>
|
||||
</mrow>
|
||||
</math>
|
||||
</p>
|
||||
<p>
|
||||
<math>
|
||||
<mrow>
|
||||
<mi>x</mi> <mspace width="verythickmathspace"></mspace> <mi>y</mi>
|
||||
</mrow>
|
||||
</math>
|
||||
</p>
|
||||
<p>
|
||||
<math>
|
||||
<mrow>
|
||||
<mi>x</mi> <mspace width="veryverythickmathspace"></mspace> <mi>y</mi>
|
||||
</mrow>
|
||||
</math>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
|
@ -21,7 +21,7 @@ fails-if(winWidget) == mfenced-10.html mfenced-10-ref.html
|
|||
== mi-mathvariant-2.xhtml mi-mathvariant-2-ref.xhtml
|
||||
!= non-spacing-accent-1.xhtml non-spacing-accent-1-ref.xhtml
|
||||
== overbar-width-1.xhtml overbar-width-1-ref.xhtml
|
||||
== quotes-1.xhtml quotes-1-ref.xhtml
|
||||
fails-if(Android&&layersOpenGL) == quotes-1.xhtml quotes-1-ref.xhtml
|
||||
!= stretchy-underbar-1.xhtml stretchy-underbar-1-ref.xhtml
|
||||
== table-width-1.xhtml table-width-1-ref.xhtml
|
||||
== underbar-width-1.xhtml underbar-width-1-ref.xhtml
|
||||
|
@ -79,3 +79,4 @@ fails == mstyle-5.xhtml mstyle-5-ref.xhtml # See bug 569125#c29
|
|||
== mathml-negativespace.html mathml-negativespace-ref.html
|
||||
!= link-1.xhtml link-ref.xhtml
|
||||
== munderover-empty-scripts.html munderover-empty-scripts-ref.html
|
||||
== positive-namedspace.html positive-namedspace-ref.html
|
||||
|
|
|
@ -6,8 +6,8 @@ HTTP(..) == aspect-ratio-3a.xhtml aspect-ratio-3-ref.xhtml
|
|||
HTTP(..) == aspect-ratio-3b.xhtml aspect-ratio-3-ref.xhtml
|
||||
fails-if(Android) random-if(layersGPUAccelerated) fails-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) == encoded-aspect-ratio-1.html encoded-aspect-ratio-1-ref.html # bug 623460 for WinXP
|
||||
fails-if(Android) HTTP(..) == basic-1.xhtml basic-1-ref.html
|
||||
skip-if(Android) HTTP(..) == canvas-1a.xhtml basic-1-ref.html
|
||||
fails-if(Android) HTTP(..) == canvas-1b.xhtml basic-1-ref.html
|
||||
skip-if(Android) skip-if(Android&&layersOpenGL) HTTP(..) == canvas-1a.xhtml basic-1-ref.html
|
||||
fails-if(Android) skip-if(Android&&layersOpenGL) HTTP(..) == canvas-1b.xhtml basic-1-ref.html
|
||||
== clipping-1a.html clipping-1-ref.html
|
||||
== empty-1a.html empty-1-ref.html
|
||||
== empty-1b.html empty-1-ref.html
|
||||
|
|
|
@ -89,7 +89,7 @@ needs-focus == data:text/plain, about:blank
|
|||
# Sanity check of viewport+displayport overrides
|
||||
fails-if(!browserIsRemote) == test-displayport.html test-displayport-ref.html # bug 593168
|
||||
skip-if(!browserIsRemote) != test-displayport-2.html test-displayport-ref.html # bug 593168
|
||||
skip-if(!browserIsRemote) == 647192-1.html 647192-1-ref.html
|
||||
skip-if(!browserIsRemote) fails-if(Android&&layersOpenGL) == 647192-1.html 647192-1-ref.html
|
||||
skip-if(!browserIsRemote) == 656041-1.html 656041-1-ref.html
|
||||
|
||||
# IPC Position-fixed frames/layers test
|
||||
|
|
|
@ -39,7 +39,7 @@ skip-if(Android) include box-shadow/reftest.list
|
|||
skip-if(Android) include bugs/reftest.list
|
||||
|
||||
# canvas 2D
|
||||
include canvas/reftest.list
|
||||
skip-if(Android&&layersOpenGL) include canvas/reftest.list
|
||||
|
||||
# css calc() tests
|
||||
include css-calc/reftest.list
|
||||
|
@ -60,7 +60,7 @@ skip-if(Android) include css-enabled/reftest.list
|
|||
include css-import/reftest.list
|
||||
|
||||
# css gradients
|
||||
include css-gradients/reftest.list
|
||||
skip-if(Android&&layersOpenGL) include css-gradients/reftest.list
|
||||
|
||||
# css media queries (tests for print mode)
|
||||
include css-mediaqueries/reftest.list
|
||||
|
@ -165,7 +165,7 @@ include ib-split/reftest.list
|
|||
include image/reftest.list
|
||||
|
||||
# image-element/
|
||||
include image-element/reftest.list
|
||||
skip-if(Android&&layersOpenGL) include image-element/reftest.list
|
||||
|
||||
# image-rect/
|
||||
include image-rect/reftest.list
|
||||
|
@ -232,7 +232,7 @@ include scrolling/reftest.list
|
|||
include selection/reftest.list
|
||||
|
||||
# svg/
|
||||
include svg/reftest.list
|
||||
skip-if(Android&&layersOpenGL) include svg/reftest.list
|
||||
|
||||
# tab-size/
|
||||
include tab-size/reftest.list
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
HTTP == fixed-1.html fixed-1.html?ref
|
||||
HTTP == fixed-opacity-1.html fixed-opacity-1.html?ref
|
||||
HTTP == fixed-opacity-2.html fixed-opacity-2.html?ref
|
||||
HTTP == fixed-text-1.html fixed-text-1.html?ref
|
||||
HTTP == fixed-text-2.html fixed-text-2.html?ref
|
||||
fails-if(Android&&layersOpenGL) HTTP == fixed-text-1.html fixed-text-1.html?ref
|
||||
fails-if(Android&&layersOpenGL) HTTP == fixed-text-2.html fixed-text-2.html?ref
|
||||
HTTP == opacity-mixed-scrolling-1.html opacity-mixed-scrolling-1.html?ref
|
||||
random-if(cocoaWidget) HTTP == opacity-mixed-scrolling-2.html opacity-mixed-scrolling-2.html?ref # see bug 625357
|
||||
HTTP == simple-1.html simple-1.html?ref
|
||||
random-if(cocoaWidget) fails-if(Android&&layersOpenGL) HTTP == opacity-mixed-scrolling-2.html opacity-mixed-scrolling-2.html?ref # see bug 625357
|
||||
fails-if(Android&&layersOpenGL) HTTP == simple-1.html simple-1.html?ref
|
||||
HTTP == text-1.html text-1.html?ref
|
||||
HTTP == transformed-1.html transformed-1.html?ref
|
||||
HTTP == transformed-1.html?up transformed-1.html?ref
|
||||
== uncovering-1.html uncovering-1-ref.html
|
||||
== uncovering-2.html uncovering-2-ref.html
|
||||
fails-if(Android&&layersOpenGL) == uncovering-1.html uncovering-1-ref.html
|
||||
fails-if(Android&&layersOpenGL) == uncovering-2.html uncovering-2-ref.html
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
== dynamic-text-1a.html dynamic-text-1-ref.html
|
||||
fails-if(Android&&layersOpenGL) == dynamic-text-1a.html dynamic-text-1-ref.html
|
||||
== dynamic-text-1b.html dynamic-text-1-ref.html
|
||||
!= extend-1-sanity.html extend-1-ref.html
|
||||
== extend-1a.html extend-1-ref.html
|
||||
|
@ -18,9 +18,9 @@
|
|||
== extend-3c.html extend-3-ref.html
|
||||
== extend-3d.html extend-3-ref.html
|
||||
== extend-3e.html extend-3-ref.html
|
||||
== extend-3f.html extend-3-ref.html
|
||||
fails-if(Android&&layersOpenGL) == extend-3f.html extend-3-ref.html
|
||||
== extend-3g.html extend-3-ref.html
|
||||
== extend-3h.html extend-3-ref.html
|
||||
fails-if(Android&&layersOpenGL) == extend-3h.html extend-3-ref.html
|
||||
== extend-3i.html extend-3-ref.html
|
||||
== extend-4a.html extend-4-ref.html
|
||||
== extend-4b.html extend-4-ref.html
|
||||
|
@ -30,4 +30,4 @@ fails-if(cocoaWidget) == non-themed-widget.html non-themed-widget-ref.html
|
|||
fails-if(cocoaWidget) == themed-widget.html themed-widget-ref.html
|
||||
== addrange-1.html addrange-ref.html
|
||||
== addrange-2.html addrange-ref.html
|
||||
== splitText-normalize.html splitText-normalize-ref.html
|
||||
fails-if(Android&&layersOpenGL) == splitText-normalize.html splitText-normalize-ref.html
|
||||
|
|
|
@ -28,18 +28,18 @@ include zoom/reftest.list
|
|||
# Test for canvas "drawImage" method
|
||||
# NOTE: The canvas reftests that involve scaling currently fail with fuzziness
|
||||
# on various edges, as noted below. These will be fixed in followup bugs.
|
||||
== canvas-drawImage-simple-1a.html lime100x100-ref.html
|
||||
== canvas-drawImage-simple-1b.html lime100x100-ref.html
|
||||
skip-if(Android&&layersOpenGL) == canvas-drawImage-simple-1a.html lime100x100-ref.html
|
||||
skip-if(Android&&layersOpenGL) == canvas-drawImage-simple-1b.html lime100x100-ref.html
|
||||
|
||||
== canvas-drawImage-scale-1a.html lime100x100-ref.html
|
||||
== canvas-drawImage-scale-1b.html lime100x100-ref.html
|
||||
== canvas-drawImage-scale-1c.html lime100x100-ref.html
|
||||
skip-if(Android&&layersOpenGL) == canvas-drawImage-scale-1a.html lime100x100-ref.html
|
||||
skip-if(Android&&layersOpenGL) == canvas-drawImage-scale-1b.html lime100x100-ref.html
|
||||
skip-if(Android&&layersOpenGL) == canvas-drawImage-scale-1c.html lime100x100-ref.html
|
||||
|
||||
fails == canvas-drawImage-scale-2a.html canvas-drawImage-scale-2-ref.html # XXX all edges fuzzy
|
||||
fails == canvas-drawImage-scale-2b.html canvas-drawImage-scale-2-ref.html # XXX all edges fuzzy
|
||||
skip-if(Android&&layersOpenGL) fails == canvas-drawImage-scale-2a.html canvas-drawImage-scale-2-ref.html # XXX all edges fuzzy
|
||||
skip-if(Android&&layersOpenGL) fails == canvas-drawImage-scale-2b.html canvas-drawImage-scale-2-ref.html # XXX all edges fuzzy
|
||||
|
||||
== canvas-drawImage-slice-1a.html lime100x100-ref.html
|
||||
fails == canvas-drawImage-slice-1b.html lime100x100-ref.html # XXX all edges fuzzy
|
||||
skip-if(Android&&layersOpenGL) == canvas-drawImage-slice-1a.html lime100x100-ref.html
|
||||
skip-if(Android&&layersOpenGL) fails == canvas-drawImage-slice-1b.html lime100x100-ref.html # XXX all edges fuzzy
|
||||
|
||||
# Simple <img> tests
|
||||
== img-simple-1.html lime100x100-ref.html
|
||||
|
|
|
@ -12,7 +12,7 @@ fails == xbl-grad-ref--grad-in-resources-02.svg pass.svg
|
|||
== xbl-grad-ref--grad-in-binding-03.svg pass.svg
|
||||
== xbl-grad-ref--grad-in-bound-03.svg pass.svg
|
||||
== xbl-grad-ref--grad-in-binding-04.svg pass.svg
|
||||
== xbl-grad-ref--grad-in-bound-04.svg pass.svg
|
||||
skip-if(Android&&layersOpenGL) == xbl-grad-ref--grad-in-bound-04.svg pass.svg
|
||||
|
||||
# Tests for zooming with the full page zoom UI
|
||||
== feImage-zoom-01a.svg feImage-zoom-01-ref.svg
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# svg-as-an-image tests
|
||||
include as-image/reftest.list
|
||||
skip-if(Android&&layersOpenGL) include as-image/reftest.list
|
||||
|
||||
# <image> tests
|
||||
include image/reftest.list
|
||||
|
@ -61,7 +61,7 @@ fails-if(Android) == dynamic-conditions-01.svg pass.svg # bug 652050
|
|||
== dynamic-conditions-11.svg pass.svg
|
||||
== dynamic-conditions-12.svg pass.svg
|
||||
== dynamic-conditions-13.svg about:blank
|
||||
== dynamic-clipPath-01.svg pass.svg
|
||||
fails-if(Android&&layersOpenGL) == dynamic-clipPath-01.svg pass.svg
|
||||
== dynamic-clipPath-02.svg pass.svg
|
||||
== dynamic-feFlood-01.svg pass.svg
|
||||
== dynamic-feImage-01.svg pass.svg
|
||||
|
@ -98,7 +98,7 @@ fails-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) == dynamic-text-04.svg dynam
|
|||
== dynamic-use-02.svg pass.svg
|
||||
== dynamic-use-03.svg pass.svg
|
||||
== dynamic-use-04.svg pass.svg
|
||||
== dynamic-use-05.svg pass.svg
|
||||
fails-if(Android&&layersOpenGL) == dynamic-use-05.svg pass.svg
|
||||
random == dynamic-use-nested-01.svg dynamic-use-nested-01-ref.svg # bug 467498
|
||||
== dynamic-use-remove-width.svg dynamic-use-remove-width-ref.svg
|
||||
== linked-pattern-01.svg pass.svg
|
||||
|
@ -163,11 +163,11 @@ random-if(gtk2Widget) == objectBoundingBox-and-fePointLight-02.svg objectBoundin
|
|||
== opacity-and-gradient-01.svg pass.svg
|
||||
== opacity-and-gradient-02.svg opacity-and-gradient-02-ref.svg
|
||||
== opacity-and-pattern-01.svg pass.svg
|
||||
== outer-svg-border-and-padding-01.svg outer-svg-border-and-padding-01-ref.svg
|
||||
fails-if(Android&&layersOpenGL) == outer-svg-border-and-padding-01.svg outer-svg-border-and-padding-01-ref.svg
|
||||
== path-01.svg path-01-ref.svg
|
||||
== path-02.svg pass.svg
|
||||
== path-03.svg pass.svg
|
||||
== path-04.svg pass.svg
|
||||
fails-if(Android&&layersOpenGL) == path-04.svg pass.svg
|
||||
== path-05.svg pass.svg
|
||||
== pathLength-01.svg pass.svg
|
||||
== pathLength-02.svg pass.svg
|
||||
|
|
|
@ -10,11 +10,11 @@ random-if(Android) == event-begin-timeevent-3.svg green-box-ref.svg
|
|||
== event-bubble-1.svg green-box-ref.svg
|
||||
== event-custom-1.svg green-box-ref.svg
|
||||
== event-end-1.svg green-box-ref.svg
|
||||
== event-end-2.svg green-box-ref.svg
|
||||
fails-if(Android&&layersOpenGL) == event-end-2.svg green-box-ref.svg
|
||||
== event-end-open-1.svg green-box-ref.svg
|
||||
== event-end-trimmed-1.svg green-box-ref.svg
|
||||
== event-preventDefault-1.svg green-box-ref.svg
|
||||
== event-seek-1.svg green-box-ref.svg
|
||||
fails-if(Android&&layersOpenGL) == event-seek-1.svg green-box-ref.svg
|
||||
== event-target-default-1.svg green-box-ref.svg
|
||||
== event-target-default-2.svg green-box-ref.svg
|
||||
== event-target-id-change-1.svg green-box-ref.svg
|
||||
|
|
|
@ -121,7 +121,7 @@ fails == anim-fillcolor-1.svg anim-standard-ref.svg # bug 436296
|
|||
|
||||
# animate some enumeration attributes:
|
||||
== anim-feComposite-operator-01.svg lime.svg
|
||||
== anim-filter-filterUnits-01.svg lime.svg
|
||||
fails-if(Android&&layersOpenGL) == anim-filter-filterUnits-01.svg lime.svg
|
||||
|
||||
# animate some boolean attributes:
|
||||
== anim-feConvolveMatrix-preserveAlpha-01.svg lime.svg
|
||||
|
@ -164,8 +164,8 @@ fails == anim-fillcolor-1.svg anim-standard-ref.svg # bug 436296
|
|||
== anim-remove-5.svg anim-standard-ref.svg
|
||||
== anim-remove-6.svg anim-standard-ref.svg
|
||||
== anim-remove-7.svg anim-standard-ref.svg
|
||||
== anim-remove-8css.svg anim-standard-ref.svg
|
||||
== anim-remove-8xml.svg anim-standard-ref.svg
|
||||
fails-if(Android&&layersOpenGL) == anim-remove-8css.svg anim-standard-ref.svg
|
||||
fails-if(Android&&layersOpenGL) == anim-remove-8xml.svg anim-standard-ref.svg
|
||||
== anim-retarget-1.svg anim-standard-ref.svg
|
||||
== anim-retarget-2.svg anim-standard-ref.svg
|
||||
== anim-retarget-3.svg anim-standard-ref.svg
|
||||
|
|
|
@ -10,6 +10,6 @@
|
|||
== rotate-angle-5.svg rotate-angle-ref.svg
|
||||
== scale-1.svg scale-1-ref.svg
|
||||
== skew-1.svg skew-1-ref.svg
|
||||
== translate-clipPath-1.svg lime.svg
|
||||
fails-if(Android&&layersOpenGL) == translate-clipPath-1.svg lime.svg
|
||||
fails-if(cocoaWidget) == translate-gradient-1.svg lime.svg
|
||||
== translate-pattern-1.svg lime.svg
|
||||
fails-if(Android&&layersOpenGL) == translate-pattern-1.svg lime.svg
|
||||
|
|
|
@ -7,7 +7,7 @@ HTTP(..) == scroll-rounding.html scroll-rounding-ref.html
|
|||
HTTP(..) == anonymous-block.html anonymous-block-ref.html
|
||||
HTTP(..) == false-marker-overlap.html false-marker-overlap-ref.html
|
||||
HTTP(..) == visibility-hidden.html visibility-hidden-ref.html
|
||||
HTTP(..) == block-padding.html block-padding-ref.html
|
||||
fails-if(Android&&layersOpenGL) HTTP(..) == block-padding.html block-padding-ref.html
|
||||
HTTP(..) == quirks-decorations.html quirks-decorations-ref.html
|
||||
HTTP(..) == quirks-line-height.html quirks-line-height-ref.html
|
||||
HTTP(..) == standards-decorations.html standards-decorations-ref.html
|
||||
|
|
|
@ -17,11 +17,11 @@ random-if(!cocoaWidget) == font-size-adjust-02.html font-size-adjust-02-ref.html
|
|||
== justification-2c.html justification-2-ref.html
|
||||
!= justification-2d.html justification-2-ref.html
|
||||
load ligature-with-space-1.html
|
||||
== line-editing-1a.html line-editing-1-ref.html
|
||||
== line-editing-1b.html line-editing-1-ref.html
|
||||
== line-editing-1c.html line-editing-1-ref.html
|
||||
== line-editing-1d.html line-editing-1-ref.html
|
||||
== line-editing-1e.html line-editing-1-ref.html
|
||||
fails-if(Android&&layersOpenGL) == line-editing-1a.html line-editing-1-ref.html
|
||||
fails-if(Android&&layersOpenGL) == line-editing-1b.html line-editing-1-ref.html
|
||||
fails-if(Android&&layersOpenGL) == line-editing-1c.html line-editing-1-ref.html
|
||||
fails-if(Android&&layersOpenGL) == line-editing-1d.html line-editing-1-ref.html
|
||||
fails-if(Android&&layersOpenGL) == line-editing-1e.html line-editing-1-ref.html
|
||||
fails-if(cocoaWidget||winWidget) HTTP(..) == lineheight-metrics-1.html lineheight-metrics-1-ref.html # bug 657864
|
||||
== long-1.html long-ref.html
|
||||
== pre-line-1.html pre-line-1-ref.html
|
||||
|
@ -46,8 +46,8 @@ fails-if(Android) skip-if(d2d||cocoaWidget) == subpixel-glyphs-x-1a.html subpixe
|
|||
# D2D/DirectWrite results depend on the rendering mode chosen, so considering this as random for now.
|
||||
skip-if(!(d2d||cocoaWidget)) random-if(d2d) != subpixel-glyphs-x-2a.html subpixel-glyphs-x-2b.html
|
||||
# No platforms do subpixel positioning vertically
|
||||
== subpixel-glyphs-y-1a.html subpixel-glyphs-y-1b.html
|
||||
== subpixel-lineheight-1a.html subpixel-lineheight-1b.html
|
||||
fails-if(Android&&layersOpenGL) == subpixel-glyphs-y-1a.html subpixel-glyphs-y-1b.html
|
||||
fails-if(Android&&layersOpenGL) == subpixel-lineheight-1a.html subpixel-lineheight-1b.html
|
||||
== swash-1.html swash-1-ref.html
|
||||
HTTP(..) != synthetic-bold-metrics-01.html synthetic-bold-metrics-01-notref.html
|
||||
== variation-selector-unsupported-1.html variation-selector-unsupported-1-ref.html
|
||||
|
|
|
@ -6,8 +6,8 @@ HTTP(..) == aspect-ratio-3a.xhtml aspect-ratio-3-ref.xhtml
|
|||
HTTP(..) == aspect-ratio-3b.xhtml aspect-ratio-3-ref.xhtml
|
||||
fails-if(Android) random-if(layersGPUAccelerated) fails-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) == encoded-aspect-ratio-1.html encoded-aspect-ratio-1-ref.html # bug 623460 for WinXP
|
||||
fails-if(Android) HTTP(..) == basic-1.xhtml basic-1-ref.html
|
||||
skip-if(Android) HTTP(..) == canvas-1a.xhtml basic-1-ref.html
|
||||
fails-if(Android) HTTP(..) == canvas-1b.xhtml basic-1-ref.html
|
||||
skip-if(Android) skip-if(Android&&layersOpenGL) HTTP(..) == canvas-1a.xhtml basic-1-ref.html
|
||||
fails-if(Android) skip-if(Android&&layersOpenGL) HTTP(..) == canvas-1b.xhtml basic-1-ref.html
|
||||
== clipping-1a.html clipping-1-ref.html
|
||||
== empty-1a.html empty-1-ref.html
|
||||
== empty-1b.html empty-1-ref.html
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
#include "nsThreadUtils.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsDocShellCID.h"
|
||||
#include "nsIThreadInternal.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsXULPrototypeCache.h"
|
||||
|
@ -132,7 +133,8 @@ namespace css {
|
|||
*********************************************/
|
||||
|
||||
class SheetLoadData : public nsIRunnable,
|
||||
public nsIUnicharStreamLoaderObserver
|
||||
public nsIUnicharStreamLoaderObserver,
|
||||
public nsIThreadObserver
|
||||
{
|
||||
public:
|
||||
virtual ~SheetLoadData(void);
|
||||
|
@ -167,8 +169,11 @@ public:
|
|||
|
||||
already_AddRefed<nsIURI> GetReferrerURI();
|
||||
|
||||
void ScheduleLoadEventIfNeeded(nsresult aStatus);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
NS_DECL_NSITHREADOBSERVER
|
||||
NS_DECL_NSIUNICHARSTREAMLOADEROBSERVER
|
||||
|
||||
// Hold a ref to the CSSLoader so we can call back to it to let it
|
||||
|
@ -224,7 +229,9 @@ public:
|
|||
|
||||
// mMustNotify is true if the load data is being loaded async and
|
||||
// the original function call that started the load has returned.
|
||||
// XXXbz sort our relationship with load/error events!
|
||||
// This applies only to observer notifications; load/error events
|
||||
// are fired for any SheetLoadData that has a non-null
|
||||
// mOwningElement.
|
||||
PRPackedBool mMustNotify : 1;
|
||||
|
||||
// mWasAlternate is true if the sheet was an alternate when the load data was
|
||||
|
@ -240,8 +247,12 @@ public:
|
|||
// loads.
|
||||
PRPackedBool mUseSystemPrincipal : 1;
|
||||
|
||||
// If true, this SheetLoadData is being used as a way to handle
|
||||
// async observer notification for an already-complete sheet.
|
||||
PRPackedBool mSheetAlreadyComplete : 1;
|
||||
|
||||
// This is the element that imported the sheet. Needed to get the
|
||||
// charset set on it.
|
||||
// charset set on it and to fire load/error events.
|
||||
nsCOMPtr<nsIStyleSheetLinkingElement> mOwningElement;
|
||||
|
||||
// The observer that wishes to be notified of load completion
|
||||
|
@ -253,6 +264,15 @@ public:
|
|||
// The charset to use if the transport and sheet don't indicate one.
|
||||
// May be empty. Must be empty if mOwningElement is non-null.
|
||||
nsCString mCharsetHint;
|
||||
|
||||
// The status our load ended up with; this determines whether we
|
||||
// should fire error events or load events. This gets initialized
|
||||
// by ScheduleLoadEventIfNeeded, and is only used after that has
|
||||
// been called.
|
||||
nsresult mStatus;
|
||||
|
||||
private:
|
||||
void FireLoadEvent(nsIThreadInternal* aThread);
|
||||
};
|
||||
|
||||
#ifdef MOZ_LOGGING
|
||||
|
@ -304,7 +324,8 @@ static const char* const gStateStrings[] = {
|
|||
/********************************
|
||||
* SheetLoadData implementation *
|
||||
********************************/
|
||||
NS_IMPL_ISUPPORTS2(SheetLoadData, nsIUnicharStreamLoaderObserver, nsIRunnable)
|
||||
NS_IMPL_ISUPPORTS3(SheetLoadData, nsIUnicharStreamLoaderObserver, nsIRunnable,
|
||||
nsIThreadObserver)
|
||||
|
||||
SheetLoadData::SheetLoadData(Loader* aLoader,
|
||||
const nsSubstring& aTitle,
|
||||
|
@ -330,6 +351,7 @@ SheetLoadData::SheetLoadData(Loader* aLoader,
|
|||
mWasAlternate(aIsAlternate),
|
||||
mAllowUnsafeRules(PR_FALSE),
|
||||
mUseSystemPrincipal(PR_FALSE),
|
||||
mSheetAlreadyComplete(PR_FALSE),
|
||||
mOwningElement(aOwningElement),
|
||||
mObserver(aObserver),
|
||||
mLoaderPrincipal(aLoaderPrincipal)
|
||||
|
@ -359,6 +381,7 @@ SheetLoadData::SheetLoadData(Loader* aLoader,
|
|||
mWasAlternate(PR_FALSE),
|
||||
mAllowUnsafeRules(PR_FALSE),
|
||||
mUseSystemPrincipal(PR_FALSE),
|
||||
mSheetAlreadyComplete(PR_FALSE),
|
||||
mOwningElement(nsnull),
|
||||
mObserver(aObserver),
|
||||
mLoaderPrincipal(aLoaderPrincipal)
|
||||
|
@ -402,6 +425,7 @@ SheetLoadData::SheetLoadData(Loader* aLoader,
|
|||
mWasAlternate(PR_FALSE),
|
||||
mAllowUnsafeRules(aAllowUnsafeRules),
|
||||
mUseSystemPrincipal(aUseSystemPrincipal),
|
||||
mSheetAlreadyComplete(PR_FALSE),
|
||||
mOwningElement(nsnull),
|
||||
mObserver(aObserver),
|
||||
mLoaderPrincipal(aLoaderPrincipal),
|
||||
|
@ -428,6 +452,78 @@ SheetLoadData::Run()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SheetLoadData::OnDispatchedEvent(nsIThreadInternal* aThread)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SheetLoadData::OnProcessNextEvent(nsIThreadInternal* aThread,
|
||||
PRBool aMayWait,
|
||||
PRUint32 aRecursionDepth)
|
||||
{
|
||||
// We want to fire our load even before or after event processing,
|
||||
// whichever comes first.
|
||||
FireLoadEvent(aThread);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SheetLoadData::AfterProcessNextEvent(nsIThreadInternal* aThread,
|
||||
PRUint32 aRecursionDepth)
|
||||
{
|
||||
// We want to fire our load even before or after event processing,
|
||||
// whichever comes first.
|
||||
FireLoadEvent(aThread);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
SheetLoadData::FireLoadEvent(nsIThreadInternal* aThread)
|
||||
{
|
||||
|
||||
// First remove ourselves as a thread observer. But we need to keep
|
||||
// ourselves alive while doing that!
|
||||
nsRefPtr<SheetLoadData> kungFuDeathGrip(this);
|
||||
aThread->RemoveObserver(this);
|
||||
|
||||
// Now fire the event
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(mOwningElement);
|
||||
NS_ASSERTION(node, "How did that happen???");
|
||||
|
||||
nsContentUtils::DispatchTrustedEvent(node->GetOwnerDoc(),
|
||||
node,
|
||||
NS_SUCCEEDED(mStatus) ?
|
||||
NS_LITERAL_STRING("load") :
|
||||
NS_LITERAL_STRING("error"),
|
||||
PR_FALSE, PR_FALSE);
|
||||
|
||||
// And unblock onload
|
||||
if (mLoader->mDocument) {
|
||||
mLoader->mDocument->UnblockOnload(PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SheetLoadData::ScheduleLoadEventIfNeeded(nsresult aStatus)
|
||||
{
|
||||
if (!mOwningElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
mStatus = aStatus;
|
||||
|
||||
nsCOMPtr<nsIThread> thread = do_GetMainThread();
|
||||
nsCOMPtr<nsIThreadInternal> internalThread = do_QueryInterface(thread);
|
||||
if (NS_SUCCEEDED(internalThread->AddObserver(this))) {
|
||||
// Make sure to block onload here
|
||||
if (mLoader->mDocument) {
|
||||
mLoader->mDocument->BlockOnload();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************
|
||||
* Loader Implementation *
|
||||
*************************/
|
||||
|
@ -1650,7 +1746,10 @@ Loader::DoSheetComplete(SheetLoadData* aLoadData, nsresult aStatus,
|
|||
while (data) {
|
||||
NS_ABORT_IF_FALSE(!data->mSheet->IsModified(),
|
||||
"should not get marked modified during parsing");
|
||||
data->mSheet->SetComplete();
|
||||
if (!data->mSheetAlreadyComplete) {
|
||||
data->mSheet->SetComplete();
|
||||
data->ScheduleLoadEventIfNeeded(aStatus);
|
||||
}
|
||||
if (data->mMustNotify && (data->mObserver || !mObservers.IsEmpty())) {
|
||||
// Don't notify here so we don't trigger script. Remember the
|
||||
// info we need to notify, then do it later when it's safe.
|
||||
|
@ -1678,7 +1777,10 @@ Loader::DoSheetComplete(SheetLoadData* aLoadData, nsresult aStatus,
|
|||
data = data->mNext;
|
||||
}
|
||||
|
||||
// Now that it's marked complete, put the sheet in our cache
|
||||
// Now that it's marked complete, put the sheet in our cache.
|
||||
// If we ever start doing this for failure aStatus, we'll need to
|
||||
// adjust the PostLoadEvent code that thinks anything already
|
||||
// complete must have loaded succesfully.
|
||||
if (NS_SUCCEEDED(aStatus) && aLoadData->mURI) {
|
||||
#ifdef MOZ_XUL
|
||||
if (IsChromeURI(aLoadData->mURI)) {
|
||||
|
@ -1751,11 +1853,6 @@ Loader::LoadInlineStyle(nsIContent* aElement,
|
|||
owningElement, *aIsAlternate,
|
||||
aObserver, nsnull);
|
||||
|
||||
if (!data) {
|
||||
sheet->SetComplete();
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// We never actually load this, so just set its principal directly
|
||||
sheet->SetPrincipal(aElement->NodePrincipal());
|
||||
|
||||
|
@ -1824,28 +1921,24 @@ Loader::LoadStyleLink(nsIContent* aElement,
|
|||
rv = InsertSheetInDoc(sheet, aElement, mDocument);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIStyleSheetLinkingElement> owningElement(do_QueryInterface(aElement));
|
||||
|
||||
if (state == eSheetComplete) {
|
||||
LOG((" Sheet already complete: 0x%p",
|
||||
static_cast<void*>(sheet.get())));
|
||||
if (aObserver) {
|
||||
rv = PostLoadEvent(aURL, sheet, aObserver, *aIsAlternate);
|
||||
if (aObserver || !mObservers.IsEmpty() || owningElement) {
|
||||
rv = PostLoadEvent(aURL, sheet, aObserver, *aIsAlternate,
|
||||
owningElement);
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIStyleSheetLinkingElement> owningElement(do_QueryInterface(aElement));
|
||||
|
||||
// Now we need to actually load it
|
||||
SheetLoadData* data = new SheetLoadData(this, aTitle, aURL, sheet,
|
||||
owningElement, *aIsAlternate,
|
||||
aObserver, principal);
|
||||
if (!data) {
|
||||
sheet->SetComplete();
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_ADDREF(data);
|
||||
|
||||
// If we have to parse and it's an alternate non-inline, defer it
|
||||
|
@ -1996,11 +2089,6 @@ Loader::LoadChildSheet(nsCSSStyleSheet* aParentSheet,
|
|||
SheetLoadData* data = new SheetLoadData(this, aURL, sheet, parentData,
|
||||
observer, principal);
|
||||
|
||||
if (!data) {
|
||||
sheet->SetComplete();
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_ADDREF(data);
|
||||
PRBool syncLoad = data->mSyncLoad;
|
||||
|
||||
|
@ -2097,8 +2185,8 @@ Loader::InternalLoadNonDocumentSheet(nsIURI* aURL,
|
|||
|
||||
if (state == eSheetComplete) {
|
||||
LOG((" Sheet already complete"));
|
||||
if (aObserver) {
|
||||
rv = PostLoadEvent(aURL, sheet, aObserver, PR_FALSE);
|
||||
if (aObserver || !mObservers.IsEmpty()) {
|
||||
rv = PostLoadEvent(aURL, sheet, aObserver, PR_FALSE, nsnull);
|
||||
}
|
||||
if (aSheet) {
|
||||
sheet.swap(*aSheet);
|
||||
|
@ -2111,11 +2199,6 @@ Loader::InternalLoadNonDocumentSheet(nsIURI* aURL,
|
|||
aUseSystemPrincipal, aCharset, aObserver,
|
||||
aOriginPrincipal);
|
||||
|
||||
if (!data) {
|
||||
sheet->SetComplete();
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_ADDREF(data);
|
||||
rv = LoadSheet(data, state);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -2134,17 +2217,19 @@ nsresult
|
|||
Loader::PostLoadEvent(nsIURI* aURI,
|
||||
nsCSSStyleSheet* aSheet,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
PRBool aWasAlternate)
|
||||
PRBool aWasAlternate,
|
||||
nsIStyleSheetLinkingElement* aElement)
|
||||
{
|
||||
LOG(("css::Loader::PostLoadEvent"));
|
||||
NS_PRECONDITION(aSheet, "Must have sheet");
|
||||
NS_PRECONDITION(aObserver, "Must have observer");
|
||||
NS_PRECONDITION(aObserver || !mObservers.IsEmpty() || aElement,
|
||||
"Must have observer or element");
|
||||
|
||||
nsRefPtr<SheetLoadData> evt =
|
||||
new SheetLoadData(this, EmptyString(), // title doesn't matter here
|
||||
aURI,
|
||||
aSheet,
|
||||
nsnull, // owning element doesn't matter here
|
||||
aElement,
|
||||
aWasAlternate,
|
||||
aObserver,
|
||||
nsnull);
|
||||
|
@ -2166,6 +2251,13 @@ Loader::PostLoadEvent(nsIURI* aURI,
|
|||
|
||||
// We want to notify the observer for this data.
|
||||
evt->mMustNotify = PR_TRUE;
|
||||
evt->mSheetAlreadyComplete = PR_TRUE;
|
||||
|
||||
// If we get to this code, aSheet loaded correctly at some point, so
|
||||
// we can just use NS_OK for the status. Note that we do this here
|
||||
// and not from inside our SheetComplete so that we don't end up
|
||||
// running the load event async.
|
||||
evt->ScheduleLoadEventIfNeeded(NS_OK);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -2178,6 +2270,12 @@ Loader::HandleLoadEvent(SheetLoadData* aEvent)
|
|||
// we're unblocking the parser
|
||||
// NS_ASSERTION(aEvent->mObserver, "Must have observer");
|
||||
NS_ASSERTION(aEvent->mSheet, "Must have sheet");
|
||||
|
||||
// Very important: this needs to come before the SheetComplete call
|
||||
// below, so that HasPendingLoads() will test true as needed under
|
||||
// notifications we send from that SheetComplete call.
|
||||
mPostedEvents.RemoveElement(aEvent);
|
||||
|
||||
if (!aEvent->mIsCancelled) {
|
||||
// SheetComplete will call Release(), so give it a reference to do
|
||||
// that with.
|
||||
|
@ -2185,8 +2283,6 @@ Loader::HandleLoadEvent(SheetLoadData* aEvent)
|
|||
SheetComplete(aEvent, NS_OK);
|
||||
}
|
||||
|
||||
mPostedEvents.RemoveElement(aEvent);
|
||||
|
||||
if (mDocument) {
|
||||
mDocument->UnblockOnload(PR_TRUE);
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ class nsIContent;
|
|||
class nsIDocument;
|
||||
class nsCSSParser;
|
||||
class nsMediaList;
|
||||
class nsIStyleSheetLinkingElement;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -422,11 +423,13 @@ private:
|
|||
// canceled at some point (in which case it will be sent with
|
||||
// NS_BINDING_ABORTED). aWasAlternate indicates the state when the load was
|
||||
// initiated, not the state at some later time. aURI should be the URI the
|
||||
// sheet was loaded from (may be null for inline sheets).
|
||||
// sheet was loaded from (may be null for inline sheets). aElement is the
|
||||
// owning element for this sheet.
|
||||
nsresult PostLoadEvent(nsIURI* aURI,
|
||||
nsCSSStyleSheet* aSheet,
|
||||
nsICSSLoaderObserver* aObserver,
|
||||
PRBool aWasAlternate);
|
||||
PRBool aWasAlternate,
|
||||
nsIStyleSheetLinkingElement* aElement);
|
||||
|
||||
// Start the loads of all the sheets in mPendingDatas
|
||||
void StartAlternateLoads();
|
||||
|
@ -472,6 +475,7 @@ private:
|
|||
LoadDataArray mPostedEvents;
|
||||
|
||||
// Our array of "global" observers
|
||||
// XXXbz these are strong refs; should we be cycle collecting CSS loaders?
|
||||
nsTObserverArray<nsCOMPtr<nsICSSLoaderObserver> > mObservers;
|
||||
|
||||
// the load data needs access to the document...
|
||||
|
|
|
@ -159,7 +159,9 @@ using namespace mozilla;
|
|||
#define VARIANT_UK (VARIANT_URL | VARIANT_KEYWORD)
|
||||
#define VARIANT_UO (VARIANT_URL | VARIANT_NONE)
|
||||
#define VARIANT_ANGLE_OR_ZERO (VARIANT_ANGLE | VARIANT_ZERO_ANGLE)
|
||||
#define VARIANT_TRANSFORM_LPCALC (VARIANT_LP | VARIANT_CALC)
|
||||
#define VARIANT_LPCALC (VARIANT_LENGTH | VARIANT_CALC | VARIANT_PERCENT)
|
||||
#define VARIANT_LNCALC (VARIANT_LENGTH | VARIANT_CALC | VARIANT_NUMBER)
|
||||
#define VARIANT_LPNCALC (VARIANT_LNCALC | VARIANT_PERCENT)
|
||||
#define VARIANT_IMAGE (VARIANT_URL | VARIANT_NONE | VARIANT_GRADIENT | \
|
||||
VARIANT_IMAGE_RECT | VARIANT_ELEMENT)
|
||||
|
||||
|
@ -4545,7 +4547,6 @@ CSSParserImpl::ParseVariant(nsCSSValue& aValue,
|
|||
eCSSToken_Number == tk->mType &&
|
||||
tk->mNumber == 0.0f)) {
|
||||
if ((aVariantMask & VARIANT_POSITIVE_LENGTH) != 0 &&
|
||||
eCSSToken_Number == tk->mType &&
|
||||
tk->mNumber <= 0.0) {
|
||||
UngetToken();
|
||||
return PR_FALSE;
|
||||
|
@ -7344,10 +7345,10 @@ static PRBool GetFunctionParseInformation(nsCSSKeyword aToken,
|
|||
eNumVariantMasks };
|
||||
static const PRInt32 kMaxElemsPerFunction = 16;
|
||||
static const PRInt32 kVariantMasks[eNumVariantMasks][kMaxElemsPerFunction] = {
|
||||
{VARIANT_TRANSFORM_LPCALC},
|
||||
{VARIANT_LPCALC},
|
||||
{VARIANT_LENGTH|VARIANT_CALC},
|
||||
{VARIANT_TRANSFORM_LPCALC, VARIANT_TRANSFORM_LPCALC},
|
||||
{VARIANT_TRANSFORM_LPCALC, VARIANT_TRANSFORM_LPCALC, VARIANT_LENGTH|VARIANT_CALC},
|
||||
{VARIANT_LPCALC, VARIANT_LPCALC},
|
||||
{VARIANT_LPCALC, VARIANT_LPCALC, VARIANT_LENGTH|VARIANT_CALC},
|
||||
{VARIANT_ANGLE_OR_ZERO},
|
||||
{VARIANT_ANGLE_OR_ZERO, VARIANT_ANGLE_OR_ZERO},
|
||||
{VARIANT_NUMBER},
|
||||
|
@ -7356,11 +7357,11 @@ static PRBool GetFunctionParseInformation(nsCSSKeyword aToken,
|
|||
{VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER},
|
||||
{VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_ANGLE_OR_ZERO},
|
||||
{VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER,
|
||||
VARIANT_TRANSFORM_LPCALC, VARIANT_TRANSFORM_LPCALC},
|
||||
VARIANT_LPNCALC, VARIANT_LPNCALC},
|
||||
{VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER,
|
||||
VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER,
|
||||
VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER,
|
||||
VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER}};
|
||||
VARIANT_LPNCALC, VARIANT_LPNCALC, VARIANT_LNCALC, VARIANT_NUMBER}};
|
||||
|
||||
#ifdef DEBUG
|
||||
static const PRUint8 kVariantMaskLengths[eNumVariantMasks] =
|
||||
|
|
|
@ -1058,27 +1058,53 @@ nsComputedDOMStyle::DoGetMozTransform()
|
|||
bounds,
|
||||
float(nsDeviceContext::AppUnitsPerCSSPixel()));
|
||||
|
||||
if (!matrix.Is2D()) {
|
||||
nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
|
||||
PRBool is3D = !matrix.Is2D();
|
||||
|
||||
/* Set it to "none." */
|
||||
val->SetIdent(eCSSKeyword_none);
|
||||
return val;
|
||||
nsAutoString resultString(NS_LITERAL_STRING("matrix"));
|
||||
if (is3D) {
|
||||
resultString.Append(NS_LITERAL_STRING("3d"));
|
||||
}
|
||||
|
||||
nsAutoString resultString(NS_LITERAL_STRING("matrix("));
|
||||
resultString.Append(NS_LITERAL_STRING("("));
|
||||
resultString.AppendFloat(matrix._11);
|
||||
resultString.Append(NS_LITERAL_STRING(", "));
|
||||
resultString.AppendFloat(matrix._12);
|
||||
resultString.Append(NS_LITERAL_STRING(", "));
|
||||
if (is3D) {
|
||||
resultString.AppendFloat(matrix._13);
|
||||
resultString.Append(NS_LITERAL_STRING(", "));
|
||||
resultString.AppendFloat(matrix._14);
|
||||
resultString.Append(NS_LITERAL_STRING(", "));
|
||||
}
|
||||
resultString.AppendFloat(matrix._21);
|
||||
resultString.Append(NS_LITERAL_STRING(", "));
|
||||
resultString.AppendFloat(matrix._22);
|
||||
resultString.Append(NS_LITERAL_STRING(", "));
|
||||
if (is3D) {
|
||||
resultString.AppendFloat(matrix._23);
|
||||
resultString.Append(NS_LITERAL_STRING(", "));
|
||||
resultString.AppendFloat(matrix._24);
|
||||
resultString.Append(NS_LITERAL_STRING(", "));
|
||||
resultString.AppendFloat(matrix._31);
|
||||
resultString.Append(NS_LITERAL_STRING(", "));
|
||||
resultString.AppendFloat(matrix._32);
|
||||
resultString.Append(NS_LITERAL_STRING(", "));
|
||||
resultString.AppendFloat(matrix._33);
|
||||
resultString.Append(NS_LITERAL_STRING(", "));
|
||||
resultString.AppendFloat(matrix._34);
|
||||
resultString.Append(NS_LITERAL_STRING(", "));
|
||||
}
|
||||
resultString.AppendFloat(matrix._41);
|
||||
resultString.Append(NS_LITERAL_STRING("px, "));
|
||||
resultString.AppendFloat(matrix._42);
|
||||
resultString.Append(NS_LITERAL_STRING("px)"));
|
||||
resultString.Append(NS_LITERAL_STRING("px"));
|
||||
if (is3D) {
|
||||
resultString.Append(NS_LITERAL_STRING(", "));
|
||||
resultString.AppendFloat(matrix._43);
|
||||
resultString.Append(NS_LITERAL_STRING("px, "));
|
||||
resultString.AppendFloat(matrix._44);
|
||||
}
|
||||
resultString.Append(NS_LITERAL_STRING(")"));
|
||||
|
||||
/* Create a value to hold our result. */
|
||||
nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "prlog.h"
|
||||
#include <math.h>
|
||||
#include "gfxMatrix.h"
|
||||
#include "gfxQuaternion.h"
|
||||
|
||||
namespace css = mozilla::css;
|
||||
namespace dom = mozilla::dom;
|
||||
|
@ -908,24 +909,43 @@ AppendTransformFunction(nsCSSKeyword aTransformFunction,
|
|||
nsCSSValueList**& aListTail)
|
||||
{
|
||||
PRUint32 nargs;
|
||||
if (aTransformFunction == eCSSKeyword_matrix) {
|
||||
nargs = 6;
|
||||
} else if (aTransformFunction == eCSSKeyword_translate ||
|
||||
aTransformFunction == eCSSKeyword_skew ||
|
||||
aTransformFunction == eCSSKeyword_scale) {
|
||||
nargs = 2;
|
||||
} else if (aTransformFunction == eCSSKeyword_interpolatematrix) {
|
||||
nargs = 4;
|
||||
} else {
|
||||
NS_ABORT_IF_FALSE(aTransformFunction == eCSSKeyword_translatex ||
|
||||
aTransformFunction == eCSSKeyword_translatey ||
|
||||
aTransformFunction == eCSSKeyword_scalex ||
|
||||
aTransformFunction == eCSSKeyword_scaley ||
|
||||
aTransformFunction == eCSSKeyword_skewx ||
|
||||
aTransformFunction == eCSSKeyword_skewy ||
|
||||
aTransformFunction == eCSSKeyword_rotate,
|
||||
"must be a transform function");
|
||||
nargs = 1;
|
||||
switch (aTransformFunction) {
|
||||
case eCSSKeyword_matrix3d:
|
||||
nargs = 16;
|
||||
break;
|
||||
case eCSSKeyword_matrix:
|
||||
nargs = 6;
|
||||
break;
|
||||
case eCSSKeyword_rotate3d:
|
||||
nargs = 4;
|
||||
break;
|
||||
case eCSSKeyword_interpolatematrix:
|
||||
case eCSSKeyword_translate3d:
|
||||
case eCSSKeyword_scale3d:
|
||||
nargs = 3;
|
||||
break;
|
||||
case eCSSKeyword_translate:
|
||||
case eCSSKeyword_skew:
|
||||
case eCSSKeyword_scale:
|
||||
nargs = 2;
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("must be a transform function");
|
||||
case eCSSKeyword_translatex:
|
||||
case eCSSKeyword_translatey:
|
||||
case eCSSKeyword_translatez:
|
||||
case eCSSKeyword_scalex:
|
||||
case eCSSKeyword_scaley:
|
||||
case eCSSKeyword_scalez:
|
||||
case eCSSKeyword_skewx:
|
||||
case eCSSKeyword_skewy:
|
||||
case eCSSKeyword_rotate:
|
||||
case eCSSKeyword_rotatex:
|
||||
case eCSSKeyword_rotatey:
|
||||
case eCSSKeyword_rotatez:
|
||||
case eCSSKeyword_perspective:
|
||||
nargs = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
nsRefPtr<nsCSSValue::Array> arr = nsCSSValue::Array::Create(nargs + 1);
|
||||
|
@ -1064,12 +1084,17 @@ AppendTransformFunction(nsCSSKeyword aTransformFunction,
|
|||
*/
|
||||
|
||||
/*
|
||||
* DecomposeMatrix implements the non-translation parts of the above
|
||||
* decomposition algorithm.
|
||||
* Decompose2DMatrix implements the above decomposition algorithm.
|
||||
*/
|
||||
|
||||
#define XYSHEAR 0
|
||||
#define XZSHEAR 1
|
||||
#define YZSHEAR 2
|
||||
|
||||
static PRBool
|
||||
DecomposeMatrix(const gfxMatrix &aMatrix,
|
||||
float &aRotate, float &aXYShear, float &aScaleX, float &aScaleY)
|
||||
Decompose2DMatrix(const gfxMatrix &aMatrix, gfxPoint3D &aScale,
|
||||
float aShear[3], gfxQuaternion &aRotate,
|
||||
gfxPoint3D &aTranslate)
|
||||
{
|
||||
float A = aMatrix.xx,
|
||||
B = aMatrix.yx,
|
||||
|
@ -1093,7 +1118,7 @@ DecomposeMatrix(const gfxMatrix &aMatrix,
|
|||
D /= scaleY;
|
||||
XYshear /= scaleY;
|
||||
|
||||
// A*D - B*C should now be 1 or -1
|
||||
// A*D - B*C should now be 1 or -1
|
||||
NS_ASSERTION(0.99 < NS_ABS(A*D - B*C) && NS_ABS(A*D - B*C) < 1.01,
|
||||
"determinant should now be 1 or -1");
|
||||
if (A * D < B * C) {
|
||||
|
@ -1105,84 +1130,200 @@ DecomposeMatrix(const gfxMatrix &aMatrix,
|
|||
scaleX = -scaleX;
|
||||
}
|
||||
|
||||
float rotation = atan2f(B, A);
|
||||
float rotate = atan2f(B, A);
|
||||
aRotate = gfxQuaternion(0, 0, sin(rotate/2), cos(rotate/2));
|
||||
aShear[XYSHEAR] = XYshear;
|
||||
aScale.x = scaleX;
|
||||
aScale.y = scaleY;
|
||||
aTranslate.x = aMatrix.x0;
|
||||
aTranslate.y = aMatrix.y0;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
aRotate = rotation;
|
||||
aXYShear = XYshear;
|
||||
aScaleX = scaleX;
|
||||
aScaleY = scaleY;
|
||||
/**
|
||||
* Implementation of the unmatrix algorithm, specified by:
|
||||
*
|
||||
* http://dev.w3.org/csswg/css3-2d-transforms/#unmatrix
|
||||
*
|
||||
* This, in turn, refers to the unmatrix program in Graphics Gems,
|
||||
* available from http://tog.acm.org/resources/GraphicsGems/ , and in
|
||||
* particular as the file GraphicsGems/gemsii/unmatrix.c
|
||||
* in http://tog.acm.org/resources/GraphicsGems/AllGems.tar.gz
|
||||
*/
|
||||
static PRBool
|
||||
Decompose3DMatrix(const gfx3DMatrix &aMatrix, gfxPoint3D &aScale,
|
||||
float aShear[3], gfxQuaternion &aRotate,
|
||||
gfxPoint3D &aTranslate, gfxPointH3D &aPerspective)
|
||||
{
|
||||
gfx3DMatrix local = aMatrix;
|
||||
|
||||
if (local[3][3] == 0) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Normalize the matrix */
|
||||
local.Normalize();
|
||||
|
||||
/**
|
||||
* perspective is used to solve for perspective, but it also provides
|
||||
* an easy way to test for singularity of the upper 3x3 component.
|
||||
*/
|
||||
gfx3DMatrix perspective = local;
|
||||
gfxPointH3D empty(0, 0, 0, 1);
|
||||
perspective.SetTransposedVector(3, empty);
|
||||
|
||||
if (perspective.Determinant() == 0.0) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/* First, isolate perspective. */
|
||||
if (local[0][3] != 0 || local[1][3] != 0 ||
|
||||
local[2][3] != 0) {
|
||||
/* aPerspective is the right hand side of the equation. */
|
||||
aPerspective = local.TransposedVector(3);
|
||||
|
||||
/**
|
||||
* Solve the equation by inverting perspective and multiplying
|
||||
* aPerspective by the inverse.
|
||||
*/
|
||||
perspective.Invert();
|
||||
aPerspective = perspective.TransposeTransform4D(aPerspective);
|
||||
|
||||
/* Clear the perspective partition */
|
||||
local.SetTransposedVector(3, empty);
|
||||
} else {
|
||||
aPerspective = gfxPointH3D(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
/* Next take care of translation */
|
||||
for (int i = 0; i < 3; i++) {
|
||||
aTranslate[i] = local[3][i];
|
||||
local[3][i] = 0;
|
||||
}
|
||||
|
||||
/* Now get scale and shear. */
|
||||
|
||||
/* Compute X scale factor and normalize first row. */
|
||||
aScale.x = local[0].Length();
|
||||
local[0] /= aScale.x;
|
||||
|
||||
/* Compute XY shear factor and make 2nd local orthogonal to 1st. */
|
||||
aShear[XYSHEAR] = local[0].DotProduct(local[1]);
|
||||
local[1] -= local[0] * aShear[XYSHEAR];
|
||||
|
||||
/* Now, compute Y scale and normalize 2nd local. */
|
||||
aScale.y = local[1].Length();
|
||||
local[1] /= aScale.y;
|
||||
aShear[XYSHEAR] /= aScale.y;
|
||||
|
||||
/* Compute XZ and YZ shears, make 3rd local orthogonal */
|
||||
aShear[XZSHEAR] = local[0].DotProduct(local[2]);
|
||||
local[2] -= local[0] * aShear[XZSHEAR];
|
||||
aShear[YZSHEAR] = local[1].DotProduct(local[2]);
|
||||
local[2] -= local[1] * aShear[YZSHEAR];
|
||||
|
||||
/* Next, get Z scale and normalize 3rd local. */
|
||||
aScale.z = local[2].Length();
|
||||
local[2] /= aScale.z;
|
||||
|
||||
aShear[XZSHEAR] /= aScale.z;
|
||||
aShear[YZSHEAR] /= aScale.z;
|
||||
|
||||
/**
|
||||
* At this point, the matrix (in locals) is orthonormal.
|
||||
* Check for a coordinate system flip. If the determinant
|
||||
* is -1, then negate the matrix and the scaling factors.
|
||||
*/
|
||||
if (local[0].DotProduct(local[1].CrossProduct(local[2])) < 0) {
|
||||
aScale *= -1;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
local[i] *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now, get the rotations out */
|
||||
aRotate = gfxQuaternion(local);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/* Force small values to zero. We do this to avoid having sin(360deg)
|
||||
* evaluate to a tiny but nonzero value.
|
||||
*/
|
||||
static double FlushToZero(double aVal)
|
||||
template<typename T>
|
||||
T InterpolateNumerically(const T& aOne, const T& aTwo, double aCoeff)
|
||||
{
|
||||
if (-FLT_EPSILON < aVal && aVal < FLT_EPSILON)
|
||||
return 0.0f;
|
||||
else
|
||||
return aVal;
|
||||
}
|
||||
|
||||
/* Computes tan(aTheta). For values of aTheta such that tan(aTheta) is
|
||||
* undefined or very large, SafeTangent returns a manageably large value
|
||||
* of the correct sign.
|
||||
*/
|
||||
static double SafeTangent(double aTheta)
|
||||
{
|
||||
const double kEpsilon = 0.0001;
|
||||
|
||||
/* tan(theta) = sin(theta)/cos(theta); problems arise when
|
||||
* cos(theta) is too close to zero. Limit cos(theta) to the
|
||||
* range [-1, -epsilon] U [epsilon, 1].
|
||||
*/
|
||||
double sinTheta = sin(aTheta);
|
||||
double cosTheta = cos(aTheta);
|
||||
|
||||
if (cosTheta >= 0 && cosTheta < kEpsilon)
|
||||
cosTheta = kEpsilon;
|
||||
else if (cosTheta < 0 && cosTheta >= -kEpsilon)
|
||||
cosTheta = -kEpsilon;
|
||||
|
||||
return FlushToZero(sinTheta / cosTheta);
|
||||
return aOne + (aTwo - aOne) * aCoeff;
|
||||
}
|
||||
|
||||
|
||||
/* static */ gfxMatrix
|
||||
nsStyleAnimation::InterpolateTransformMatrix(const gfxMatrix &aMatrix1,
|
||||
double aCoeff1,
|
||||
const gfxMatrix &aMatrix2,
|
||||
double aCoeff2)
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleAnimation::InterpolateTransformMatrix(const gfx3DMatrix &aMatrix1,
|
||||
const gfx3DMatrix &aMatrix2,
|
||||
double aProgress)
|
||||
{
|
||||
float rotate1, XYshear1, scaleX1, scaleY1;
|
||||
DecomposeMatrix(aMatrix1, rotate1, XYshear1, scaleX1, scaleY1);
|
||||
float rotate2, XYshear2, scaleX2, scaleY2;
|
||||
DecomposeMatrix(aMatrix2, rotate2, XYshear2, scaleX2, scaleY2);
|
||||
// Decompose both matrices
|
||||
|
||||
float rotate = rotate1 * aCoeff1 + rotate2 * aCoeff2;
|
||||
// TODO: What do we do if one of these returns PR_FALSE (singular matrix)
|
||||
|
||||
float skewX = atanf(XYshear1) * aCoeff1 + atanf(XYshear2) * aCoeff2;
|
||||
gfxPoint3D scale1(1, 1, 1), translate1;
|
||||
gfxPointH3D perspective1(0, 0, 0, 1);
|
||||
gfxQuaternion rotate1;
|
||||
float shear1[3] = { 0.0f, 0.0f, 0.0f};
|
||||
|
||||
// Handle scale, and the two matrix components where identity is 1, by
|
||||
// subtracting 1, multiplying by the coefficients, and then adding 1
|
||||
// back. This gets the right AddWeighted behavior and gets us the
|
||||
// interpolation-against-identity behavior for free.
|
||||
float scaleX =
|
||||
((scaleX1 - 1.0f) * aCoeff1 + (scaleX2 - 1.0f) * aCoeff2) + 1.0f;
|
||||
float scaleY =
|
||||
((scaleY1 - 1.0f) * aCoeff1 + (scaleY2 - 1.0f) * aCoeff2) + 1.0f;
|
||||
gfxPoint3D scale2(1, 1, 1), translate2;
|
||||
gfxPointH3D perspective2(0, 0, 0, 1);
|
||||
gfxQuaternion rotate2;
|
||||
float shear2[3] = { 0.0f, 0.0f, 0.0f};
|
||||
|
||||
gfxMatrix result;
|
||||
gfxMatrix matrix2d1, matrix2d2;
|
||||
if (aMatrix1.Is2D(&matrix2d1) && aMatrix2.Is2D(&matrix2d2)) {
|
||||
Decompose2DMatrix(matrix2d1, scale1, shear1, rotate1, translate1);
|
||||
Decompose2DMatrix(matrix2d2, scale2, shear2, rotate2, translate2);
|
||||
} else {
|
||||
Decompose3DMatrix(aMatrix1, scale1, shear1,
|
||||
rotate1, translate1, perspective1);
|
||||
Decompose3DMatrix(aMatrix2, scale2, shear2,
|
||||
rotate2, translate2, perspective2);
|
||||
}
|
||||
|
||||
gfxMatrix skew;
|
||||
skew.xy = SafeTangent(skewX);
|
||||
result.Translate(gfxPoint(aMatrix1.x0 * aCoeff1 + aMatrix2.x0 * aCoeff2,
|
||||
aMatrix1.y0 * aCoeff1 + aMatrix2.y0 * aCoeff2));
|
||||
result.Rotate(rotate);
|
||||
result.PreMultiply(skew);
|
||||
result.Scale(scaleX, scaleY);
|
||||
// Interpolate each of the pieces
|
||||
gfx3DMatrix result;
|
||||
|
||||
gfxPointH3D perspective =
|
||||
InterpolateNumerically(perspective1, perspective2, aProgress);
|
||||
result.SetTransposedVector(3, perspective);
|
||||
|
||||
gfxPoint3D translate =
|
||||
InterpolateNumerically(translate1, translate2, aProgress);
|
||||
result.Translate(translate);
|
||||
|
||||
gfxQuaternion q3 = rotate1.Slerp(rotate2, aProgress);
|
||||
gfx3DMatrix rotate = q3.ToMatrix();
|
||||
if (!rotate.IsIdentity()) {
|
||||
result = rotate * result;
|
||||
}
|
||||
|
||||
// TODO: Would it be better to interpolate these as angles? How do we convert back to angles?
|
||||
float yzshear =
|
||||
InterpolateNumerically(shear1[YZSHEAR], shear2[YZSHEAR], aProgress);
|
||||
if (yzshear != 0.0) {
|
||||
result.SkewYZ(yzshear);
|
||||
}
|
||||
|
||||
float xzshear =
|
||||
InterpolateNumerically(shear1[XZSHEAR], shear2[XZSHEAR], aProgress);
|
||||
if (xzshear != 0.0) {
|
||||
result.SkewXZ(xzshear);
|
||||
}
|
||||
|
||||
float xyshear =
|
||||
InterpolateNumerically(shear1[XYSHEAR], shear2[XYSHEAR], aProgress);
|
||||
if (xyshear != 0.0) {
|
||||
result.SkewXY(xyshear);
|
||||
}
|
||||
|
||||
gfxPoint3D scale =
|
||||
InterpolateNumerically(scale1, scale2, aProgress);
|
||||
if (scale != gfxPoint3D(1.0, 1.0, 1.0)) {
|
||||
result.Scale(scale.x, scale.y, scale.z);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -1196,15 +1337,36 @@ AddDifferentTransformLists(const nsCSSValueList* aList1, double aCoeff1,
|
|||
|
||||
nsRefPtr<nsCSSValue::Array> arr;
|
||||
arr = AppendTransformFunction(eCSSKeyword_interpolatematrix, resultTail);
|
||||
|
||||
// FIXME: We should change the other transform code to also only
|
||||
// take a single progress value, as having values that don't
|
||||
// sum to 1 doesn't make sense for these.
|
||||
if (aList1 == aList2) {
|
||||
arr->Item(1).Reset();
|
||||
} else {
|
||||
aList1->CloneInto(arr->Item(1).SetListValue());
|
||||
}
|
||||
|
||||
arr->Item(1).SetPercentValue(aCoeff1);
|
||||
aList1->CloneInto(arr->Item(2).SetListValue());
|
||||
aList2->CloneInto(arr->Item(2).SetListValue());
|
||||
arr->Item(3).SetPercentValue(aCoeff2);
|
||||
aList2->CloneInto(arr->Item(4).SetListValue());
|
||||
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
static PRBool
|
||||
TransformFunctionsMatch(nsCSSKeyword func1, nsCSSKeyword func2)
|
||||
{
|
||||
if (func1 == func2) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
if (func1 == eCSSKeyword_rotatez && func2 == eCSSKeyword_rotate ||
|
||||
func1 == eCSSKeyword_rotate && func2 == eCSSKeyword_rotatez) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static nsCSSValueList*
|
||||
AddTransformLists(const nsCSSValueList* aList1, double aCoeff1,
|
||||
const nsCSSValueList* aList2, double aCoeff2)
|
||||
|
@ -1215,13 +1377,17 @@ AddTransformLists(const nsCSSValueList* aList1, double aCoeff1,
|
|||
do {
|
||||
const nsCSSValue::Array *a1 = aList1->mValue.GetArrayValue(),
|
||||
*a2 = aList2->mValue.GetArrayValue();
|
||||
NS_ABORT_IF_FALSE(nsStyleTransformMatrix::TransformFunctionOf(a1) ==
|
||||
nsStyleTransformMatrix::TransformFunctionOf(a2),
|
||||
NS_ABORT_IF_FALSE(TransformFunctionsMatch(nsStyleTransformMatrix::TransformFunctionOf(a1),
|
||||
nsStyleTransformMatrix::TransformFunctionOf(a2)),
|
||||
"transform function mismatch");
|
||||
|
||||
nsCSSKeyword tfunc = nsStyleTransformMatrix::TransformFunctionOf(a1);
|
||||
nsRefPtr<nsCSSValue::Array> arr;
|
||||
if (tfunc != eCSSKeyword_matrix && tfunc != eCSSKeyword_interpolatematrix) {
|
||||
if (tfunc != eCSSKeyword_matrix &&
|
||||
tfunc != eCSSKeyword_matrix3d &&
|
||||
tfunc != eCSSKeyword_interpolatematrix &&
|
||||
tfunc != eCSSKeyword_rotate3d &&
|
||||
tfunc != eCSSKeyword_perspective) {
|
||||
arr = AppendTransformFunction(tfunc, resultTail);
|
||||
}
|
||||
|
||||
|
@ -1250,13 +1416,25 @@ AddTransformLists(const nsCSSValueList* aList1, double aCoeff1,
|
|||
break;
|
||||
}
|
||||
case eCSSKeyword_translatex:
|
||||
case eCSSKeyword_translatey: {
|
||||
case eCSSKeyword_translatey:
|
||||
case eCSSKeyword_translatez: {
|
||||
NS_ABORT_IF_FALSE(a1->Count() == 2, "unexpected count");
|
||||
NS_ABORT_IF_FALSE(a2->Count() == 2, "unexpected count");
|
||||
AddTransformTranslate(a1->Item(1), aCoeff1, a2->Item(1), aCoeff2,
|
||||
arr->Item(1));
|
||||
break;
|
||||
}
|
||||
case eCSSKeyword_translate3d: {
|
||||
NS_ABORT_IF_FALSE(a1->Count() == 4, "unexpected count");
|
||||
NS_ABORT_IF_FALSE(a2->Count() == 4, "unexpected count");
|
||||
AddTransformTranslate(a1->Item(1), aCoeff1, a2->Item(1), aCoeff2,
|
||||
arr->Item(1));
|
||||
AddTransformTranslate(a1->Item(2), aCoeff1, a2->Item(2), aCoeff2,
|
||||
arr->Item(2));
|
||||
AddTransformTranslate(a1->Item(3), aCoeff1, a2->Item(3), aCoeff2,
|
||||
arr->Item(3));
|
||||
break;
|
||||
}
|
||||
case eCSSKeyword_scale: {
|
||||
NS_ABORT_IF_FALSE(a1->Count() == 2 || a1->Count() == 3,
|
||||
"unexpected count");
|
||||
|
@ -1281,7 +1459,8 @@ AddTransformLists(const nsCSSValueList* aList1, double aCoeff1,
|
|||
break;
|
||||
}
|
||||
case eCSSKeyword_scalex:
|
||||
case eCSSKeyword_scaley: {
|
||||
case eCSSKeyword_scaley:
|
||||
case eCSSKeyword_scalez: {
|
||||
NS_ABORT_IF_FALSE(a1->Count() == 2, "unexpected count");
|
||||
NS_ABORT_IF_FALSE(a2->Count() == 2, "unexpected count");
|
||||
|
||||
|
@ -1290,6 +1469,19 @@ AddTransformLists(const nsCSSValueList* aList1, double aCoeff1,
|
|||
|
||||
break;
|
||||
}
|
||||
case eCSSKeyword_scale3d: {
|
||||
NS_ABORT_IF_FALSE(a1->Count() == 4, "unexpected count");
|
||||
NS_ABORT_IF_FALSE(a2->Count() == 4, "unexpected count");
|
||||
|
||||
AddTransformScale(a1->Item(1), aCoeff1, a2->Item(1), aCoeff2,
|
||||
arr->Item(1));
|
||||
AddTransformScale(a1->Item(2), aCoeff1, a2->Item(2), aCoeff2,
|
||||
arr->Item(2));
|
||||
AddTransformScale(a1->Item(3), aCoeff1, a2->Item(3), aCoeff2,
|
||||
arr->Item(3));
|
||||
|
||||
break;
|
||||
}
|
||||
// It would probably be nicer to animate skew in tangent space
|
||||
// rather than angle space. However, it's easy to specify
|
||||
// skews with infinite tangents, and behavior changes pretty
|
||||
|
@ -1318,7 +1510,10 @@ AddTransformLists(const nsCSSValueList* aList1, double aCoeff1,
|
|||
}
|
||||
case eCSSKeyword_skewx:
|
||||
case eCSSKeyword_skewy:
|
||||
case eCSSKeyword_rotate: {
|
||||
case eCSSKeyword_rotate:
|
||||
case eCSSKeyword_rotatex:
|
||||
case eCSSKeyword_rotatey:
|
||||
case eCSSKeyword_rotatez: {
|
||||
NS_ABORT_IF_FALSE(a1->Count() == 2, "unexpected count");
|
||||
NS_ABORT_IF_FALSE(a2->Count() == 2, "unexpected count");
|
||||
|
||||
|
@ -1328,18 +1523,25 @@ AddTransformLists(const nsCSSValueList* aList1, double aCoeff1,
|
|||
break;
|
||||
}
|
||||
case eCSSKeyword_matrix:
|
||||
case eCSSKeyword_interpolatematrix: {
|
||||
case eCSSKeyword_matrix3d:
|
||||
case eCSSKeyword_interpolatematrix:
|
||||
case eCSSKeyword_rotate3d:
|
||||
case eCSSKeyword_perspective: {
|
||||
// FIXME: If the matrix contains only numbers then we could decompose
|
||||
// here. We can't do this for matrix3d though, so it's probably
|
||||
// best to stay consistent.
|
||||
// here.
|
||||
|
||||
// Construct temporary lists with only this item in them.
|
||||
nsCSSValueList tempList1, tempList2;
|
||||
tempList1.mValue = aList1->mValue;
|
||||
tempList2.mValue = aList2->mValue;
|
||||
|
||||
*resultTail =
|
||||
AddDifferentTransformLists(&tempList1, aCoeff1, &tempList2, aCoeff2);
|
||||
if (aList1 == aList2) {
|
||||
*resultTail =
|
||||
AddDifferentTransformLists(&tempList1, aCoeff1, &tempList1, aCoeff2);
|
||||
} else {
|
||||
*resultTail =
|
||||
AddDifferentTransformLists(&tempList1, aCoeff1, &tempList2, aCoeff2);
|
||||
}
|
||||
|
||||
while ((*resultTail)->mNext) {
|
||||
resultTail = &(*resultTail)->mNext;
|
||||
|
@ -1774,11 +1976,11 @@ nsStyleAnimation::AddWeighted(nsCSSProperty aProperty,
|
|||
result->mValue.SetNoneValue();
|
||||
}
|
||||
} else {
|
||||
result = AddTransformLists(list2, aCoeff2, list2, 0);
|
||||
result = AddTransformLists(list2, 0, list2, aCoeff2);
|
||||
}
|
||||
} else {
|
||||
if (list2->mValue.GetUnit() == eCSSUnit_None) {
|
||||
result = AddTransformLists(list1, aCoeff1, list1, 0);
|
||||
result = AddTransformLists(list1, 0, list1, aCoeff1);
|
||||
} else {
|
||||
PRBool match = PR_TRUE;
|
||||
|
||||
|
@ -1789,7 +1991,8 @@ nsStyleAnimation::AddWeighted(nsCSSProperty aProperty,
|
|||
item1->mValue.GetArrayValue());
|
||||
nsCSSKeyword func2 = nsStyleTransformMatrix::TransformFunctionOf(
|
||||
item2->mValue.GetArrayValue());
|
||||
if (func1 != func2) {
|
||||
|
||||
if (!TransformFunctionsMatch(func1, func2)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ struct nsCSSValuePair;
|
|||
struct nsCSSValueTriplet;
|
||||
struct nsCSSValuePairList;
|
||||
struct nsCSSRect;
|
||||
struct gfxMatrix;
|
||||
class gfx3DMatrix;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -233,12 +233,12 @@ public:
|
|||
* Interpolates between 2 matrices by decomposing them.
|
||||
*
|
||||
* @param aMatrix1 First matrix, using CSS pixel units.
|
||||
* @param aCoeff1 Interpolation value in the range [0.0, 1.0]
|
||||
* @param aMatrix2 Second matrix, using CSS pixel units.
|
||||
* @param aCoeff2 Interpolation value in the range [0.0, 1.0]
|
||||
* @param aProgress Interpolation value in the range [0.0, 1.0]
|
||||
*/
|
||||
static gfxMatrix InterpolateTransformMatrix(const gfxMatrix &aMatrix1, double aCoeff1,
|
||||
const gfxMatrix &aMatrix2, double aCoeff2);
|
||||
static gfx3DMatrix InterpolateTransformMatrix(const gfx3DMatrix &aMatrix1,
|
||||
const gfx3DMatrix &aMatrix2,
|
||||
double aProgress);
|
||||
|
||||
/**
|
||||
* The types and values for the values that we extract and animate.
|
||||
|
|
|
@ -52,6 +52,8 @@
|
|||
|
||||
namespace css = mozilla::css;
|
||||
|
||||
namespace nsStyleTransformMatrix {
|
||||
|
||||
/* Note on floating point precision: The transform matrix is an array
|
||||
* of single precision 'float's, and so are most of the input values
|
||||
* we get from the style system, but intermediate calculations
|
||||
|
@ -69,50 +71,29 @@ static double FlushToZero(double aVal)
|
|||
return aVal;
|
||||
}
|
||||
|
||||
/* Computes tan(aTheta). For values of aTheta such that tan(aTheta) is
|
||||
* undefined or very large, SafeTangent returns a manageably large value
|
||||
* of the correct sign.
|
||||
*/
|
||||
static double SafeTangent(double aTheta)
|
||||
{
|
||||
const double kEpsilon = 0.0001;
|
||||
|
||||
/* tan(theta) = sin(theta)/cos(theta); problems arise when
|
||||
* cos(theta) is too close to zero. Limit cos(theta) to the
|
||||
* range [-1, -epsilon] U [epsilon, 1].
|
||||
*/
|
||||
double sinTheta = sin(aTheta);
|
||||
double cosTheta = cos(aTheta);
|
||||
|
||||
if (cosTheta >= 0 && cosTheta < kEpsilon)
|
||||
cosTheta = kEpsilon;
|
||||
else if (cosTheta < 0 && cosTheta >= -kEpsilon)
|
||||
cosTheta = -kEpsilon;
|
||||
|
||||
return FlushToZero(sinTheta / cosTheta);
|
||||
}
|
||||
|
||||
/* Helper function to fill in an nscoord with the specified nsCSSValue. */
|
||||
static nscoord CalcLength(const nsCSSValue &aValue,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool &aCanStoreInRuleTree)
|
||||
{
|
||||
if (aValue.GetUnit() == eCSSUnit_Pixel) {
|
||||
if (aValue.GetUnit() == eCSSUnit_Pixel ||
|
||||
aValue.GetUnit() == eCSSUnit_Number) {
|
||||
// Handle this here (even though nsRuleNode::CalcLength handles it
|
||||
// fine) so that callers are allowed to pass a null style context
|
||||
// and pres context to SetToTransformFunction if they know (as
|
||||
// nsStyleAnimation does) that all lengths within the transform
|
||||
// function have already been computed to pixels and percents.
|
||||
//
|
||||
// Raw numbers are treated as being pixels.
|
||||
return nsPresContext::CSSPixelsToAppUnits(aValue.GetFloatValue());
|
||||
}
|
||||
return nsRuleNode::CalcLength(aValue, aContext, aPresContext,
|
||||
aCanStoreInRuleTree);
|
||||
}
|
||||
|
||||
static void
|
||||
ProcessTranslatePart(float& aResult,
|
||||
const nsCSSValue& aValue,
|
||||
static float
|
||||
ProcessTranslatePart(const nsCSSValue& aValue,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool& aCanStoreInRuleTree,
|
||||
|
@ -134,46 +115,57 @@ ProcessTranslatePart(float& aResult,
|
|||
aCanStoreInRuleTree);
|
||||
}
|
||||
|
||||
aResult = (percent * NSAppUnitsToFloatPixels(aSize, aAppUnitsPerMatrixUnit)) +
|
||||
NSAppUnitsToFloatPixels(offset, aAppUnitsPerMatrixUnit);
|
||||
return (percent * NSAppUnitsToFloatPixels(aSize, aAppUnitsPerMatrixUnit)) +
|
||||
NSAppUnitsToFloatPixels(offset, aAppUnitsPerMatrixUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper functions to process all the transformation function types.
|
||||
*
|
||||
* These take a matrix parameter to accumulate the current matrix.
|
||||
*/
|
||||
|
||||
/* Helper function to process a matrix entry. */
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessMatrix(const nsCSSValue::Array* aData,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool& aCanStoreInRuleTree,
|
||||
nsRect& aBounds, float aAppUnitsPerMatrixUnit,
|
||||
PRBool *aPercentX, PRBool *aPercentY)
|
||||
static void
|
||||
ProcessMatrix(gfx3DMatrix& aMatrix,
|
||||
const nsCSSValue::Array* aData,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool& aCanStoreInRuleTree,
|
||||
nsRect& aBounds, float aAppUnitsPerMatrixUnit)
|
||||
{
|
||||
NS_PRECONDITION(aData->Count() == 7, "Invalid array!");
|
||||
|
||||
gfx3DMatrix result;
|
||||
gfxMatrix result;
|
||||
|
||||
/* Take the first four elements out of the array as floats and store
|
||||
* them.
|
||||
*/
|
||||
result._11 = aData->Item(1).GetFloatValue();
|
||||
result._12 = aData->Item(2).GetFloatValue();
|
||||
result._21 = aData->Item(3).GetFloatValue();
|
||||
result._22 = aData->Item(4).GetFloatValue();
|
||||
result.xx = aData->Item(1).GetFloatValue();
|
||||
result.yx = aData->Item(2).GetFloatValue();
|
||||
result.xy = aData->Item(3).GetFloatValue();
|
||||
result.yy = aData->Item(4).GetFloatValue();
|
||||
|
||||
/* The last two elements have their length parts stored in aDelta
|
||||
* and their percent parts stored in aX[0] and aY[1].
|
||||
*/
|
||||
ProcessTranslatePart(result._41, aData->Item(5),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
aBounds.Width(), aAppUnitsPerMatrixUnit);
|
||||
ProcessTranslatePart(result._42, aData->Item(6),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
aBounds.Height(), aAppUnitsPerMatrixUnit);
|
||||
result.x0 = ProcessTranslatePart(aData->Item(5),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
aBounds.Width(), aAppUnitsPerMatrixUnit);
|
||||
result.y0 = ProcessTranslatePart(aData->Item(6),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
aBounds.Height(), aAppUnitsPerMatrixUnit);
|
||||
|
||||
return result;
|
||||
aMatrix.PreMultiply(result);
|
||||
}
|
||||
|
||||
/*static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessMatrix3D(const nsCSSValue::Array* aData)
|
||||
static void
|
||||
ProcessMatrix3D(gfx3DMatrix& aMatrix,
|
||||
const nsCSSValue::Array* aData,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool& aCanStoreInRuleTree,
|
||||
nsRect& aBounds, float aAppUnitsPerMatrixUnit)
|
||||
{
|
||||
NS_PRECONDITION(aData->Count() == 17, "Invalid array!");
|
||||
|
||||
|
@ -191,232 +183,205 @@ nsStyleTransformMatrix::ProcessMatrix3D(const nsCSSValue::Array* aData)
|
|||
temp._32 = aData->Item(10).GetFloatValue();
|
||||
temp._33 = aData->Item(11).GetFloatValue();
|
||||
temp._34 = aData->Item(12).GetFloatValue();
|
||||
temp._41 = aData->Item(13).GetFloatValue();
|
||||
temp._42 = aData->Item(14).GetFloatValue();
|
||||
temp._43 = aData->Item(15).GetFloatValue();
|
||||
temp._44 = aData->Item(16).GetFloatValue();
|
||||
return temp;
|
||||
|
||||
temp._41 = ProcessTranslatePart(aData->Item(13),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
aBounds.Width(), aAppUnitsPerMatrixUnit);
|
||||
temp._42 = ProcessTranslatePart(aData->Item(14),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
aBounds.Height(), aAppUnitsPerMatrixUnit);
|
||||
temp._43 = ProcessTranslatePart(aData->Item(15),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
aBounds.Height(), aAppUnitsPerMatrixUnit);
|
||||
|
||||
aMatrix.PreMultiply(temp);
|
||||
}
|
||||
|
||||
/* Helper function to process two matrices that we need to interpolate between */
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessInterpolateMatrix(const nsCSSValue::Array* aData,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool& aCanStoreInRuleTree,
|
||||
nsRect& aBounds, float aAppUnitsPerMatrixUnit)
|
||||
static void
|
||||
ProcessInterpolateMatrix(gfx3DMatrix& aMatrix,
|
||||
const nsCSSValue::Array* aData,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool& aCanStoreInRuleTree,
|
||||
nsRect& aBounds, float aAppUnitsPerMatrixUnit)
|
||||
{
|
||||
NS_PRECONDITION(aData->Count() == 5, "Invalid array!");
|
||||
NS_PRECONDITION(aData->Count() == 4, "Invalid array!");
|
||||
|
||||
double coeff1 = aData->Item(1).GetPercentValue();
|
||||
gfx3DMatrix matrix1 = ReadTransforms(aData->Item(2).GetListValue(),
|
||||
aContext, aPresContext,
|
||||
aCanStoreInRuleTree,
|
||||
aBounds, aAppUnitsPerMatrixUnit);
|
||||
double coeff2 = aData->Item(3).GetPercentValue();
|
||||
gfx3DMatrix matrix2 = ReadTransforms(aData->Item(4).GetListValue(),
|
||||
aContext, aPresContext,
|
||||
aCanStoreInRuleTree,
|
||||
aBounds, aAppUnitsPerMatrixUnit);
|
||||
gfx3DMatrix matrix1, matrix2;
|
||||
if (aData->Item(1).GetUnit() == eCSSUnit_List) {
|
||||
matrix1 = nsStyleTransformMatrix::ReadTransforms(aData->Item(1).GetListValue(),
|
||||
aContext, aPresContext,
|
||||
aCanStoreInRuleTree,
|
||||
aBounds, aAppUnitsPerMatrixUnit);
|
||||
}
|
||||
if (aData->Item(2).GetUnit() == eCSSUnit_List) {
|
||||
matrix2 = ReadTransforms(aData->Item(2).GetListValue(),
|
||||
aContext, aPresContext,
|
||||
aCanStoreInRuleTree,
|
||||
aBounds, aAppUnitsPerMatrixUnit);
|
||||
}
|
||||
double progress = aData->Item(3).GetPercentValue();
|
||||
|
||||
gfxMatrix matrix2d1, matrix2d2;
|
||||
#ifdef DEBUG
|
||||
PRBool is2d =
|
||||
#endif
|
||||
matrix1.Is2D(&matrix2d1);
|
||||
NS_ABORT_IF_FALSE(is2d, "Can't do animations with 3d transforms!");
|
||||
#ifdef DEBUG
|
||||
is2d =
|
||||
#endif
|
||||
matrix2.Is2D(&matrix2d2);
|
||||
NS_ABORT_IF_FALSE(is2d, "Can't do animations with 3d transforms!");
|
||||
|
||||
return gfx3DMatrix::From2D(
|
||||
nsStyleAnimation::InterpolateTransformMatrix(matrix2d1, coeff1,
|
||||
matrix2d2, coeff2));
|
||||
aMatrix = nsStyleAnimation::InterpolateTransformMatrix(matrix1, matrix2, progress) * aMatrix;
|
||||
}
|
||||
|
||||
/* Helper function to process a translatex function. */
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessTranslateX(const nsCSSValue::Array* aData,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool& aCanStoreInRuleTree,
|
||||
nsRect& aBounds, float aAppUnitsPerMatrixUnit)
|
||||
static void
|
||||
ProcessTranslateX(gfx3DMatrix& aMatrix,
|
||||
const nsCSSValue::Array* aData,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool& aCanStoreInRuleTree,
|
||||
nsRect& aBounds, float aAppUnitsPerMatrixUnit)
|
||||
{
|
||||
NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
|
||||
|
||||
gfx3DMatrix temp;
|
||||
gfxPoint3D temp;
|
||||
|
||||
/* There are two cases. If we have a number, we want our matrix to look
|
||||
* like this:
|
||||
*
|
||||
* | 1 0 0 0 |
|
||||
* | 0 1 0 0 |
|
||||
* | 0 0 1 0 |
|
||||
* | dx 0 0 1 |
|
||||
* So E = value
|
||||
*
|
||||
* Otherwise, we might have a percentage, so we want to set the dX component
|
||||
* to the percent.
|
||||
*/
|
||||
ProcessTranslatePart(temp._41, aData->Item(1),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
aBounds.Width(), aAppUnitsPerMatrixUnit);
|
||||
return temp;
|
||||
temp.x = ProcessTranslatePart(aData->Item(1),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
aBounds.Width(), aAppUnitsPerMatrixUnit);
|
||||
aMatrix.Translate(temp);
|
||||
}
|
||||
|
||||
/* Helper function to process a translatey function. */
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessTranslateY(const nsCSSValue::Array* aData,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool& aCanStoreInRuleTree,
|
||||
nsRect& aBounds, float aAppUnitsPerMatrixUnit)
|
||||
static void
|
||||
ProcessTranslateY(gfx3DMatrix& aMatrix,
|
||||
const nsCSSValue::Array* aData,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool& aCanStoreInRuleTree,
|
||||
nsRect& aBounds, float aAppUnitsPerMatrixUnit)
|
||||
{
|
||||
NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
|
||||
|
||||
gfx3DMatrix temp;
|
||||
gfxPoint3D temp;
|
||||
|
||||
/* There are two cases. If we have a number, we want our matrix to look
|
||||
* like this:
|
||||
*
|
||||
* | 1 0 0 0 |
|
||||
* | 0 1 0 0 |
|
||||
* | 0 0 1 0 |
|
||||
* | 0 dy 0 1 |
|
||||
* So E = value
|
||||
*
|
||||
* Otherwise, we might have a percentage, so we want to set the dY component
|
||||
* to the percent.
|
||||
*/
|
||||
ProcessTranslatePart(temp._42, aData->Item(1),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
aBounds.Height(), aAppUnitsPerMatrixUnit);
|
||||
return temp;
|
||||
temp.y = ProcessTranslatePart(aData->Item(1),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
aBounds.Height(), aAppUnitsPerMatrixUnit);
|
||||
aMatrix.Translate(temp);
|
||||
}
|
||||
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessTranslateZ(const nsCSSValue::Array* aData,
|
||||
nsStyleContext* aContext,
|
||||
static void
|
||||
ProcessTranslateZ(gfx3DMatrix& aMatrix,
|
||||
const nsCSSValue::Array* aData,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool& aCanStoreInRuleTree,
|
||||
float aAppUnitsPerMatrixUnit)
|
||||
{
|
||||
NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
|
||||
|
||||
gfx3DMatrix temp;
|
||||
gfxPoint3D temp;
|
||||
|
||||
ProcessTranslatePart(temp._43, aData->Item(1),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
0, aAppUnitsPerMatrixUnit);
|
||||
return temp;
|
||||
temp.z = ProcessTranslatePart(aData->Item(1),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
0, aAppUnitsPerMatrixUnit);
|
||||
aMatrix.Translate(temp);
|
||||
}
|
||||
|
||||
/* Helper function to process a translate function. */
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessTranslate(const nsCSSValue::Array* aData,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool& aCanStoreInRuleTree,
|
||||
nsRect& aBounds, float aAppUnitsPerMatrixUnit)
|
||||
static void
|
||||
ProcessTranslate(gfx3DMatrix& aMatrix,
|
||||
const nsCSSValue::Array* aData,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool& aCanStoreInRuleTree,
|
||||
nsRect& aBounds, float aAppUnitsPerMatrixUnit)
|
||||
{
|
||||
NS_PRECONDITION(aData->Count() == 2 || aData->Count() == 3, "Invalid array!");
|
||||
|
||||
gfx3DMatrix temp;
|
||||
gfxPoint3D temp;
|
||||
|
||||
ProcessTranslatePart(temp._41, aData->Item(1),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
aBounds.Width(), aAppUnitsPerMatrixUnit);
|
||||
temp.x = ProcessTranslatePart(aData->Item(1),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
aBounds.Width(), aAppUnitsPerMatrixUnit);
|
||||
|
||||
/* If we read in a Y component, set it appropriately */
|
||||
if (aData->Count() == 3) {
|
||||
ProcessTranslatePart(temp._42, aData->Item(2),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
aBounds.Height(), aAppUnitsPerMatrixUnit);
|
||||
temp.y = ProcessTranslatePart(aData->Item(2),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
aBounds.Height(), aAppUnitsPerMatrixUnit);
|
||||
}
|
||||
return temp;
|
||||
aMatrix.Translate(temp);
|
||||
}
|
||||
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessTranslate3D(const nsCSSValue::Array* aData,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool& aCanStoreInRuleTree,
|
||||
nsRect& aBounds, float aAppUnitsPerMatrixUnit)
|
||||
static void
|
||||
ProcessTranslate3D(gfx3DMatrix& aMatrix,
|
||||
const nsCSSValue::Array* aData,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool& aCanStoreInRuleTree,
|
||||
nsRect& aBounds, float aAppUnitsPerMatrixUnit)
|
||||
{
|
||||
NS_PRECONDITION(aData->Count() == 4, "Invalid array!");
|
||||
|
||||
gfx3DMatrix temp;
|
||||
gfxPoint3D temp;
|
||||
|
||||
ProcessTranslatePart(temp._41, aData->Item(1),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
aBounds.Width(), aAppUnitsPerMatrixUnit);
|
||||
temp.x = ProcessTranslatePart(aData->Item(1),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
aBounds.Width(), aAppUnitsPerMatrixUnit);
|
||||
|
||||
ProcessTranslatePart(temp._42, aData->Item(2),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
aBounds.Height(), aAppUnitsPerMatrixUnit);
|
||||
temp.y = ProcessTranslatePart(aData->Item(2),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
aBounds.Height(), aAppUnitsPerMatrixUnit);
|
||||
|
||||
ProcessTranslatePart(temp._43, aData->Item(3),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
0, aAppUnitsPerMatrixUnit);
|
||||
temp.z = ProcessTranslatePart(aData->Item(3),
|
||||
aContext, aPresContext, aCanStoreInRuleTree,
|
||||
0, aAppUnitsPerMatrixUnit);
|
||||
|
||||
return temp;
|
||||
aMatrix.Translate(temp);
|
||||
}
|
||||
|
||||
/* Helper function to set up a scale matrix. */
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessScaleHelper(float aXScale, float aYScale, float aZScale)
|
||||
static void
|
||||
ProcessScaleHelper(gfx3DMatrix& aMatrix,
|
||||
float aXScale,
|
||||
float aYScale,
|
||||
float aZScale)
|
||||
{
|
||||
/* We want our matrix to look like this:
|
||||
* | dx 0 0 0 |
|
||||
* | 0 dy 0 0 |
|
||||
* | 0 0 dz 0 |
|
||||
* | 0 0 0 1 |
|
||||
* So A = value
|
||||
*/
|
||||
gfx3DMatrix temp;
|
||||
temp._11 = aXScale;
|
||||
temp._22 = aYScale;
|
||||
temp._33 = aZScale;
|
||||
return temp;
|
||||
aMatrix.Scale(aXScale, aYScale, aZScale);
|
||||
}
|
||||
|
||||
/* Process a scalex function. */
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessScaleX(const nsCSSValue::Array* aData)
|
||||
static void
|
||||
ProcessScaleX(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
|
||||
{
|
||||
NS_PRECONDITION(aData->Count() == 2, "Bad array!");
|
||||
return ProcessScaleHelper(aData->Item(1).GetFloatValue(), 1.0f, 1.0f);
|
||||
ProcessScaleHelper(aMatrix, aData->Item(1).GetFloatValue(), 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
/* Process a scaley function. */
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessScaleY(const nsCSSValue::Array* aData)
|
||||
static void
|
||||
ProcessScaleY(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
|
||||
{
|
||||
NS_PRECONDITION(aData->Count() == 2, "Bad array!");
|
||||
return ProcessScaleHelper(1.0f, aData->Item(1).GetFloatValue(), 1.0f);
|
||||
ProcessScaleHelper(aMatrix, 1.0f, aData->Item(1).GetFloatValue(), 1.0f);
|
||||
}
|
||||
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessScaleZ(const nsCSSValue::Array* aData)
|
||||
static void
|
||||
ProcessScaleZ(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
|
||||
{
|
||||
NS_PRECONDITION(aData->Count() == 2, "Bad array!");
|
||||
return ProcessScaleHelper(1.0f, 1.0f, aData->Item(1).GetFloatValue());
|
||||
ProcessScaleHelper(aMatrix, 1.0f, 1.0f, aData->Item(1).GetFloatValue());
|
||||
}
|
||||
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessScale3D(const nsCSSValue::Array* aData)
|
||||
static void
|
||||
ProcessScale3D(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
|
||||
{
|
||||
NS_PRECONDITION(aData->Count() == 4, "Bad array!");
|
||||
return ProcessScaleHelper(aData->Item(1).GetFloatValue(),
|
||||
aData->Item(2).GetFloatValue(),
|
||||
aData->Item(3).GetFloatValue());
|
||||
ProcessScaleHelper(aMatrix,
|
||||
aData->Item(1).GetFloatValue(),
|
||||
aData->Item(2).GetFloatValue(),
|
||||
aData->Item(3).GetFloatValue());
|
||||
}
|
||||
|
||||
/* Process a scale function. */
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessScale(const nsCSSValue::Array* aData)
|
||||
static void
|
||||
ProcessScale(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
|
||||
{
|
||||
NS_PRECONDITION(aData->Count() == 2 || aData->Count() == 3, "Bad array!");
|
||||
/* We either have one element or two. If we have one, it's for both X and Y.
|
||||
|
@ -426,50 +391,40 @@ nsStyleTransformMatrix::ProcessScale(const nsCSSValue::Array* aData)
|
|||
const nsCSSValue& scaleY = (aData->Count() == 2 ? scaleX :
|
||||
aData->Item(2));
|
||||
|
||||
return ProcessScaleHelper(scaleX.GetFloatValue(),
|
||||
scaleY.GetFloatValue(),
|
||||
1.0f);
|
||||
ProcessScaleHelper(aMatrix,
|
||||
scaleX.GetFloatValue(),
|
||||
scaleY.GetFloatValue(),
|
||||
1.0f);
|
||||
}
|
||||
|
||||
/* Helper function that, given a set of angles, constructs the appropriate
|
||||
* skew matrix.
|
||||
*/
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessSkewHelper(double aXAngle, double aYAngle)
|
||||
static void
|
||||
ProcessSkewHelper(gfx3DMatrix& aMatrix, double aXAngle, double aYAngle)
|
||||
{
|
||||
/* We want our matrix to look like this:
|
||||
* | 1 tan(ThetaY) 0 0 |
|
||||
* | tan(ThetaX) 1 0 0 |
|
||||
* | 0 0 1 0 |
|
||||
* | 0 0 0 1 |
|
||||
* However, to avoid infinite values, we'll use the SafeTangent function
|
||||
* instead of the C standard tan function.
|
||||
*/
|
||||
gfx3DMatrix temp;
|
||||
temp._12 = SafeTangent(aYAngle);
|
||||
temp._21 = SafeTangent(aXAngle);
|
||||
return temp;
|
||||
aMatrix.SkewXY(aXAngle, aYAngle);
|
||||
}
|
||||
|
||||
/* Function that converts a skewx transform into a matrix. */
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessSkewX(const nsCSSValue::Array* aData)
|
||||
static void
|
||||
ProcessSkewX(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
|
||||
{
|
||||
NS_ASSERTION(aData->Count() == 2, "Bad array!");
|
||||
return ProcessSkewHelper(aData->Item(1).GetAngleValueInRadians(), 0.0);
|
||||
ProcessSkewHelper(aMatrix, aData->Item(1).GetAngleValueInRadians(), 0.0);
|
||||
}
|
||||
|
||||
/* Function that converts a skewy transform into a matrix. */
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessSkewY(const nsCSSValue::Array* aData)
|
||||
static void
|
||||
ProcessSkewY(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
|
||||
{
|
||||
NS_ASSERTION(aData->Count() == 2, "Bad array!");
|
||||
return ProcessSkewHelper(0.0, aData->Item(1).GetAngleValueInRadians());
|
||||
ProcessSkewHelper(aMatrix, 0.0, aData->Item(1).GetAngleValueInRadians());
|
||||
}
|
||||
|
||||
/* Function that converts a skew transform into a matrix. */
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessSkew(const nsCSSValue::Array* aData)
|
||||
static void
|
||||
ProcessSkew(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
|
||||
{
|
||||
NS_ASSERTION(aData->Count() == 2 || aData->Count() == 3, "Bad array!");
|
||||
|
||||
|
@ -477,87 +432,36 @@ nsStyleTransformMatrix::ProcessSkew(const nsCSSValue::Array* aData)
|
|||
double ySkew = (aData->Count() == 2
|
||||
? 0.0 : aData->Item(2).GetAngleValueInRadians());
|
||||
|
||||
return ProcessSkewHelper(xSkew, ySkew);
|
||||
ProcessSkewHelper(aMatrix, xSkew, ySkew);
|
||||
}
|
||||
|
||||
/* Function that converts a rotate transform into a matrix. */
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessRotateZ(const nsCSSValue::Array* aData)
|
||||
static void
|
||||
ProcessRotateZ(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
|
||||
{
|
||||
NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
|
||||
|
||||
/* We want our matrix to look like this:
|
||||
* | cos(theta) sin(theta) 0 0 |
|
||||
* | -sin(theta) cos(theta) 0 0 |
|
||||
* | 0 0 1 0 |
|
||||
* | 0 0 0 1 |
|
||||
* (see http://www.w3.org/TR/SVG/coords.html#RotationDefined)
|
||||
*/
|
||||
double theta = aData->Item(1).GetAngleValueInRadians();
|
||||
float cosTheta = FlushToZero(cos(theta));
|
||||
float sinTheta = FlushToZero(sin(theta));
|
||||
|
||||
gfx3DMatrix temp;
|
||||
|
||||
temp._11 = cosTheta;
|
||||
temp._12 = sinTheta;
|
||||
temp._21 = -sinTheta;
|
||||
temp._22 = cosTheta;
|
||||
return temp;
|
||||
aMatrix.RotateZ(theta);
|
||||
}
|
||||
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessRotateX(const nsCSSValue::Array* aData)
|
||||
static void
|
||||
ProcessRotateX(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
|
||||
{
|
||||
NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
|
||||
|
||||
/* We want our matrix to look like this:
|
||||
* | 1 0 0 0 |
|
||||
* | 0 cos(theta) sin(theta) 0 |
|
||||
* | 0 -sin(theta) cos(theta) 0 |
|
||||
* | 0 0 0 1 |
|
||||
* (see http://www.w3.org/TR/SVG/coords.html#RotationDefined)
|
||||
*/
|
||||
double theta = aData->Item(1).GetAngleValueInRadians();
|
||||
float cosTheta = FlushToZero(cos(theta));
|
||||
float sinTheta = FlushToZero(sin(theta));
|
||||
|
||||
gfx3DMatrix temp;
|
||||
|
||||
temp._22 = cosTheta;
|
||||
temp._23 = sinTheta;
|
||||
temp._32 = -sinTheta;
|
||||
temp._33 = cosTheta;
|
||||
return temp;
|
||||
aMatrix.RotateX(theta);
|
||||
}
|
||||
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessRotateY(const nsCSSValue::Array* aData)
|
||||
static void
|
||||
ProcessRotateY(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
|
||||
{
|
||||
NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
|
||||
|
||||
/* We want our matrix to look like this:
|
||||
* | cos(theta) 0 -sin(theta) 0 |
|
||||
* | 0 1 0 0 |
|
||||
* | sin(theta) 0 cos(theta) 0 |
|
||||
* | 0 0 0 1 |
|
||||
* (see http://www.w3.org/TR/SVG/coords.html#RotationDefined)
|
||||
*/
|
||||
double theta = aData->Item(1).GetAngleValueInRadians();
|
||||
float cosTheta = FlushToZero(cos(theta));
|
||||
float sinTheta = FlushToZero(sin(theta));
|
||||
|
||||
gfx3DMatrix temp;
|
||||
|
||||
temp._11 = cosTheta;
|
||||
temp._13 = -sinTheta;
|
||||
temp._31 = sinTheta;
|
||||
temp._33 = cosTheta;
|
||||
return temp;
|
||||
aMatrix.RotateY(theta);
|
||||
}
|
||||
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessRotate3D(const nsCSSValue::Array* aData)
|
||||
static void
|
||||
ProcessRotate3D(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
|
||||
{
|
||||
NS_PRECONDITION(aData->Count() == 5, "Invalid array!");
|
||||
|
||||
|
@ -579,7 +483,7 @@ nsStyleTransformMatrix::ProcessRotate3D(const nsCSSValue::Array* aData)
|
|||
/* Normalize [x,y,z] */
|
||||
float length = sqrt(x*x + y*y + z*z);
|
||||
if (length == 0.0) {
|
||||
return gfx3DMatrix();
|
||||
return;
|
||||
}
|
||||
x /= length;
|
||||
y /= length;
|
||||
|
@ -604,60 +508,39 @@ nsStyleTransformMatrix::ProcessRotate3D(const nsCSSValue::Array* aData)
|
|||
temp._42 = 0.0f;
|
||||
temp._43 = 0.0f;
|
||||
temp._44 = 1.0f;
|
||||
return temp;
|
||||
|
||||
aMatrix = temp * aMatrix;
|
||||
}
|
||||
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ProcessPerspective(const nsCSSValue::Array* aData,
|
||||
nsStyleContext *aContext,
|
||||
nsPresContext *aPresContext,
|
||||
PRBool &aCanStoreInRuleTree,
|
||||
float aAppUnitsPerMatrixUnit)
|
||||
static void
|
||||
ProcessPerspective(gfx3DMatrix& aMatrix,
|
||||
const nsCSSValue::Array* aData,
|
||||
nsStyleContext *aContext,
|
||||
nsPresContext *aPresContext,
|
||||
PRBool &aCanStoreInRuleTree,
|
||||
float aAppUnitsPerMatrixUnit)
|
||||
{
|
||||
NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
|
||||
|
||||
/* We want our matrix to look like this:
|
||||
* | 1 0 0 0 |
|
||||
* | 0 1 0 0 |
|
||||
* | 0 0 1 -1/depth |
|
||||
* | 0 0 0 1 |
|
||||
*/
|
||||
|
||||
gfx3DMatrix temp;
|
||||
|
||||
float depth;
|
||||
ProcessTranslatePart(depth, aData->Item(1), aContext,
|
||||
aPresContext, aCanStoreInRuleTree,
|
||||
0, aAppUnitsPerMatrixUnit);
|
||||
NS_ASSERTION(depth > 0.0, "Perspective must be positive!");
|
||||
temp._34 = -1.0/depth;
|
||||
|
||||
return temp;
|
||||
float depth = ProcessTranslatePart(aData->Item(1), aContext,
|
||||
aPresContext, aCanStoreInRuleTree,
|
||||
0, aAppUnitsPerMatrixUnit);
|
||||
aMatrix.Perspective(depth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the transform function, as an nsCSSKeyword, for the given
|
||||
* nsCSSValue::Array from a transform list.
|
||||
*/
|
||||
/* static */ nsCSSKeyword
|
||||
nsStyleTransformMatrix::TransformFunctionOf(const nsCSSValue::Array* aData)
|
||||
{
|
||||
nsAutoString keyword;
|
||||
aData->Item(0).GetStringValue(keyword);
|
||||
return nsCSSKeywords::LookupKeyword(keyword);
|
||||
}
|
||||
|
||||
/**
|
||||
* SetToTransformFunction is essentially a giant switch statement that fans
|
||||
* out to many smaller helper functions.
|
||||
*/
|
||||
gfx3DMatrix
|
||||
nsStyleTransformMatrix::MatrixForTransformFunction(const nsCSSValue::Array * aData,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool& aCanStoreInRuleTree,
|
||||
nsRect& aBounds,
|
||||
float aAppUnitsPerMatrixUnit)
|
||||
static void
|
||||
MatrixForTransformFunction(gfx3DMatrix& aMatrix,
|
||||
const nsCSSValue::Array * aData,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool& aCanStoreInRuleTree,
|
||||
nsRect& aBounds,
|
||||
float aAppUnitsPerMatrixUnit)
|
||||
{
|
||||
NS_PRECONDITION(aData, "Why did you want to get data from a null array?");
|
||||
// It's OK if aContext and aPresContext are null if the caller already
|
||||
|
@ -668,69 +551,102 @@ nsStyleTransformMatrix::MatrixForTransformFunction(const nsCSSValue::Array * aDa
|
|||
/* Get the keyword for the transform. */
|
||||
switch (TransformFunctionOf(aData)) {
|
||||
case eCSSKeyword_translatex:
|
||||
return ProcessTranslateX(aData, aContext, aPresContext,
|
||||
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
|
||||
ProcessTranslateX(aMatrix, aData, aContext, aPresContext,
|
||||
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
|
||||
break;
|
||||
case eCSSKeyword_translatey:
|
||||
return ProcessTranslateY(aData, aContext, aPresContext,
|
||||
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
|
||||
ProcessTranslateY(aMatrix, aData, aContext, aPresContext,
|
||||
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
|
||||
break;
|
||||
case eCSSKeyword_translatez:
|
||||
return ProcessTranslateZ(aData, aContext, aPresContext,
|
||||
aCanStoreInRuleTree, aAppUnitsPerMatrixUnit);
|
||||
ProcessTranslateZ(aMatrix, aData, aContext, aPresContext,
|
||||
aCanStoreInRuleTree, aAppUnitsPerMatrixUnit);
|
||||
break;
|
||||
case eCSSKeyword_translate:
|
||||
return ProcessTranslate(aData, aContext, aPresContext,
|
||||
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
|
||||
ProcessTranslate(aMatrix, aData, aContext, aPresContext,
|
||||
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
|
||||
break;
|
||||
case eCSSKeyword_translate3d:
|
||||
return ProcessTranslate3D(aData, aContext, aPresContext,
|
||||
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
|
||||
ProcessTranslate3D(aMatrix, aData, aContext, aPresContext,
|
||||
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
|
||||
break;
|
||||
case eCSSKeyword_scalex:
|
||||
return ProcessScaleX(aData);
|
||||
ProcessScaleX(aMatrix, aData);
|
||||
break;
|
||||
case eCSSKeyword_scaley:
|
||||
return ProcessScaleY(aData);
|
||||
ProcessScaleY(aMatrix, aData);
|
||||
break;
|
||||
case eCSSKeyword_scalez:
|
||||
return ProcessScaleZ(aData);
|
||||
ProcessScaleZ(aMatrix, aData);
|
||||
break;
|
||||
case eCSSKeyword_scale:
|
||||
return ProcessScale(aData);
|
||||
ProcessScale(aMatrix, aData);
|
||||
break;
|
||||
case eCSSKeyword_scale3d:
|
||||
return ProcessScale3D(aData);
|
||||
ProcessScale3D(aMatrix, aData);
|
||||
break;
|
||||
case eCSSKeyword_skewx:
|
||||
return ProcessSkewX(aData);
|
||||
ProcessSkewX(aMatrix, aData);
|
||||
break;
|
||||
case eCSSKeyword_skewy:
|
||||
return ProcessSkewY(aData);
|
||||
ProcessSkewY(aMatrix, aData);
|
||||
break;
|
||||
case eCSSKeyword_skew:
|
||||
return ProcessSkew(aData);
|
||||
ProcessSkew(aMatrix, aData);
|
||||
break;
|
||||
case eCSSKeyword_rotatex:
|
||||
return ProcessRotateX(aData);
|
||||
ProcessRotateX(aMatrix, aData);
|
||||
break;
|
||||
case eCSSKeyword_rotatey:
|
||||
return ProcessRotateY(aData);
|
||||
ProcessRotateY(aMatrix, aData);
|
||||
break;
|
||||
case eCSSKeyword_rotatez:
|
||||
case eCSSKeyword_rotate:
|
||||
return ProcessRotateZ(aData);
|
||||
ProcessRotateZ(aMatrix, aData);
|
||||
break;
|
||||
case eCSSKeyword_rotate3d:
|
||||
return ProcessRotate3D(aData);
|
||||
ProcessRotate3D(aMatrix, aData);
|
||||
break;
|
||||
case eCSSKeyword_matrix:
|
||||
return ProcessMatrix(aData, aContext, aPresContext,
|
||||
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
|
||||
ProcessMatrix(aMatrix, aData, aContext, aPresContext,
|
||||
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
|
||||
break;
|
||||
case eCSSKeyword_matrix3d:
|
||||
return ProcessMatrix3D(aData);
|
||||
ProcessMatrix3D(aMatrix, aData, aContext, aPresContext,
|
||||
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
|
||||
break;
|
||||
case eCSSKeyword_interpolatematrix:
|
||||
return ProcessInterpolateMatrix(aData, aContext, aPresContext,
|
||||
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
|
||||
ProcessInterpolateMatrix(aMatrix, aData, aContext, aPresContext,
|
||||
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
|
||||
break;
|
||||
case eCSSKeyword_perspective:
|
||||
return ProcessPerspective(aData, aContext, aPresContext,
|
||||
aCanStoreInRuleTree, aAppUnitsPerMatrixUnit);
|
||||
ProcessPerspective(aMatrix, aData, aContext, aPresContext,
|
||||
aCanStoreInRuleTree, aAppUnitsPerMatrixUnit);
|
||||
break;
|
||||
default:
|
||||
NS_NOTREACHED("Unknown transform function!");
|
||||
}
|
||||
return gfx3DMatrix();
|
||||
}
|
||||
|
||||
/* static */ gfx3DMatrix
|
||||
nsStyleTransformMatrix::ReadTransforms(const nsCSSValueList* aList,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool &aCanStoreInRuleTree,
|
||||
nsRect& aBounds,
|
||||
float aAppUnitsPerMatrixUnit)
|
||||
/**
|
||||
* Return the transform function, as an nsCSSKeyword, for the given
|
||||
* nsCSSValue::Array from a transform list.
|
||||
*/
|
||||
nsCSSKeyword
|
||||
TransformFunctionOf(const nsCSSValue::Array* aData)
|
||||
{
|
||||
nsAutoString keyword;
|
||||
aData->Item(0).GetStringValue(keyword);
|
||||
return nsCSSKeywords::LookupKeyword(keyword);
|
||||
}
|
||||
|
||||
gfx3DMatrix
|
||||
ReadTransforms(const nsCSSValueList* aList,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool &aCanStoreInRuleTree,
|
||||
nsRect& aBounds,
|
||||
float aAppUnitsPerMatrixUnit)
|
||||
{
|
||||
gfx3DMatrix result;
|
||||
|
||||
|
@ -741,12 +657,13 @@ nsStyleTransformMatrix::ReadTransforms(const nsCSSValueList* aList,
|
|||
NS_ASSERTION(currElem.GetArrayValue()->Count() >= 1,
|
||||
"Incoming function is too short!");
|
||||
|
||||
/* Read in a single transform matrix, then accumulate it with the total. */
|
||||
result = MatrixForTransformFunction(currElem.GetArrayValue(), aContext,
|
||||
aPresContext, aCanStoreInRuleTree,
|
||||
aBounds, aAppUnitsPerMatrixUnit) * result;
|
||||
/* Read in a single transform matrix. */
|
||||
MatrixForTransformFunction(result, currElem.GetArrayValue(), aContext,
|
||||
aPresContext, aCanStoreInRuleTree,
|
||||
aBounds, aAppUnitsPerMatrixUnit);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace nsStyleTransformMatrix
|
||||
|
|
|
@ -52,22 +52,21 @@ class nsStyleContext;
|
|||
class nsPresContext;
|
||||
|
||||
/**
|
||||
* A helper class to generate gfxMatrixes from css transform functions.
|
||||
* A helper to generate gfxMatrixes from css transform functions.
|
||||
*/
|
||||
class nsStyleTransformMatrix
|
||||
{
|
||||
public:
|
||||
namespace nsStyleTransformMatrix {
|
||||
|
||||
/**
|
||||
* Return the transform function, as an nsCSSKeyword, for the given
|
||||
* nsCSSValue::Array from a transform list.
|
||||
*/
|
||||
static nsCSSKeyword TransformFunctionOf(const nsCSSValue::Array* aData);
|
||||
nsCSSKeyword TransformFunctionOf(const nsCSSValue::Array* aData);
|
||||
|
||||
/**
|
||||
* Given an nsCSSValue::Array* containing a -moz-transform function,
|
||||
* returns a matrix containing the value of that function.
|
||||
* Given an nsCSSValueList containing -moz-transform functions,
|
||||
* returns a matrix containing the value of those functions.
|
||||
*
|
||||
* @param aData The nsCSSValue::Array* containing the transform function.
|
||||
* @param aData The nsCSSValueList containing the transform functions
|
||||
* @param aContext The style context, used for unit conversion.
|
||||
* @param aPresContext The presentation context, used for unit conversion.
|
||||
* @param aCanStoreInRuleTree Set to false if the result cannot be cached
|
||||
|
@ -79,82 +78,13 @@ class nsStyleTransformMatrix
|
|||
* length values in aData are already known to have been converted to
|
||||
* eCSSUnit_Pixel (as they are in an nsStyleAnimation::Value)
|
||||
*/
|
||||
static gfx3DMatrix MatrixForTransformFunction(const nsCSSValue::Array* aData,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool& aCanStoreInRuleTree,
|
||||
nsRect& aBounds,
|
||||
float aAppUnitsPerMatrixUnit);
|
||||
gfx3DMatrix ReadTransforms(const nsCSSValueList* aList,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool &aCanStoreInRuleTree,
|
||||
nsRect& aBounds,
|
||||
float aAppUnitsPerMatrixUnit);
|
||||
|
||||
/**
|
||||
* The same as MatrixForTransformFunction, but for a list of transform
|
||||
* functions.
|
||||
*/
|
||||
static gfx3DMatrix ReadTransforms(const nsCSSValueList* aList,
|
||||
nsStyleContext* aContext,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool &aCanStoreInRuleTree,
|
||||
nsRect& aBounds,
|
||||
float aAppUnitsPerMatrixUnit);
|
||||
|
||||
private:
|
||||
static gfx3DMatrix ProcessMatrix(const nsCSSValue::Array *aData,
|
||||
nsStyleContext *aContext,
|
||||
nsPresContext *aPresContext,
|
||||
PRBool &aCanStoreInRuleTree,
|
||||
nsRect& aBounds, float aAppUnitsPerMatrixUnit,
|
||||
PRBool *aPercentX = nsnull,
|
||||
PRBool *aPercentY = nsnull);
|
||||
static gfx3DMatrix ProcessMatrix3D(const nsCSSValue::Array *aData);
|
||||
static gfx3DMatrix ProcessInterpolateMatrix(const nsCSSValue::Array *aData,
|
||||
nsStyleContext *aContext,
|
||||
nsPresContext *aPresContext,
|
||||
PRBool &aCanStoreInRuleTree,
|
||||
nsRect& aBounds, float aAppUnitsPerMatrixUnit);
|
||||
static gfx3DMatrix ProcessTranslateX(const nsCSSValue::Array *aData,
|
||||
nsStyleContext *aContext,
|
||||
nsPresContext *aPresContext,
|
||||
PRBool &aCanStoreInRuleTree,
|
||||
nsRect& aBounds, float aAppUnitsPerMatrixUnit);
|
||||
static gfx3DMatrix ProcessTranslateY(const nsCSSValue::Array *aData,
|
||||
nsStyleContext *aContext,
|
||||
nsPresContext *aPresContext,
|
||||
PRBool &aCanStoreInRuleTree,
|
||||
nsRect& aBounds, float aAppUnitsPerMatrixUnit);
|
||||
static gfx3DMatrix ProcessTranslateZ(const nsCSSValue::Array *aData,
|
||||
nsStyleContext *aContext,
|
||||
nsPresContext *aPresContext,
|
||||
PRBool &aCanStoreInRuleTree,
|
||||
float aAppUnitsPerMatrixUnit);
|
||||
static gfx3DMatrix ProcessTranslate(const nsCSSValue::Array *aData,
|
||||
nsStyleContext *aContext,
|
||||
nsPresContext *aPresContext,
|
||||
PRBool &aCanStoreInRuleTree,
|
||||
nsRect& aBounds, float aAppUnitsPerMatrixUnit);
|
||||
static gfx3DMatrix ProcessTranslate3D(const nsCSSValue::Array *aData,
|
||||
nsStyleContext *aContext,
|
||||
nsPresContext *aPresContext,
|
||||
PRBool &aCanStoreInRuleTree,
|
||||
nsRect& aBounds, float aAppUnitsPerMatrixUnit);
|
||||
static gfx3DMatrix ProcessScaleHelper(float aXScale, float aYScale, float aZScale);
|
||||
static gfx3DMatrix ProcessScaleX(const nsCSSValue::Array *aData);
|
||||
static gfx3DMatrix ProcessScaleY(const nsCSSValue::Array *aData);
|
||||
static gfx3DMatrix ProcessScaleZ(const nsCSSValue::Array *aData);
|
||||
static gfx3DMatrix ProcessScale(const nsCSSValue::Array *aData);
|
||||
static gfx3DMatrix ProcessScale3D(const nsCSSValue::Array *aData);
|
||||
static gfx3DMatrix ProcessSkewHelper(double aXAngle, double aYAngle);
|
||||
static gfx3DMatrix ProcessSkewX(const nsCSSValue::Array *aData);
|
||||
static gfx3DMatrix ProcessSkewY(const nsCSSValue::Array *aData);
|
||||
static gfx3DMatrix ProcessSkew(const nsCSSValue::Array *aData);
|
||||
static gfx3DMatrix ProcessRotateX(const nsCSSValue::Array *aData);
|
||||
static gfx3DMatrix ProcessRotateY(const nsCSSValue::Array *aData);
|
||||
static gfx3DMatrix ProcessRotateZ(const nsCSSValue::Array *aData);
|
||||
static gfx3DMatrix ProcessRotate3D(const nsCSSValue::Array *aData);
|
||||
static gfx3DMatrix ProcessPerspective(const nsCSSValue::Array *aData,
|
||||
nsStyleContext *aContext,
|
||||
nsPresContext *aPresContext,
|
||||
PRBool &aCanStoreInRuleTree,
|
||||
float aAppUnitsPerMatrixUnit);
|
||||
};
|
||||
} // namespace nsStyleTransformMatrix
|
||||
|
||||
#endif
|
||||
|
|
|
@ -226,6 +226,7 @@ _TEST_FILES = test_acid3_test46.html \
|
|||
visited_image_loading.sjs \
|
||||
visited_image_loading_frame.html \
|
||||
visited_image_loading_frame_empty.html \
|
||||
test_load_events_on_stylesheets.html \
|
||||
$(NULL)
|
||||
|
||||
_VISITED_REFTEST_FILES = \
|
||||
|
|
|
@ -931,7 +931,7 @@ var gCSSProperties = {
|
|||
type: CSS_TYPE_LONGHAND,
|
||||
prerequisites: { "width": "300px", "height": "50px" },
|
||||
initial_values: [ "none" ],
|
||||
other_values: [ "translatex(1px)", "translatex(4em)", "translatex(-4px)", "translatex(3px)", "translatex(0px) translatex(1px) translatex(2px) translatex(3px) translatex(4px)", "translatey(4em)", "translate(3px)", "translate(10px, -3px)", "rotate(45deg)", "rotate(45grad)", "rotate(45rad)", "rotate(0)", "scalex(10)", "scaley(10)", "scale(10)", "scale(10, 20)", "skewx(30deg)", "skewx(0)", "skewy(0)", "skewx(30grad)", "skewx(30rad)", "skewy(30deg)", "skewy(30grad)", "skewy(30rad)", "matrix(1, 2, 3, 4, 5px, 6em)", "rotate(45deg) scale(2, 1)", "skewx(45deg) skewx(-50grad)", "translate(0, 0) scale(1, 1) skewx(0) skewy(0) matrix(1, 0, 0, 1, 0, 0)", "translatex(50%)", "translatey(50%)", "translate(50%)", "translate(3%, 5px)", "translate(5px, 3%)", "matrix(1, 2, 3, 4, 5px, 6%)", "matrix(1, 2, 3, 4, 5%, 6px)", "matrix(1, 2, 3, 4, 5%, 6%)",
|
||||
other_values: [ "translatex(1px)", "translatex(4em)", "translatex(-4px)", "translatex(3px)", "translatex(0px) translatex(1px) translatex(2px) translatex(3px) translatex(4px)", "translatey(4em)", "translate(3px)", "translate(10px, -3px)", "rotate(45deg)", "rotate(45grad)", "rotate(45rad)", "rotate(0)", "scalex(10)", "scaley(10)", "scale(10)", "scale(10, 20)", "skewx(30deg)", "skewx(0)", "skewy(0)", "skewx(30grad)", "skewx(30rad)", "skewy(30deg)", "skewy(30grad)", "skewy(30rad)", "matrix(1, 2, 3, 4, 5px, 6em)", "rotate(45deg) scale(2, 1)", "skewx(45deg) skewx(-50grad)", "translate(0, 0) scale(1, 1) skewx(0) skewy(0) matrix(1, 0, 0, 1, 0, 0)", "translatex(50%)", "translatey(50%)", "translate(50%)", "translate(3%, 5px)", "translate(5px, 3%)", "matrix(1, 2, 3, 4, 5px, 6%)", "matrix(1, 2, 3, 4, 5%, 6px)", "matrix(1, 2, 3, 4, 5%, 6%)", "matrix(1, 2, 3, 4, 5, 6)",
|
||||
/* valid calc() values */
|
||||
"translatex(-moz-calc(5px + 10%))",
|
||||
"translatey(-moz-calc(0.25 * 5px + 10% / 3))",
|
||||
|
@ -940,9 +940,9 @@ var gCSSProperties = {
|
|||
"translate(-50px, -moz-calc(5px - 10% * 3))",
|
||||
"matrix(1, 0, 0, 1, -moz-calc(5px * 3), -moz-calc(10% - 3px))"
|
||||
].concat(SpecialPowers.getBoolPref("layout.3d-transforms.enabled") ? [
|
||||
"translatez(1px)", "translatez(4em)", "translatez(-4px)", "translatez(0px)", "translatez(2px) translatez(5px)", "translate3d(3px, 4px, 5px)", "translate3d(2em, 3px, 1em)", "translatex(2px) translate3d(4px, 5px, 6px) translatey(1px)", "scale3d(4, 4, 4)", "scale3d(-2, 3, -7)", "scalez(4)", "scalez(-6)", "rotate3d(2, 3, 4, 45deg)", "rotate3d(-3, 7, 0, 12rad)", "rotatex(15deg)", "rotatey(-12grad)", "rotatez(72rad)", "perspective(1000px)", "matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)"
|
||||
"translatez(1px)", "translatez(4em)", "translatez(-4px)", "translatez(0px)", "translatez(2px) translatez(5px)", "translate3d(3px, 4px, 5px)", "translate3d(2em, 3px, 1em)", "translatex(2px) translate3d(4px, 5px, 6px) translatey(1px)", "scale3d(4, 4, 4)", "scale3d(-2, 3, -7)", "scalez(4)", "scalez(-6)", "rotate3d(2, 3, 4, 45deg)", "rotate3d(-3, 7, 0, 12rad)", "rotatex(15deg)", "rotatey(-12grad)", "rotatez(72rad)", "perspective(1000px)", "matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)", "matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13px, 14em, 15px, 16)", "matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 20%, 10%, 15, 16)"
|
||||
] : []),
|
||||
invalid_values: ["1px", "#0000ff", "red", "auto", "translatex(1px 1px)", "translatex(translatex(1px))", "translatex(#0000ff)", "translatex(red)", "translatey()", "matrix(1, 2, 3, 4, 5, 6)", "matrix(1px, 2px, 3px, 4px, 5px, 6px)", "scale(150%)", "skewx(red)", "matrix(1%, 0, 0, 0, 0px, 0px)", "matrix(0, 1%, 2, 3, 4px,5px)", "matrix(0, 1, 2%, 3, 4px, 5px)", "matrix(0, 1, 2, 3%, 4%, 5%)",
|
||||
invalid_values: ["1px", "#0000ff", "red", "auto", "translatex(1px 1px)", "translatex(translatex(1px))", "translatex(#0000ff)", "translatex(red)", "translatey()", "matrix(1px, 2px, 3px, 4px, 5px, 6px)", "scale(150%)", "skewx(red)", "matrix(1%, 0, 0, 0, 0px, 0px)", "matrix(0, 1%, 2, 3, 4px,5px)", "matrix(0, 1, 2%, 3, 4px, 5px)", "matrix(0, 1, 2, 3%, 4%, 5%)",
|
||||
/* invalid calc() values */
|
||||
"translatey(-moz-min(5px,10%))",
|
||||
"translatex(-moz-max(5px,10%))",
|
||||
|
@ -950,7 +950,7 @@ var gCSSProperties = {
|
|||
"translate(-moz-calc(max(5px,10%)), 10%)",
|
||||
"matrix(1, 0, 0, 1, -moz-max(5px * 3), -moz-calc(10% - 3px))"
|
||||
].concat(SpecialPowers.getBoolPref("layout.3d-transforms.enabled") ? [
|
||||
"perspective(0px)", "perspective(-10px)", "matrix3d(dinosaur)", "matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)", "matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)", "rotatey(words)", "rotatex(7)", "translate3d(3px, 4px, 1px, 7px)"
|
||||
"perspective(0px)", "perspective(-10px)", "matrix3d(dinosaur)", "matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)", "matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)", "matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15%, 16)", "matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16px)", "rotatey(words)", "rotatex(7)", "translate3d(3px, 4px, 1px, 7px)"
|
||||
] : [])
|
||||
},
|
||||
"-moz-transform-origin": {
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=185236
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 185236</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script>
|
||||
var pendingEventCounter = 0;
|
||||
var messagePosted = false;
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(function() {
|
||||
is(messagePosted, true, "Should have gotten onmessage event");
|
||||
is(pendingEventCounter, 0,
|
||||
"How did onload for the page fire before onload for all the stylesheets?");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
// Count the link we're about to parse
|
||||
pendingEventCounter = 1;
|
||||
</script>
|
||||
<link rel="stylesheet" href="data:text/css,*{}"
|
||||
onload="--pendingEventCounter;
|
||||
ok(true, 'Load event firing on basic stylesheet')"
|
||||
onerror="--pendingEventCounter;
|
||||
ok(false, 'Error event firing on basic stylesheet')">
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=185236">Mozilla Bug 185236</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
/** Test for Bug 185236 **/
|
||||
// Verify that there are no in-flight sheet loads right now; we should have
|
||||
// waited for them when we hit the script tag
|
||||
is(pendingEventCounter, 0, "There should be no pending events");
|
||||
|
||||
// Test sheet that will already be complete when we write it out
|
||||
++pendingEventCounter;
|
||||
|
||||
// Make sure that a postMessage we do right now fires after the onload handler
|
||||
// for the stylesheet. If we ever change the timing of sheet onload, we will
|
||||
// need to change that.
|
||||
window.onmessage = function() {
|
||||
messagePosted = true;
|
||||
// There are 4 pending events: two from the two direct example.com loads,
|
||||
// and 2 from the two data:text/css loads that import things
|
||||
is(pendingEventCounter, 4, "Load event for sheet should have fired");
|
||||
}
|
||||
window.postMessage("", "*");
|
||||
|
||||
document.write('<link rel="stylesheet" href="data:text/css,*{}"\
|
||||
onload="--pendingEventCounter;\
|
||||
ok(true, \'Load event firing on basic stylesheet\')"\
|
||||
onerror="--pendingEventCounter;\
|
||||
ok(false, \'Error event firing on basic stylesheet\')">');
|
||||
|
||||
// Make sure we have that second stylesheet
|
||||
is(document.styleSheets.length, 3, "Should have three stylesheets");
|
||||
|
||||
// Make sure that the second stylesheet is all loaded
|
||||
// If we ever switch away from sync loading of already-complete sheets, this
|
||||
// test will need adjusting
|
||||
is(document.styleSheets[2].cssRules.length, 1, "Should have one rule");
|
||||
|
||||
// Make sure the load event for that stylesheet has not fired yet
|
||||
is(pendingEventCounter, 1, "There should be one pending event");
|
||||
|
||||
++pendingEventCounter;
|
||||
document.write('<style\
|
||||
onload="--pendingEventCounter;\
|
||||
ok(true, \'Load event firing on inline stylesheet\')"\
|
||||
onerror="--pendingEventCounter;\
|
||||
ok(false, \'Error event firing on inline stylesheet\')"></style>');
|
||||
|
||||
// Make sure the load event for that second stylesheet has not fired yet
|
||||
is(pendingEventCounter, 2, "There should be two pending events");
|
||||
|
||||
++pendingEventCounter;
|
||||
document.write('<link rel="stylesheet" href="http://www.example.com"\
|
||||
onload="--pendingEventCounter;\
|
||||
ok(false, \'Load event firing on broken stylesheet\')"\
|
||||
onerror="--pendingEventCounter;\
|
||||
ok(true, \'Error event firing on broken stylesheet\')">');
|
||||
|
||||
++pendingEventCounter;
|
||||
var link = document.createElement("link");
|
||||
link.rel = "stylesheet";
|
||||
link.href = "http://www.example.com";
|
||||
link.onload = function() { --pendingEventCounter;
|
||||
ok(false, 'Load event firing on broken stylesheet');
|
||||
};
|
||||
link.onerror = function() { --pendingEventCounter;
|
||||
ok(true, 'Error event firing on broken stylesheet');
|
||||
}
|
||||
document.body.appendChild(link);
|
||||
|
||||
++pendingEventCounter;
|
||||
link = document.createElement("link");
|
||||
link.rel = "stylesheet";
|
||||
link.href = "data:text/css,*{}";
|
||||
link.onload = function() { --pendingEventCounter;
|
||||
ok(true, 'Load event firing on external stylesheet');
|
||||
};
|
||||
link.onerror = function() { --pendingEventCounter;
|
||||
ok(false, 'Error event firing on external stylesheet');
|
||||
}
|
||||
document.body.appendChild(link);
|
||||
|
||||
// Make sure we have that last stylesheet
|
||||
is(document.styleSheets.length, 7, "Should have seven stylesheets here");
|
||||
|
||||
// Make sure that the sixth stylesheet is all loaded
|
||||
// If we ever switch away from sync loading of already-complete sheets, this
|
||||
// test will need adjusting
|
||||
is(document.styleSheets[6].cssRules.length, 1, "Should have one rule");
|
||||
|
||||
++pendingEventCounter;
|
||||
link = document.createElement("link");
|
||||
link.rel = "stylesheet";
|
||||
link.href = "data:text/css,@import url('data:text/css,*{}')";
|
||||
link.onload = function() { --pendingEventCounter;
|
||||
ok(true, 'Load event firing on external stylesheet');
|
||||
};
|
||||
link.onerror = function() { --pendingEventCounter;
|
||||
ok(false, 'Error event firing on external stylesheet');
|
||||
}
|
||||
document.body.appendChild(link);
|
||||
|
||||
++pendingEventCounter;
|
||||
link = document.createElement("link");
|
||||
link.rel = "stylesheet";
|
||||
link.href = "data:text/css,@import url('http://www.example.com')";
|
||||
link.onload = function() { --pendingEventCounter;
|
||||
ok(false, 'Load event firing on broken stylesheet');
|
||||
};
|
||||
link.onerror = function() { --pendingEventCounter;
|
||||
ok(true, 'Error event firing on broken stylesheet');
|
||||
}
|
||||
document.body.appendChild(link);
|
||||
|
||||
// Make sure the load events for all those stylesheets have not fired yet
|
||||
is(pendingEventCounter, 7, "There should be one pending event");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1425,20 +1425,23 @@ function test_transform_transition(prop) {
|
|||
|
||||
// matrix : skewX
|
||||
{ start: 'matrix(1, 0, 3, 1, 0px, 0px)', end: 'none',
|
||||
expected: 'matrix(1, 0, ' + Math.tan(Math.atan(3) * 0.75) + ', 1, 0px, 0px)',
|
||||
expected: 'matrix(1, 0, ' + 3 * 0.75 + ', 1, 0px, 0px)',
|
||||
round_error_ok: true },
|
||||
{ start: 'skewX(0)', end: 'skewX(-45deg) translate(0)',
|
||||
expected: 'matrix(1, 0, -0.198912367, 1, 0px, 0px)',
|
||||
expected: 'matrix(1, 0, -0.25, 1, 0px, 0px)',
|
||||
round_error_ok: true },
|
||||
// matrix : rotate
|
||||
{ start: 'rotate(-30deg)', end: 'matrix(0, 1, -1, 0, 0px, 0px)',
|
||||
expected: 'matrix(1, 0, 0, 1, 0px, 0px)' },
|
||||
expected: 'matrix(1, 0, 0, 1, 0px, 0px)',
|
||||
round_error_ok: true },
|
||||
{ start: 'rotate(-30deg) translateX(0)',
|
||||
end: 'translateX(0) rotate(-90deg)',
|
||||
expected: c('rotate(-45deg)') },
|
||||
expected: c('rotate(-45deg)'),
|
||||
round_error_ok: true },
|
||||
// matrix decomposition of skewY
|
||||
{ start: 'skewY(60deg)', end: 'skewY(-60deg) translateX(0)',
|
||||
expected: c('rotate(30deg) skewX(30deg) scale(2, 0.5)'),
|
||||
/* rotate(30deg) skewX(60deg)/2 scale(2, 0.5) */
|
||||
expected: c('rotate(30deg) skewX(' + Math.atan(Math.tan(Math.PI * 60/180) / 2) + 'rad) scale(2, 0.5)'),
|
||||
round_error_ok: true },
|
||||
|
||||
// matrix decomposition
|
||||
|
@ -1493,42 +1496,42 @@ function test_transform_transition(prop) {
|
|||
{ start: 'none',
|
||||
end: 'matrix(1, 0, 1.5, 1, 0pt, 0pt)',
|
||||
/* skewX(atan(1.5)) */
|
||||
expected: 'matrix(1, 0, ' + Math.tan(Math.atan(1.5) * 0.25).toFixed(6) + ', 1, 0px, 0px)',
|
||||
expected: 'matrix(1, 0, ' + 1.5 * 0.25 + ', 1, 0px, 0px)',
|
||||
round_error_ok: true },
|
||||
{ start: 'none',
|
||||
end: 'matrix(-1, 0, 2, -1, 0pt, 0pt)',
|
||||
/* rotate(180deg) skewX(atan(-2)) */
|
||||
expected: c('rotate(45deg) matrix(1, 0, ' + Math.tan(Math.atan(-2) * 0.25) + ', 1, 0px, 0px)'),
|
||||
expected: c('rotate(45deg) matrix(1, 0, ' + -2 * 0.25 + ', 1, 0px, 0px)'),
|
||||
round_error_ok: true },
|
||||
{ start: 'none',
|
||||
end: 'matrix(0, -1, 1, -3, 0pt, 0pt)',
|
||||
/* rotate(-90deg) skewX(atan(3)) */
|
||||
expected: c('rotate(-22.5deg) matrix(1, 0, ' + Math.tan(Math.atan(3) * 0.25) + ', 1, 0px, 0px)'),
|
||||
expected: c('rotate(-22.5deg) matrix(1, 0, ' + 3 * 0.25 + ', 1, 0px, 0px)'),
|
||||
round_error_ok: true },
|
||||
{ start: 'none',
|
||||
end: 'matrix(0, 1, -1, 4, 0pt, 0pt)',
|
||||
/* rotate(90deg) skewX(atan(4)) */
|
||||
expected: c('rotate(22.5deg) matrix(1, 0, ' + Math.tan(Math.atan(4) * 0.25) + ', 1, 0px, 0px)'),
|
||||
expected: c('rotate(22.5deg) matrix(1, 0, ' + 4 * 0.25 + ', 1, 0px, 0px)'),
|
||||
round_error_ok: true },
|
||||
// and then four with negative determinants
|
||||
{ start: 'none',
|
||||
end: 'matrix(1, 0, 1, -1, 0pt, 0pt)',
|
||||
/* rotate(-180deg) skewX(atan(-1)) scaleX(-1) */
|
||||
expected: c('rotate(-45deg) matrix(1, 0, ' + Math.tan(Math.atan(-1) * 0.25) + ', 1, 0px, 0px) scaleX(0.5)'),
|
||||
expected: c('rotate(-45deg) matrix(1, 0, ' + -1 * 0.25 + ', 1, 0px, 0px) scaleX(0.5)'),
|
||||
round_error_ok: true },
|
||||
{ start: 'none',
|
||||
end: 'matrix(-1, 0, -1, 1, 0pt, 0pt)',
|
||||
/* skewX(atan(-1)) scaleX(-1) */
|
||||
expected: c('matrix(1, 0, ' + Math.tan(Math.atan(-1) * 0.25) + ', 1, 0px, 0px) scaleX(0.5)') },
|
||||
expected: c('matrix(1, 0, ' + -1 * 0.25 + ', 1, 0px, 0px) scaleX(0.5)') },
|
||||
{ start: 'none',
|
||||
end: 'matrix(0, 1, 1, -2, 0pt, 0pt)',
|
||||
/* rotate(-90deg) skewX(atan(2)) scaleX(-1) */
|
||||
expected: c('rotate(-22.5deg) matrix(1, 0, ' + Math.tan(Math.atan(2) * 0.25) + ', 1, 0px, 0px) scaleX(0.5)'),
|
||||
expected: c('rotate(-22.5deg) matrix(1, 0, ' + 2 * 0.25 + ', 1, 0px, 0px) scaleX(0.5)'),
|
||||
round_error_ok: true },
|
||||
{ start: 'none',
|
||||
end: 'matrix(0, -1, -1, 0.5, 0pt, 0pt)',
|
||||
/* rotate(90deg) skewX(atan(0.5)) scaleX(-1) */
|
||||
expected: c('rotate(22.5deg) matrix(1, 0, ' + Math.tan(Math.atan(0.5) * 0.25) + ', 1, 0px, 0px) scaleX(0.5)'),
|
||||
expected: c('rotate(22.5deg) matrix(1, 0, ' + 0.5 * 0.25 + ', 1, 0px, 0px) scaleX(0.5)'),
|
||||
round_error_ok: true },
|
||||
|
||||
// lists vs. matrix decomposition
|
||||
|
@ -1540,14 +1543,14 @@ function test_transform_transition(prop) {
|
|||
expected_uncomputed: 'skewY(22.5deg) rotate(90deg)' },
|
||||
{ start: 'skewY(45deg) rotate(90deg) translate(0)',
|
||||
end: 'skewY(-45deg) rotate(90deg)',
|
||||
expected: c('rotate(90deg) skewX(-22.5deg)'),
|
||||
expected: 'matrix(0, 1, -1, -0.5, 0px, 0px)',
|
||||
round_error_ok: true },
|
||||
{ start: 'skewX(45deg) rotate(90deg)',
|
||||
end: 'skewX(-45deg) rotate(90deg)',
|
||||
expected_uncomputed: 'skewX(22.5deg) rotate(90deg)' },
|
||||
{ start: 'skewX(-60deg) rotate(90deg) translate(0)',
|
||||
end: 'skewX(60deg) rotate(90deg)',
|
||||
expected: c('rotate(120deg) skewX(30deg) scale(2, 0.5)'),
|
||||
expected: c('rotate(120deg) skewX(' + Math.atan(Math.tan(Math.PI * 60/180) / 2) + 'rad) scale(2, 0.5)'),
|
||||
round_error_ok: true },
|
||||
];
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
== not-full-grid-pack-align.xul not-full-basic-ref.xhtml
|
||||
== not-full-row-group-align.xul not-full-row-group-align-ref.xhtml # does anyone want/need this behavior?
|
||||
== not-full-row-group-pack.xul not-full-row-group-pack-ref.xhtml
|
||||
== not-full-row-group-direction.xul not-full-row-group-direction-ref.xhtml
|
||||
fails-if(Android&&layersOpenGL) == not-full-row-group-direction.xul not-full-row-group-direction-ref.xhtml
|
||||
== not-full-row-leaf-align.xul not-full-basic-ref.xhtml
|
||||
== not-full-row-leaf-pack.xul not-full-row-leaf-pack-ref.xhtml
|
||||
== not-full-row-leaf-direction.xul not-full-row-leaf-pack-ref.xhtml
|
||||
|
|
|
@ -678,3 +678,7 @@ pref("browser.firstrun.show.localepicker", true);
|
|||
// $ adb shell setprop log.redirect-stdio true
|
||||
// $ adb shell start
|
||||
pref("browser.dom.window.dump.enabled", false);
|
||||
|
||||
// controls if we want camera support
|
||||
pref("device.camera.enabled", true);
|
||||
pref("media.realtime_decoder.enabled", true);
|
||||
|
|
|
@ -73,65 +73,6 @@ var BookmarkHelper = {
|
|||
this.box.hidden = true;
|
||||
},
|
||||
|
||||
createShortcut: function BH_createShortcut(aTitle, aURL, aIconURL) {
|
||||
// The background images are 72px, but Android will resize as needed.
|
||||
// Bigger is better than too small.
|
||||
const kIconSize = 72;
|
||||
const kOverlaySize = 32;
|
||||
const kOffset = 20;
|
||||
|
||||
// We have to fallback to something
|
||||
aTitle = aTitle || aURL;
|
||||
|
||||
let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
canvas.setAttribute("style", "display: none");
|
||||
|
||||
function _createShortcut() {
|
||||
let icon = canvas.toDataURL("image/png", "");
|
||||
canvas = null;
|
||||
try {
|
||||
let shell = Cc["@mozilla.org/browser/shell-service;1"].createInstance(Ci.nsIShellService);
|
||||
shell.createShortcut(aTitle, aURL, icon, "bookmark");
|
||||
} catch(e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Load the main background image first
|
||||
let image = new Image();
|
||||
image.onload = function() {
|
||||
canvas.width = canvas.height = kIconSize;
|
||||
let ctx = canvas.getContext("2d");
|
||||
ctx.drawImage(image, 0, 0, kIconSize, kIconSize);
|
||||
|
||||
// If we have a favicon, lets draw it next
|
||||
if (aIconURL) {
|
||||
let favicon = new Image();
|
||||
favicon.onload = function() {
|
||||
// Center the favicon and overlay it on the background
|
||||
ctx.drawImage(favicon, kOffset, kOffset, kOverlaySize, kOverlaySize);
|
||||
_createShortcut();
|
||||
}
|
||||
|
||||
favicon.onerror = function() {
|
||||
Cu.reportError("CreateShortcut: favicon image load error");
|
||||
}
|
||||
|
||||
favicon.src = aIconURL;
|
||||
} else {
|
||||
_createShortcut();
|
||||
}
|
||||
}
|
||||
|
||||
image.onerror = function() {
|
||||
Cu.reportError("CreateShortcut: background image load error");
|
||||
}
|
||||
|
||||
// Pick the right background
|
||||
image.src = aIconURL ? "chrome://browser/skin/images/homescreen-blank-hdpi.png"
|
||||
: "chrome://browser/skin/images/homescreen-default-hdpi.png";
|
||||
},
|
||||
|
||||
removeBookmarksForURI: function BH_removeBookmarksForURI(aURI) {
|
||||
//XXX blargle xpconnect! might not matter, but a method on
|
||||
// nsINavBookmarksService that takes an array of items to
|
||||
|
|
|
@ -47,6 +47,6 @@ var BookmarkPopup = {
|
|||
this.hide();
|
||||
|
||||
let browser = getBrowser();
|
||||
BookmarkHelper.createShortcut(browser.contentTitle, browser.currentURI.spec, browser.mIconURL);
|
||||
Util.createShortcut(browser.contentTitle, browser.currentURI.spec, browser.mIconURL, "bookmark");
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,174 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Fabrice Desré <fabrice@mozilla.com>, Original author
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
var CaptureDialog = {
|
||||
_video: null,
|
||||
_container: null,
|
||||
_lastOrientationEvent: null,
|
||||
|
||||
init: function() {
|
||||
document.getElementsByAttribute('command', 'cmd_ok')[0].focus();
|
||||
this._video = document.getElementById("capturepicker-video");
|
||||
this._container = document.getElementById("capturepicker-container");
|
||||
window.addEventListener("resize", this, false);
|
||||
window.addEventListener("deviceorientation", this, false);
|
||||
this.handleEvent({ type: "resize" });
|
||||
},
|
||||
|
||||
setPreviewOrientation: function(aEvent) {
|
||||
if (window.innerWidth < window.innerHeight) {
|
||||
if (aEvent.beta > 0)
|
||||
this._video.style.MozTransform = "rotate(90deg)";
|
||||
else
|
||||
this._video.style.MozTransform = "rotate(-90deg)";
|
||||
this._container.classList.add("vertical");
|
||||
}
|
||||
else {
|
||||
if (aEvent.gamma > 0)
|
||||
this._video.style.MozTransform = "rotate(180deg)";
|
||||
else
|
||||
this._video.style.MozTransform = "";
|
||||
this._container.classList.remove("vertical");
|
||||
}
|
||||
},
|
||||
|
||||
handleEvent: function(aEvent) {
|
||||
if (aEvent.type == "deviceorientation") {
|
||||
if (!this._lastOrientationEvent)
|
||||
this.setPreviewOrientation(aEvent);
|
||||
this._lastOrientationEvent = aEvent;
|
||||
}
|
||||
else if (aEvent.type == "resize") {
|
||||
if (this._lastOrientationEvent)
|
||||
this.setPreviewOrientation(this._lastOrientationEvent);
|
||||
}
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
this.doClose(false);
|
||||
},
|
||||
|
||||
capture: function() {
|
||||
this.doClose(true);
|
||||
},
|
||||
|
||||
doClose: function(aResult) {
|
||||
window.removeEventListener("resize", this, false);
|
||||
window.removeEventListener("deviceorientation", this, false);
|
||||
let dialog = document.getElementById("capturepicker-dialog");
|
||||
dialog.arguments.result = aResult;
|
||||
if (aResult)
|
||||
dialog.arguments.path = this.saveFrame();
|
||||
document.getElementById("capturepicker-video").setAttribute("src", "");
|
||||
dialog.close();
|
||||
},
|
||||
|
||||
saveFrame: function() {
|
||||
let Cc = Components.classes;
|
||||
let Ci = Components.interfaces;
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
let width = 320;
|
||||
let height = 240;
|
||||
let rotation = 0;
|
||||
|
||||
if (window.innerWidth < window.innerHeight) {
|
||||
width = 240;
|
||||
height = 320;
|
||||
if (this._lastOrientationEvent.beta > 0)
|
||||
rotation = Math.PI / 2;
|
||||
else
|
||||
rotation = -Math.PI / 2;
|
||||
}
|
||||
else {
|
||||
if (this._lastOrientationEvent.gamma > 0)
|
||||
rotation = Math.PI;
|
||||
}
|
||||
|
||||
let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
let ctx = canvas.getContext("2d");
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
//ctx.save();
|
||||
if (rotation != 0) {
|
||||
if (rotation == Math.PI / 2)
|
||||
ctx.translate(width, 0);
|
||||
else if (rotation == -Math.PI / 2)
|
||||
ctx.translate(-width, 0);
|
||||
else
|
||||
ctx.translate(width, height);
|
||||
ctx.rotate(rotation);
|
||||
}
|
||||
ctx.drawImage(document.getElementById("capturepicker-video"), 0, 0, 320, 240);
|
||||
//ctx.restore();
|
||||
let url = canvas.toDataURL("image/png");
|
||||
|
||||
let tmpDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
|
||||
let file = tmpDir.clone();
|
||||
file.append("capture.png");
|
||||
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0600);
|
||||
let persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"].createInstance(Ci.nsIWebBrowserPersist);
|
||||
|
||||
persist.persistFlags = Ci.nsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES | Ci.nsIWebBrowserPersist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
|
||||
|
||||
let mDone = false;
|
||||
let mFailed = false;
|
||||
|
||||
let progressListener = {
|
||||
onProgressChange: function() {
|
||||
/* Ignore progress callback */
|
||||
},
|
||||
onStateChange: function(aProgress, aRequest, aStateFlag, aStatus) {
|
||||
if (aStateFlag & Ci.nsIWebProgressListener.STATE_STOP) {
|
||||
mDone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
persist.progressListener = progressListener;
|
||||
|
||||
let source = Services.io.newURI(url, "UTF8", null);;
|
||||
persist.saveURI(source, null, null, null, null, file);
|
||||
|
||||
// don't wait more than 3 seconds for a successful save
|
||||
window.setTimeout(function() {
|
||||
mDone = true;
|
||||
mFailed = true;
|
||||
}, 3000);
|
||||
|
||||
while (!mDone)
|
||||
Services.tm.currentThread.processNextEvent(true);
|
||||
|
||||
return (mFailed ? null : file.path);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE dialog SYSTEM "chrome://browser/locale/prompt.dtd">
|
||||
<dialog id="capturepicker-dialog"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="document.getElementById('capturepicker-dialog').CaptureDialog.init()"
|
||||
script="chrome://browser/content/CaptureDialog.js">
|
||||
|
||||
<keyset>
|
||||
<key keycode="VK_RETURN" command="cmd_ok"/>
|
||||
<key keycode="VK_ESCAPE" command="cmd_cancel"/>
|
||||
</keyset>
|
||||
|
||||
<commandset>
|
||||
<command id="cmd_ok" oncommand="document.getElementById('capturepicker-dialog').CaptureDialog.capture();"/>
|
||||
<command id="cmd_cancel" oncommand="document.getElementById('capturepicker-dialog').CaptureDialog.cancel();"/>
|
||||
</commandset>
|
||||
|
||||
<vbox class="prompt-header" flex="1">
|
||||
<description id="capturepicker-title" class="prompt-title" crop="center" flex="1"/>
|
||||
<separator id="capturepicker-separator" class="prompt-line"/>
|
||||
<hbox flex="1" pack="center">
|
||||
<vbox id="capturepicker-container" pack="center">
|
||||
<video xmlns="http://www.w3.org/1999/xhtml" id="capturepicker-video"
|
||||
width="320" height="240"
|
||||
src="moz-device:?width=320&height=240&type=video/x-raw-yuv"
|
||||
autoplay="true"> </video>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<hbox id="capturepicker-buttons-box" class="prompt-buttons">
|
||||
<button class="prompt-button" label="&ok.label;" command="cmd_ok"/>
|
||||
<button class="prompt-button" label="&cancel.label;" command="cmd_cancel"/>
|
||||
</hbox>
|
||||
</dialog>
|
|
@ -0,0 +1,20 @@
|
|||
var CapturePickerUI = {
|
||||
init: function() {
|
||||
this.messageManager = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
|
||||
this.messageManager.addMessageListener("CapturePicker:Show", this);
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
switch (aMessage.name) {
|
||||
case "CapturePicker:Show":
|
||||
let params = { result: true };
|
||||
let dialog = importDialog(null, "chrome://browser/content/CaptureDialog.xul", params);
|
||||
document.getElementById("capturepicker-title").appendChild(document.createTextNode(aMessage.json.title));
|
||||
dialog.waitForClose();
|
||||
return { value: params.result, path: params.path };
|
||||
break;
|
||||
}
|
||||
// prevents warning from the script loader
|
||||
return null;
|
||||
}
|
||||
};
|
|
@ -129,6 +129,6 @@ var ContextCommands = {
|
|||
|
||||
shortcutBookmark: function cc_shortcutBookmark() {
|
||||
let target = ContextHelper.popupState.target;
|
||||
BookmarkHelper.createShortcut(target.getAttribute("title"), target.getAttribute("uri"), target.getAttribute("src"));
|
||||
Util.createShortcut(target.getAttribute("title"), target.getAttribute("uri"), target.getAttribute("src"), "bookmark");
|
||||
}
|
||||
};
|
||||
|
|
|
@ -214,7 +214,66 @@ let Util = {
|
|||
// determine browser dir first to know which direction to snap to
|
||||
let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry);
|
||||
return chromeReg.isLocaleRTL("global") ? this.LOCALE_DIR_RTL : this.LOCALE_DIR_LTR;
|
||||
}
|
||||
},
|
||||
|
||||
createShortcut: function Util_createShortcut(aTitle, aURL, aIconURL, aType) {
|
||||
// The background images are 72px, but Android will resize as needed.
|
||||
// Bigger is better than too small.
|
||||
const kIconSize = 72;
|
||||
const kOverlaySize = 32;
|
||||
const kOffset = 20;
|
||||
|
||||
// We have to fallback to something
|
||||
aTitle = aTitle || aURL;
|
||||
|
||||
let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
canvas.setAttribute("style", "display: none");
|
||||
|
||||
function _createShortcut() {
|
||||
let icon = canvas.toDataURL("image/png", "");
|
||||
canvas = null;
|
||||
try {
|
||||
let shell = Cc["@mozilla.org/browser/shell-service;1"].createInstance(Ci.nsIShellService);
|
||||
shell.createShortcut(aTitle, aURL, icon, aType);
|
||||
} catch(e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Load the main background image first
|
||||
let image = new Image();
|
||||
image.onload = function() {
|
||||
canvas.width = canvas.height = kIconSize;
|
||||
let ctx = canvas.getContext("2d");
|
||||
ctx.drawImage(image, 0, 0, kIconSize, kIconSize);
|
||||
|
||||
// If we have a favicon, lets draw it next
|
||||
if (aIconURL) {
|
||||
let favicon = new Image();
|
||||
favicon.onload = function() {
|
||||
// Center the favicon and overlay it on the background
|
||||
ctx.drawImage(favicon, kOffset, kOffset, kOverlaySize, kOverlaySize);
|
||||
_createShortcut();
|
||||
}
|
||||
|
||||
favicon.onerror = function() {
|
||||
Cu.reportError("CreateShortcut: favicon image load error");
|
||||
}
|
||||
|
||||
favicon.src = aIconURL;
|
||||
} else {
|
||||
_createShortcut();
|
||||
}
|
||||
}
|
||||
|
||||
image.onerror = function() {
|
||||
Cu.reportError("CreateShortcut: background image load error");
|
||||
}
|
||||
|
||||
// Pick the right background
|
||||
image.src = aIconURL ? "chrome://browser/skin/images/homescreen-blank-hdpi.png"
|
||||
: "chrome://browser/skin/images/homescreen-default-hdpi.png";
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -248,6 +248,11 @@ var WebappsUI = {
|
|||
}
|
||||
},
|
||||
|
||||
addToHome: function addToHome() {
|
||||
let uri = this._application.appURI + (this._application.manifest.launch_path ? this._application.manifest.launch_path : "");
|
||||
Util.createShortcut(this._application.title, uri, this._application.iconURI, "webapp");
|
||||
},
|
||||
|
||||
launch: function launch() {
|
||||
let title = document.getElementById("webapps-title").value;
|
||||
if (!title)
|
||||
|
@ -259,6 +264,9 @@ var WebappsUI = {
|
|||
this._updatePermission("webapps-geoloc-checkbox", "geo");
|
||||
this._updatePermission("webapps-notifications-checkbox", "desktop-notification");
|
||||
|
||||
if (document.getElementById("webapps-homescreen-checkbox").checked)
|
||||
WebappsUI.addToHome(this._application);
|
||||
|
||||
this.close();
|
||||
try {
|
||||
OpenWebapps.install(this._application);
|
||||
|
|
|
@ -118,7 +118,11 @@
|
|||
if (vertPos == 0) {
|
||||
hideArrow = true;
|
||||
} else {
|
||||
arrowbox.style.marginLeft = ((targetRect.left - popupRect.left) + (targetRect.width / 2) - HALF_ARROW_WIDTH) + "px";
|
||||
let anchorPosX = 0.5;
|
||||
// check for hasAttribute because, in some cases, anchorNode is actually a rect
|
||||
if (this.anchorNode && this.anchorNode.hasAttribute && this.anchorNode.hasAttribute("anchorPosX"))
|
||||
anchorPosX = parseFloat(this.anchorNode.getAttribute("anchorPosX")) || 0.5;
|
||||
arrowbox.style.marginLeft = ((targetRect.left - popupRect.left) + (targetRect.width * anchorPosX) - HALF_ARROW_WIDTH) + "px";
|
||||
if (vertPos == 1) {
|
||||
container.dir = "normal";
|
||||
anchorClass = "top";
|
||||
|
@ -130,7 +134,11 @@
|
|||
} else if (vertPos == 0) {
|
||||
container.orient = "";
|
||||
arrowbox.orient = "vertical";
|
||||
arrowbox.style.marginTop = ((targetRect.top - popupRect.top) + (targetRect.height / 2) - HALF_ARROW_WIDTH) + "px";
|
||||
let anchorPosY = 0.5;
|
||||
// check for hasAttribute because, in some cases, anchorNode is actually a rect
|
||||
if (this.anchorNode && this.anchorNode.hasAttribute && this.anchorNode.hasAttribute("anchorPosY"))
|
||||
anchorPosY = parseFloat(this.anchorNode.getAttribute("anchorPosY")) || 0.5;
|
||||
arrowbox.style.marginTop = ((targetRect.top - popupRect.top) + (targetRect.height * anchorPosY) - HALF_ARROW_WIDTH) + "px";
|
||||
if (horizPos == 1) {
|
||||
container.dir = "ltr";
|
||||
anchorClass = "left";
|
||||
|
|
|
@ -114,7 +114,8 @@ XPCOMUtils.defineLazyGetter(this, "CommonUI", function() {
|
|||
["WeaveGlue", "chrome://browser/content/sync.js"],
|
||||
#endif
|
||||
["WebappsUI", "chrome://browser/content/WebappsUI.js"],
|
||||
["SSLExceptions", "chrome://browser/content/exceptions.js"]
|
||||
["SSLExceptions", "chrome://browser/content/exceptions.js"],
|
||||
["CapturePickerUI", "chrome://browser/content/CapturePickerUI.js"]
|
||||
].forEach(function (aScript) {
|
||||
let [name, script] = aScript;
|
||||
XPCOMUtils.defineLazyGetter(window, name, function() {
|
||||
|
|
|
@ -491,6 +491,7 @@ var BrowserUI = {
|
|||
FullScreenVideo.init();
|
||||
NewTabPopup.init();
|
||||
WebappsUI.init();
|
||||
CapturePickerUI.init();
|
||||
|
||||
// If some add-ons were disabled during during an application update, alert user
|
||||
let addonIDs = AddonManager.getStartupChanges("disabled");
|
||||
|
|
|
@ -221,7 +221,7 @@
|
|||
<box id="toolbar-container" class="panel-dark toolbar-height">
|
||||
<box id="toolbar-moveable-container" observes="bcast_uidiscovery">
|
||||
<toolbar id="toolbar-main" class="panel-dark viewable-width" observes="bcast_urlbarState">
|
||||
<toolbarbutton id="tool-tabs" class="button-actionbar" command="cmd_showTabs"/>
|
||||
<toolbarbutton id="tool-tabs" class="button-actionbar" command="cmd_showTabs" anchorPosX="0.3"/>
|
||||
<toolbarbutton id="tool-back2" class="tool-back button-actionbar" command="cmd_back"/>
|
||||
<toolbarbutton id="tool-forward2" class="tool-forward button-actionbar" command="cmd_forward"/>
|
||||
#ifdef MOZ_PLATFORM_MAEMO
|
||||
|
@ -767,7 +767,7 @@
|
|||
<svg:svg height="0">
|
||||
<svg:mask id="back-button-mask" maskContentUnits="objectBoundingBox">
|
||||
<svg:rect x="0" y="0" width="1" height="1" fill="white"/>
|
||||
<svg:circle cx="-0.5" cy="0.5" r="0.7"/>
|
||||
<svg:circle cx="-0.85" cy="0.5" r="0.96"/>
|
||||
</svg:mask>
|
||||
</svg:svg>
|
||||
|
||||
|
|
|
@ -201,6 +201,9 @@ var NewTabPopup = {
|
|||
},
|
||||
|
||||
show: function nt_show(aTab) {
|
||||
if (Util.isTablet() && TabsPopup.visible)
|
||||
return;
|
||||
|
||||
BrowserUI.pushPopup(this, this.box);
|
||||
|
||||
this._tabs.push(aTab);
|
||||
|
@ -219,7 +222,10 @@ var NewTabPopup = {
|
|||
// being anchored to might be overflowing the tabs
|
||||
// scrollbox which confuses the dynamic arrow direction
|
||||
// calculation (see bug 662520).
|
||||
if (Elements.tabList.getBoundingClientRect().left < 0)
|
||||
if (Util.isTablet()) {
|
||||
let toolbarbutton = document.getElementById("tool-tabs");
|
||||
this.box.anchorTo(toolbarbutton, "after_start");
|
||||
} else if (Elements.tabList.getBoundingClientRect().left < 0)
|
||||
this.box.pointLeftAt(aTab);
|
||||
else
|
||||
this.box.pointRightAt(aTab);
|
||||
|
|
|
@ -85,6 +85,10 @@
|
|||
</vbox>
|
||||
</button>
|
||||
</scrollbox>
|
||||
<button id="webapps-homescreen-checkbox" type="checkbox" class="button-checkbox" flex="1">
|
||||
<image class="button-image-icon"/>
|
||||
<description class="prompt-checkbox-label" flex="1">&webapps.add-homescreen;</description>
|
||||
</button>
|
||||
<hbox pack="center" class="prompt-buttons">
|
||||
<button class="prompt-button" command="cmd_ok" label="&ok.label;"/>
|
||||
<separator/>
|
||||
|
|
|
@ -80,6 +80,9 @@ chrome.jar:
|
|||
content/fullscreen-video.js (content/fullscreen-video.js)
|
||||
content/fullscreen-video.xhtml (content/fullscreen-video.xhtml)
|
||||
content/netError.xhtml (content/netError.xhtml)
|
||||
|
||||
content/CapturePickerUI.js (content/CapturePickerUI.js)
|
||||
content/CaptureDialog.js (content/CaptureDialog.js)
|
||||
content/CaptureDialog.xul (content/CaptureDialog.xul)
|
||||
|
||||
% override chrome://global/content/config.xul chrome://browser/content/config.xul
|
||||
% override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче