merge the last green changeset on fx-team to m-c

This commit is contained in:
Tim Taubert 2011-09-27 13:21:17 +02:00
Родитель 0b91f2c432 975a20d00c
Коммит 22a09be64a
137 изменённых файлов: 3464 добавлений и 1125 удалений

Просмотреть файл

@ -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__ */

89
js/src/vm/NumberObject.h Normal file
Просмотреть файл

@ -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&amp;height=240&amp;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

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше