mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge inbound to central, a=merge
This commit is contained in:
commit
4a23e18b0a
@ -410,6 +410,8 @@
|
||||
@RESPATH@/components/AlarmsManager.manifest
|
||||
@RESPATH@/components/FeedProcessor.manifest
|
||||
@RESPATH@/components/FeedProcessor.js
|
||||
@RESPATH@/components/PackagedAppUtils.manifest
|
||||
@RESPATH@/components/PackagedAppUtils.js
|
||||
@RESPATH@/components/BrowserFeeds.manifest
|
||||
@RESPATH@/components/FeedConverter.js
|
||||
@RESPATH@/components/FeedWriter.js
|
||||
|
@ -369,6 +369,8 @@
|
||||
@RESPATH@/components/BrowserElementParent.js
|
||||
@RESPATH@/components/FeedProcessor.manifest
|
||||
@RESPATH@/components/FeedProcessor.js
|
||||
@RESPATH@/components/PackagedAppUtils.js
|
||||
@RESPATH@/components/PackagedAppUtils.manifest
|
||||
@RESPATH@/browser/components/BrowserFeeds.manifest
|
||||
@RESPATH@/browser/components/FeedConverter.js
|
||||
@RESPATH@/browser/components/FeedWriter.js
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/RefCounted.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
@ -942,6 +942,7 @@ NS_INTERFACE_MAP_BEGIN(nsDocShell)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIClipboardCommands)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMStorageManager)
|
||||
NS_INTERFACE_MAP_ENTRY(nsINetworkInterceptController)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDeprecationWarner)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDocLoader)
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -14060,3 +14061,13 @@ nsDocShell::InFrameSwap()
|
||||
} while (shell);
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::IssueWarning(uint32_t aWarning, bool aAsError)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc = mContentViewer->GetDocument();
|
||||
if (doc) {
|
||||
doc->WarnOnceAbout(nsIDocument::DeprecatedOperations(aWarning), aAsError);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -58,6 +58,7 @@
|
||||
#include "prtime.h"
|
||||
#include "nsRect.h"
|
||||
#include "Units.h"
|
||||
#include "nsIDeprecationWarner.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -145,6 +146,7 @@ class nsDocShell final
|
||||
, public nsIClipboardCommands
|
||||
, public nsIDOMStorageManager
|
||||
, public nsINetworkInterceptController
|
||||
, public nsIDeprecationWarner
|
||||
, public mozilla::SupportsWeakPtr<nsDocShell>
|
||||
{
|
||||
friend class nsDSURIContentListener;
|
||||
@ -176,6 +178,7 @@ public:
|
||||
NS_DECL_NSICLIPBOARDCOMMANDS
|
||||
NS_DECL_NSIWEBSHELLSERVICES
|
||||
NS_DECL_NSINETWORKINTERCEPTCONTROLLER
|
||||
NS_DECL_NSIDEPRECATIONWARNER
|
||||
NS_FORWARD_SAFE_NSIDOMSTORAGEMANAGER(TopSessionStorageManager())
|
||||
|
||||
NS_IMETHOD Stop() override
|
||||
|
@ -252,6 +252,18 @@ this.AlarmService = {
|
||||
debug("_onAlarmFired()");
|
||||
|
||||
if (this._currentAlarm) {
|
||||
let currentAlarmTime = this._getAlarmTime(this._currentAlarm);
|
||||
|
||||
// If a alarm fired before the actual time that the current
|
||||
// alarm should occur, we reset this current alarm.
|
||||
if (currentAlarmTime > Date.now()) {
|
||||
let currentAlarm = this._currentAlarm;
|
||||
this._currentAlarm = currentAlarm;
|
||||
|
||||
this._debugCurrentAlarm();
|
||||
return;
|
||||
}
|
||||
|
||||
this._removeAlarmFromDb(this._currentAlarm.id, null);
|
||||
this._notifyAlarmObserver(this._currentAlarm);
|
||||
this._currentAlarm = null;
|
||||
@ -414,6 +426,16 @@ this.AlarmService = {
|
||||
// the non-serializable callback to the in-memory object.
|
||||
aNewAlarm['alarmFiredCb'] = aAlarmFiredCb;
|
||||
|
||||
// If the new alarm already expired at this moment, we directly
|
||||
// notify this alarm
|
||||
let aNewAlarmTime = this._getAlarmTime(aNewAlarm);
|
||||
if (aNewAlarmTime < Date.now()) {
|
||||
aSuccessCb(aNewId);
|
||||
this._removeAlarmFromDb(aNewAlarm.id, null);
|
||||
this._notifyAlarmObserver(aNewAlarm);
|
||||
return;
|
||||
}
|
||||
|
||||
// If there is no alarm being set in system, set the new alarm.
|
||||
if (this._currentAlarm == null) {
|
||||
this._currentAlarm = aNewAlarm;
|
||||
@ -425,7 +447,6 @@ this.AlarmService = {
|
||||
// If the new alarm is earlier than the current alarm, swap them and
|
||||
// push the previous alarm back to the queue.
|
||||
let alarmQueue = this._alarmQueue;
|
||||
let aNewAlarmTime = this._getAlarmTime(aNewAlarm);
|
||||
let currentAlarmTime = this._getAlarmTime(this._currentAlarm);
|
||||
if (aNewAlarmTime < currentAlarmTime) {
|
||||
alarmQueue.unshift(this._currentAlarm);
|
||||
|
@ -16,6 +16,7 @@ const APP_TRUSTED_ROOTS= ["AppMarketplaceProdPublicRoot",
|
||||
"AppMarketplaceDevPublicRoot",
|
||||
"AppMarketplaceDevReviewersRoot",
|
||||
"AppMarketplaceStageRoot",
|
||||
"PrivilegedPackageRoot",
|
||||
"AppXPCShellRoot"];
|
||||
|
||||
this.TrustedRootCertificate = {
|
||||
|
@ -41,3 +41,4 @@ DEPRECATED_OPERATION(DataContainerEvent)
|
||||
DEPRECATED_OPERATION(Window_Controllers)
|
||||
DEPRECATED_OPERATION(ImportXULIntoContent)
|
||||
DEPRECATED_OPERATION(PannerNodeDoppler)
|
||||
DEPRECATED_OPERATION(AppCache)
|
||||
|
@ -158,8 +158,10 @@ IndexedDBTransactionAbortNavigation=An IndexedDB transaction that was not yet co
|
||||
IgnoringWillChangeOverBudgetWarning=Will-change memory consumption is too high. Budget limit is the document surface area multiplied by %1$S (%2$S px). Occurrences of will-change over the budget will be ignored.
|
||||
# LOCALIZATION NOTE: Do not translate "ServiceWorker".
|
||||
HittingMaxWorkersPerDomain=A ServiceWorker could not be started immediately because other documents in the same origin are already using the maximum number of workers. The ServiceWorker is now queued and will be started after some of the other workers have completed.
|
||||
# LOCALIZATION NOTE: Do no translate "setVelocity", "PannerNode", "AudioListener", "speedOfSound" and "dopplerFactor"
|
||||
# LOCALIZATION NOTE: Do not translate "setVelocity", "PannerNode", "AudioListener", "speedOfSound" and "dopplerFactor"
|
||||
PannerNodeDopplerWarning=Use of setVelocity on the PannerNode and AudioListener, and speedOfSound and dopplerFactor on the AudioListener are deprecated and those members will be removed. For more help https://developer.mozilla.org/en-US/docs/Web/API/AudioListener#Deprecated_features
|
||||
# LOCALIZATION NOTE: Do not translate "Application Cache API", "AppCache" and "ServiceWorker".
|
||||
AppCacheWarning=The Application Cache API (AppCache) is deprecated and will be removed at a future date. Please consider using ServiceWorker for offline support.
|
||||
# LOCALIZATION NOTE: Do not translate "Worker".
|
||||
EmptyWorkerSourceWarning=Attempting to create a Worker from an empty source. This is probably unintentional.
|
||||
# LOCALIZATION NOTE: Do not translate "ServiceWorker".
|
||||
|
@ -930,8 +930,10 @@ MediaDecoderStateMachine::OnVideoDecoded(MediaData* aVideoSample)
|
||||
// in this case, we'll just decode forward. Bug 1026330.
|
||||
mCurrentSeek.mTarget.mType = SeekTarget::Accurate;
|
||||
}
|
||||
if (mCurrentSeek.mTarget.mType == SeekTarget::PrevSyncPoint) {
|
||||
// Non-precise seek; we can stop the seek at the first sample.
|
||||
if (mCurrentSeek.mTarget.mType == SeekTarget::PrevSyncPoint ||
|
||||
mPendingSeek.Exists()) {
|
||||
// Non-precise seek; or a pending seek exists ; we can stop the seek
|
||||
// at the first sample.
|
||||
Push(video, MediaData::VIDEO_DATA);
|
||||
} else {
|
||||
// We're doing an accurate seek. We still need to discard
|
||||
@ -2728,19 +2730,19 @@ MediaDecoderStateMachine::DropAudioUpToSeekTarget(MediaData* aSample)
|
||||
mCurrentSeek.Exists() &&
|
||||
mCurrentSeek.mTarget.mType == SeekTarget::Accurate);
|
||||
|
||||
CheckedInt64 startFrame = UsecsToFrames(audio->mTime,
|
||||
mInfo.mAudio.mRate);
|
||||
CheckedInt64 targetFrame = UsecsToFrames(mCurrentSeek.mTarget.mTime,
|
||||
mInfo.mAudio.mRate);
|
||||
if (!startFrame.isValid() || !targetFrame.isValid()) {
|
||||
CheckedInt64 sampleDuration =
|
||||
FramesToUsecs(audio->mFrames, mInfo.mAudio.mRate);
|
||||
if (!sampleDuration.isValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (startFrame.value() + audio->mFrames <= targetFrame.value()) {
|
||||
|
||||
if (audio->mTime + sampleDuration.value() <= mCurrentSeek.mTarget.mTime) {
|
||||
// Our seek target lies after the frames in this AudioData. Don't
|
||||
// push it onto the audio queue, and keep decoding forwards.
|
||||
return NS_OK;
|
||||
}
|
||||
if (startFrame.value() > targetFrame.value()) {
|
||||
|
||||
if (audio->mTime > mCurrentSeek.mTarget.mTime) {
|
||||
// The seek target doesn't lie in the audio block just after the last
|
||||
// audio frames we've seen which were before the seek target. This
|
||||
// could have been the first audio data we've seen after seek, i.e. the
|
||||
@ -2756,23 +2758,27 @@ MediaDecoderStateMachine::DropAudioUpToSeekTarget(MediaData* aSample)
|
||||
// The seek target lies somewhere in this AudioData's frames, strip off
|
||||
// any frames which lie before the seek target, so we'll begin playback
|
||||
// exactly at the seek target.
|
||||
NS_ASSERTION(targetFrame.value() >= startFrame.value(),
|
||||
NS_ASSERTION(mCurrentSeek.mTarget.mTime >= audio->mTime,
|
||||
"Target must at or be after data start.");
|
||||
NS_ASSERTION(targetFrame.value() < startFrame.value() + audio->mFrames,
|
||||
NS_ASSERTION(mCurrentSeek.mTarget.mTime < audio->mTime + sampleDuration.value(),
|
||||
"Data must end after target.");
|
||||
|
||||
int64_t framesToPrune = targetFrame.value() - startFrame.value();
|
||||
if (framesToPrune > audio->mFrames) {
|
||||
CheckedInt64 framesToPrune =
|
||||
UsecsToFrames(mCurrentSeek.mTarget.mTime - audio->mTime, mInfo.mAudio.mRate);
|
||||
if (!framesToPrune.isValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (framesToPrune.value() > audio->mFrames) {
|
||||
// We've messed up somehow. Don't try to trim frames, the |frames|
|
||||
// variable below will overflow.
|
||||
DECODER_WARN("Can't prune more frames that we have!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
uint32_t frames = audio->mFrames - static_cast<uint32_t>(framesToPrune);
|
||||
uint32_t frames = audio->mFrames - static_cast<uint32_t>(framesToPrune.value());
|
||||
uint32_t channels = audio->mChannels;
|
||||
nsAutoArrayPtr<AudioDataValue> audioData(new AudioDataValue[frames * channels]);
|
||||
memcpy(audioData.get(),
|
||||
audio->mAudioData.get() + (framesToPrune * channels),
|
||||
audio->mAudioData.get() + (framesToPrune.value() * channels),
|
||||
frames * channels * sizeof(AudioDataValue));
|
||||
CheckedInt64 duration = FramesToUsecs(frames, mInfo.mAudio.mRate);
|
||||
if (!duration.isValid()) {
|
||||
|
@ -1485,6 +1485,7 @@ MediaManager::MediaManager()
|
||||
: mMediaThread(nullptr)
|
||||
, mMutex("mozilla::MediaManager")
|
||||
, mBackend(nullptr) {
|
||||
mPrefs.mFreq = 1000; // 1KHz test tone
|
||||
mPrefs.mWidth = 0; // adaptive default
|
||||
mPrefs.mHeight = 0; // adaptive default
|
||||
mPrefs.mFPS = MediaEngine::DEFAULT_VIDEO_FPS;
|
||||
@ -1497,8 +1498,8 @@ MediaManager::MediaManager()
|
||||
GetPrefs(branch, nullptr);
|
||||
}
|
||||
}
|
||||
LOG(("%s: default prefs: %dx%d @%dfps (min %d)", __FUNCTION__,
|
||||
mPrefs.mWidth, mPrefs.mHeight, mPrefs.mFPS, mPrefs.mMinFPS));
|
||||
LOG(("%s: default prefs: %dx%d @%dfps (min %d), %dHz test tones", __FUNCTION__,
|
||||
mPrefs.mWidth, mPrefs.mHeight, mPrefs.mFPS, mPrefs.mMinFPS, mPrefs.mFreq));
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(MediaManager, nsIMediaManagerService, nsIObserver)
|
||||
@ -2512,6 +2513,7 @@ MediaManager::GetPrefs(nsIPrefBranch *aBranch, const char *aData)
|
||||
GetPref(aBranch, "media.navigator.video.default_height", aData, &mPrefs.mHeight);
|
||||
GetPref(aBranch, "media.navigator.video.default_fps", aData, &mPrefs.mFPS);
|
||||
GetPref(aBranch, "media.navigator.video.default_minfps", aData, &mPrefs.mMinFPS);
|
||||
GetPref(aBranch, "media.navigator.audio.fake_frequency", aData, &mPrefs.mFreq);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -2544,6 +2546,7 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
prefs->RemoveObserver("media.navigator.video.default_height", this);
|
||||
prefs->RemoveObserver("media.navigator.video.default_fps", this);
|
||||
prefs->RemoveObserver("media.navigator.video.default_minfps", this);
|
||||
prefs->RemoveObserver("media.navigator.audio.fake_frequency", this);
|
||||
}
|
||||
|
||||
// Close off any remaining active windows.
|
||||
|
@ -25,20 +25,29 @@ namespace mozilla {
|
||||
|
||||
using layers::PlanarYCbCrImage;
|
||||
|
||||
static inline CheckedInt64 SaferMultDiv(int64_t aValue, uint32_t aMul, uint32_t aDiv) {
|
||||
int64_t major = aValue / aDiv;
|
||||
int64_t remainder = aValue % aDiv;
|
||||
return CheckedInt64(remainder) * aMul / aDiv + major * aMul;
|
||||
}
|
||||
|
||||
// Converts from number of audio frames to microseconds, given the specified
|
||||
// audio rate.
|
||||
CheckedInt64 FramesToUsecs(int64_t aFrames, uint32_t aRate) {
|
||||
return (CheckedInt64(aFrames) * USECS_PER_S) / aRate;
|
||||
return SaferMultDiv(aFrames, USECS_PER_S, aRate);
|
||||
}
|
||||
|
||||
media::TimeUnit FramesToTimeUnit(int64_t aFrames, uint32_t aRate) {
|
||||
return (media::TimeUnit::FromMicroseconds(aFrames) * USECS_PER_S) / aRate;
|
||||
int64_t major = aFrames / aRate;
|
||||
int64_t remainder = aFrames % aRate;
|
||||
return media::TimeUnit::FromMicroseconds(major) * USECS_PER_S +
|
||||
(media::TimeUnit::FromMicroseconds(remainder) * USECS_PER_S) / aRate;
|
||||
}
|
||||
|
||||
// Converts from microseconds to number of audio frames, given the specified
|
||||
// audio rate.
|
||||
CheckedInt64 UsecsToFrames(int64_t aUsecs, uint32_t aRate) {
|
||||
return (CheckedInt64(aUsecs) * aRate) / USECS_PER_S;
|
||||
return SaferMultDiv(aUsecs, aRate, USECS_PER_S);
|
||||
}
|
||||
|
||||
// Format TimeUnit as number of frames at given rate.
|
||||
|
@ -54,6 +54,12 @@ public:
|
||||
static const int DEFAULT_169_VIDEO_HEIGHT = 720;
|
||||
static const int DEFAULT_AUDIO_TIMER_MS = 10;
|
||||
|
||||
#ifndef MOZ_B2G
|
||||
static const int DEFAULT_SAMPLE_RATE = 32000;
|
||||
#else
|
||||
static const int DEFAULT_SAMPLE_RATE = 16000;
|
||||
#endif
|
||||
|
||||
/* Populate an array of video sources in the nsTArray. Also include devices
|
||||
* that are currently unavailable. */
|
||||
virtual void EnumerateVideoDevices(dom::MediaSourceEnum,
|
||||
@ -197,6 +203,7 @@ public:
|
||||
int32_t mHeight;
|
||||
int32_t mFPS;
|
||||
int32_t mMinFPS;
|
||||
int32_t mFreq; // for test tones (fake:true)
|
||||
|
||||
// mWidth and/or mHeight may be zero (=adaptive default), so use functions.
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include "YuvStamper.h"
|
||||
#endif
|
||||
|
||||
#define AUDIO_RATE 16000
|
||||
#define AUDIO_RATE mozilla::MediaEngine::DEFAULT_SAMPLE_RATE
|
||||
#define AUDIO_FRAME_LENGTH ((AUDIO_RATE * MediaEngine::DEFAULT_AUDIO_TIMER_MS) / 1000)
|
||||
namespace mozilla {
|
||||
|
||||
@ -302,15 +302,16 @@ class SineWaveGenerator
|
||||
{
|
||||
public:
|
||||
static const int bytesPerSample = 2;
|
||||
static const int millisecondsPerSecond = 1000;
|
||||
static const int frequency = 1000;
|
||||
static const int millisecondsPerSecond = PR_MSEC_PER_SEC;
|
||||
|
||||
explicit SineWaveGenerator(int aSampleRate) :
|
||||
mTotalLength(aSampleRate / frequency),
|
||||
explicit SineWaveGenerator(uint32_t aSampleRate, uint32_t aFrequency) :
|
||||
mTotalLength(aSampleRate / aFrequency),
|
||||
mReadLength(0) {
|
||||
MOZ_ASSERT(mTotalLength * frequency == aSampleRate);
|
||||
// If we allow arbitrary frequencies, there's no guarantee we won't get rounded here
|
||||
// We could include an error term and adjust for it in generation; not worth the trouble
|
||||
//MOZ_ASSERT(mTotalLength * aFrequency == aSampleRate);
|
||||
mAudioBuffer = new int16_t[mTotalLength];
|
||||
for(int i = 0; i < mTotalLength; i++) {
|
||||
for (int i = 0; i < mTotalLength; i++) {
|
||||
// Set volume to -20db. It's from 32768.0 * 10^(-20/20) = 3276.8
|
||||
mAudioBuffer[i] = (3276.8f * sin(2 * M_PI * i / mTotalLength));
|
||||
}
|
||||
@ -397,8 +398,9 @@ MediaEngineDefaultAudioSource::Allocate(const dom::MediaTrackConstraints &aConst
|
||||
}
|
||||
|
||||
mState = kAllocated;
|
||||
// generate 1Khz sine wave
|
||||
mSineGenerator = new SineWaveGenerator(AUDIO_RATE);
|
||||
// generate sine wave (default 1KHz)
|
||||
mSineGenerator = new SineWaveGenerator(AUDIO_RATE,
|
||||
static_cast<uint32_t>(aPrefs.mFreq ? aPrefs.mFreq : 1000));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -137,6 +137,7 @@ public:
|
||||
, mChannel(-1)
|
||||
, mInitDone(false)
|
||||
, mStarted(false)
|
||||
, mSampleFrequency(MediaEngine::DEFAULT_SAMPLE_RATE)
|
||||
, mEchoOn(false), mAgcOn(false), mNoiseOn(false)
|
||||
, mEchoCancel(webrtc::kEcDefault)
|
||||
, mAGC(webrtc::kAgcDefault)
|
||||
@ -225,6 +226,7 @@ private:
|
||||
nsString mDeviceName;
|
||||
nsCString mDeviceUUID;
|
||||
|
||||
uint32_t mSampleFrequency;
|
||||
bool mEchoOn, mAgcOn, mNoiseOn;
|
||||
webrtc::EcModes mEchoCancel;
|
||||
webrtc::AgcModes mAGC;
|
||||
|
@ -19,9 +19,8 @@
|
||||
#define ENCODING "L16"
|
||||
#define DEFAULT_PORT 5555
|
||||
|
||||
#define SAMPLE_RATE 256000
|
||||
#define SAMPLE_FREQUENCY 16000
|
||||
#define SAMPLE_LENGTH ((SAMPLE_FREQUENCY*10)/1000)
|
||||
#define SAMPLE_RATE(freq) ((freq)*2*8) // bps, 16-bit samples
|
||||
#define SAMPLE_LENGTH(freq) (((freq)*10)/1000)
|
||||
|
||||
// These are restrictions from the webrtc.org code
|
||||
#define MAX_CHANNELS 2
|
||||
@ -345,7 +344,7 @@ MediaEngineWebRTCMicrophoneSource::Start(SourceMediaStream *aStream,
|
||||
}
|
||||
|
||||
AudioSegment* segment = new AudioSegment();
|
||||
aStream->AddAudioTrack(aID, SAMPLE_FREQUENCY, 0, segment, SourceMediaStream::ADDTRACK_QUEUED);
|
||||
aStream->AddAudioTrack(aID, mSampleFrequency, 0, segment, SourceMediaStream::ADDTRACK_QUEUED);
|
||||
|
||||
// XXX Make this based on the pref.
|
||||
aStream->RegisterForAudioMixing();
|
||||
@ -470,6 +469,9 @@ MediaEngineWebRTCMicrophoneSource::Init()
|
||||
return;
|
||||
}
|
||||
|
||||
mSampleFrequency = MediaEngine::DEFAULT_SAMPLE_RATE;
|
||||
LOG(("%s: sampling rate %u", __FUNCTION__, mSampleFrequency));
|
||||
|
||||
// Check for availability.
|
||||
ScopedCustomReleasePtr<webrtc::VoEHardware> ptrVoEHw(webrtc::VoEHardware::GetInterface(mVoiceEngine));
|
||||
if (!ptrVoEHw || ptrVoEHw->SetRecordingDevice(mCapIndex)) {
|
||||
@ -495,9 +497,10 @@ MediaEngineWebRTCMicrophoneSource::Init()
|
||||
webrtc::CodecInst codec;
|
||||
strcpy(codec.plname, ENCODING);
|
||||
codec.channels = CHANNELS;
|
||||
codec.rate = SAMPLE_RATE;
|
||||
codec.plfreq = SAMPLE_FREQUENCY;
|
||||
codec.pacsize = SAMPLE_LENGTH;
|
||||
MOZ_ASSERT(mSampleFrequency == 16000 || mSampleFrequency == 32000);
|
||||
codec.rate = SAMPLE_RATE(mSampleFrequency);
|
||||
codec.plfreq = mSampleFrequency;
|
||||
codec.pacsize = SAMPLE_LENGTH(mSampleFrequency);
|
||||
codec.pltype = 0; // Default payload type
|
||||
|
||||
if (!ptrVoECodec->SetSendCodec(mChannel, codec)) {
|
||||
|
@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
#include "GonkGPSGeolocationProvider.h"
|
||||
#include "mozstumbler/MozStumbler.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <hardware/gps.h>
|
||||
@ -40,6 +39,7 @@
|
||||
#include "mozilla/dom/SettingChangeNotificationBinding.h"
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
#include "mozstumbler/MozStumbler.h"
|
||||
#include "nsIIccInfo.h"
|
||||
#include "nsIMobileConnectionInfo.h"
|
||||
#include "nsIMobileConnectionService.h"
|
||||
@ -148,7 +148,9 @@ GonkGPSGeolocationProvider::LocationCallback(GpsLocation* location)
|
||||
nsRefPtr<UpdateLocationEvent> event = new UpdateLocationEvent(somewhere);
|
||||
NS_DispatchToMainThread(event);
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
MozStumble(somewhere);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -35,7 +35,6 @@ XPIDL_MODULE = 'dom_system_gonk'
|
||||
EXPORTS += [
|
||||
'GeolocationUtil.h',
|
||||
'GonkGPSGeolocationProvider.h',
|
||||
'mozstumbler/MozStumbler.h',
|
||||
'nsVolume.h',
|
||||
'nsVolumeService.h',
|
||||
]
|
||||
@ -49,10 +48,6 @@ UNIFIED_SOURCES += [
|
||||
'MozMtpDatabase.cpp',
|
||||
'MozMtpServer.cpp',
|
||||
'MozMtpStorage.cpp',
|
||||
'mozstumbler/MozStumbler.cpp',
|
||||
'mozstumbler/StumblerLogging.cpp',
|
||||
'mozstumbler/UploadStumbleRunnable.cpp',
|
||||
'mozstumbler/WriteStumbleOnThread.cpp',
|
||||
'NetIdManager.cpp',
|
||||
'NetworkUtils.cpp',
|
||||
'NetworkWorker.cpp',
|
||||
@ -93,6 +88,15 @@ EXTRA_JS_MODULES += [
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_B2G_RIL']:
|
||||
EXPORTS += [
|
||||
'mozstumbler/MozStumbler.h',
|
||||
]
|
||||
UNIFIED_SOURCES += [
|
||||
'mozstumbler/MozStumbler.cpp',
|
||||
'mozstumbler/StumblerLogging.cpp',
|
||||
'mozstumbler/UploadStumbleRunnable.cpp',
|
||||
'mozstumbler/WriteStumbleOnThread.cpp'
|
||||
]
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDataCallInterfaceService.idl',
|
||||
'nsIDataCallManager.idl',
|
||||
|
@ -3531,7 +3531,7 @@ nsHTMLEditor::SelectAll()
|
||||
nsCOMPtr<nsIDOMNode> rootElement = do_QueryInterface(rootContent, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
Maybe<mozilla::dom::Selection::AutoApplyUserSelectStyle> userSelection;
|
||||
Maybe<mozilla::dom::Selection::AutoUserInitiated> userSelection;
|
||||
if (!rootContent->IsEditable()) {
|
||||
userSelection.emplace(selection);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#define MOZILLA_GENERICREFCOUNTED_H_
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/RefCounted.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "base/message_loop.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "FrameMetrics.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
|
@ -6,6 +6,10 @@
|
||||
|
||||
#include "WheelScrollAnimation.h"
|
||||
|
||||
#include "AsyncPanZoomController.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "nsPoint.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
|
@ -13,6 +13,8 @@
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class AsyncPanZoomController;
|
||||
|
||||
class WheelScrollAnimation
|
||||
: public AsyncPanZoomAnimation,
|
||||
public AsyncScrollBase
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "TextureHost.h"
|
||||
|
||||
#include "CompositableHost.h" // for CompositableHost
|
||||
#include "LayerScope.h"
|
||||
#include "LayersLogging.h" // for AppendToString
|
||||
#include "mozilla/gfx/2D.h" // for DataSourceSurface, Factory
|
||||
#include "mozilla/ipc/Shmem.h" // for Shmem
|
||||
@ -23,6 +24,7 @@
|
||||
#include "mozilla/unused.h"
|
||||
#include <limits>
|
||||
#include "../opengl/CompositorOGL.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "gfxUtils.h"
|
||||
|
||||
#ifdef MOZ_ENABLE_D3D10_LAYER
|
||||
|
@ -178,22 +178,17 @@ CompositorChild::AllocPLayerTransactionChild(const nsTArray<LayersBackend>& aBac
|
||||
return c;
|
||||
}
|
||||
|
||||
/*static*/ PLDHashOperator
|
||||
CompositorChild::RemoveSharedMetricsForLayersId(const uint64_t& aKey,
|
||||
nsAutoPtr<SharedFrameMetricsData>& aData,
|
||||
void* aLayerTransactionChild)
|
||||
{
|
||||
uint64_t childId = static_cast<LayerTransactionChild*>(aLayerTransactionChild)->GetId();
|
||||
if (aData->GetLayersId() == childId) {
|
||||
return PLDHashOperator::PL_DHASH_REMOVE;
|
||||
}
|
||||
return PLDHashOperator::PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorChild::DeallocPLayerTransactionChild(PLayerTransactionChild* actor)
|
||||
{
|
||||
mFrameMetricsTable.Enumerate(RemoveSharedMetricsForLayersId, actor);
|
||||
uint64_t childId = static_cast<LayerTransactionChild*>(actor)->GetId();
|
||||
|
||||
for (auto iter = mFrameMetricsTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsAutoPtr<SharedFrameMetricsData>& data = iter.Data();
|
||||
if (data->GetLayersId() == childId) {
|
||||
iter.Remove();
|
||||
}
|
||||
}
|
||||
static_cast<LayerTransactionChild*>(actor)->ReleaseIPDLReference();
|
||||
return true;
|
||||
}
|
||||
|
@ -174,10 +174,6 @@ private:
|
||||
uint32_t mAPZCId;
|
||||
};
|
||||
|
||||
static PLDHashOperator RemoveSharedMetricsForLayersId(const uint64_t& aKey,
|
||||
nsAutoPtr<SharedFrameMetricsData>& aData,
|
||||
void* aLayerTransactionChild);
|
||||
|
||||
nsRefPtr<ClientLayerManager> mLayerManager;
|
||||
// When not multi-process, hold a reference to the CompositorParent to keep it
|
||||
// alive. This reference should be null in multi-process.
|
||||
|
@ -1115,22 +1115,19 @@ gfxFT2FontList::AppendFacesFromOmnijarEntry(nsZipArchive* aArchive,
|
||||
// Called on each family after all fonts are added to the list;
|
||||
// this will sort faces to give priority to "standard" font files
|
||||
// if aUserArg is non-null (i.e. we're using it as a boolean flag)
|
||||
static PLDHashOperator
|
||||
static void
|
||||
FinalizeFamilyMemberList(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamily,
|
||||
void* aUserArg)
|
||||
bool aSortFaces)
|
||||
{
|
||||
gfxFontFamily *family = aFamily.get();
|
||||
bool sortFaces = (aUserArg != nullptr);
|
||||
|
||||
family->SetHasStyles(true);
|
||||
|
||||
if (sortFaces) {
|
||||
if (aSortFaces) {
|
||||
family->SortAvailableFonts();
|
||||
}
|
||||
family->CheckForSimpleFamily();
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1157,8 +1154,17 @@ gfxFT2FontList::FindFonts()
|
||||
// Passing null for userdata tells Finalize that it does not need
|
||||
// to sort faces (because they were already sorted by chrome,
|
||||
// so we just maintain the existing order)
|
||||
mFontFamilies.Enumerate(FinalizeFamilyMemberList, nullptr);
|
||||
mHiddenFontFamilies.Enumerate(FinalizeFamilyMemberList, nullptr);
|
||||
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsStringHashKey::KeyType key = iter.Key();
|
||||
nsRefPtr<gfxFontFamily>& family = iter.Data();
|
||||
FinalizeFamilyMemberList(key, family, /* aSortFaces */ false);
|
||||
}
|
||||
for (auto iter = mHiddenFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsStringHashKey::KeyType key = iter.Key();
|
||||
nsRefPtr<gfxFontFamily>& family = iter.Data();
|
||||
FinalizeFamilyMemberList(key, family, /* aSortFaces */ false );
|
||||
}
|
||||
|
||||
LOG(("got font list from chrome process: %d faces in %d families "
|
||||
"and %d in hidden families",
|
||||
fonts.Length(), mFontFamilies.Count(),
|
||||
@ -1237,8 +1243,16 @@ gfxFT2FontList::FindFonts()
|
||||
// Finalize the families by sorting faces into standard order
|
||||
// and marking "simple" families.
|
||||
// Passing non-null userData here says that we want faces to be sorted.
|
||||
mFontFamilies.Enumerate(FinalizeFamilyMemberList, this);
|
||||
mHiddenFontFamilies.Enumerate(FinalizeFamilyMemberList, this);
|
||||
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsStringHashKey::KeyType key = iter.Key();
|
||||
nsRefPtr<gfxFontFamily>& family = iter.Data();
|
||||
FinalizeFamilyMemberList(key, family, /* aSortFaces */ true);
|
||||
}
|
||||
for (auto iter = mHiddenFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsStringHashKey::KeyType key = iter.Key();
|
||||
nsRefPtr<gfxFontFamily>& family = iter.Data();
|
||||
FinalizeFamilyMemberList(key, family, /* aSortFaces */ true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -1328,39 +1342,17 @@ gfxFT2FontList::AppendFaceFromFontListEntry(const FontListEntry& aFLE,
|
||||
}
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
AddFamilyToFontList(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamily,
|
||||
void* aUserArg)
|
||||
{
|
||||
InfallibleTArray<FontListEntry>* fontlist =
|
||||
reinterpret_cast<InfallibleTArray<FontListEntry>*>(aUserArg);
|
||||
|
||||
FT2FontFamily *family = static_cast<FT2FontFamily*>(aFamily.get());
|
||||
family->AddFacesToFontList(fontlist, FT2FontFamily::kVisible);
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
AddHiddenFamilyToFontList(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamily,
|
||||
void* aUserArg)
|
||||
{
|
||||
InfallibleTArray<FontListEntry>* fontlist =
|
||||
reinterpret_cast<InfallibleTArray<FontListEntry>*>(aUserArg);
|
||||
|
||||
FT2FontFamily *family = static_cast<FT2FontFamily*>(aFamily.get());
|
||||
family->AddFacesToFontList(fontlist, FT2FontFamily::kHidden);
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
gfxFT2FontList::GetSystemFontList(InfallibleTArray<FontListEntry>* retValue)
|
||||
{
|
||||
mFontFamilies.Enumerate(AddFamilyToFontList, retValue);
|
||||
mHiddenFontFamilies.Enumerate(AddHiddenFamilyToFontList, retValue);
|
||||
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
auto family = static_cast<FT2FontFamily*>(iter.Data().get());
|
||||
family->AddFacesToFontList(retValue, FT2FontFamily::kVisible);
|
||||
}
|
||||
for (auto iter = mHiddenFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
auto family = static_cast<FT2FontFamily*>(iter.Data().get());
|
||||
family->AddFacesToFontList(retValue, FT2FontFamily::kHidden);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1377,10 +1369,9 @@ LoadSkipSpaceLookupCheck(nsTHashtable<nsStringHashKey>& aSkipSpaceLookupCheck)
|
||||
}
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
void
|
||||
PreloadAsUserFontFaces(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamily,
|
||||
void* aUserArg)
|
||||
nsRefPtr<gfxFontFamily>& aFamily)
|
||||
{
|
||||
gfxFontFamily *family = aFamily.get();
|
||||
|
||||
@ -1433,8 +1424,6 @@ PreloadAsUserFontFaces(nsStringHashKey::KeyType aKey,
|
||||
gfxUserFontSet::UserFontCache::CacheFont(
|
||||
fe, gfxUserFontSet::UserFontCache::kPersistent);
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -1443,74 +1432,65 @@ gfxFT2FontList::InitFontList()
|
||||
// reset font lists
|
||||
gfxPlatformFontList::InitFontList();
|
||||
mHiddenFontFamilies.Clear();
|
||||
|
||||
|
||||
LoadSkipSpaceLookupCheck(mSkipSpaceLookupCheckFamilies);
|
||||
|
||||
FindFonts();
|
||||
|
||||
mHiddenFontFamilies.Enumerate(PreloadAsUserFontFaces, this);
|
||||
|
||||
for (auto iter = mHiddenFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsStringHashKey::KeyType key = iter.Key();
|
||||
nsRefPtr<gfxFontFamily>& family = iter.Data();
|
||||
PreloadAsUserFontFaces(key, family);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
struct FullFontNameSearch {
|
||||
FullFontNameSearch(const nsAString& aFullName)
|
||||
: mFullName(aFullName), mFontEntry(nullptr)
|
||||
{ }
|
||||
|
||||
nsString mFullName;
|
||||
FT2FontEntry *mFontEntry;
|
||||
};
|
||||
|
||||
// callback called for each family name, based on the assumption that the
|
||||
// called for each family name, based on the assumption that the
|
||||
// first part of the full name is the family name
|
||||
static PLDHashOperator
|
||||
FindFullName(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFontFamily,
|
||||
void* userArg)
|
||||
{
|
||||
FullFontNameSearch *data = reinterpret_cast<FullFontNameSearch*>(userArg);
|
||||
|
||||
// does the family name match up to the length of the family name?
|
||||
const nsString& family = aFontFamily->Name();
|
||||
|
||||
nsString fullNameFamily;
|
||||
data->mFullName.Left(fullNameFamily, family.Length());
|
||||
|
||||
// if so, iterate over faces in this family to see if there is a match
|
||||
if (family.Equals(fullNameFamily, nsCaseInsensitiveStringComparator())) {
|
||||
nsTArray<nsRefPtr<gfxFontEntry> >& fontList = aFontFamily->GetFontList();
|
||||
int index, len = fontList.Length();
|
||||
for (index = 0; index < len; index++) {
|
||||
gfxFontEntry* fe = fontList[index];
|
||||
if (!fe) {
|
||||
continue;
|
||||
}
|
||||
if (fe->Name().Equals(data->mFullName,
|
||||
nsCaseInsensitiveStringComparator())) {
|
||||
data->mFontEntry = static_cast<FT2FontEntry*>(fe);
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxFontEntry*
|
||||
gfxFT2FontList::LookupLocalFont(const nsAString& aFontName,
|
||||
uint16_t aWeight,
|
||||
int16_t aStretch,
|
||||
bool aItalic)
|
||||
{
|
||||
// walk over list of names
|
||||
FullFontNameSearch data(aFontName);
|
||||
FT2FontEntry* fontEntry = nullptr;
|
||||
nsString fullName(aFontName);
|
||||
|
||||
// Note that we only check mFontFamilies here, not mHiddenFontFamilies;
|
||||
// hence @font-face { src:local(...) } will not find hidden fonts.
|
||||
mFontFamilies.Enumerate(FindFullName, &data);
|
||||
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
// Check family name, based on the assumption that the
|
||||
// first part of the full name is the family name
|
||||
nsRefPtr<gfxFontFamily>& fontFamily = iter.Data();
|
||||
|
||||
if (!data.mFontEntry) {
|
||||
// does the family name match up to the length of the family name?
|
||||
const nsString& family = fontFamily->Name();
|
||||
nsString fullNameFamily;
|
||||
|
||||
fullName.Left(fullNameFamily, family.Length());
|
||||
|
||||
// if so, iterate over faces in this family to see if there is a match
|
||||
if (family.Equals(fullNameFamily, nsCaseInsensitiveStringComparator())) {
|
||||
nsTArray<nsRefPtr<gfxFontEntry> >& fontList = fontFamily->GetFontList();
|
||||
int index, len = fontList.Length();
|
||||
for (index = 0; index < len; index++) {
|
||||
gfxFontEntry* fe = fontList[index];
|
||||
if (!fe) {
|
||||
continue;
|
||||
}
|
||||
if (fe->Name().Equals(fullName,
|
||||
nsCaseInsensitiveStringComparator())) {
|
||||
fontEntry = static_cast<FT2FontEntry*>(fe);
|
||||
goto searchDone;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
searchDone:
|
||||
if (!fontEntry) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1518,16 +1498,16 @@ gfxFT2FontList::LookupLocalFont(const nsAString& aFontName,
|
||||
// from the userfont entry rather than the actual font.
|
||||
|
||||
// Ensure existence of mFTFace in the original entry
|
||||
data.mFontEntry->CairoFontFace();
|
||||
if (!data.mFontEntry->mFTFace) {
|
||||
fontEntry->CairoFontFace();
|
||||
if (!fontEntry->mFTFace) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FT2FontEntry* fe =
|
||||
FT2FontEntry::CreateFontEntry(data.mFontEntry->mFTFace,
|
||||
data.mFontEntry->mFilename.get(),
|
||||
data.mFontEntry->mFTFontIndex,
|
||||
data.mFontEntry->Name(), nullptr);
|
||||
FT2FontEntry::CreateFontEntry(fontEntry->mFTFace,
|
||||
fontEntry->mFilename.get(),
|
||||
fontEntry->mFTFontIndex,
|
||||
fontEntry->Name(), nullptr);
|
||||
if (fe) {
|
||||
fe->mItalic = aItalic;
|
||||
fe->mWeight = aWeight;
|
||||
@ -1569,21 +1549,15 @@ gfxFT2FontList::MakePlatformFont(const nsAString& aFontName,
|
||||
aItalic, aFontData, aLength);
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
AppendFamily(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamily,
|
||||
void* aUserArg)
|
||||
{
|
||||
nsTArray<nsRefPtr<gfxFontFamily> > * familyArray =
|
||||
reinterpret_cast<nsTArray<nsRefPtr<gfxFontFamily>>*>(aUserArg);
|
||||
|
||||
familyArray->AppendElement(aFamily);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
gfxFT2FontList::GetFontFamilyList(nsTArray<nsRefPtr<gfxFontFamily> >& aFamilyArray)
|
||||
{
|
||||
mFontFamilies.Enumerate(AppendFamily, &aFamilyArray);
|
||||
mHiddenFontFamilies.Enumerate(AppendFamily, &aFamilyArray);
|
||||
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsRefPtr<gfxFontFamily>& family = iter.Data();
|
||||
aFamilyArray.AppendElement(family);
|
||||
}
|
||||
for (auto iter = mHiddenFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsRefPtr<gfxFontFamily>& family = iter.Data();
|
||||
aFamilyArray.AppendElement(family);
|
||||
}
|
||||
}
|
||||
|
@ -428,7 +428,7 @@ gfxFontShaper::MergeFontFeatures(
|
||||
bool aDisableLigatures,
|
||||
const nsAString& aFamilyName,
|
||||
bool aAddSmallCaps,
|
||||
PLDHashOperator (*aHandleFeature)(const uint32_t&, uint32_t&, void*),
|
||||
void (*aHandleFeature)(const uint32_t&, uint32_t&, void*),
|
||||
void* aHandleFeatureData)
|
||||
{
|
||||
uint32_t numAlts = aStyle->alternateValues.Length();
|
||||
@ -530,7 +530,9 @@ gfxFontShaper::MergeFontFeatures(
|
||||
}
|
||||
|
||||
if (mergedFeatures.Count() != 0) {
|
||||
mergedFeatures.Enumerate(aHandleFeature, aHandleFeatureData);
|
||||
for (auto iter = mergedFeatures.Iter(); !iter.Done(); iter.Next()) {
|
||||
aHandleFeature(iter.Key(), iter.Data(), aHandleFeatureData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1742,7 +1744,8 @@ gfxFont::DrawGlyphs(gfxShapedText *aShapedText,
|
||||
gfxFloat& inlineCoord = aFontParams.isVerticalFont ? aPt->y : aPt->x;
|
||||
|
||||
if (aRunParams.spacing) {
|
||||
inlineCoord += aRunParams.direction * aRunParams.spacing[0].mBefore;
|
||||
inlineCoord += aRunParams.isRTL ? -aRunParams.spacing[0].mBefore
|
||||
: aRunParams.spacing[0].mBefore;
|
||||
}
|
||||
|
||||
const gfxShapedText::CompressedGlyph *glyphData =
|
||||
@ -1821,7 +1824,7 @@ gfxFont::DrawGlyphs(gfxShapedText *aShapedText,
|
||||
buffer, &emittedGlyphs);
|
||||
}
|
||||
|
||||
inlineCoord += aRunParams.direction * advance;
|
||||
inlineCoord += aRunParams.isRTL ? -advance : advance;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1831,7 +1834,7 @@ gfxFont::DrawGlyphs(gfxShapedText *aShapedText,
|
||||
if (i + 1 < aCount) {
|
||||
space += aRunParams.spacing[i + 1].mBefore;
|
||||
}
|
||||
inlineCoord += aRunParams.direction * space;
|
||||
inlineCoord += aRunParams.isRTL ? -space : space;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1874,10 +1877,15 @@ gfxFont::Draw(gfxTextRun *aTextRun, uint32_t aStart, uint32_t aEnd,
|
||||
const Metrics& metrics = GetMetrics(eHorizontal);
|
||||
// Get a matrix we can use to draw the (horizontally-shaped) textrun
|
||||
// with 90-degree CW rotation.
|
||||
gfxMatrix mat = aRunParams.context->CurrentMatrix().
|
||||
Translate(p). // translate origin for rotation
|
||||
Rotate(M_PI / 2.0). // turn 90deg clockwise
|
||||
Translate(-p); // undo the translation
|
||||
const gfxFloat
|
||||
rotation = (aOrientation ==
|
||||
gfxTextRunFactory::TEXT_ORIENT_VERTICAL_SIDEWAYS_LEFT)
|
||||
? -M_PI / 2.0 : M_PI / 2.0;
|
||||
gfxMatrix mat =
|
||||
aRunParams.context->CurrentMatrix().
|
||||
Translate(p). // translate origin for rotation
|
||||
Rotate(rotation). // turn 90deg CCW (sideways-left) or CW (*-right)
|
||||
Translate(-p); // undo the translation
|
||||
|
||||
// If we're drawing rotated horizontal text for an element styled
|
||||
// text-orientation:mixed, the dominant baseline will be vertical-
|
||||
@ -1987,7 +1995,14 @@ gfxFont::Draw(gfxTextRun *aTextRun, uint32_t aStart, uint32_t aEnd,
|
||||
|
||||
if (sideways) {
|
||||
aRunParams.context->Restore();
|
||||
*aPt = gfxPoint(origPt.x, origPt.y + (aPt->x - origPt.x));
|
||||
// adjust updated aPt to account for the transform we were using
|
||||
gfxFloat advance = aPt->x - origPt.x;
|
||||
if (aOrientation ==
|
||||
gfxTextRunFactory::TEXT_ORIENT_VERTICAL_SIDEWAYS_LEFT) {
|
||||
*aPt = gfxPoint(origPt.x, origPt.y - advance);
|
||||
} else {
|
||||
*aPt = gfxPoint(origPt.x, origPt.y + advance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -636,8 +636,8 @@ public:
|
||||
bool aDisableLigatures,
|
||||
const nsAString& aFamilyName,
|
||||
bool aAddSmallCaps,
|
||||
PLDHashOperator (*aHandleFeature)(const uint32_t&,
|
||||
uint32_t&, void*),
|
||||
void (*aHandleFeature)(const uint32_t&,
|
||||
uint32_t&, void*),
|
||||
void* aHandleFeatureData);
|
||||
|
||||
protected:
|
||||
@ -965,8 +965,19 @@ public:
|
||||
return (GetFlags() & gfxTextRunFactory::TEXT_IS_RTL) != 0;
|
||||
}
|
||||
|
||||
bool IsSidewaysLeft() const {
|
||||
return (GetFlags() & gfxTextRunFactory::TEXT_ORIENT_MASK) ==
|
||||
gfxTextRunFactory::TEXT_ORIENT_VERTICAL_SIDEWAYS_LEFT;
|
||||
}
|
||||
|
||||
// Return true if the logical inline direction is reversed compared to
|
||||
// normal physical coordinates (i.e. if it is leftwards or upwards)
|
||||
bool IsInlineReversed() const {
|
||||
return IsSidewaysLeft() != IsRightToLeft();
|
||||
}
|
||||
|
||||
gfxFloat GetDirection() const {
|
||||
return IsRightToLeft() ? -1.0f : 1.0f;
|
||||
return IsInlineReversed() ? -1.0f : 1.0f;
|
||||
}
|
||||
|
||||
bool DisableLigatures() const {
|
||||
|
@ -146,13 +146,6 @@ gfxFontEntry::gfxFontEntry(const nsAString& aName, bool aIsStandardFace) :
|
||||
memset(&mNonDefaultSubSpaceFeatures, 0, sizeof(mNonDefaultSubSpaceFeatures));
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
DestroyHBSet(const uint32_t& aTag, hb_set_t*& aSet, void *aUserArg)
|
||||
{
|
||||
hb_set_destroy(aSet);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
gfxFontEntry::~gfxFontEntry()
|
||||
{
|
||||
if (mCOLR) {
|
||||
@ -170,7 +163,10 @@ gfxFontEntry::~gfxFontEntry()
|
||||
}
|
||||
|
||||
if (mFeatureInputs) {
|
||||
mFeatureInputs->Enumerate(DestroyHBSet, nullptr);
|
||||
for (auto iter = mFeatureInputs->Iter(); !iter.Done(); iter.Next()) {
|
||||
hb_set_t*& set = iter.Data();
|
||||
hb_set_destroy(set);
|
||||
}
|
||||
}
|
||||
|
||||
// By the time the entry is destroyed, all font instances that were
|
||||
|
@ -72,7 +72,7 @@ struct GrFontFeatures {
|
||||
gr_feature_val *mFeatures;
|
||||
};
|
||||
|
||||
static PLDHashOperator
|
||||
static void
|
||||
AddFeature(const uint32_t& aTag, uint32_t& aValue, void *aUserArg)
|
||||
{
|
||||
GrFontFeatures *f = static_cast<GrFontFeatures*>(aUserArg);
|
||||
@ -81,7 +81,6 @@ AddFeature(const uint32_t& aTag, uint32_t& aValue, void *aUserArg)
|
||||
if (fref) {
|
||||
gr_fref_set_feature_value(fref, aValue, f->mFeatures);
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1224,7 +1224,7 @@ HBUnicodeDecompose(hb_unicode_funcs_t *ufuncs,
|
||||
#endif
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
static void
|
||||
AddOpenTypeFeature(const uint32_t& aTag, uint32_t& aValue, void *aUserArg)
|
||||
{
|
||||
nsTArray<hb_feature_t>* features = static_cast<nsTArray<hb_feature_t>*> (aUserArg);
|
||||
@ -1233,7 +1233,6 @@ AddOpenTypeFeature(const uint32_t& aTag, uint32_t& aValue, void *aUserArg)
|
||||
feat.tag = aTag;
|
||||
feat.value = aValue;
|
||||
features->AppendElement(feat);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -237,18 +237,9 @@ gfxPlatformFontList::GenerateFontListKey(const nsAString& aKeyName, nsAString& a
|
||||
ToLowerCase(aResult);
|
||||
}
|
||||
|
||||
struct InitOtherNamesData {
|
||||
InitOtherNamesData(gfxPlatformFontList *aFontList,
|
||||
TimeStamp aStartTime)
|
||||
: mFontList(aFontList), mStartTime(aStartTime), mTimedOut(false)
|
||||
{}
|
||||
#define OTHERNAMES_TIMEOUT 200
|
||||
|
||||
gfxPlatformFontList *mFontList;
|
||||
TimeStamp mStartTime;
|
||||
bool mTimedOut;
|
||||
};
|
||||
|
||||
void
|
||||
void
|
||||
gfxPlatformFontList::InitOtherFamilyNames()
|
||||
{
|
||||
if (mOtherFamilyNamesInitialized) {
|
||||
@ -256,14 +247,19 @@ gfxPlatformFontList::InitOtherFamilyNames()
|
||||
}
|
||||
|
||||
TimeStamp start = TimeStamp::Now();
|
||||
bool timedOut = false;
|
||||
|
||||
// iterate over all font families and read in other family names
|
||||
InitOtherNamesData otherNamesData(this, start);
|
||||
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsRefPtr<gfxFontFamily>& family = iter.Data();
|
||||
family->ReadOtherFamilyNames(this);
|
||||
TimeDuration elapsed = TimeStamp::Now() - start;
|
||||
if (elapsed.ToMilliseconds() > OTHERNAMES_TIMEOUT) {
|
||||
timedOut = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mFontFamilies.Enumerate(gfxPlatformFontList::InitOtherFamilyNamesProc,
|
||||
&otherNamesData);
|
||||
|
||||
if (!otherNamesData.mTimedOut) {
|
||||
if (!timedOut) {
|
||||
mOtherFamilyNamesInitialized = true;
|
||||
}
|
||||
TimeStamp end = TimeStamp::Now();
|
||||
@ -274,55 +270,44 @@ gfxPlatformFontList::InitOtherFamilyNames()
|
||||
TimeDuration elapsed = end - start;
|
||||
LOG_FONTINIT(("(fontinit) InitOtherFamilyNames took %8.2f ms %s",
|
||||
elapsed.ToMilliseconds(),
|
||||
(otherNamesData.mTimedOut ? "timeout" : "")));
|
||||
(timedOut ? "timeout" : "")));
|
||||
}
|
||||
}
|
||||
|
||||
#define OTHERNAMES_TIMEOUT 200
|
||||
|
||||
PLDHashOperator
|
||||
gfxPlatformFontList::InitOtherFamilyNamesProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamilyEntry,
|
||||
void* userArg)
|
||||
{
|
||||
InitOtherNamesData *data = static_cast<InitOtherNamesData*>(userArg);
|
||||
|
||||
aFamilyEntry->ReadOtherFamilyNames(data->mFontList);
|
||||
TimeDuration elapsed = TimeStamp::Now() - data->mStartTime;
|
||||
if (elapsed.ToMilliseconds() > OTHERNAMES_TIMEOUT) {
|
||||
data->mTimedOut = true;
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
struct ReadFaceNamesData {
|
||||
ReadFaceNamesData(gfxPlatformFontList *aFontList, TimeStamp aStartTime)
|
||||
: mFontList(aFontList), mStartTime(aStartTime), mTimedOut(false),
|
||||
mFirstChar(0)
|
||||
{}
|
||||
|
||||
gfxPlatformFontList *mFontList;
|
||||
TimeStamp mStartTime;
|
||||
bool mTimedOut;
|
||||
|
||||
// if mFirstChar is not 0, only load facenames for families
|
||||
// that start with this character
|
||||
char16_t mFirstChar;
|
||||
};
|
||||
// time limit for loading facename lists (ms)
|
||||
#define NAMELIST_TIMEOUT 200
|
||||
|
||||
gfxFontEntry*
|
||||
gfxPlatformFontList::SearchFamiliesForFaceName(const nsAString& aFaceName)
|
||||
{
|
||||
TimeStamp start = TimeStamp::Now();
|
||||
bool timedOut = false;
|
||||
// if mFirstChar is not 0, only load facenames for families
|
||||
// that start with this character
|
||||
char16_t firstChar = 0;
|
||||
gfxFontEntry *lookup = nullptr;
|
||||
|
||||
ReadFaceNamesData faceNameListsData(this, start);
|
||||
|
||||
// iterate over familes starting with the same letter
|
||||
faceNameListsData.mFirstChar = ToLowerCase(aFaceName.CharAt(0));
|
||||
mFontFamilies.Enumerate(gfxPlatformFontList::ReadFaceNamesProc,
|
||||
&faceNameListsData);
|
||||
firstChar = ToLowerCase(aFaceName.CharAt(0));
|
||||
|
||||
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsStringHashKey::KeyType key = iter.Key();
|
||||
nsRefPtr<gfxFontFamily>& family = iter.Data();
|
||||
|
||||
// when filtering, skip names that don't start with the filter character
|
||||
if (firstChar && ToLowerCase(key.CharAt(0)) != firstChar) {
|
||||
continue;
|
||||
}
|
||||
|
||||
family->ReadFaceNames(this, NeedFullnamePostscriptNames());
|
||||
|
||||
TimeDuration elapsed = TimeStamp::Now() - start;
|
||||
if (elapsed.ToMilliseconds() > NAMELIST_TIMEOUT) {
|
||||
timedOut = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lookup = FindFaceName(aFaceName);
|
||||
|
||||
TimeStamp end = TimeStamp::Now();
|
||||
@ -333,38 +318,12 @@ gfxPlatformFontList::SearchFamiliesForFaceName(const nsAString& aFaceName)
|
||||
LOG_FONTINIT(("(fontinit) SearchFamiliesForFaceName took %8.2f ms %s %s",
|
||||
elapsed.ToMilliseconds(),
|
||||
(lookup ? "found name" : ""),
|
||||
(faceNameListsData.mTimedOut ? "timeout" : "")));
|
||||
(timedOut ? "timeout" : "")));
|
||||
}
|
||||
|
||||
return lookup;
|
||||
}
|
||||
|
||||
// time limit for loading facename lists (ms)
|
||||
#define NAMELIST_TIMEOUT 200
|
||||
|
||||
PLDHashOperator
|
||||
gfxPlatformFontList::ReadFaceNamesProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamilyEntry,
|
||||
void* userArg)
|
||||
{
|
||||
ReadFaceNamesData *data = static_cast<ReadFaceNamesData*>(userArg);
|
||||
gfxPlatformFontList *fc = data->mFontList;
|
||||
|
||||
// when filtering, skip names that don't start with the filter character
|
||||
if (data->mFirstChar && ToLowerCase(aKey.CharAt(0)) != data->mFirstChar) {
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
aFamilyEntry->ReadFaceNames(fc, fc->NeedFullnamePostscriptNames());
|
||||
|
||||
TimeDuration elapsed = TimeStamp::Now() - data->mStartTime;
|
||||
if (elapsed.ToMilliseconds() > NAMELIST_TIMEOUT) {
|
||||
data->mTimedOut = true;
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxPlatformFontList::FindFaceName(const nsAString& aFaceName)
|
||||
{
|
||||
@ -449,84 +408,49 @@ gfxPlatformFontList::UpdateFontList()
|
||||
RebuildLocalFonts();
|
||||
}
|
||||
|
||||
struct FontListData {
|
||||
FontListData(nsIAtom *aLangGroup,
|
||||
const nsACString& aGenericFamily,
|
||||
nsTArray<nsString>& aListOfFonts) :
|
||||
mLangGroup(aLangGroup), mGenericFamily(aGenericFamily),
|
||||
mListOfFonts(aListOfFonts) {}
|
||||
nsIAtom *mLangGroup;
|
||||
const nsACString& mGenericFamily;
|
||||
nsTArray<nsString>& mListOfFonts;
|
||||
};
|
||||
|
||||
PLDHashOperator
|
||||
gfxPlatformFontList::HashEnumFuncForFamilies(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamilyEntry,
|
||||
void *aUserArg)
|
||||
{
|
||||
FontListData *data = static_cast<FontListData*>(aUserArg);
|
||||
|
||||
// use the first variation for now. This data should be the same
|
||||
// for all the variations and should probably be moved up to
|
||||
// the Family
|
||||
gfxFontStyle style;
|
||||
style.language = data->mLangGroup;
|
||||
bool needsBold;
|
||||
nsRefPtr<gfxFontEntry> aFontEntry = aFamilyEntry->FindFontForStyle(style, needsBold);
|
||||
NS_ASSERTION(aFontEntry, "couldn't find any font entry in family");
|
||||
if (!aFontEntry)
|
||||
return PL_DHASH_NEXT;
|
||||
|
||||
/* skip symbol fonts */
|
||||
if (aFontEntry->IsSymbolFont())
|
||||
return PL_DHASH_NEXT;
|
||||
|
||||
if (aFontEntry->SupportsLangGroup(data->mLangGroup) &&
|
||||
aFontEntry->MatchesGenericFamily(data->mGenericFamily)) {
|
||||
nsAutoString localizedFamilyName;
|
||||
aFamilyEntry->LocalizedName(localizedFamilyName);
|
||||
data->mListOfFonts.AppendElement(localizedFamilyName);
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::GetFontList(nsIAtom *aLangGroup,
|
||||
const nsACString& aGenericFamily,
|
||||
nsTArray<nsString>& aListOfFonts)
|
||||
{
|
||||
FontListData data(aLangGroup, aGenericFamily, aListOfFonts);
|
||||
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsRefPtr<gfxFontFamily>& family = iter.Data();
|
||||
// use the first variation for now. This data should be the same
|
||||
// for all the variations and should probably be moved up to
|
||||
// the Family
|
||||
gfxFontStyle style;
|
||||
style.language = aLangGroup;
|
||||
bool needsBold;
|
||||
nsRefPtr<gfxFontEntry> fontEntry = family->FindFontForStyle(style, needsBold);
|
||||
NS_ASSERTION(fontEntry, "couldn't find any font entry in family");
|
||||
if (!fontEntry) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mFontFamilies.Enumerate(gfxPlatformFontList::HashEnumFuncForFamilies, &data);
|
||||
/* skip symbol fonts */
|
||||
if (fontEntry->IsSymbolFont()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fontEntry->SupportsLangGroup(aLangGroup) &&
|
||||
fontEntry->MatchesGenericFamily(aGenericFamily)) {
|
||||
nsAutoString localizedFamilyName;
|
||||
family->LocalizedName(localizedFamilyName);
|
||||
aListOfFonts.AppendElement(localizedFamilyName);
|
||||
}
|
||||
}
|
||||
|
||||
aListOfFonts.Sort();
|
||||
aListOfFonts.Compact();
|
||||
}
|
||||
|
||||
struct FontFamilyListData {
|
||||
explicit FontFamilyListData(nsTArray<nsRefPtr<gfxFontFamily> >& aFamilyArray)
|
||||
: mFamilyArray(aFamilyArray)
|
||||
{}
|
||||
|
||||
static PLDHashOperator AppendFamily(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamilyEntry,
|
||||
void *aUserArg)
|
||||
{
|
||||
FontFamilyListData *data = static_cast<FontFamilyListData*>(aUserArg);
|
||||
data->mFamilyArray.AppendElement(aFamilyEntry);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsTArray<nsRefPtr<gfxFontFamily> >& mFamilyArray;
|
||||
};
|
||||
|
||||
void
|
||||
gfxPlatformFontList::GetFontFamilyList(nsTArray<nsRefPtr<gfxFontFamily> >& aFamilyArray)
|
||||
{
|
||||
FontFamilyListData data(aFamilyArray);
|
||||
mFontFamilies.Enumerate(FontFamilyListData::AppendFamily, &data);
|
||||
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsRefPtr<gfxFontFamily>& family = iter.Data();
|
||||
aFamilyArray.AppendElement(family);
|
||||
}
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
@ -616,18 +540,6 @@ gfxPlatformFontList::SystemFindFontForChar(uint32_t aCh, uint32_t aNextCh,
|
||||
return fontEntry;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
gfxPlatformFontList::FindFontForCharProc(nsStringHashKey::KeyType aKey, nsRefPtr<gfxFontFamily>& aFamilyEntry,
|
||||
void *userArg)
|
||||
{
|
||||
GlobalFontMatch *data = static_cast<GlobalFontMatch*>(userArg);
|
||||
|
||||
// evaluate all fonts in this family for a match
|
||||
aFamilyEntry->FindFontForChar(data);
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
#define NUM_FALLBACK_FONTS 8
|
||||
|
||||
gfxFontEntry*
|
||||
@ -677,7 +589,11 @@ gfxPlatformFontList::GlobalFontFallback(const uint32_t aCh,
|
||||
GlobalFontMatch data(aCh, aRunScript, aMatchStyle);
|
||||
|
||||
// iterate over all font families to find a font that support the character
|
||||
mFontFamilies.Enumerate(gfxPlatformFontList::FindFontForCharProc, &data);
|
||||
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsRefPtr<gfxFontFamily>& family = iter.Data();
|
||||
// evaluate all fonts in this family for a match
|
||||
family->FindFontForChar(&data);
|
||||
}
|
||||
|
||||
aCmapCount = data.mCmapsTested;
|
||||
*aMatchedFamily = data.mMatchedFamily;
|
||||
@ -885,22 +801,16 @@ gfxPlatformFontList::RemoveCmap(const gfxCharacterMap* aCharMap)
|
||||
}
|
||||
}
|
||||
|
||||
static PLDHashOperator AppendFamilyToList(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamilyEntry,
|
||||
void *aUserArg)
|
||||
{
|
||||
nsTArray<nsString> *familyNames = static_cast<nsTArray<nsString> *>(aUserArg);
|
||||
familyNames->AppendElement(aFamilyEntry->Name());
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::GetFontFamilyNames(nsTArray<nsString>& aFontFamilyNames)
|
||||
{
|
||||
mFontFamilies.Enumerate(AppendFamilyToList, &aFontFamilyNames);
|
||||
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsRefPtr<gfxFontFamily>& family = iter.Data();
|
||||
aFontFamilyNames.AppendElement(family->Name());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
gfxPlatformFontList::InitLoader()
|
||||
{
|
||||
GetFontFamilyNames(mFontInfo->mFontFamiliesToLoad);
|
||||
|
@ -212,10 +212,6 @@ protected:
|
||||
|
||||
static gfxPlatformFontList *sPlatformFontList;
|
||||
|
||||
static PLDHashOperator FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamilyEntry,
|
||||
void* userArg);
|
||||
|
||||
// Lookup family name in global family list without substitutions or
|
||||
// localized family name lookup. Used for common font fallback families.
|
||||
gfxFontFamily* FindFamilyByCanonicalName(const nsAString& aFamily) {
|
||||
@ -251,21 +247,11 @@ protected:
|
||||
// initialize localized family names
|
||||
void InitOtherFamilyNames();
|
||||
|
||||
static PLDHashOperator
|
||||
InitOtherFamilyNamesProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamilyEntry,
|
||||
void* userArg);
|
||||
|
||||
// search through font families, looking for a given name, initializing
|
||||
// facename lists along the way. first checks all families with names
|
||||
// close to face name, then searchs all families if not found.
|
||||
gfxFontEntry* SearchFamiliesForFaceName(const nsAString& aFaceName);
|
||||
|
||||
static PLDHashOperator
|
||||
ReadFaceNamesProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamilyEntry,
|
||||
void* userArg);
|
||||
|
||||
// helper method for finding fullname/postscript names in facename lists
|
||||
gfxFontEntry* FindFaceName(const nsAString& aFaceName);
|
||||
|
||||
|
@ -811,14 +811,14 @@ RasterImage::OnAddedFrame(uint32_t aNewFrameCount,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
RasterImage::SetMetadata(const ImageMetadata& aMetadata,
|
||||
bool aFromMetadataDecode)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mError) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aMetadata.HasSize()) {
|
||||
@ -826,7 +826,7 @@ RasterImage::SetMetadata(const ImageMetadata& aMetadata,
|
||||
if (size.width < 0 || size.height < 0) {
|
||||
NS_WARNING("Image has negative intrinsic size");
|
||||
DoError();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aMetadata.HasOrientation());
|
||||
@ -837,7 +837,7 @@ RasterImage::SetMetadata(const ImageMetadata& aMetadata,
|
||||
NS_WARNING("Image changed size or orientation on redecode! "
|
||||
"This should not happen!");
|
||||
DoError();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set the size and flag that we have it.
|
||||
@ -859,7 +859,7 @@ RasterImage::SetMetadata(const ImageMetadata& aMetadata,
|
||||
// discovered that it actually was during the full decode. This is a
|
||||
// rare failure that only occurs for corrupt images. To recover, we need
|
||||
// to discard all existing surfaces and redecode.
|
||||
RecoverFromInvalidFrames(mSize, DECODE_FLAGS_DEFAULT);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -881,6 +881,8 @@ RasterImage::SetMetadata(const ImageMetadata& aMetadata,
|
||||
Set("hotspotX", intwrapx);
|
||||
Set("hotspotY", intwrapy);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -1732,7 +1734,18 @@ RasterImage::FinalizeDecoder(Decoder* aDecoder)
|
||||
}
|
||||
|
||||
// Record all the metadata the decoder gathered about this image.
|
||||
SetMetadata(aDecoder->GetImageMetadata(), wasMetadata);
|
||||
bool metadataOK = SetMetadata(aDecoder->GetImageMetadata(), wasMetadata);
|
||||
if (!metadataOK) {
|
||||
// This indicates a serious error that requires us to discard all existing
|
||||
// surfaces and redecode to recover. We'll drop the results from this
|
||||
// decoder on the floor, since they aren't valid.
|
||||
aDecoder->TakeProgress();
|
||||
aDecoder->TakeInvalidRect();
|
||||
RecoverFromInvalidFrames(mSize,
|
||||
FromSurfaceFlags(aDecoder->GetSurfaceFlags()));
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mError || mHasSize || !aDecoder->HasSize(),
|
||||
"SetMetadata should've gotten a size");
|
||||
|
||||
|
@ -324,8 +324,11 @@ private:
|
||||
* @param aMetadata The metadata to set on this image.
|
||||
* @param aFromMetadataDecode True if this metadata came from a metadata
|
||||
* decode; false if it came from a full decode.
|
||||
* @return |true| unless a catastrophic failure was discovered. If |false| is
|
||||
* returned, it indicates that the image is corrupt in a way that requires all
|
||||
* surfaces to be discarded to recover.
|
||||
*/
|
||||
void SetMetadata(const ImageMetadata& aMetadata, bool aFromMetadataDecode);
|
||||
bool SetMetadata(const ImageMetadata& aMetadata, bool aFromMetadataDecode);
|
||||
|
||||
/**
|
||||
* In catastrophic circumstances like a GPU driver crash, the contents of our
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/RefCounted.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/nsRefPtr.h"
|
||||
#include "nsTArray.h"
|
||||
|
@ -50,6 +50,23 @@ ToSurfaceFlags(uint32_t aFlags)
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a set of SurfaceFlags, returns a set of imgIContainer FLAG_* flags with
|
||||
* the corresponding flags set.
|
||||
*/
|
||||
inline uint32_t
|
||||
FromSurfaceFlags(SurfaceFlags aFlags)
|
||||
{
|
||||
uint32_t flags = imgIContainer::DECODE_FLAGS_DEFAULT;
|
||||
if (aFlags & SurfaceFlags::NO_PREMULTIPLY_ALPHA) {
|
||||
flags |= imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA;
|
||||
}
|
||||
if (aFlags & SurfaceFlags::NO_COLORSPACE_CONVERSION) {
|
||||
flags |= imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
} // namespace image
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -497,14 +497,23 @@ NS_IMETHODIMP
|
||||
VectorImage::GetWidth(int32_t* aWidth)
|
||||
{
|
||||
if (mError || !mIsFullyLoaded) {
|
||||
*aWidth = -1;
|
||||
} else {
|
||||
SVGSVGElement* rootElem = mSVGDocumentWrapper->GetRootSVGElem();
|
||||
MOZ_ASSERT(rootElem, "Should have a root SVG elem, since we finished "
|
||||
"loading without errors");
|
||||
*aWidth = rootElem->GetIntrinsicWidth();
|
||||
// XXXdholbert Technically we should leave outparam untouched when we
|
||||
// fail. But since many callers don't check for failure, we set it to 0 on
|
||||
// failure, for sane/predictable results.
|
||||
*aWidth = 0;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return *aWidth >= 0 ? NS_OK : NS_ERROR_FAILURE;
|
||||
|
||||
SVGSVGElement* rootElem = mSVGDocumentWrapper->GetRootSVGElem();
|
||||
MOZ_ASSERT(rootElem, "Should have a root SVG elem, since we finished "
|
||||
"loading without errors");
|
||||
int32_t rootElemWidth = rootElem->GetIntrinsicWidth();
|
||||
if (rootElemWidth < 0) {
|
||||
*aWidth = 0;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
*aWidth = rootElemWidth;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
@ -561,14 +570,23 @@ NS_IMETHODIMP
|
||||
VectorImage::GetHeight(int32_t* aHeight)
|
||||
{
|
||||
if (mError || !mIsFullyLoaded) {
|
||||
*aHeight = -1;
|
||||
} else {
|
||||
SVGSVGElement* rootElem = mSVGDocumentWrapper->GetRootSVGElem();
|
||||
MOZ_ASSERT(rootElem, "Should have a root SVG elem, since we finished "
|
||||
"loading without errors");
|
||||
*aHeight = rootElem->GetIntrinsicHeight();
|
||||
// XXXdholbert Technically we should leave outparam untouched when we
|
||||
// fail. But since many callers don't check for failure, we set it to 0 on
|
||||
// failure, for sane/predictable results.
|
||||
*aHeight = 0;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return *aHeight >= 0 ? NS_OK : NS_ERROR_FAILURE;
|
||||
|
||||
SVGSVGElement* rootElem = mSVGDocumentWrapper->GetRootSVGElem();
|
||||
MOZ_ASSERT(rootElem, "Should have a root SVG elem, since we finished "
|
||||
"loading without errors");
|
||||
int32_t rootElemHeight = rootElem->GetIntrinsicHeight();
|
||||
if (rootElemHeight < 0) {
|
||||
*aHeight = 0;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
*aHeight = rootElemHeight;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
36
image/test/crashtests/1205923-1.html
Normal file
36
image/test/crashtests/1205923-1.html
Normal file
@ -0,0 +1,36 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<body>
|
||||
</body>
|
||||
<script>
|
||||
function createImage(loadHandler) {
|
||||
var newImage = new Image;
|
||||
newImage.id = "thepreviewimage";
|
||||
newImage.setAttribute("src", "unsized-svg.svg");
|
||||
if (loadHandler) {
|
||||
newImage.onload = loadHandler;
|
||||
}
|
||||
|
||||
// Query width & height, and display them in document:
|
||||
physWidth = newImage.width;
|
||||
physHeight = newImage.height;
|
||||
document.documentElement.innerHTML +=
|
||||
physWidth + " x " + physHeight + "<br>";
|
||||
}
|
||||
|
||||
function part2() {
|
||||
// Load image again:
|
||||
createImage();
|
||||
|
||||
// End the crashtest.
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
// Trigger image load, and call part2() when it's loaded:
|
||||
createImage(part2);
|
||||
}
|
||||
|
||||
startTest();
|
||||
</script>
|
||||
</html>
|
@ -53,6 +53,8 @@ load invalid-disposal-method-1.gif
|
||||
load invalid-disposal-method-2.gif
|
||||
load invalid-disposal-method-3.gif
|
||||
|
||||
load 1205923-1.html
|
||||
|
||||
# Ensure we handle ICO directory entries which specify the wrong size for the
|
||||
# contained resource.
|
||||
load invalid_ico_height.ico
|
||||
|
1
image/test/crashtests/unsized-svg.svg
Normal file
1
image/test/crashtests/unsized-svg.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg"></svg>
|
After Width: | Height: | Size: 47 B |
@ -32,7 +32,6 @@ ChildThread::~ChildThread() {
|
||||
bool ChildThread::Run() {
|
||||
bool r = StartWithOptions(options_);
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
NS_ASSERTION(NuwaMarkCurrentThread, "NuwaMarkCurrentThread is not defined!");
|
||||
if (IsNuwaProcess()) {
|
||||
message_loop()->PostTask(FROM_HERE,
|
||||
NewRunnableFunction(&ChildThread::MarkThread));
|
||||
|
@ -3889,13 +3889,8 @@ BytecodeEmitter::emitDestructuringOpsArrayHelper(ParseNode* pattern, VarEmitOpti
|
||||
|
||||
if (elem->isKind(PNK_SPREAD)) {
|
||||
/* Create a new array with the rest of the iterator */
|
||||
ptrdiff_t off;
|
||||
if (!emitN(JSOP_NEWARRAY, 3, &off)) // ... OBJ? ITER ARRAY
|
||||
if (!emitUint32Operand(JSOP_NEWARRAY, 0)) // ... OBJ? ITER ARRAY
|
||||
return false;
|
||||
checkTypeSet(JSOP_NEWARRAY);
|
||||
jsbytecode* pc = code(off);
|
||||
SET_UINT24(pc, 0);
|
||||
|
||||
if (!emitNumberOp(0)) // ... OBJ? ITER ARRAY INDEX
|
||||
return false;
|
||||
if (!emitSpread()) // ... OBJ? ARRAY INDEX
|
||||
@ -7214,29 +7209,35 @@ BytecodeEmitter::emitArray(ParseNode* pn, uint32_t count, JSOp op)
|
||||
*/
|
||||
MOZ_ASSERT(op == JSOP_NEWARRAY || op == JSOP_SPREADCALLARRAY);
|
||||
|
||||
int32_t nspread = 0;
|
||||
uint32_t nspread = 0;
|
||||
for (ParseNode* elt = pn; elt; elt = elt->pn_next) {
|
||||
if (elt->isKind(PNK_SPREAD))
|
||||
nspread++;
|
||||
}
|
||||
|
||||
ptrdiff_t off;
|
||||
if (!emitN(op, 3, &off)) // ARRAY
|
||||
return false;
|
||||
checkTypeSet(op);
|
||||
jsbytecode* pc = code(off);
|
||||
// Array literal's length is limited to NELEMENTS_LIMIT in parser.
|
||||
static_assert(NativeObject::MAX_DENSE_ELEMENTS_COUNT <= INT32_MAX,
|
||||
"array literals' maximum length must not exceed limits "
|
||||
"required by BaselineCompiler::emit_JSOP_NEWARRAY, "
|
||||
"BaselineCompiler::emit_JSOP_INITELEM_ARRAY, "
|
||||
"and DoSetElemFallback's handling of JSOP_INITELEM_ARRAY");
|
||||
MOZ_ASSERT(count >= nspread);
|
||||
MOZ_ASSERT(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT,
|
||||
"the parser must throw an error if the array exceeds maximum "
|
||||
"length");
|
||||
|
||||
// For arrays with spread, this is a very pessimistic allocation, the
|
||||
// minimum possible final size.
|
||||
SET_UINT24(pc, count - nspread);
|
||||
if (!emitUint32Operand(op, count - nspread)) // ARRAY
|
||||
return false;
|
||||
|
||||
ParseNode* pn2 = pn;
|
||||
jsatomid atomIndex;
|
||||
uint32_t index;
|
||||
bool afterSpread = false;
|
||||
for (atomIndex = 0; pn2; atomIndex++, pn2 = pn2->pn_next) {
|
||||
for (index = 0; pn2; index++, pn2 = pn2->pn_next) {
|
||||
if (!afterSpread && pn2->isKind(PNK_SPREAD)) {
|
||||
afterSpread = true;
|
||||
if (!emitNumberOp(atomIndex)) // ARRAY INDEX
|
||||
if (!emitNumberOp(index)) // ARRAY INDEX
|
||||
return false;
|
||||
}
|
||||
if (!updateSourceCoordNotes(pn2->pn_pos.begin))
|
||||
@ -7262,12 +7263,11 @@ BytecodeEmitter::emitArray(ParseNode* pn, uint32_t count, JSOp op)
|
||||
if (!emit1(JSOP_INITELEM_INC))
|
||||
return false;
|
||||
} else {
|
||||
if (!emitN(JSOP_INITELEM_ARRAY, 3, &off))
|
||||
if (!emitUint32Operand(JSOP_INITELEM_ARRAY, index))
|
||||
return false;
|
||||
SET_UINT24(code(off), atomIndex);
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(atomIndex == count);
|
||||
MOZ_ASSERT(index == count);
|
||||
if (afterSpread) {
|
||||
if (!emit1(JSOP_POP)) // ARRAY
|
||||
return false;
|
||||
|
@ -8767,7 +8767,7 @@ Parser<ParseHandler>::arrayInitializer(YieldHandling yieldHandling)
|
||||
uint32_t index = 0;
|
||||
TokenStream::Modifier modifier = TokenStream::Operand;
|
||||
for (; ; index++) {
|
||||
if (index == NativeObject::NELEMENTS_LIMIT) {
|
||||
if (index >= NativeObject::MAX_DENSE_ELEMENTS_COUNT) {
|
||||
report(ParseError, false, null(), JSMSG_ARRAY_INIT_TOO_BIG);
|
||||
return null();
|
||||
}
|
||||
|
40
js/src/jit-test/tests/arrays/dense-from-sparse.js
Normal file
40
js/src/jit-test/tests/arrays/dense-from-sparse.js
Normal file
@ -0,0 +1,40 @@
|
||||
// |jit-test| allow-oom
|
||||
// Appending elements to a dense array should make the array sparse when the
|
||||
// length exceeds the limit.
|
||||
|
||||
function test() {
|
||||
const MAX_DENSE_ELEMENTS_ALLOCATION = (1 << 28) - 1;
|
||||
const VALUES_PER_HEADER = 2;
|
||||
const MAX_DENSE_ELEMENTS_COUNT = MAX_DENSE_ELEMENTS_ALLOCATION - VALUES_PER_HEADER;
|
||||
const SPARSE_DENSITY_RATIO = 8;
|
||||
const MIN_DENSE = MAX_DENSE_ELEMENTS_COUNT / SPARSE_DENSITY_RATIO;
|
||||
const MARGIN = 16;
|
||||
|
||||
let a = [];
|
||||
// Fill the beginning of array to make it keep dense until length exceeds
|
||||
// MAX_DENSE_ELEMENTS_COUNT.
|
||||
for (let i = 0; i < MIN_DENSE; i++)
|
||||
a[i] = i;
|
||||
|
||||
// Skip from MIN_DENSE to MAX_DENSE_ELEMENTS_COUNT - MARGIN, to reduce the
|
||||
// time taken by test.
|
||||
|
||||
// Fill the ending of array to make it sparse at MAX_DENSE_ELEMENTS_COUNT.
|
||||
for (let i = MAX_DENSE_ELEMENTS_COUNT - MARGIN; i < MAX_DENSE_ELEMENTS_COUNT + MARGIN; i++)
|
||||
a[i] = i;
|
||||
|
||||
// Make sure the last element is defined.
|
||||
assertEq(a.length, MAX_DENSE_ELEMENTS_COUNT + MARGIN);
|
||||
assertEq(a[a.length - 1], MAX_DENSE_ELEMENTS_COUNT + MARGIN - 1);
|
||||
|
||||
// Make sure elements around MAX_DENSE_ELEMENTS_COUNT are also defined.
|
||||
assertEq(a[MAX_DENSE_ELEMENTS_COUNT - 1], MAX_DENSE_ELEMENTS_COUNT - 1);
|
||||
assertEq(a[MAX_DENSE_ELEMENTS_COUNT], MAX_DENSE_ELEMENTS_COUNT);
|
||||
assertEq(a[MAX_DENSE_ELEMENTS_COUNT + 1], MAX_DENSE_ELEMENTS_COUNT + 1);
|
||||
}
|
||||
|
||||
var config = getBuildConfiguration();
|
||||
// Takes too long time on debug build.
|
||||
if (!config.debug) {
|
||||
test();
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "jit/BaselineCompiler.h"
|
||||
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
#include "jit/BaselineIC.h"
|
||||
@ -32,6 +33,8 @@
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
|
||||
using mozilla::AssertedCast;
|
||||
|
||||
BaselineCompiler::BaselineCompiler(JSContext* cx, TempAllocator& alloc, JSScript* script)
|
||||
: BaselineCompilerSpecific(cx, alloc, script),
|
||||
yieldOffsets_(cx),
|
||||
@ -1792,10 +1795,13 @@ BaselineCompiler::emit_JSOP_NEWARRAY()
|
||||
{
|
||||
frame.syncStack(0);
|
||||
|
||||
uint32_t length = GET_UINT24(pc);
|
||||
uint32_t length = GET_UINT32(pc);
|
||||
MOZ_ASSERT(length <= INT32_MAX,
|
||||
"the bytecode emitter must fail to compile code that would "
|
||||
"produce JSOP_NEWARRAY with a length exceeding int32_t range");
|
||||
|
||||
// Pass length in R0.
|
||||
masm.move32(Imm32(length), R0.scratchReg());
|
||||
masm.move32(Imm32(AssertedCast<int32_t>(length)), R0.scratchReg());
|
||||
|
||||
ObjectGroup* group = ObjectGroup::allocationSiteGroup(cx, script, pc, JSProto_Array);
|
||||
if (!group)
|
||||
@ -1849,7 +1855,12 @@ BaselineCompiler::emit_JSOP_INITELEM_ARRAY()
|
||||
|
||||
// Load object in R0, index in R1.
|
||||
masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R0);
|
||||
masm.moveValue(Int32Value(GET_UINT24(pc)), R1);
|
||||
uint32_t index = GET_UINT32(pc);
|
||||
MOZ_ASSERT(index <= INT32_MAX,
|
||||
"the bytecode emitter must fail to compile code that would "
|
||||
"produce JSOP_INITELEM_ARRAY with a length exceeding "
|
||||
"int32_t range");
|
||||
masm.moveValue(Int32Value(AssertedCast<int32_t>(index)), R1);
|
||||
|
||||
// Call IC.
|
||||
ICSetElem_Fallback::Compiler stubCompiler(cx);
|
||||
|
@ -3689,7 +3689,11 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_
|
||||
if (!InitElemOperation(cx, obj, index, rhs))
|
||||
return false;
|
||||
} else if (op == JSOP_INITELEM_ARRAY) {
|
||||
MOZ_ASSERT(uint32_t(index.toInt32()) == GET_UINT24(pc));
|
||||
MOZ_ASSERT(uint32_t(index.toInt32()) <= INT32_MAX,
|
||||
"the bytecode emitter must fail to compile code that would "
|
||||
"produce JSOP_INITELEM_ARRAY with an index exceeding "
|
||||
"int32_t range");
|
||||
MOZ_ASSERT(uint32_t(index.toInt32()) == GET_UINT32(pc));
|
||||
if (!InitArrayElemOperation(cx, pc, obj, index.toInt32(), rhs))
|
||||
return false;
|
||||
} else if (op == JSOP_INITELEM_INC) {
|
||||
|
@ -4220,12 +4220,12 @@ CodeGenerator::visitNewArrayCallVM(LNewArray* lir)
|
||||
if (templateObject) {
|
||||
pushArg(Imm32(lir->mir()->convertDoubleElements()));
|
||||
pushArg(ImmGCPtr(templateObject->group()));
|
||||
pushArg(Imm32(lir->mir()->count()));
|
||||
pushArg(Imm32(lir->mir()->length()));
|
||||
|
||||
callVM(NewArrayWithGroupInfo, lir);
|
||||
} else {
|
||||
pushArg(Imm32(GenericObject));
|
||||
pushArg(Imm32(lir->mir()->count()));
|
||||
pushArg(Imm32(lir->mir()->length()));
|
||||
pushArg(ImmPtr(lir->mir()->pc()));
|
||||
pushArg(ImmGCPtr(lir->mir()->block()->info().script()));
|
||||
|
||||
@ -4301,9 +4301,9 @@ CodeGenerator::visitNewArray(LNewArray* lir)
|
||||
Register objReg = ToRegister(lir->output());
|
||||
Register tempReg = ToRegister(lir->temp());
|
||||
JSObject* templateObject = lir->mir()->templateObject();
|
||||
DebugOnly<uint32_t> count = lir->mir()->count();
|
||||
DebugOnly<uint32_t> length = lir->mir()->length();
|
||||
|
||||
MOZ_ASSERT(count < NativeObject::NELEMENTS_LIMIT);
|
||||
MOZ_ASSERT(length <= NativeObject::MAX_DENSE_ELEMENTS_COUNT);
|
||||
|
||||
if (lir->mir()->shouldUseVM()) {
|
||||
visitNewArrayCallVM(lir);
|
||||
@ -6946,7 +6946,7 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
|
||||
key, &callStub);
|
||||
|
||||
// Update initialized length. The capacity guard above ensures this won't overflow,
|
||||
// due to NELEMENTS_LIMIT.
|
||||
// due to MAX_DENSE_ELEMENTS_COUNT.
|
||||
masm.bumpKey(&key, 1);
|
||||
masm.storeKey(key, Address(elements, ObjectElements::offsetOfInitializedLength()));
|
||||
|
||||
|
@ -1794,7 +1794,7 @@ IonBuilder::inspectOpcode(JSOp op)
|
||||
return jsop_newobject();
|
||||
|
||||
case JSOP_NEWARRAY:
|
||||
return jsop_newarray(GET_UINT24(pc));
|
||||
return jsop_newarray(GET_UINT32(pc));
|
||||
|
||||
case JSOP_NEWARRAY_COPYONWRITE:
|
||||
return jsop_newarray_copyonwrite();
|
||||
@ -6925,7 +6925,7 @@ IonBuilder::compareTrySharedStub(bool* emitted, JSOp op, MDefinition* left, MDef
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::jsop_newarray(uint32_t count)
|
||||
IonBuilder::jsop_newarray(uint32_t length)
|
||||
{
|
||||
JSObject* templateObject = inspector->getTemplateObject(pc);
|
||||
gc::InitialHeap heap;
|
||||
@ -6940,7 +6940,7 @@ IonBuilder::jsop_newarray(uint32_t count)
|
||||
}
|
||||
current->add(templateConst);
|
||||
|
||||
MNewArray* ins = MNewArray::New(alloc(), constraints(), count, templateConst, heap, pc);
|
||||
MNewArray* ins = MNewArray::New(alloc(), constraints(), length, templateConst, heap, pc);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
|
||||
@ -7052,13 +7052,14 @@ IonBuilder::jsop_initelem_array()
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t index = GET_UINT32(pc);
|
||||
if (needStub) {
|
||||
MCallInitElementArray* store = MCallInitElementArray::New(alloc(), obj, GET_UINT24(pc), value);
|
||||
MCallInitElementArray* store = MCallInitElementArray::New(alloc(), obj, index, value);
|
||||
current->add(store);
|
||||
return resumeAfter(store);
|
||||
}
|
||||
|
||||
return initializeArrayElement(obj, GET_UINT24(pc), value, unboxedType, /* addResumePoint = */ true);
|
||||
return initializeArrayElement(obj, index, value, unboxedType, /* addResumePoint = */ true);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -696,7 +696,7 @@ class IonBuilder
|
||||
bool jsop_setprop(PropertyName* name);
|
||||
bool jsop_delprop(PropertyName* name);
|
||||
bool jsop_delelem();
|
||||
bool jsop_newarray(uint32_t count);
|
||||
bool jsop_newarray(uint32_t length);
|
||||
bool jsop_newarray_copyonwrite();
|
||||
bool jsop_newobject();
|
||||
bool jsop_initelem();
|
||||
|
@ -442,8 +442,9 @@ IonBuilder::inlineArray(CallInfo& callInfo)
|
||||
|
||||
// Negative lengths generate a RangeError, unhandled by the inline path.
|
||||
initLength = arg->constantValue().toInt32();
|
||||
if (initLength >= NativeObject::NELEMENTS_LIMIT)
|
||||
if (initLength > NativeObject::MAX_DENSE_ELEMENTS_COUNT)
|
||||
return InliningStatus_NotInlined;
|
||||
MOZ_ASSERT(initLength <= INT32_MAX);
|
||||
|
||||
// Make sure initLength matches the template object's length. This is
|
||||
// not guaranteed to be the case, for instance if we're inlining the
|
||||
|
@ -4050,7 +4050,7 @@ MArrayState::MArrayState(MDefinition* arr)
|
||||
// This instruction is only used as a summary for bailout paths.
|
||||
setResultType(MIRType_Object);
|
||||
setRecoveredOnBailout();
|
||||
numElements_ = arr->toNewArray()->count();
|
||||
numElements_ = arr->toNewArray()->length();
|
||||
}
|
||||
|
||||
bool
|
||||
@ -4090,10 +4090,10 @@ MArrayState::Copy(TempAllocator& alloc, MArrayState* state)
|
||||
return res;
|
||||
}
|
||||
|
||||
MNewArray::MNewArray(CompilerConstraintList* constraints, uint32_t count, MConstant* templateConst,
|
||||
MNewArray::MNewArray(CompilerConstraintList* constraints, uint32_t length, MConstant* templateConst,
|
||||
gc::InitialHeap initialHeap, jsbytecode* pc)
|
||||
: MUnaryInstruction(templateConst),
|
||||
count_(count),
|
||||
length_(length),
|
||||
initialHeap_(initialHeap),
|
||||
convertDoubleElements_(false),
|
||||
pc_(pc)
|
||||
@ -4115,16 +4115,16 @@ MNewArray::shouldUseVM() const
|
||||
return true;
|
||||
|
||||
if (templateObject()->is<UnboxedArrayObject>()) {
|
||||
MOZ_ASSERT(templateObject()->as<UnboxedArrayObject>().capacity() >= count());
|
||||
MOZ_ASSERT(templateObject()->as<UnboxedArrayObject>().capacity() >= length());
|
||||
return !templateObject()->as<UnboxedArrayObject>().hasInlineElements();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(count() < NativeObject::NELEMENTS_LIMIT);
|
||||
MOZ_ASSERT(length() <= NativeObject::MAX_DENSE_ELEMENTS_COUNT);
|
||||
|
||||
size_t arraySlots =
|
||||
gc::GetGCKindSlots(templateObject()->asTenured().getAllocKind()) - ObjectElements::VALUES_PER_HEADER;
|
||||
|
||||
return count() > arraySlots;
|
||||
return length() > arraySlots;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -2905,8 +2905,8 @@ class MNewArray
|
||||
public NoTypePolicy::Data
|
||||
{
|
||||
private:
|
||||
// Number of space to allocate for the array.
|
||||
uint32_t count_;
|
||||
// Number of elements to allocate for the array.
|
||||
uint32_t length_;
|
||||
|
||||
// Heap where the array should be allocated.
|
||||
gc::InitialHeap initialHeap_;
|
||||
@ -2916,21 +2916,21 @@ class MNewArray
|
||||
|
||||
jsbytecode* pc_;
|
||||
|
||||
MNewArray(CompilerConstraintList* constraints, uint32_t count, MConstant* templateConst,
|
||||
MNewArray(CompilerConstraintList* constraints, uint32_t length, MConstant* templateConst,
|
||||
gc::InitialHeap initialHeap, jsbytecode* pc);
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(NewArray)
|
||||
|
||||
static MNewArray* New(TempAllocator& alloc, CompilerConstraintList* constraints,
|
||||
uint32_t count, MConstant* templateConst,
|
||||
uint32_t length, MConstant* templateConst,
|
||||
gc::InitialHeap initialHeap, jsbytecode* pc)
|
||||
{
|
||||
return new(alloc) MNewArray(constraints, count, templateConst, initialHeap, pc);
|
||||
return new(alloc) MNewArray(constraints, length, templateConst, initialHeap, pc);
|
||||
}
|
||||
|
||||
uint32_t count() const {
|
||||
return count_;
|
||||
uint32_t length() const {
|
||||
return length_;
|
||||
}
|
||||
|
||||
JSObject* templateObject() const {
|
||||
|
@ -1734,7 +1734,7 @@ MArrayLength::computeRange(TempAllocator& alloc)
|
||||
void
|
||||
MInitializedLength::computeRange(TempAllocator& alloc)
|
||||
{
|
||||
setRange(Range::NewUInt32Range(alloc, 0, NativeObject::NELEMENTS_LIMIT));
|
||||
setRange(Range::NewUInt32Range(alloc, 0, NativeObject::MAX_DENSE_ELEMENTS_COUNT));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1207,7 +1207,7 @@ MNewArray::writeRecoverData(CompactBufferWriter& writer) const
|
||||
{
|
||||
MOZ_ASSERT(canRecoverOnBailout());
|
||||
writer.writeUnsigned(uint32_t(RInstruction::Recover_NewArray));
|
||||
writer.writeUnsigned(count());
|
||||
writer.writeUnsigned(length());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -895,7 +895,7 @@ IsArrayEscaped(MInstruction* ins)
|
||||
{
|
||||
MOZ_ASSERT(ins->type() == MIRType_Object);
|
||||
MOZ_ASSERT(ins->isNewArray());
|
||||
uint32_t count = ins->toNewArray()->count();
|
||||
uint32_t length = ins->toNewArray()->length();
|
||||
|
||||
JitSpewDef(JitSpew_Escape, "Check array\n", ins);
|
||||
JitSpewIndent spewIndent(JitSpew_Escape);
|
||||
@ -911,7 +911,7 @@ IsArrayEscaped(MInstruction* ins)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (count >= 16) {
|
||||
if (length >= 16) {
|
||||
JitSpew(JitSpew_Escape, "Array has too many elements");
|
||||
return true;
|
||||
}
|
||||
@ -935,7 +935,7 @@ IsArrayEscaped(MInstruction* ins)
|
||||
case MDefinition::Op_Elements: {
|
||||
MElements *elem = def->toElements();
|
||||
MOZ_ASSERT(elem->object() == ins);
|
||||
if (IsElementEscaped(elem, count)) {
|
||||
if (IsElementEscaped(elem, length)) {
|
||||
JitSpewDef(JitSpew_Escape, "is indirectly escaped by\n", elem);
|
||||
return true;
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ GetGCObjectKind(size_t numSlots)
|
||||
|
||||
/* As for GetGCObjectKind, but for dense array allocation. */
|
||||
static inline AllocKind
|
||||
GetGCArrayKind(size_t numSlots)
|
||||
GetGCArrayKind(size_t numElements)
|
||||
{
|
||||
/*
|
||||
* Dense arrays can use their fixed slots to hold their elements array
|
||||
@ -181,9 +181,12 @@ GetGCArrayKind(size_t numSlots)
|
||||
* unused.
|
||||
*/
|
||||
JS_STATIC_ASSERT(ObjectElements::VALUES_PER_HEADER == 2);
|
||||
if (numSlots > NativeObject::NELEMENTS_LIMIT || numSlots + 2 >= SLOTS_TO_THING_KIND_LIMIT)
|
||||
if (numElements > NativeObject::MAX_DENSE_ELEMENTS_COUNT ||
|
||||
numElements + ObjectElements::VALUES_PER_HEADER >= SLOTS_TO_THING_KIND_LIMIT)
|
||||
{
|
||||
return AllocKind::OBJECT2;
|
||||
return slotsToThingKind[numSlots + 2];
|
||||
}
|
||||
return slotsToThingKind[numElements + ObjectElements::VALUES_PER_HEADER];
|
||||
}
|
||||
|
||||
static inline AllocKind
|
||||
|
@ -791,23 +791,23 @@ NewObjectWithGroup(ExclusiveContext* cx, HandleObjectGroup group,
|
||||
}
|
||||
|
||||
/*
|
||||
* As for gc::GetGCObjectKind, where numSlots is a guess at the final size of
|
||||
* As for gc::GetGCObjectKind, where numElements is a guess at the final size of
|
||||
* the object, zero if the final size is unknown. This should only be used for
|
||||
* objects that do not require any fixed slots.
|
||||
*/
|
||||
static inline gc::AllocKind
|
||||
GuessObjectGCKind(size_t numSlots)
|
||||
GuessObjectGCKind(size_t numElements)
|
||||
{
|
||||
if (numSlots)
|
||||
return gc::GetGCObjectKind(numSlots);
|
||||
if (numElements)
|
||||
return gc::GetGCObjectKind(numElements);
|
||||
return gc::AllocKind::OBJECT4;
|
||||
}
|
||||
|
||||
static inline gc::AllocKind
|
||||
GuessArrayGCKind(size_t numSlots)
|
||||
GuessArrayGCKind(size_t numElements)
|
||||
{
|
||||
if (numSlots)
|
||||
return gc::GetGCArrayKind(numSlots);
|
||||
if (numElements)
|
||||
return gc::GetGCArrayKind(numElements);
|
||||
return gc::AllocKind::OBJECT8;
|
||||
}
|
||||
|
||||
|
@ -10,29 +10,26 @@
|
||||
/*
|
||||
* JS Capability Macros.
|
||||
*/
|
||||
#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
|
||||
#define JS_HAS_STR_HTML_HELPERS 1 /* (no longer used) */
|
||||
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
||||
#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
|
||||
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
|
||||
#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
|
||||
#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
|
||||
#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
|
||||
#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
|
||||
#define JS_HAS_CONST 1 /* (no longer used) */
|
||||
#define JS_HAS_FUN_EXPR_STMT 1 /* (no longer used) */
|
||||
#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
|
||||
#define JS_HAS_FOR_EACH_IN 1 /* has for each (lhs in iterable) */
|
||||
#define JS_HAS_GENERATORS 1 /* has yield in generator function */
|
||||
#define JS_HAS_BLOCK_SCOPE 1 /* has block scope via let/arraycomp */
|
||||
#define JS_HAS_DESTRUCTURING 2 /* has [a,b] = ... or {p:a,q:b} = ... */
|
||||
#define JS_HAS_GENERATORS 1 /* (no longer used) */
|
||||
#define JS_HAS_BLOCK_SCOPE 1 /* (no longer used) */
|
||||
#define JS_HAS_DESTRUCTURING 2 /* (no longer used) */
|
||||
#define JS_HAS_GENERATOR_EXPRS 1 /* has (expr for (lhs in iterable)) */
|
||||
#define JS_HAS_EXPR_CLOSURES 1 /* has function (formals) listexpr */
|
||||
|
||||
/* Support for JS_NewGlobalObject. */
|
||||
/* (no longer used) */
|
||||
#define JS_HAS_NEW_GLOBAL_OBJECT 1
|
||||
|
||||
/* Support for JS_MakeSystemObject. */
|
||||
#define JS_HAS_MAKE_SYSTEM_OBJECT 1
|
||||
|
||||
/* Feature-test macro for evolving destructuring support. */
|
||||
/* (no longer used) */
|
||||
#define JS_HAS_DESTRUCTURING_SHORTHAND (JS_HAS_DESTRUCTURING == 2)
|
||||
|
||||
/*
|
||||
|
@ -3609,7 +3609,8 @@ END_CASE(JSOP_NEWINIT)
|
||||
CASE(JSOP_NEWARRAY)
|
||||
CASE(JSOP_SPREADCALLARRAY)
|
||||
{
|
||||
JSObject* obj = NewArrayOperation(cx, script, REGS.pc, GET_UINT24(REGS.pc));
|
||||
uint32_t length = GET_UINT32(REGS.pc);
|
||||
JSObject* obj = NewArrayOperation(cx, script, REGS.pc, length);
|
||||
if (!obj)
|
||||
goto error;
|
||||
PUSH_OBJECT(*obj);
|
||||
@ -3705,7 +3706,7 @@ CASE(JSOP_INITELEM_ARRAY)
|
||||
|
||||
ReservedRooted<JSObject*> obj(&rootObject0, ®S.sp[-2].toObject());
|
||||
|
||||
uint32_t index = GET_UINT24(REGS.pc);
|
||||
uint32_t index = GET_UINT32(REGS.pc);
|
||||
if (!InitArrayElemOperation(cx, REGS.pc, obj, index, val))
|
||||
goto error;
|
||||
|
||||
|
@ -6,7 +6,8 @@
|
||||
|
||||
#include "vm/NativeObject-inl.h"
|
||||
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Casting.h"
|
||||
|
||||
#include "jswatchpoint.h"
|
||||
|
||||
@ -25,6 +26,7 @@
|
||||
using namespace js;
|
||||
|
||||
using JS::GenericNaN;
|
||||
using mozilla::ArrayLength;
|
||||
using mozilla::DebugOnly;
|
||||
using mozilla::PodCopy;
|
||||
using mozilla::RoundUpPow2;
|
||||
@ -397,7 +399,7 @@ NativeObject::growSlots(ExclusiveContext* cx, uint32_t oldCount, uint32_t newCou
|
||||
* throttled well before the slot capacity can overflow.
|
||||
*/
|
||||
NativeObject::slotsSizeMustNotOverflow();
|
||||
MOZ_ASSERT(newCount < NELEMENTS_LIMIT);
|
||||
MOZ_ASSERT(newCount <= MAX_SLOTS_COUNT);
|
||||
|
||||
if (!oldCount) {
|
||||
MOZ_ASSERT(!slots_);
|
||||
@ -519,7 +521,7 @@ NativeObject::willBeSparseElements(uint32_t requiredCapacity, uint32_t newElemen
|
||||
uint32_t cap = getDenseCapacity();
|
||||
MOZ_ASSERT(requiredCapacity >= cap);
|
||||
|
||||
if (requiredCapacity >= NELEMENTS_LIMIT)
|
||||
if (requiredCapacity > MAX_DENSE_ELEMENTS_COUNT)
|
||||
return true;
|
||||
|
||||
uint32_t minimalDenseCount = requiredCapacity / SPARSE_DENSITY_RATIO;
|
||||
@ -593,7 +595,7 @@ NativeObject::maybeDensifySparseElements(js::ExclusiveContext* cx, HandleNativeO
|
||||
if (numDenseElements * SPARSE_DENSITY_RATIO < newInitializedLength)
|
||||
return DenseElementResult::Incomplete;
|
||||
|
||||
if (newInitializedLength >= NELEMENTS_LIMIT)
|
||||
if (newInitializedLength > MAX_DENSE_ELEMENTS_COUNT)
|
||||
return DenseElementResult::Incomplete;
|
||||
|
||||
/*
|
||||
@ -654,97 +656,95 @@ NativeObject::maybeDensifySparseElements(js::ExclusiveContext* cx, HandleNativeO
|
||||
return DenseElementResult::Success;
|
||||
}
|
||||
|
||||
// Round up |reqAllocated| to a good size. Up to 1 Mebi (i.e. 1,048,576) the
|
||||
// slot count is usually a power-of-two:
|
||||
// Given a requested allocation amount (in elements) and (potentially) the
|
||||
// length of an array for which elements are being allocated, compute an actual
|
||||
// allocation amount (in elements). (Allocation amounts include space for an
|
||||
// ObjectElements instance, so a return value of |N| implies
|
||||
// |N - ObjectElements::VALUES_PER_HEADER| usable elements.)
|
||||
//
|
||||
// 8, 16, 32, 64, ..., 256 Ki, 512 Ki, 1 Mi
|
||||
// The requested/actual allocation distinction is meant to:
|
||||
//
|
||||
// Beyond that, we use this formula:
|
||||
//
|
||||
// count(n+1) = Math.ceil(count(n) * 1.125)
|
||||
//
|
||||
// where |count(n)| is the size of the nth bucket measured in MiSlots.
|
||||
//
|
||||
// These counts lets us add N elements to an array in amortized O(N) time.
|
||||
// Having the second class means that for bigger arrays the constant factor is
|
||||
// higher, but we waste less space.
|
||||
//
|
||||
// There is one exception to the above rule: for the power-of-two cases, if the
|
||||
// chosen capacity would be 2/3 or more of the array's length, the chosen
|
||||
// capacity is adjusted (up or down) to be equal to the array's length
|
||||
// (assuming length is at least as large as the required capacity). This avoids
|
||||
// the allocation of excess elements which are unlikely to be needed, either in
|
||||
// this resizing or a subsequent one. The 2/3 factor is chosen so that
|
||||
// exceptional resizings will at most triple the capacity, as opposed to the
|
||||
// usual doubling.
|
||||
// * preserve amortized O(N) time to add N elements;
|
||||
// * minimize the number of unused elements beyond an array's length, and
|
||||
// * provide at least SLOT_CAPACITY_MIN elements no matter what (so adding
|
||||
// the first several elements to small arrays only needs one allocation).
|
||||
//
|
||||
// Note: the structure and behavior of this method follow along with
|
||||
// UnboxedArrayObject::chooseCapacityIndex. Changes to the allocation strategy
|
||||
// in one should generally be matched by the other.
|
||||
/* static */ uint32_t
|
||||
NativeObject::goodAllocated(uint32_t reqAllocated, uint32_t length = 0)
|
||||
NativeObject::goodElementsAllocationAmount(uint32_t reqAllocated, uint32_t length = 0)
|
||||
{
|
||||
static const uint32_t Mebi = 1024 * 1024;
|
||||
// Handle "small" requests primarily by doubling.
|
||||
const uint32_t Mebi = 1 << 20;
|
||||
if (reqAllocated < Mebi) {
|
||||
uint32_t goodAmount = mozilla::AssertedCast<uint32_t>(RoundUpPow2(reqAllocated));
|
||||
|
||||
// This table was generated with this JavaScript code and a small amount
|
||||
// subsequent reformatting:
|
||||
//
|
||||
// for (let n = 1, i = 0; i < 57; i++) {
|
||||
// print((n * 1024 * 1024) + ', ');
|
||||
// n = Math.ceil(n * 1.125);
|
||||
// }
|
||||
// print('0');
|
||||
//
|
||||
// The final element is a sentinel value.
|
||||
static const uint32_t BigBuckets[] = {
|
||||
1048576, 2097152, 3145728, 4194304, 5242880, 6291456, 7340032, 8388608,
|
||||
9437184, 11534336, 13631488, 15728640, 17825792, 20971520, 24117248,
|
||||
27262976, 31457280, 35651584, 40894464, 46137344, 52428800, 59768832,
|
||||
68157440, 77594624, 88080384, 99614720, 112197632, 126877696,
|
||||
143654912, 162529280, 183500800, 206569472, 232783872, 262144000,
|
||||
295698432, 333447168, 375390208, 422576128, 476053504, 535822336,
|
||||
602931200, 678428672, 763363328, 858783744, 966787072, 1088421888,
|
||||
1224736768, 1377828864, 1550843904, 1744830464, 1962934272, 2208301056,
|
||||
2485125120, 2796552192, 3146776576, 3541041152, 3984588800, 0
|
||||
};
|
||||
|
||||
// This code relies very much on |goodAllocated| being a uint32_t.
|
||||
uint32_t goodAllocated = reqAllocated;
|
||||
if (goodAllocated < Mebi) {
|
||||
goodAllocated = RoundUpPow2(goodAllocated);
|
||||
|
||||
// Look for the abovementioned exception.
|
||||
uint32_t goodCapacity = goodAllocated - ObjectElements::VALUES_PER_HEADER;
|
||||
// If |goodAmount| would be 2/3 or more of the array's length, adjust
|
||||
// it (up or down) to be equal to the array's length. This avoids
|
||||
// allocating excess elements that aren't likely to be needed, either
|
||||
// in this resizing or a subsequent one. The 2/3 factor is chosen so
|
||||
// that exceptional resizings will at most triple the capacity, as
|
||||
// opposed to the usual doubling.
|
||||
uint32_t goodCapacity = goodAmount - ObjectElements::VALUES_PER_HEADER;
|
||||
uint32_t reqCapacity = reqAllocated - ObjectElements::VALUES_PER_HEADER;
|
||||
if (length >= reqCapacity && goodCapacity > (length / 3) * 2)
|
||||
goodAllocated = length + ObjectElements::VALUES_PER_HEADER;
|
||||
goodAmount = length + ObjectElements::VALUES_PER_HEADER;
|
||||
|
||||
if (goodAllocated < SLOT_CAPACITY_MIN)
|
||||
goodAllocated = SLOT_CAPACITY_MIN;
|
||||
if (goodAmount < SLOT_CAPACITY_MIN)
|
||||
goodAmount = SLOT_CAPACITY_MIN;
|
||||
|
||||
} else {
|
||||
uint32_t i = 0;
|
||||
while (true) {
|
||||
uint32_t b = BigBuckets[i++];
|
||||
if (b >= goodAllocated) {
|
||||
// Found the first bucket greater than or equal to
|
||||
// |goodAllocated|.
|
||||
goodAllocated = b;
|
||||
break;
|
||||
} else if (b == 0) {
|
||||
// Hit the end; return the maximum possible goodAllocated.
|
||||
goodAllocated = 0xffffffff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return goodAmount;
|
||||
}
|
||||
|
||||
return goodAllocated;
|
||||
// The almost-doubling above wastes a lot of space for larger bucket sizes.
|
||||
// For large amounts, switch to bucket sizes that obey this formula:
|
||||
//
|
||||
// count(n+1) = Math.ceil(count(n) * 1.125)
|
||||
//
|
||||
// where |count(n)| is the size of the nth bucket, measured in 2**20 slots.
|
||||
// These bucket sizes still preserve amortized O(N) time to add N elements,
|
||||
// just with a larger constant factor.
|
||||
//
|
||||
// The bucket size table below was generated with this JavaScript (and
|
||||
// manual reformatting):
|
||||
//
|
||||
// for (let n = 1, i = 0; i < 34; i++) {
|
||||
// print('0x' + (n * (1 << 20)).toString(16) + ', ');
|
||||
// n = Math.ceil(n * 1.125);
|
||||
// }
|
||||
// print('MAX_DENSE_ELEMENTS_ALLOCATION');
|
||||
//
|
||||
// Dense array elements can't exceed |MAX_DENSE_ELEMENTS_ALLOCATION|, so
|
||||
// |MAX_DENSE_ELEMENTS_ALLOCATION| is the biggest allowed length.
|
||||
static const uint32_t BigBuckets[] = {
|
||||
0x100000, 0x200000, 0x300000, 0x400000, 0x500000, 0x600000, 0x700000,
|
||||
0x800000, 0x900000, 0xb00000, 0xd00000, 0xf00000, 0x1100000, 0x1400000,
|
||||
0x1700000, 0x1a00000, 0x1e00000, 0x2200000, 0x2700000, 0x2c00000,
|
||||
0x3200000, 0x3900000, 0x4100000, 0x4a00000, 0x5400000, 0x5f00000,
|
||||
0x6b00000, 0x7900000, 0x8900000, 0x9b00000, 0xaf00000, 0xc500000,
|
||||
0xde00000, 0xfa00000, MAX_DENSE_ELEMENTS_ALLOCATION
|
||||
};
|
||||
MOZ_ASSERT(BigBuckets[ArrayLength(BigBuckets) - 2] <= MAX_DENSE_ELEMENTS_ALLOCATION);
|
||||
|
||||
// Pick the first bucket that'll fit |reqAllocated|.
|
||||
for (uint32_t b : BigBuckets) {
|
||||
if (b >= reqAllocated)
|
||||
return b;
|
||||
}
|
||||
|
||||
// Otherwise, return the maximum bucket size.
|
||||
return MAX_DENSE_ELEMENTS_ALLOCATION;
|
||||
}
|
||||
|
||||
bool
|
||||
NativeObject::growElements(ExclusiveContext* cx, uint32_t reqCapacity)
|
||||
{
|
||||
if (reqCapacity > MAX_DENSE_ELEMENTS_COUNT) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(nonProxyIsExtensible());
|
||||
MOZ_ASSERT(canHaveNonEmptyElements());
|
||||
if (denseElementsAreCopyOnWrite())
|
||||
@ -753,17 +753,9 @@ NativeObject::growElements(ExclusiveContext* cx, uint32_t reqCapacity)
|
||||
uint32_t oldCapacity = getDenseCapacity();
|
||||
MOZ_ASSERT(oldCapacity < reqCapacity);
|
||||
|
||||
using mozilla::CheckedInt;
|
||||
|
||||
CheckedInt<uint32_t> checkedOldAllocated =
|
||||
CheckedInt<uint32_t>(oldCapacity) + ObjectElements::VALUES_PER_HEADER;
|
||||
CheckedInt<uint32_t> checkedReqAllocated =
|
||||
CheckedInt<uint32_t>(reqCapacity) + ObjectElements::VALUES_PER_HEADER;
|
||||
if (!checkedOldAllocated.isValid() || !checkedReqAllocated.isValid())
|
||||
return false;
|
||||
|
||||
uint32_t reqAllocated = checkedReqAllocated.value();
|
||||
uint32_t oldAllocated = checkedOldAllocated.value();
|
||||
uint32_t reqAllocated = reqCapacity + ObjectElements::VALUES_PER_HEADER;
|
||||
uint32_t oldAllocated = oldCapacity + ObjectElements::VALUES_PER_HEADER;
|
||||
MOZ_ASSERT(oldAllocated <= MAX_DENSE_ELEMENTS_ALLOCATION);
|
||||
|
||||
uint32_t newAllocated;
|
||||
if (is<ArrayObject>() && !as<ArrayObject>().lengthIsWritable()) {
|
||||
@ -773,15 +765,15 @@ NativeObject::growElements(ExclusiveContext* cx, uint32_t reqCapacity)
|
||||
// enforces this requirement.
|
||||
newAllocated = reqAllocated;
|
||||
} else {
|
||||
newAllocated = goodAllocated(reqAllocated, getElementsHeader()->length);
|
||||
newAllocated = goodElementsAllocationAmount(reqAllocated, getElementsHeader()->length);
|
||||
}
|
||||
|
||||
uint32_t newCapacity = newAllocated - ObjectElements::VALUES_PER_HEADER;
|
||||
MOZ_ASSERT(newCapacity > oldCapacity && newCapacity >= reqCapacity);
|
||||
|
||||
// Don't let nelements get close to wrapping around uint32_t.
|
||||
if (newCapacity >= NELEMENTS_LIMIT)
|
||||
return false;
|
||||
// If newCapacity exceeds MAX_DENSE_ELEMENTS_COUNT, the array should become
|
||||
// sparse.
|
||||
MOZ_ASSERT(newCapacity <= MAX_DENSE_ELEMENTS_COUNT);
|
||||
|
||||
uint32_t initlen = getDenseInitializedLength();
|
||||
|
||||
@ -822,12 +814,13 @@ NativeObject::shrinkElements(ExclusiveContext* cx, uint32_t reqCapacity)
|
||||
|
||||
uint32_t oldAllocated = oldCapacity + ObjectElements::VALUES_PER_HEADER;
|
||||
uint32_t reqAllocated = reqCapacity + ObjectElements::VALUES_PER_HEADER;
|
||||
uint32_t newAllocated = goodAllocated(reqAllocated);
|
||||
uint32_t newAllocated = goodElementsAllocationAmount(reqAllocated);
|
||||
if (newAllocated == oldAllocated)
|
||||
return; // Leave elements at its old size.
|
||||
|
||||
MOZ_ASSERT(newAllocated > ObjectElements::VALUES_PER_HEADER);
|
||||
uint32_t newCapacity = newAllocated - ObjectElements::VALUES_PER_HEADER;
|
||||
MOZ_ASSERT(newCapacity <= MAX_DENSE_ELEMENTS_COUNT);
|
||||
|
||||
HeapSlot* oldHeaderSlots = reinterpret_cast<HeapSlot*>(getElementsHeader());
|
||||
HeapSlot* newHeaderSlots = ReallocateObjectBuffer<HeapSlot>(cx, this, oldHeaderSlots,
|
||||
@ -852,12 +845,12 @@ NativeObject::CopyElementsForWrite(ExclusiveContext* cx, NativeObject* obj)
|
||||
|
||||
uint32_t initlen = obj->getDenseInitializedLength();
|
||||
uint32_t allocated = initlen + ObjectElements::VALUES_PER_HEADER;
|
||||
uint32_t newAllocated = goodAllocated(allocated);
|
||||
uint32_t newAllocated = goodElementsAllocationAmount(allocated);
|
||||
|
||||
uint32_t newCapacity = newAllocated - ObjectElements::VALUES_PER_HEADER;
|
||||
|
||||
if (newCapacity >= NELEMENTS_LIMIT)
|
||||
return false;
|
||||
// COPY_ON_WRITE flags is set only if obj is a dense array.
|
||||
MOZ_ASSERT(newCapacity <= MAX_DENSE_ELEMENTS_COUNT);
|
||||
|
||||
JSObject::writeBarrierPre(obj->getElementsHeader()->ownerObject());
|
||||
|
||||
|
@ -556,8 +556,13 @@ class NativeObject : public JSObject
|
||||
bool shadowingShapeChange(ExclusiveContext* cx, const Shape& shape);
|
||||
bool clearFlag(ExclusiveContext* cx, BaseShape::Flag flag);
|
||||
|
||||
// The maximum number of slots in an object.
|
||||
// |MAX_SLOTS_COUNT * sizeof(JS::Value)| shouldn't overflow
|
||||
// int32_t (see slotsSizeMustNotOverflow).
|
||||
static const uint32_t MAX_SLOTS_COUNT = (1 << 28) - 1;
|
||||
|
||||
static void slotsSizeMustNotOverflow() {
|
||||
static_assert((NativeObject::NELEMENTS_LIMIT - 1) <= INT32_MAX / sizeof(JS::Value),
|
||||
static_assert(NativeObject::MAX_SLOTS_COUNT <= INT32_MAX / sizeof(JS::Value),
|
||||
"every caller of this method requires that a slot "
|
||||
"number (or slot count) count multiplied by "
|
||||
"sizeof(Value) can't overflow uint32_t (and sometimes "
|
||||
@ -882,11 +887,19 @@ class NativeObject : public JSObject
|
||||
|
||||
/* Elements accessors. */
|
||||
|
||||
/* Upper bound on the number of elements in an object. */
|
||||
static const uint32_t NELEMENTS_LIMIT = JS_BIT(28);
|
||||
// The maximum size, in sizeof(Value), of the allocation used for an
|
||||
// object's dense elements. (This includes space used to store an
|
||||
// ObjectElements instance.)
|
||||
// |MAX_DENSE_ELEMENTS_ALLOCATION * sizeof(JS::Value)| shouldn't overflow
|
||||
// int32_t (see elementsSizeMustNotOverflow).
|
||||
static const uint32_t MAX_DENSE_ELEMENTS_ALLOCATION = (1 << 28) - 1;
|
||||
|
||||
// The maximum number of usable dense elements in an object.
|
||||
static const uint32_t MAX_DENSE_ELEMENTS_COUNT =
|
||||
MAX_DENSE_ELEMENTS_ALLOCATION - ObjectElements::VALUES_PER_HEADER;
|
||||
|
||||
static void elementsSizeMustNotOverflow() {
|
||||
static_assert((NativeObject::NELEMENTS_LIMIT - 1) <= INT32_MAX / sizeof(JS::Value),
|
||||
static_assert(NativeObject::MAX_DENSE_ELEMENTS_COUNT <= INT32_MAX / sizeof(JS::Value),
|
||||
"every caller of this method require that an element "
|
||||
"count multiplied by sizeof(Value) can't overflow "
|
||||
"uint32_t (and sometimes int32_t ,too)");
|
||||
@ -904,7 +917,7 @@ class NativeObject : public JSObject
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t goodAllocated(uint32_t n, uint32_t length);
|
||||
static uint32_t goodElementsAllocationAmount(uint32_t n, uint32_t length);
|
||||
bool growElements(ExclusiveContext* cx, uint32_t newcap);
|
||||
void shrinkElements(ExclusiveContext* cx, uint32_t cap);
|
||||
void setDynamicElements(ObjectElements* header) {
|
||||
|
@ -847,10 +847,10 @@
|
||||
* This opcode takes the final length, which is preallocated.
|
||||
* Category: Literals
|
||||
* Type: Array
|
||||
* Operands: uint24_t length
|
||||
* Operands: uint32_t length
|
||||
* Stack: => obj
|
||||
*/ \
|
||||
macro(JSOP_NEWARRAY, 90, "newarray", NULL, 4, 0, 1, JOF_UINT24) \
|
||||
macro(JSOP_NEWARRAY, 90, "newarray", NULL, 5, 0, 1, JOF_UINT32) \
|
||||
/*
|
||||
* Pushes newly created object onto the stack.
|
||||
*
|
||||
@ -920,10 +920,10 @@
|
||||
* property of 'obj' as 'val', pushes 'obj' onto the stack.
|
||||
* Category: Literals
|
||||
* Type: Array
|
||||
* Operands: uint24_t index
|
||||
* Operands: uint32_t index
|
||||
* Stack: obj, val => obj
|
||||
*/ \
|
||||
macro(JSOP_INITELEM_ARRAY,96, "initelem_array", NULL, 4, 2, 1, JOF_UINT24|JOF_ELEM|JOF_SET|JOF_DETECTING) \
|
||||
macro(JSOP_INITELEM_ARRAY,96, "initelem_array", NULL, 5, 2, 1, JOF_UINT32|JOF_ELEM|JOF_SET|JOF_DETECTING) \
|
||||
\
|
||||
/*
|
||||
* Initialize a getter in an object literal.
|
||||
@ -1277,13 +1277,12 @@
|
||||
* the same semantics as JSOP_NEWARRAY, but is distinguished to avoid
|
||||
* using unboxed arrays in spread calls, which would make compiling spread
|
||||
* calls in baseline more complex.
|
||||
*
|
||||
* Category: Literals
|
||||
* Type: Array
|
||||
* Operands: uint24_t length
|
||||
* Operands: uint32_t length
|
||||
* Stack: => obj
|
||||
*/ \
|
||||
macro(JSOP_SPREADCALLARRAY, 126, "spreadcallarray", NULL, 4, 0, 1, JOF_UINT24) \
|
||||
macro(JSOP_SPREADCALLARRAY, 126, "spreadcallarray", NULL, 5, 0, 1, JOF_UINT32) \
|
||||
\
|
||||
/*
|
||||
* Defines the given function on the current scope.
|
||||
|
@ -29,7 +29,7 @@ namespace js {
|
||||
*
|
||||
* https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
|
||||
*/
|
||||
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 309;
|
||||
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 310;
|
||||
static const uint32_t XDR_BYTECODE_VERSION =
|
||||
uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);
|
||||
|
||||
|
@ -5118,9 +5118,11 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
|
||||
scale = gfxSize(1.0, 1.0);
|
||||
}
|
||||
// If this is a transform container layer, then pre-rendering might
|
||||
// mean we try render a layer bigger than the max texture size. Apply
|
||||
// clmaping to prevent this.
|
||||
if (aTransform) {
|
||||
// mean we try render a layer bigger than the max texture size. If we have
|
||||
// tiling, that's not a problem, since we'll automatically choose a tiled
|
||||
// layer for layers of that size. If not, we need to apply clamping to
|
||||
// prevent this.
|
||||
if (aTransform && !gfxPrefs::LayersTilesEnabled()) {
|
||||
RestrictScaleToMaxLayerSize(scale, aVisibleRect, aContainerFrame, aLayer);
|
||||
}
|
||||
} else {
|
||||
|
@ -4606,8 +4606,7 @@ nsCSSRendering::GetTextDecorationRectInternal(const gfxPoint& aPt,
|
||||
}
|
||||
|
||||
if (aVertical) {
|
||||
r.y = baseline + floor(offset + 0.5); // this will need updating when we
|
||||
// support sideways-left orientation
|
||||
r.y = baseline + floor(offset + 0.5);
|
||||
Swap(r.x, r.y);
|
||||
Swap(r.width, r.height);
|
||||
} else {
|
||||
|
@ -925,7 +925,8 @@ nsCaret::ComputeCaretRects(nsIFrame* aFrame, int32_t aFrameOffset,
|
||||
{
|
||||
NS_ASSERTION(aFrame, "Should have a frame here");
|
||||
|
||||
bool isVertical = aFrame->GetWritingMode().IsVertical();
|
||||
WritingMode wm = aFrame->GetWritingMode();
|
||||
bool isVertical = wm.IsVertical();
|
||||
|
||||
nscoord bidiIndicatorSize;
|
||||
*aCaretRect = GetGeometryForFrame(aFrame, aFrameOffset, &bidiIndicatorSize);
|
||||
@ -957,11 +958,20 @@ nsCaret::ComputeCaretRects(nsIFrame* aFrame, int32_t aFrameOffset,
|
||||
}
|
||||
bool isCaretRTL = caretBidiLevel % 2;
|
||||
if (isVertical) {
|
||||
aHookRect->SetRect(aCaretRect->XMost() - bidiIndicatorSize,
|
||||
aCaretRect->y + (isCaretRTL ? bidiIndicatorSize * -1 :
|
||||
aCaretRect->height),
|
||||
aCaretRect->height,
|
||||
bidiIndicatorSize);
|
||||
bool isSidewaysLR = wm.IsVerticalLR() && !wm.IsLineInverted();
|
||||
if (isSidewaysLR) {
|
||||
aHookRect->SetRect(aCaretRect->x + bidiIndicatorSize,
|
||||
aCaretRect->y + (!isCaretRTL ? bidiIndicatorSize * -1 :
|
||||
aCaretRect->height),
|
||||
aCaretRect->height,
|
||||
bidiIndicatorSize);
|
||||
} else {
|
||||
aHookRect->SetRect(aCaretRect->XMost() - bidiIndicatorSize,
|
||||
aCaretRect->y + (isCaretRTL ? bidiIndicatorSize * -1 :
|
||||
aCaretRect->height),
|
||||
aCaretRect->height,
|
||||
bidiIndicatorSize);
|
||||
}
|
||||
} else {
|
||||
aHookRect->SetRect(aCaretRect->x + (isCaretRTL ? bidiIndicatorSize * -1 :
|
||||
aCaretRect->width),
|
||||
|
@ -2613,7 +2613,7 @@ NS_IMETHODIMP nsDocumentViewer::SelectAll()
|
||||
rv = selection->RemoveAllRanges();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mozilla::dom::Selection::AutoApplyUserSelectStyle userSelection(selection);
|
||||
mozilla::dom::Selection::AutoUserInitiated userSelection(selection);
|
||||
rv = selection->SelectAllChildren(bodyNode);
|
||||
return rv;
|
||||
}
|
||||
|
@ -6663,10 +6663,9 @@ nsLayoutUtils::GetTextRunOrientFlagsForStyle(nsStyleContext* aStyleContext)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* not yet implemented:
|
||||
case NS_STYLE_WRITING_MODE_SIDEWAYS_LR:
|
||||
return gfxTextRunFactory::TEXT_ORIENT_VERTICAL_SIDEWAYS_LEFT;
|
||||
*/
|
||||
|
||||
case NS_STYLE_WRITING_MODE_SIDEWAYS_RL:
|
||||
return gfxTextRunFactory::TEXT_ORIENT_VERTICAL_SIDEWAYS_RIGHT;
|
||||
|
||||
|
@ -103,7 +103,7 @@ public:
|
||||
nsresult SubtractRange(RangeData* aRange, nsRange* aSubtract,
|
||||
nsTArray<RangeData>* aOutput);
|
||||
/**
|
||||
* AddItem adds aRange to this Selection. If mApplyUserSelectStyle is true,
|
||||
* AddItem adds aRange to this Selection. If mUserInitiated is true,
|
||||
* then aRange is first scanned for -moz-user-select:none nodes and split up
|
||||
* into multiple ranges to exclude those before adding the resulting ranges
|
||||
* to this Selection.
|
||||
@ -219,15 +219,15 @@ public:
|
||||
|
||||
nsresult NotifySelectionListeners();
|
||||
|
||||
friend struct AutoApplyUserSelectStyle;
|
||||
struct MOZ_RAII AutoApplyUserSelectStyle
|
||||
friend struct AutoUserInitiated;
|
||||
struct MOZ_RAII AutoUserInitiated
|
||||
{
|
||||
explicit AutoApplyUserSelectStyle(Selection* aSelection
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mSavedValue(aSelection->mApplyUserSelectStyle)
|
||||
explicit AutoUserInitiated(Selection* aSelection
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mSavedValue(aSelection->mUserInitiated)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
aSelection->mApplyUserSelectStyle = true;
|
||||
aSelection->mUserInitiated = true;
|
||||
}
|
||||
AutoRestore<bool> mSavedValue;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
@ -321,7 +321,7 @@ private:
|
||||
* It determines whether we exclude -moz-user-select:none nodes or not,
|
||||
* as well as whether selectstart events will be fired.
|
||||
*/
|
||||
bool mApplyUserSelectStyle;
|
||||
bool mUserInitiated;
|
||||
|
||||
// Non-zero if we don't want any changes we make to the selection to be
|
||||
// visible to content. If non-zero, content won't be notified about changes.
|
||||
|
@ -204,7 +204,15 @@ public:
|
||||
BidiDir GetBidiDir() const { return BidiDir(mWritingMode & eBidiMask); }
|
||||
|
||||
/**
|
||||
* Return true if LTR. (Convenience method)
|
||||
* Return true if the inline flow direction is against physical direction
|
||||
* (i.e. right-to-left or bottom-to-top).
|
||||
* This occurs when writing-mode is sideways-lr OR direction is rtl (but not
|
||||
* if both of those are true).
|
||||
*/
|
||||
bool IsInlineReversed() const { return !!(mWritingMode & eInlineFlowMask); }
|
||||
|
||||
/**
|
||||
* Return true if bidi direction is LTR. (Convenience method)
|
||||
*/
|
||||
bool IsBidiLTR() const { return eBidiLTR == GetBidiDir(); }
|
||||
|
||||
@ -226,9 +234,7 @@ public:
|
||||
|
||||
/**
|
||||
* True if line-over/line-under are inverted from block-start/block-end.
|
||||
* This is true when
|
||||
* - writing-mode is vertical-rl && text-orientation is sideways-left
|
||||
* - writing-mode is vertical-lr && text-orientation is not sideways-left
|
||||
* This is true only when writing-mode is vertical-lr.
|
||||
*/
|
||||
bool IsLineInverted() const { return !!(mWritingMode & eLineOrientMask); }
|
||||
|
||||
@ -315,23 +321,27 @@ public:
|
||||
// bit 1 = the eInlineFlowMask value
|
||||
// bit 2 = the eBlockFlowMask value
|
||||
// bit 3 = the eLineOrientMask value
|
||||
// Not all of these combinations can actually be specified via CSS: there
|
||||
// is no horizontal-bt writing-mode, and no text-orientation value that
|
||||
// produces "inverted" text. (The former 'sideways-left' value, no longer
|
||||
// in the spec, would have produced this in vertical-rl mode.)
|
||||
static const mozilla::css::Side kLogicalInlineSides[][2] = {
|
||||
{ NS_SIDE_LEFT, NS_SIDE_RIGHT }, // horizontal-tb ltr
|
||||
{ NS_SIDE_TOP, NS_SIDE_BOTTOM }, // vertical-rl ltr
|
||||
{ NS_SIDE_RIGHT, NS_SIDE_LEFT }, // horizontal-tb rtl
|
||||
{ NS_SIDE_BOTTOM, NS_SIDE_TOP }, // vertical-rl rtl
|
||||
{ NS_SIDE_RIGHT, NS_SIDE_LEFT }, // (horizontal-bt) (inverted) ltr
|
||||
{ NS_SIDE_TOP, NS_SIDE_BOTTOM }, // vertical-lr sideways-left rtl
|
||||
{ NS_SIDE_LEFT, NS_SIDE_RIGHT }, // (horizontal-bt) (inverted) rtl
|
||||
{ NS_SIDE_BOTTOM, NS_SIDE_TOP }, // vertical-lr sideways-left ltr
|
||||
{ NS_SIDE_LEFT, NS_SIDE_RIGHT }, // horizontal-tb (inverted) rtl
|
||||
{ NS_SIDE_TOP, NS_SIDE_BOTTOM }, // vertical-rl sideways-left rtl
|
||||
{ NS_SIDE_RIGHT, NS_SIDE_LEFT }, // horizontal-tb (inverted) ltr
|
||||
{ NS_SIDE_BOTTOM, NS_SIDE_TOP }, // vertical-rl sideways-left ltr
|
||||
{ NS_SIDE_LEFT, NS_SIDE_RIGHT }, // (horizontal-bt) ltr
|
||||
{ NS_SIDE_TOP, NS_SIDE_BOTTOM }, // vertical-lr ltr
|
||||
{ NS_SIDE_RIGHT, NS_SIDE_LEFT }, // (horizontal-bt) rtl
|
||||
{ NS_SIDE_BOTTOM, NS_SIDE_TOP }, // vertical-lr rtl
|
||||
{ NS_SIDE_LEFT, NS_SIDE_RIGHT }, // horizontal-tb ltr
|
||||
{ NS_SIDE_TOP, NS_SIDE_BOTTOM }, // vertical-rl ltr
|
||||
{ NS_SIDE_RIGHT, NS_SIDE_LEFT }, // horizontal-tb rtl
|
||||
{ NS_SIDE_BOTTOM, NS_SIDE_TOP }, // vertical-rl rtl
|
||||
{ NS_SIDE_RIGHT, NS_SIDE_LEFT }, // (horizontal-bt) (inverted) ltr
|
||||
{ NS_SIDE_TOP, NS_SIDE_BOTTOM }, // sideways-lr rtl
|
||||
{ NS_SIDE_LEFT, NS_SIDE_RIGHT }, // (horizontal-bt) (inverted) rtl
|
||||
{ NS_SIDE_BOTTOM, NS_SIDE_TOP }, // sideways-lr ltr
|
||||
{ NS_SIDE_LEFT, NS_SIDE_RIGHT }, // horizontal-tb (inverted) rtl
|
||||
{ NS_SIDE_TOP, NS_SIDE_BOTTOM }, // vertical-rl (inverted) rtl
|
||||
{ NS_SIDE_RIGHT, NS_SIDE_LEFT }, // horizontal-tb (inverted) ltr
|
||||
{ NS_SIDE_BOTTOM, NS_SIDE_TOP }, // vertical-rl (inverted) ltr
|
||||
{ NS_SIDE_LEFT, NS_SIDE_RIGHT }, // (horizontal-bt) ltr
|
||||
{ NS_SIDE_TOP, NS_SIDE_BOTTOM }, // vertical-lr ltr
|
||||
{ NS_SIDE_RIGHT, NS_SIDE_LEFT }, // (horizontal-bt) rtl
|
||||
{ NS_SIDE_BOTTOM, NS_SIDE_TOP }, // vertical-lr rtl
|
||||
};
|
||||
|
||||
// Inline axis sides depend on all three of writing-mode, text-orientation
|
||||
@ -426,7 +436,7 @@ public:
|
||||
{
|
||||
auto side = static_cast<LogicalSide>(aDir);
|
||||
if (IsInline(side)) {
|
||||
return IsBidiLTR() ? side : GetOppositeSide(side);
|
||||
return !IsInlineReversed() ? side : GetOppositeSide(side);
|
||||
}
|
||||
return !IsLineInverted() ? side : GetOppositeSide(side);
|
||||
}
|
||||
@ -686,13 +696,13 @@ public:
|
||||
#endif
|
||||
{
|
||||
if (aWritingMode.IsVertical()) {
|
||||
I() = aWritingMode.IsBidiLTR() ? aPoint.y
|
||||
: aContainerSize.height - aPoint.y;
|
||||
I() = aWritingMode.IsInlineReversed() ? aContainerSize.height - aPoint.y
|
||||
: aPoint.y;
|
||||
B() = aWritingMode.IsVerticalLR() ? aPoint.x
|
||||
: aContainerSize.width - aPoint.x;
|
||||
} else {
|
||||
I() = aWritingMode.IsBidiLTR() ? aPoint.x
|
||||
: aContainerSize.width - aPoint.x;
|
||||
I() = aWritingMode.IsInlineReversed() ? aContainerSize.width - aPoint.x
|
||||
: aPoint.x;
|
||||
B() = aPoint.y;
|
||||
}
|
||||
}
|
||||
@ -737,11 +747,11 @@ public:
|
||||
if (aWritingMode.IsVertical()) {
|
||||
return nsPoint(aWritingMode.IsVerticalLR()
|
||||
? B() : aContainerSize.width - B(),
|
||||
aWritingMode.IsBidiLTR()
|
||||
? I() : aContainerSize.height - I());
|
||||
aWritingMode.IsInlineReversed()
|
||||
? aContainerSize.height - I() : I());
|
||||
} else {
|
||||
return nsPoint(aWritingMode.IsBidiLTR()
|
||||
? I() : aContainerSize.width - I(),
|
||||
return nsPoint(aWritingMode.IsInlineReversed()
|
||||
? aContainerSize.width - I() : I(),
|
||||
B());
|
||||
}
|
||||
}
|
||||
@ -1097,22 +1107,22 @@ public:
|
||||
mMargin.top = aPhysicalMargin.right;
|
||||
mMargin.bottom = aPhysicalMargin.left;
|
||||
}
|
||||
if (aWritingMode.IsBidiLTR()) {
|
||||
mMargin.left = aPhysicalMargin.top;
|
||||
mMargin.right = aPhysicalMargin.bottom;
|
||||
} else {
|
||||
if (aWritingMode.IsInlineReversed()) {
|
||||
mMargin.left = aPhysicalMargin.bottom;
|
||||
mMargin.right = aPhysicalMargin.top;
|
||||
} else {
|
||||
mMargin.left = aPhysicalMargin.top;
|
||||
mMargin.right = aPhysicalMargin.bottom;
|
||||
}
|
||||
} else {
|
||||
mMargin.top = aPhysicalMargin.top;
|
||||
mMargin.bottom = aPhysicalMargin.bottom;
|
||||
if (aWritingMode.IsBidiLTR()) {
|
||||
mMargin.left = aPhysicalMargin.left;
|
||||
mMargin.right = aPhysicalMargin.right;
|
||||
} else {
|
||||
if (aWritingMode.IsInlineReversed()) {
|
||||
mMargin.left = aPhysicalMargin.right;
|
||||
mMargin.right = aPhysicalMargin.left;
|
||||
} else {
|
||||
mMargin.left = aPhysicalMargin.left;
|
||||
mMargin.right = aPhysicalMargin.right;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1211,14 +1221,14 @@ public:
|
||||
{
|
||||
CHECK_WRITING_MODE(aWritingMode);
|
||||
return aWritingMode.IsVertical() ?
|
||||
(aWritingMode.IsBidiLTR() ? IStart() : IEnd()) : BStart();
|
||||
(aWritingMode.IsInlineReversed() ? IEnd() : IStart()) : BStart();
|
||||
}
|
||||
|
||||
nscoord Bottom(WritingMode aWritingMode) const
|
||||
{
|
||||
CHECK_WRITING_MODE(aWritingMode);
|
||||
return aWritingMode.IsVertical() ?
|
||||
(aWritingMode.IsBidiLTR() ? IEnd() : IStart()) : BEnd();
|
||||
(aWritingMode.IsInlineReversed() ? IStart() : IEnd()) : BEnd();
|
||||
}
|
||||
|
||||
nscoord Left(WritingMode aWritingMode) const
|
||||
@ -1226,7 +1236,7 @@ public:
|
||||
CHECK_WRITING_MODE(aWritingMode);
|
||||
return aWritingMode.IsVertical() ?
|
||||
(aWritingMode.IsVerticalLR() ? BStart() : BEnd()) :
|
||||
(aWritingMode.IsBidiLTR() ? IStart() : IEnd());
|
||||
(aWritingMode.IsInlineReversed() ? IEnd() : IStart());
|
||||
}
|
||||
|
||||
nscoord Right(WritingMode aWritingMode) const
|
||||
@ -1234,7 +1244,7 @@ public:
|
||||
CHECK_WRITING_MODE(aWritingMode);
|
||||
return aWritingMode.IsVertical() ?
|
||||
(aWritingMode.IsVerticalLR() ? BEnd() : BStart()) :
|
||||
(aWritingMode.IsBidiLTR() ? IEnd() : IStart());
|
||||
(aWritingMode.IsInlineReversed() ? IStart() : IEnd());
|
||||
}
|
||||
|
||||
nscoord LeftRight(WritingMode aWritingMode) const
|
||||
@ -1264,15 +1274,15 @@ public:
|
||||
CHECK_WRITING_MODE(aWritingMode);
|
||||
return aWritingMode.IsVertical()
|
||||
? (aWritingMode.IsVerticalLR()
|
||||
? (aWritingMode.IsBidiLTR()
|
||||
? nsMargin(IStart(), BEnd(), IEnd(), BStart())
|
||||
: nsMargin(IEnd(), BEnd(), IStart(), BStart()))
|
||||
: (aWritingMode.IsBidiLTR()
|
||||
? nsMargin(IStart(), BStart(), IEnd(), BEnd())
|
||||
: nsMargin(IEnd(), BStart(), IStart(), BEnd())))
|
||||
: (aWritingMode.IsBidiLTR()
|
||||
? nsMargin(BStart(), IEnd(), BEnd(), IStart())
|
||||
: nsMargin(BStart(), IStart(), BEnd(), IEnd()));
|
||||
? (aWritingMode.IsInlineReversed()
|
||||
? nsMargin(IEnd(), BEnd(), IStart(), BStart())
|
||||
: nsMargin(IStart(), BEnd(), IEnd(), BStart()))
|
||||
: (aWritingMode.IsInlineReversed()
|
||||
? nsMargin(IEnd(), BStart(), IStart(), BEnd())
|
||||
: nsMargin(IStart(), BStart(), IEnd(), BEnd())))
|
||||
: (aWritingMode.IsInlineReversed()
|
||||
? nsMargin(BStart(), IStart(), BEnd(), IEnd())
|
||||
: nsMargin(BStart(), IEnd(), BEnd(), IStart()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1439,13 +1449,13 @@ public:
|
||||
if (aWritingMode.IsVertical()) {
|
||||
mRect.y = aWritingMode.IsVerticalLR()
|
||||
? aRect.x : aContainerSize.width - aRect.XMost();
|
||||
mRect.x = aWritingMode.IsBidiLTR()
|
||||
? aRect.y : aContainerSize.height - aRect.YMost();
|
||||
mRect.x = aWritingMode.IsInlineReversed()
|
||||
? aContainerSize.height - aRect.YMost() : aRect.y;
|
||||
mRect.height = aRect.width;
|
||||
mRect.width = aRect.height;
|
||||
} else {
|
||||
mRect.x = aWritingMode.IsBidiLTR()
|
||||
? aRect.x : aContainerSize.width - aRect.XMost();
|
||||
mRect.x = aWritingMode.IsInlineReversed()
|
||||
? aContainerSize.width - aRect.XMost() : aRect.x;
|
||||
mRect.y = aRect.y;
|
||||
mRect.width = aRect.width;
|
||||
mRect.height = aRect.height;
|
||||
@ -1548,8 +1558,8 @@ public:
|
||||
return aWritingMode.IsVerticalLR() ?
|
||||
mRect.Y() : aContainerWidth - mRect.YMost();
|
||||
} else {
|
||||
return aWritingMode.IsBidiLTR() ?
|
||||
mRect.X() : aContainerWidth - mRect.XMost();
|
||||
return aWritingMode.IsInlineReversed() ?
|
||||
aContainerWidth - mRect.XMost() : mRect.X();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1557,8 +1567,8 @@ public:
|
||||
{
|
||||
CHECK_WRITING_MODE(aWritingMode);
|
||||
if (aWritingMode.IsVertical()) {
|
||||
return aWritingMode.IsBidiLTR() ? mRect.X()
|
||||
: aContainerHeight - mRect.XMost();
|
||||
return aWritingMode.IsInlineReversed() ? aContainerHeight - mRect.XMost()
|
||||
: mRect.X();
|
||||
} else {
|
||||
return mRect.Y();
|
||||
}
|
||||
@ -1583,8 +1593,8 @@ public:
|
||||
return aWritingMode.IsVerticalLR() ?
|
||||
mRect.YMost() : aContainerWidth - mRect.Y();
|
||||
} else {
|
||||
return aWritingMode.IsBidiLTR() ?
|
||||
mRect.XMost() : aContainerWidth - mRect.X();
|
||||
return aWritingMode.IsInlineReversed() ?
|
||||
aContainerWidth - mRect.X() : mRect.XMost();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1592,8 +1602,8 @@ public:
|
||||
{
|
||||
CHECK_WRITING_MODE(aWritingMode);
|
||||
if (aWritingMode.IsVertical()) {
|
||||
return aWritingMode.IsBidiLTR() ? mRect.XMost()
|
||||
: aContainerHeight - mRect.x;
|
||||
return aWritingMode.IsInlineReversed() ? aContainerHeight - mRect.x
|
||||
: mRect.XMost();
|
||||
} else {
|
||||
return mRect.YMost();
|
||||
}
|
||||
@ -1707,12 +1717,12 @@ public:
|
||||
if (aWritingMode.IsVertical()) {
|
||||
return nsRect(aWritingMode.IsVerticalLR()
|
||||
? BStart() : aContainerSize.width - BEnd(),
|
||||
aWritingMode.IsBidiLTR()
|
||||
? IStart() : aContainerSize.height - IEnd(),
|
||||
aWritingMode.IsInlineReversed()
|
||||
? aContainerSize.height - IEnd() : IStart(),
|
||||
BSize(), ISize());
|
||||
} else {
|
||||
return nsRect(aWritingMode.IsBidiLTR()
|
||||
? IStart() : aContainerSize.width - IEnd(),
|
||||
return nsRect(aWritingMode.IsInlineReversed()
|
||||
? aContainerSize.width - IEnd() : IStart(),
|
||||
BStart(), ISize(), BSize());
|
||||
}
|
||||
}
|
||||
|
@ -1187,7 +1187,7 @@ nsImageFrame::DisplayAltText(nsPresContext* aPresContext,
|
||||
nscoord x, y;
|
||||
|
||||
if (isVertical) {
|
||||
x = pt.x + maxDescent; // XXX will need update for sideways-left
|
||||
x = pt.x + maxDescent;
|
||||
if (wm.IsBidiLTR()) {
|
||||
y = aRect.y;
|
||||
dir = NSBIDI_LTR;
|
||||
|
@ -350,7 +350,7 @@ struct MOZ_RAII AutoPrepareFocusRange
|
||||
if (aSelection->mFrameSelection->IsUserSelectionReason()) {
|
||||
mUserSelect.emplace(aSelection);
|
||||
}
|
||||
bool userSelection = aSelection->mApplyUserSelectStyle;
|
||||
bool userSelection = aSelection->mUserInitiated;
|
||||
|
||||
nsTArray<RangeData>& ranges = aSelection->mRanges;
|
||||
if (!userSelection ||
|
||||
@ -424,7 +424,7 @@ struct MOZ_RAII AutoPrepareFocusRange
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<Selection::AutoApplyUserSelectStyle> mUserSelect;
|
||||
Maybe<Selection::AutoUserInitiated> mUserSelect;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
@ -1682,7 +1682,7 @@ nsFrameSelection::TakeFocus(nsIContent* aNewFocus,
|
||||
if (!mDomSelections[index])
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
Maybe<Selection::AutoApplyUserSelectStyle> userSelect;
|
||||
Maybe<Selection::AutoUserInitiated> userSelect;
|
||||
if (IsUserSelectionReason()) {
|
||||
userSelect.emplace(mDomSelections[index]);
|
||||
}
|
||||
@ -3331,7 +3331,7 @@ Selection::Selection()
|
||||
: mCachedOffsetForFrame(nullptr)
|
||||
, mDirection(eDirNext)
|
||||
, mType(nsISelectionController::SELECTION_NORMAL)
|
||||
, mApplyUserSelectStyle(false)
|
||||
, mUserInitiated(false)
|
||||
, mSelectionChangeBlockerCount(0)
|
||||
{
|
||||
}
|
||||
@ -3341,7 +3341,7 @@ Selection::Selection(nsFrameSelection* aList)
|
||||
, mCachedOffsetForFrame(nullptr)
|
||||
, mDirection(eDirNext)
|
||||
, mType(nsISelectionController::SELECTION_NORMAL)
|
||||
, mApplyUserSelectStyle(false)
|
||||
, mUserInitiated(false)
|
||||
, mSelectionChangeBlockerCount(0)
|
||||
{
|
||||
}
|
||||
@ -3700,10 +3700,7 @@ Selection::AddItem(nsRange* aItem, int32_t* aOutIndex, bool aNoStartSelect)
|
||||
|
||||
NS_ASSERTION(aOutIndex, "aOutIndex can't be null");
|
||||
|
||||
// XXX Rename mApplyUserSelectStyle? Not the best name (as it is also being
|
||||
// used to detect here whether the event is user initiated for the purposes of
|
||||
// dispatching the selectstart event).
|
||||
if (mApplyUserSelectStyle) {
|
||||
if (mUserInitiated) {
|
||||
nsAutoTArray<nsRefPtr<nsRange>, 4> rangesToAdd;
|
||||
*aOutIndex = -1;
|
||||
|
||||
|
@ -5311,6 +5311,7 @@ nsTextFrame::DrawSelectionDecorations(gfxContext* aContext,
|
||||
const gfxFont::Metrics& aFontMetrics,
|
||||
DrawPathCallbacks* aCallbacks,
|
||||
bool aVertical,
|
||||
gfxFloat aDecorationOffsetDir,
|
||||
uint8_t aDecoration)
|
||||
{
|
||||
gfxPoint pt(aPt);
|
||||
@ -5417,8 +5418,8 @@ nsTextFrame::DrawSelectionDecorations(gfxContext* aContext,
|
||||
size.height *= relativeSize;
|
||||
PaintDecorationLine(aContext, aDirtyRect, color, nullptr, pt,
|
||||
(aVertical ? (pt.y - aPt.y) : (pt.x - aPt.x)) + aICoordInFrame,
|
||||
size, aAscent, offset, aDecoration, style, eSelectionDecoration,
|
||||
aCallbacks, aVertical, descentLimit);
|
||||
size, aAscent, offset * aDecorationOffsetDir, aDecoration, style,
|
||||
eSelectionDecoration, aCallbacks, aVertical, descentLimit);
|
||||
}
|
||||
|
||||
/* static */
|
||||
@ -5792,7 +5793,7 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
|
||||
mTextRun->GetAdvanceWidth(offset, length, &aProvider);
|
||||
if (NS_GET_A(background) > 0) {
|
||||
gfxRect bgRect;
|
||||
gfxFloat offs = iOffset - (mTextRun->IsRightToLeft() ? advance : 0);
|
||||
gfxFloat offs = iOffset - (mTextRun->IsInlineReversed() ? advance : 0);
|
||||
if (vertical) {
|
||||
bgRect = gfxRect(aFramePt.x, aFramePt.y + offs,
|
||||
GetSize().width, advance);
|
||||
@ -5829,7 +5830,7 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
|
||||
GetSelectionTextShadow(this, type, aTextPaintStyle, &shadow);
|
||||
if (shadow) {
|
||||
nscoord startEdge = iOffset;
|
||||
if (mTextRun->IsRightToLeft()) {
|
||||
if (mTextRun->IsInlineReversed()) {
|
||||
startEdge -= mTextRun->GetAdvanceWidth(offset, length, &aProvider) +
|
||||
hyphenWidth;
|
||||
}
|
||||
@ -5919,6 +5920,7 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx,
|
||||
}
|
||||
gfxRect dirtyRect(aDirtyRect.x / app, aDirtyRect.y / app,
|
||||
aDirtyRect.width / app, aDirtyRect.height / app);
|
||||
gfxFloat decorationOffsetDir = mTextRun->IsSidewaysLeft() ? -1.0 : 1.0;
|
||||
SelectionType type;
|
||||
TextRangeStyle selectedStyle;
|
||||
while (iterator.GetNextSegment(&iOffset, &offset, &length, &hyphenWidth,
|
||||
@ -5928,17 +5930,18 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx,
|
||||
if (type == aSelectionType) {
|
||||
if (verticalRun) {
|
||||
pt.y = (aFramePt.y + iOffset -
|
||||
(mTextRun->IsRightToLeft() ? advance : 0)) / app;
|
||||
(mTextRun->IsInlineReversed() ? advance : 0)) / app;
|
||||
} else {
|
||||
pt.x = (aFramePt.x + iOffset -
|
||||
(mTextRun->IsRightToLeft() ? advance : 0)) / app;
|
||||
(mTextRun->IsInlineReversed() ? advance : 0)) / app;
|
||||
}
|
||||
gfxFloat width = Abs(advance) / app;
|
||||
gfxFloat xInFrame = pt.x - (aFramePt.x / app);
|
||||
DrawSelectionDecorations(aCtx, dirtyRect, aSelectionType,
|
||||
aTextPaintStyle, selectedStyle, pt, xInFrame,
|
||||
width, mAscent / app, decorationMetrics,
|
||||
aCallbacks, verticalRun, kDecoration);
|
||||
aCallbacks, verticalRun, decorationOffsetDir,
|
||||
kDecoration);
|
||||
}
|
||||
iterator.UpdateWithAdvance(advance);
|
||||
}
|
||||
@ -6246,7 +6249,7 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
|
||||
provider.InitializeForDisplay(!IsSelected());
|
||||
|
||||
gfxContext* ctx = aRenderingContext->ThebesContext();
|
||||
const bool rtl = mTextRun->IsRightToLeft();
|
||||
const bool reversed = mTextRun->IsInlineReversed();
|
||||
const bool verticalRun = mTextRun->IsVertical();
|
||||
WritingMode wm = GetWritingMode();
|
||||
const nscoord frameWidth = GetSize().width;
|
||||
@ -6261,10 +6264,11 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
|
||||
nsLayoutUtils::GetSnappedBaselineX(this, ctx, aPt.x + frameWidth,
|
||||
-mAscent);
|
||||
}
|
||||
textBaselinePt.y = rtl ? aPt.y + GetSize().height : aPt.y;
|
||||
textBaselinePt.y = reversed ? aPt.y + GetSize().height : aPt.y;
|
||||
} else {
|
||||
textBaselinePt = gfxPoint(rtl ? gfxFloat(aPt.x + frameWidth) : framePt.x,
|
||||
nsLayoutUtils::GetSnappedBaselineY(this, ctx, aPt.y, mAscent));
|
||||
textBaselinePt =
|
||||
gfxPoint(reversed ? gfxFloat(aPt.x + frameWidth) : framePt.x,
|
||||
nsLayoutUtils::GetSnappedBaselineY(this, ctx, aPt.y, mAscent));
|
||||
}
|
||||
uint32_t startOffset = provider.GetStart().GetSkippedOffset();
|
||||
uint32_t maxLength = ComputeTransformedLength(provider);
|
||||
@ -6274,9 +6278,9 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
|
||||
return;
|
||||
}
|
||||
if (verticalRun) {
|
||||
textBaselinePt.y += rtl ? -snappedEndEdge : snappedStartEdge;
|
||||
textBaselinePt.y += reversed ? -snappedEndEdge : snappedStartEdge;
|
||||
} else {
|
||||
textBaselinePt.x += rtl ? -snappedEndEdge : snappedStartEdge;
|
||||
textBaselinePt.x += reversed ? -snappedEndEdge : snappedStartEdge;
|
||||
}
|
||||
nsCharClipDisplayItem::ClipEdges clipEdges(aItem, snappedStartEdge,
|
||||
snappedEndEdge);
|
||||
@ -6432,6 +6436,10 @@ nsTextFrame::DrawTextRunAndDecorations(
|
||||
nscoord inflationMinFontSize =
|
||||
nsLayoutUtils::InflationMinFontSizeFor(this);
|
||||
|
||||
// The decoration-line offsets need to be reversed for sideways-lr mode,
|
||||
// so we will multiply the values from metrics by this factor.
|
||||
gfxFloat decorationOffsetDir = mTextRun->IsSidewaysLeft() ? -1.0 : 1.0;
|
||||
|
||||
// Underlines
|
||||
for (uint32_t i = aDecorations.mUnderlines.Length(); i-- > 0; ) {
|
||||
const LineDecoration& dec = aDecorations.mUnderlines[i];
|
||||
@ -6450,7 +6458,8 @@ nsTextFrame::DrawTextRunAndDecorations(
|
||||
|
||||
PaintDecorationLine(aCtx, dirtyRect, dec.mColor,
|
||||
aDecorationOverrideColor, decPt, 0.0, decSize, ascent,
|
||||
metrics.underlineOffset, NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
|
||||
decorationOffsetDir * metrics.underlineOffset,
|
||||
NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
|
||||
dec.mStyle, eNormalDecoration, aCallbacks, verticalRun);
|
||||
}
|
||||
// Overlines
|
||||
@ -6471,7 +6480,8 @@ nsTextFrame::DrawTextRunAndDecorations(
|
||||
|
||||
PaintDecorationLine(aCtx, dirtyRect, dec.mColor,
|
||||
aDecorationOverrideColor, decPt, 0.0, decSize, ascent,
|
||||
metrics.maxAscent, NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, dec.mStyle,
|
||||
decorationOffsetDir * metrics.maxAscent,
|
||||
NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, dec.mStyle,
|
||||
eNormalDecoration, aCallbacks, verticalRun);
|
||||
}
|
||||
|
||||
@ -6498,7 +6508,8 @@ nsTextFrame::DrawTextRunAndDecorations(
|
||||
|
||||
PaintDecorationLine(aCtx, dirtyRect, dec.mColor,
|
||||
aDecorationOverrideColor, decPt, 0.0, decSize, ascent,
|
||||
metrics.strikeoutOffset, NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH,
|
||||
decorationOffsetDir * metrics.strikeoutOffset,
|
||||
NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH,
|
||||
dec.mStyle, eNormalDecoration, aCallbacks, verticalRun);
|
||||
}
|
||||
}
|
||||
@ -6631,9 +6642,9 @@ nsTextFrame::GetCharacterOffsetAtFramePointInternal(nsPoint aPoint,
|
||||
PropertyProvider provider(this, iter, nsTextFrame::eInflated);
|
||||
// Trim leading but not trailing whitespace if possible
|
||||
provider.InitializeForDisplay(false);
|
||||
gfxFloat width = mTextRun->IsVertical() ?
|
||||
(mTextRun->IsRightToLeft() ? mRect.height - aPoint.y : aPoint.y) :
|
||||
(mTextRun->IsRightToLeft() ? mRect.width - aPoint.x : aPoint.x);
|
||||
gfxFloat width = mTextRun->IsVertical()
|
||||
? (mTextRun->IsInlineReversed() ? mRect.height - aPoint.y : aPoint.y)
|
||||
: (mTextRun->IsInlineReversed() ? mRect.width - aPoint.x : aPoint.x);
|
||||
gfxFloat fitWidth;
|
||||
uint32_t skippedLength = ComputeTransformedLength(provider);
|
||||
|
||||
@ -6860,13 +6871,13 @@ nsTextFrame::GetPointFromOffset(int32_t inOffset,
|
||||
nscoord iSize = NSToCoordCeilClamped(advance);
|
||||
|
||||
if (mTextRun->IsVertical()) {
|
||||
if (mTextRun->IsRightToLeft()) {
|
||||
if (mTextRun->IsInlineReversed()) {
|
||||
outPoint->y = mRect.height - iSize;
|
||||
} else {
|
||||
outPoint->y = iSize;
|
||||
}
|
||||
} else {
|
||||
if (mTextRun->IsRightToLeft()) {
|
||||
if (mTextRun->IsInlineReversed()) {
|
||||
outPoint->x = mRect.width - iSize;
|
||||
} else {
|
||||
outPoint->x = iSize;
|
||||
|
@ -746,6 +746,7 @@ protected:
|
||||
const gfxFont::Metrics& aFontMetrics,
|
||||
DrawPathCallbacks* aCallbacks,
|
||||
bool aVertical,
|
||||
gfxFloat aDecorationOffsetDir,
|
||||
uint8_t aDecoration);
|
||||
enum DecorationType
|
||||
{
|
||||
|
21
layout/reftests/floats/float-in-rtl-slr-1-ref.html
Normal file
21
layout/reftests/floats/float-in-rtl-slr-1-ref.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="height:0px;width:0px;overflow:visible">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);display:inline-block;margin-top:calc(100vh - 316px);"></div>
|
||||
</div>
|
||||
<div style="height:0px;width:0px;overflow:visible">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);display:inline-block;margin-top:calc(100vh - 216px);"></div>
|
||||
</div>
|
||||
<div class="slr" style="background:silver; height: calc(100vh - 16px);">
|
||||
<div style="height:100px;">This text should appear BELOW the red and green blocks.</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
21
layout/reftests/floats/float-in-rtl-slr-1a.html
Normal file
21
layout/reftests/floats/float-in-rtl-slr-1a.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="slr">
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="height:300px" dir="rtl">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);float:right;"></div>
|
||||
</div>
|
||||
<div style="height:200px">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);float:right;"></div>
|
||||
</div>
|
||||
<div style="background:silver">
|
||||
This text should appear BELOW the red and green blocks.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
21
layout/reftests/floats/float-in-rtl-slr-1b.html
Normal file
21
layout/reftests/floats/float-in-rtl-slr-1b.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="slr">
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="height:300px">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);float:right;"></div>
|
||||
</div>
|
||||
<div style="height:200px" dir="rtl">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);float:right;"></div>
|
||||
</div>
|
||||
<div style="background:silver">
|
||||
This text should appear BELOW the red and green blocks.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
21
layout/reftests/floats/float-in-rtl-slr-1c.html
Normal file
21
layout/reftests/floats/float-in-rtl-slr-1c.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="slr">
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="height:300px" dir="rtl">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);float:right;"></div>
|
||||
</div>
|
||||
<div style="height:200px" dir="rtl">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);float:right;"></div>
|
||||
</div>
|
||||
<div style="background:silver">
|
||||
This text should appear BELOW the red and green blocks.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
23
layout/reftests/floats/float-in-rtl-slr-1d.html
Normal file
23
layout/reftests/floats/float-in-rtl-slr-1d.html
Normal file
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="slr">
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div dir="rtl" style="height:300px">
|
||||
<div style="height:300px">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);float:right;"></div>
|
||||
</div>
|
||||
<div style="height:200px">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);float:right;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="background:silver">
|
||||
This text should appear BELOW the red and green blocks.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
23
layout/reftests/floats/float-in-rtl-slr-2-ref.html
Normal file
23
layout/reftests/floats/float-in-rtl-slr-2-ref.html
Normal file
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="height:0px;width:0px;overflow:visible">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);display:inline-block;margin-top:calc(100vh - 116px);"></div>
|
||||
</div>
|
||||
<div style="height:0px;width:0px;overflow:visible">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);display:inline-block;margin-top:calc(100vh - 216px);"></div>
|
||||
</div>
|
||||
<div style="height:0px;width:0px;overflow:visible">
|
||||
<div class="slr" style="background:silver; height: calc(100vh - 16px);">
|
||||
<div style="margin-bottom:200px;">This text should appear ABOVE the green and red blocks.</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
21
layout/reftests/floats/float-in-rtl-slr-2a.html
Normal file
21
layout/reftests/floats/float-in-rtl-slr-2a.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="slr">
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div dir="rtl" style="height:300px">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);float:left;"></div>
|
||||
</div>
|
||||
<div style="height:200px">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);float:left;"></div>
|
||||
</div>
|
||||
<div style="background:silver">
|
||||
This text should appear ABOVE the green and red blocks.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
21
layout/reftests/floats/float-in-rtl-slr-2b.html
Normal file
21
layout/reftests/floats/float-in-rtl-slr-2b.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="slr">
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="height:300px">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);float:left;"></div>
|
||||
</div>
|
||||
<div dir="rtl" style="height:200px">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);float:left;"></div>
|
||||
</div>
|
||||
<div style="background:silver">
|
||||
This text should appear ABOVE the green and red blocks.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
21
layout/reftests/floats/float-in-rtl-slr-2c.html
Normal file
21
layout/reftests/floats/float-in-rtl-slr-2c.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="slr">
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div dir="rtl" style="height:300px">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);float:left;"></div>
|
||||
</div>
|
||||
<div dir="rtl" style="height:200px">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);float:left;"></div>
|
||||
</div>
|
||||
<div style="background:silver">
|
||||
This text should appear ABOVE the green and red blocks.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
23
layout/reftests/floats/float-in-rtl-slr-2d.html
Normal file
23
layout/reftests/floats/float-in-rtl-slr-2d.html
Normal file
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="slr">
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div dir="rtl" style="inline-size:-moz-fit-content">
|
||||
<div style="height:300px">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);float:left;"></div>
|
||||
</div>
|
||||
<div style="height:200px">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);float:left;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="background:silver">
|
||||
This text should appear ABOVE the green and red blocks.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
23
layout/reftests/floats/float-in-rtl-slr-3-ref.html
Normal file
23
layout/reftests/floats/float-in-rtl-slr-3-ref.html
Normal file
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div style="height:0px;width:0px;overflow:visible">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);display:inline-block;margin-top:200px;"></div>
|
||||
</div>
|
||||
<div style="height:0px;width:0px;overflow:visible">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);display:inline-block;margin-top:100px;"></div>
|
||||
</div>
|
||||
<div class="slr" style="background:silver; height:calc(100vh - 16px);">
|
||||
<div style="margin-bottom:calc(100vh - 116px); direction:rtl">This text should appear ABOVE the green and red blocks.</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
23
layout/reftests/floats/float-in-rtl-slr-3a.html
Normal file
23
layout/reftests/floats/float-in-rtl-slr-3a.html
Normal file
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="slr">
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="direction: rtl;">
|
||||
<div dir="ltr" style="height:300px">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);float:left;"></div>
|
||||
</div>
|
||||
<div style="height:200px">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);float:left;"></div>
|
||||
</div>
|
||||
<div style="background:silver">
|
||||
This text should appear ABOVE the green and red blocks.
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
23
layout/reftests/floats/float-in-rtl-slr-3b.html
Normal file
23
layout/reftests/floats/float-in-rtl-slr-3b.html
Normal file
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="slr">
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="direction: rtl;">
|
||||
<div style="height:300px">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);float:left;"></div>
|
||||
</div>
|
||||
<div dir="ltr" style="height:200px">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);float:left;"></div>
|
||||
</div>
|
||||
<div style="background:silver">
|
||||
This text should appear ABOVE the green and red blocks.
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
23
layout/reftests/floats/float-in-rtl-slr-3c.html
Normal file
23
layout/reftests/floats/float-in-rtl-slr-3c.html
Normal file
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="slr">
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="direction: rtl;">
|
||||
<div dir="ltr" style="height:300px">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);float:left;"></div>
|
||||
</div>
|
||||
<div dir="ltr" style="height:200px">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);float:left"></div>
|
||||
</div>
|
||||
<div style="background:silver">
|
||||
This text should appear ABOVE the green and red blocks.
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
25
layout/reftests/floats/float-in-rtl-slr-3d.html
Normal file
25
layout/reftests/floats/float-in-rtl-slr-3d.html
Normal file
@ -0,0 +1,25 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="slr">
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="direction: rtl;">
|
||||
<div dir="ltr" style="inline-size:-moz-fit-content">
|
||||
<div style="height:300px">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);float:left;"></div>
|
||||
</div>
|
||||
<div style="height:200px">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);float:left;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="background:silver">
|
||||
This text should appear ABOVE the green and red blocks.
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
24
layout/reftests/floats/float-in-rtl-slr-4-ref.html
Normal file
24
layout/reftests/floats/float-in-rtl-slr-4-ref.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
direction: rtl;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div style="height:0px;width:0px;overflow:visible">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);display:inline-block;margin-top:0"></div>
|
||||
</div>
|
||||
<div style="height:0px;width:0px;overflow:visible">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);display:inline-block;margin-top:100px"></div>
|
||||
</div>
|
||||
<div class="slr" style="background:silver; height: calc(100vh - 16px);">
|
||||
<div style="height: calc(100vh - 216px); margin-top: 200px">This text should appear BELOW the red and green blocks.</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
24
layout/reftests/floats/float-in-rtl-slr-4a.html
Normal file
24
layout/reftests/floats/float-in-rtl-slr-4a.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="slr">
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
direction: rtl;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div dir="ltr" style="height:300px">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);float:right;"></div>
|
||||
</div>
|
||||
<div style="height:200px">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);float:right;"></div>
|
||||
</div>
|
||||
<div style="background:silver">
|
||||
This text should appear BELOW the red and green blocks.
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
24
layout/reftests/floats/float-in-rtl-slr-4b.html
Normal file
24
layout/reftests/floats/float-in-rtl-slr-4b.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="slr">
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
direction: rtl;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div style="height:300px">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);float:right;"></div>
|
||||
</div>
|
||||
<div dir="ltr" style="height:200px">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);float:right;"></div>
|
||||
</div>
|
||||
<div style="background:silver">
|
||||
This text should appear BELOW the red and green blocks.
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
24
layout/reftests/floats/float-in-rtl-slr-4c.html
Normal file
24
layout/reftests/floats/float-in-rtl-slr-4c.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="slr">
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
direction: rtl;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div dir="ltr" style="height:300px">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);float:right;"></div>
|
||||
</div>
|
||||
<div dir="ltr" style="height:200px">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);float:right;"></div>
|
||||
</div>
|
||||
<div style="background:silver">
|
||||
This text should appear BELOW the red and green blocks.
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
26
layout/reftests/floats/float-in-rtl-slr-4d.html
Normal file
26
layout/reftests/floats/float-in-rtl-slr-4d.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="slr">
|
||||
<head>
|
||||
<style>
|
||||
.slr {
|
||||
writing-mode: sideways-lr;
|
||||
direction: rtl;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div dir="ltr" style="inline-size:-moz-fit-content">
|
||||
<div style="height:300px">
|
||||
<div style="height:100px;width:120px;background:rgba(0,255,0,0.8);float:right;"></div>
|
||||
</div>
|
||||
<div style="height:200px">
|
||||
<div style="height:100px;width:150px;background:rgba(255,0,0,0.8);float:right;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="background:silver">
|
||||
This text should appear BELOW the red and green blocks.
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -88,3 +88,20 @@ fuzzy-if(OSX==1010,26,7) fuzzy-if(Android,16,2) == orthogonal-floats-1a.html ort
|
||||
fuzzy-if(OSX==1010,26,7) == orthogonal-floats-1b.html orthogonal-floats-1-ref.html
|
||||
fuzzy-if(OSX==1010,103,802) fuzzy-if(winWidget,116,700) HTTP(..) == orthogonal-floats-1c.html orthogonal-floats-1-ref.html
|
||||
fuzzy-if(OSX==1010,103,802) fuzzy-if(winWidget,116,700) HTTP(..) == orthogonal-floats-1d.html orthogonal-floats-1-ref.html
|
||||
|
||||
== float-in-rtl-slr-1a.html float-in-rtl-slr-1-ref.html
|
||||
== float-in-rtl-slr-1b.html float-in-rtl-slr-1-ref.html
|
||||
== float-in-rtl-slr-1c.html float-in-rtl-slr-1-ref.html
|
||||
== float-in-rtl-slr-1d.html float-in-rtl-slr-1-ref.html
|
||||
== float-in-rtl-slr-2a.html float-in-rtl-slr-2-ref.html
|
||||
== float-in-rtl-slr-2b.html float-in-rtl-slr-2-ref.html
|
||||
== float-in-rtl-slr-2c.html float-in-rtl-slr-2-ref.html
|
||||
== float-in-rtl-slr-2d.html float-in-rtl-slr-2-ref.html
|
||||
== float-in-rtl-slr-3a.html float-in-rtl-slr-3-ref.html
|
||||
== float-in-rtl-slr-3b.html float-in-rtl-slr-3-ref.html
|
||||
== float-in-rtl-slr-3c.html float-in-rtl-slr-3-ref.html
|
||||
== float-in-rtl-slr-3d.html float-in-rtl-slr-3-ref.html
|
||||
== float-in-rtl-slr-4a.html float-in-rtl-slr-4-ref.html
|
||||
== float-in-rtl-slr-4b.html float-in-rtl-slr-4-ref.html
|
||||
== float-in-rtl-slr-4c.html float-in-rtl-slr-4-ref.html
|
||||
== float-in-rtl-slr-4d.html float-in-rtl-slr-4-ref.html
|
||||
|
24
layout/reftests/writing-mode/1193519-sideways-lr-1-ref.html
Normal file
24
layout/reftests/writing-mode/1193519-sideways-lr-1-ref.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<style>
|
||||
div { padding: 5px; display: inline-block; }
|
||||
span { display: block; width: 2em; }
|
||||
span:nth-child(1) { background: red; height: 1em; }
|
||||
span:nth-child(2) { background: orange; height: 1.1em; }
|
||||
span:nth-child(3) { background: yellow; height: 1.3em; }
|
||||
span:nth-child(4) { background: green; height: 1.5em; }
|
||||
span:nth-child(5) { background: blue; height: 1.7em; }
|
||||
span:nth-child(6) { background: indigo; height: 1.9em; }
|
||||
span:nth-child(7) { background: violet; height: 2em; }
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<p>All four columns should look the same:
|
||||
<div><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
|
||||
<div><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
|
||||
<div><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
|
||||
<div><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
|
28
layout/reftests/writing-mode/1193519-sideways-lr-1.html
Normal file
28
layout/reftests/writing-mode/1193519-sideways-lr-1.html
Normal file
@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<style>
|
||||
div { padding: 5px; display: inline-block; }
|
||||
.vlr { writing-mode: vertical-lr; text-orientation: sideways; }
|
||||
.vrl { writing-mode: vertical-rl; text-orientation: sideways; }
|
||||
.slr { writing-mode: sideways-lr; }
|
||||
.srl { writing-mode: sideways-rl; }
|
||||
span { display: inline-block; block-size: 2em; vertical-align: middle; }
|
||||
span:nth-child(1) { background: red; inline-size: 1em; }
|
||||
span:nth-child(2) { background: orange; inline-size: 1.1em; }
|
||||
span:nth-child(3) { background: yellow; inline-size: 1.3em; }
|
||||
span:nth-child(4) { background: green; inline-size: 1.5em; }
|
||||
span:nth-child(5) { background: blue; inline-size: 1.7em; }
|
||||
span:nth-child(6) { background: indigo; inline-size: 1.9em; }
|
||||
span:nth-child(7) { background: violet; inline-size: 2em; }
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<p>All four columns should look the same:
|
||||
<div dir=ltr class="vrl"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
|
||||
<div dir=ltr class="vlr"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
|
||||
<div dir=ltr class="srl"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
|
||||
<div dir=rtl class="slr"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
|
24
layout/reftests/writing-mode/1193519-sideways-lr-2-ref.html
Normal file
24
layout/reftests/writing-mode/1193519-sideways-lr-2-ref.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<style>
|
||||
div { padding: 5px; display: inline-block; }
|
||||
span { display: block; width: 2em; }
|
||||
span:nth-child(7) { background: red; height: 1em; }
|
||||
span:nth-child(6) { background: orange; height: 1.1em; }
|
||||
span:nth-child(5) { background: yellow; height: 1.3em; }
|
||||
span:nth-child(4) { background: green; height: 1.5em; }
|
||||
span:nth-child(3) { background: blue; height: 1.7em; }
|
||||
span:nth-child(2) { background: indigo; height: 1.9em; }
|
||||
span:nth-child(1) { background: violet; height: 2em; }
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<p>All four columns should look the same:
|
||||
<div><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
|
||||
<div><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
|
||||
<div><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
|
||||
<div><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user