diff --git a/content/html/document/src/MediaDocument.h b/content/html/document/src/MediaDocument.h index c97b95ec274..9ca6b63d73d 100644 --- a/content/html/document/src/MediaDocument.h +++ b/content/html/document/src/MediaDocument.h @@ -85,7 +85,7 @@ public: virtual ~MediaDocumentStreamListener(); void SetStreamListener(nsIStreamListener *aListener); - NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_ISUPPORTS NS_DECL_NSIREQUESTOBSERVER diff --git a/content/media/AudioNodeStream.cpp b/content/media/AudioNodeStream.cpp index 30d5faad403..7b958cbb6bb 100644 --- a/content/media/AudioNodeStream.cpp +++ b/content/media/AudioNodeStream.cpp @@ -60,9 +60,7 @@ void AudioNodeStream::SetStreamTimeParameterImpl(uint32_t aIndex, MediaStream* aRelativeToStream, double aStreamTime) { - TrackTicks ticks = - WebAudioUtils::ConvertDestinationStreamTimeToSourceStreamTime( - aStreamTime, this, aRelativeToStream); + TrackTicks ticks = TicksFromDestinationTime(aRelativeToStream, aStreamTime); mEngine->SetStreamTimeParameter(aIndex, ticks); } @@ -517,4 +515,36 @@ AudioNodeStream::FinishOutput() } } +TrackTicks +AudioNodeStream::TicksFromDestinationTime(MediaStream* aDestination, + double aSeconds) +{ + MOZ_ASSERT(aDestination->AsAudioNodeStream() && + aDestination->AsAudioNodeStream()->SampleRate() == SampleRate()); + + double destinationSeconds = std::max(0.0, aSeconds); + StreamTime streamTime = SecondsToMediaTime(destinationSeconds); + // MediaTime does not have the resolution of double + double offset = destinationSeconds - MediaTimeToSeconds(streamTime); + + GraphTime graphTime = aDestination->StreamTimeToGraphTime(streamTime); + StreamTime thisStreamTime = GraphTimeToStreamTimeOptimistic(graphTime); + double thisSeconds = MediaTimeToSeconds(thisStreamTime) + offset; + MOZ_ASSERT(thisSeconds >= 0.0); + // Round to nearest + TrackTicks ticks = thisSeconds * SampleRate() + 0.5; + return ticks; +} + +double +AudioNodeStream::DestinationTimeFromTicks(AudioNodeStream* aDestination, + TrackTicks aPosition) +{ + MOZ_ASSERT(SampleRate() == aDestination->SampleRate()); + StreamTime sourceTime = TicksToTimeRoundDown(SampleRate(), aPosition); + GraphTime graphTime = StreamTimeToGraphTime(sourceTime); + StreamTime destinationTime = aDestination->GraphTimeToStreamTimeOptimistic(graphTime); + return MediaTimeToSeconds(destinationTime); +} + } diff --git a/content/media/AudioNodeStream.h b/content/media/AudioNodeStream.h index ca768fe1d9b..cf1e5bfa09a 100644 --- a/content/media/AudioNodeStream.h +++ b/content/media/AudioNodeStream.h @@ -128,6 +128,19 @@ public: AudioNodeEngine* Engine() { return mEngine; } TrackRate SampleRate() const { return mSampleRate; } + /** + * Convert a time in seconds on the destination stream to TrackTicks + * on this stream. + */ + TrackTicks TicksFromDestinationTime(MediaStream* aDestination, + double aSeconds); + /** + * Get the destination stream time in seconds corresponding to a position on + * this stream. + */ + double DestinationTimeFromTicks(AudioNodeStream* aDestination, + TrackTicks aPosition); + protected: void AdvanceOutputSegment(); void FinishOutput(); diff --git a/content/media/webaudio/ScriptProcessorNode.cpp b/content/media/webaudio/ScriptProcessorNode.cpp index d9ef80e779f..1e5b1b8541b 100644 --- a/content/media/webaudio/ScriptProcessorNode.cpp +++ b/content/media/webaudio/ScriptProcessorNode.cpp @@ -314,10 +314,9 @@ private: // Add the delay caused by the main thread playbackTick += mSharedBuffers->DelaySoFar(); // Compute the playback time in the coordinate system of the destination + // FIXME: bug 970773 double playbackTime = - WebAudioUtils::StreamPositionToDestinationTime(playbackTick, - mSource, - mDestination); + mSource->DestinationTimeFromTicks(mDestination, playbackTick); class Command : public nsRunnable { diff --git a/content/media/webaudio/WebAudioUtils.cpp b/content/media/webaudio/WebAudioUtils.cpp index 9a21f9a5966..87088c4dd34 100644 --- a/content/media/webaudio/WebAudioUtils.cpp +++ b/content/media/webaudio/WebAudioUtils.cpp @@ -23,35 +23,11 @@ struct ConvertTimeToTickHelper { ConvertTimeToTickHelper* This = static_cast (aClosure); MOZ_ASSERT(This->mSourceStream->SampleRate() == This->mDestinationStream->SampleRate()); - return WebAudioUtils::ConvertDestinationStreamTimeToSourceStreamTime( - aTime, This->mSourceStream, This->mDestinationStream); + return This->mSourceStream-> + TicksFromDestinationTime(This->mDestinationStream, aTime); } }; -TrackTicks -WebAudioUtils::ConvertDestinationStreamTimeToSourceStreamTime(double aTime, - AudioNodeStream* aSource, - MediaStream* aDestination) -{ - StreamTime streamTime = std::max(0, SecondsToMediaTime(aTime)); - GraphTime graphTime = aDestination->StreamTimeToGraphTime(streamTime); - StreamTime thisStreamTime = aSource->GraphTimeToStreamTimeOptimistic(graphTime); - TrackTicks ticks = TimeToTicksRoundUp(aSource->SampleRate(), thisStreamTime); - return ticks; -} - -double -WebAudioUtils::StreamPositionToDestinationTime(TrackTicks aSourcePosition, - AudioNodeStream* aSource, - AudioNodeStream* aDestination) -{ - MOZ_ASSERT(aSource->SampleRate() == aDestination->SampleRate()); - StreamTime sourceTime = TicksToTimeRoundDown(aSource->SampleRate(), aSourcePosition); - GraphTime graphTime = aSource->StreamTimeToGraphTime(sourceTime); - StreamTime destinationTime = aDestination->GraphTimeToStreamTimeOptimistic(graphTime); - return MediaTimeToSeconds(destinationTime); -} - void WebAudioUtils::ConvertAudioParamToTicks(AudioParamTimeline& aParam, AudioNodeStream* aSource, diff --git a/content/media/webaudio/WebAudioUtils.h b/content/media/webaudio/WebAudioUtils.h index c525a2c781a..2d926e0615c 100644 --- a/content/media/webaudio/WebAudioUtils.h +++ b/content/media/webaudio/WebAudioUtils.h @@ -50,15 +50,6 @@ struct WebAudioUtils { return 1.0 - std::exp(-1.0 / (aDuration * aSampleRate)); } - /** - * Convert a time in second relative to the destination stream to - * TrackTicks relative to the source stream. - */ - static TrackTicks - ConvertDestinationStreamTimeToSourceStreamTime(double aTime, - AudioNodeStream* aSource, - MediaStream* aDestination); - /** * Converts AudioParamTimeline floating point time values to tick values * with respect to a source and a destination AudioNodeStream. @@ -114,14 +105,6 @@ struct WebAudioUtils { return aTime >= 0 && aTime <= (MEDIA_TIME_MAX >> MEDIA_TIME_FRAC_BITS); } - /** - * Convert a stream position into the time coordinate of the destination - * stream. - */ - static double StreamPositionToDestinationTime(TrackTicks aSourcePosition, - AudioNodeStream* aSource, - AudioNodeStream* aDestination); - /** * Converts a floating point value to an integral type in a safe and * platform agnostic way. The following program demonstrates the kinds diff --git a/content/media/webaudio/test/mochitest.ini b/content/media/webaudio/test/mochitest.ini index ac748a6fe31..9a7370c02cd 100644 --- a/content/media/webaudio/test/mochitest.ini +++ b/content/media/webaudio/test/mochitest.ini @@ -63,6 +63,8 @@ support-files = [test_bug875221.html] [test_bug875402.html] [test_bug894150.html] +[test_bug956489.html] +[test_bug964376.html] [test_channelMergerNode.html] [test_channelMergerNodeWithVolume.html] [test_channelSplitterNode.html] diff --git a/content/media/webaudio/test/test_bug956489.html b/content/media/webaudio/test/test_bug956489.html new file mode 100644 index 00000000000..32598c8f1d4 --- /dev/null +++ b/content/media/webaudio/test/test_bug956489.html @@ -0,0 +1,55 @@ + + + + Test when and currentTime are in the same coordinate system + + + + +
+
+
+ + diff --git a/content/media/webaudio/test/test_bug964376.html b/content/media/webaudio/test/test_bug964376.html new file mode 100644 index 00000000000..1d9af1c1e01 --- /dev/null +++ b/content/media/webaudio/test/test_bug964376.html @@ -0,0 +1,64 @@ + + + + Test repeating audio is not distorted + + + + + +
+
+
+ + diff --git a/dom/promise/Promise.cpp b/dom/promise/Promise.cpp index 7baaf209176..056b4d3667a 100644 --- a/dom/promise/Promise.cpp +++ b/dom/promise/Promise.cpp @@ -57,11 +57,11 @@ private: nsRefPtr mPromise; }; -class WorkerPromiseTask MOZ_FINAL : public WorkerRunnable +class WorkerPromiseTask MOZ_FINAL : public WorkerSameThreadRunnable { public: WorkerPromiseTask(WorkerPrivate* aWorkerPrivate, Promise* aPromise) - : WorkerRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount) + : WorkerSameThreadRunnable(aWorkerPrivate) , mPromise(aPromise) { MOZ_ASSERT(aPromise); @@ -161,7 +161,7 @@ public: } }; -class WorkerPromiseResolverTask MOZ_FINAL : public WorkerRunnable, +class WorkerPromiseResolverTask MOZ_FINAL : public WorkerSameThreadRunnable, public PromiseResolverMixin { public: @@ -169,7 +169,7 @@ public: Promise* aPromise, JS::Handle aValue, Promise::PromiseState aState) - : WorkerRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount), + : WorkerSameThreadRunnable(aWorkerPrivate), PromiseResolverMixin(aPromise, aValue, aState) {} @@ -832,7 +832,7 @@ Promise::AppendCallbacks(PromiseCallback* aResolveCallback, WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); nsRefPtr task = new WorkerPromiseTask(worker, this); - worker->Dispatch(task); + task->Dispatch(worker->GetJSContext()); } mTaskPending = true; } @@ -1045,7 +1045,7 @@ Promise::RunResolveTask(JS::Handle aValue, MOZ_ASSERT(worker); nsRefPtr task = new WorkerPromiseResolverTask(worker, this, aValue, aState); - worker->Dispatch(task); + task->Dispatch(worker->GetJSContext()); } return; } diff --git a/dom/workers/WorkerRunnable.cpp b/dom/workers/WorkerRunnable.cpp index e9bdb3e43b5..c8d771efae1 100644 --- a/dom/workers/WorkerRunnable.cpp +++ b/dom/workers/WorkerRunnable.cpp @@ -7,10 +7,12 @@ #include "nsIEventTarget.h" #include "nsIRunnable.h" +#include "nsThreadUtils.h" + +#include "mozilla/DebugOnly.h" #include "js/RootingAPI.h" #include "js/Value.h" -#include "nsThreadUtils.h" #include "WorkerPrivate.h" @@ -478,3 +480,43 @@ MainThreadWorkerControlRunnable::PostDispatch(JSContext* aCx, } NS_IMPL_ISUPPORTS_INHERITED0(WorkerControlRunnable, WorkerRunnable) + +bool +WorkerSameThreadRunnable::PreDispatch(JSContext* aCx, + WorkerPrivate* aWorkerPrivate) +{ + aWorkerPrivate->AssertIsOnWorkerThread(); + return true; +} + +void +WorkerSameThreadRunnable::PostDispatch(JSContext* aCx, + WorkerPrivate* aWorkerPrivate, + bool aDispatchResult) +{ + aWorkerPrivate->AssertIsOnWorkerThread(); + if (aDispatchResult) { + DebugOnly willIncrement = aWorkerPrivate->ModifyBusyCountFromWorker(aCx, true); + // Should never fail since if this thread is still running, so should the + // parent and it should be able to process a control runnable. + MOZ_ASSERT(willIncrement); + } +} + +void +WorkerSameThreadRunnable::PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate, + bool aRunResult) +{ + MOZ_ASSERT(aCx); + MOZ_ASSERT(aWorkerPrivate); + + aWorkerPrivate->AssertIsOnWorkerThread(); + + DebugOnly willDecrement = aWorkerPrivate->ModifyBusyCountFromWorker(aCx, false); + MOZ_ASSERT(willDecrement); + + if (!aRunResult) { + JS_ReportPendingException(aCx); + } +} + diff --git a/dom/workers/WorkerRunnable.h b/dom/workers/WorkerRunnable.h index 84acd46f443..230fdb6ae59 100644 --- a/dom/workers/WorkerRunnable.h +++ b/dom/workers/WorkerRunnable.h @@ -314,6 +314,34 @@ protected: bool aDispatchResult) MOZ_OVERRIDE; }; +// A WorkerRunnable that should be dispatched from the worker to itself for +// async tasks. This will increment the busy count PostDispatch() (only if +// dispatch was successful) and decrement it in PostRun(). +// +// Async tasks will almost always want to use this since +// a WorkerSameThreadRunnable keeps the Worker from being GCed. +class WorkerSameThreadRunnable : public WorkerRunnable +{ +protected: + WorkerSameThreadRunnable(WorkerPrivate* aWorkerPrivate) + : WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount) + { } + + virtual ~WorkerSameThreadRunnable() + { } + + virtual bool + PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate) MOZ_OVERRIDE; + + virtual void + PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate, + bool aDispatchResult) MOZ_OVERRIDE; + + virtual void + PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate, + bool aRunResult) MOZ_OVERRIDE; +}; + END_WORKERS_NAMESPACE #endif // mozilla_dom_workers_workerrunnable_h__ diff --git a/editor/libeditor/base/nsEditorEventListener.cpp b/editor/libeditor/base/nsEditorEventListener.cpp index 5a38ba649f8..bf247677508 100644 --- a/editor/libeditor/base/nsEditorEventListener.cpp +++ b/editor/libeditor/base/nsEditorEventListener.cpp @@ -1038,6 +1038,12 @@ nsEditorEventListener::ShouldHandleNativeKeyBindings(nsIDOMEvent* aKeyEvent) return false; } + nsCOMPtr doc = mEditor->GetDocument(); + if (doc->HasFlag(NODE_IS_EDITABLE)) { + // Don't need to perform any checks in designMode documents. + return true; + } + nsIContent* editingHost = htmlEditor->GetActiveEditingHost(); if (!editingHost) { return false; diff --git a/editor/libeditor/html/tests/mochitest.ini b/editor/libeditor/html/tests/mochitest.ini index 68bee257714..c4930b059e0 100644 --- a/editor/libeditor/html/tests/mochitest.ini +++ b/editor/libeditor/html/tests/mochitest.ini @@ -145,6 +145,8 @@ skip-if = toolkit == 'android' [test_bug796839.html] [test_bug832025.html] [test_bug857487.html] +[test_bug966155.html] +skip-if = os != "win" [test_bug966552.html] skip-if = os != "win" [test_contenteditable_focus.html] diff --git a/editor/libeditor/html/tests/test_bug966155.html b/editor/libeditor/html/tests/test_bug966155.html new file mode 100644 index 00000000000..524b15d6947 --- /dev/null +++ b/editor/libeditor/html/tests/test_bug966155.html @@ -0,0 +1,57 @@ + + + + + Test for Bug 966155 + + + + + +Mozilla Bug 966155 +

+ +
+
+
+ + diff --git a/editor/libeditor/html/tests/test_bug966552.html b/editor/libeditor/html/tests/test_bug966552.html index 69c6f789c90..3d0ec5fe32f 100644 --- a/editor/libeditor/html/tests/test_bug966552.html +++ b/editor/libeditor/html/tests/test_bug966552.html @@ -10,7 +10,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=966552 -Mozilla Bug 289384 +Mozilla Bug 966552

diff --git a/gfx/layers/GrallocImages.cpp b/gfx/layers/GrallocImages.cpp index bd84955023f..d7eacd88220 100644 --- a/gfx/layers/GrallocImages.cpp +++ b/gfx/layers/GrallocImages.cpp @@ -380,7 +380,7 @@ GrallocImage::GetAsSourceSurface() TextureClient* -GrallocImage::GetTextureClient() +GrallocImage::GetTextureClient(CompositableClient* aClient) { if (!mTextureClient) { const SurfaceDescriptor& sd = GetSurfaceDescriptor(); diff --git a/gfx/layers/GrallocImages.h b/gfx/layers/GrallocImages.h index 20cfdf38018..e277668d48c 100644 --- a/gfx/layers/GrallocImages.h +++ b/gfx/layers/GrallocImages.h @@ -149,7 +149,7 @@ public: virtual ISharedImage* AsSharedImage() MOZ_OVERRIDE { return this; } - virtual TextureClient* GetTextureClient() MOZ_OVERRIDE; + virtual TextureClient* GetTextureClient(CompositableClient* aClient) MOZ_OVERRIDE; virtual uint8_t* GetBuffer() { diff --git a/gfx/layers/ImageContainer.cpp b/gfx/layers/ImageContainer.cpp index 543e9b74dd4..7a7991cde70 100644 --- a/gfx/layers/ImageContainer.cpp +++ b/gfx/layers/ImageContainer.cpp @@ -22,6 +22,7 @@ #include "GrallocImages.h" #endif #include "gfx2DGlue.h" +#include "mozilla/gfx/2D.h" #ifdef XP_MACOSX #include "mozilla/gfx/QuartzSupport.h" @@ -38,15 +39,12 @@ using namespace mozilla::ipc; using namespace android; -using mozilla::gfx::DataSourceSurface; -using mozilla::gfx::SourceSurface; +using namespace mozilla::gfx; namespace mozilla { namespace layers { -class DataSourceSurface; -class SourceSurface; Atomic Image::sSerialCounter(0); @@ -711,5 +709,45 @@ RemoteBitmapImage::GetAsSourceSurface() return newSurf; } +CairoImage::CairoImage() + : Image(nullptr, ImageFormat::CAIRO_SURFACE) +{} + +CairoImage::~CairoImage() +{ +} + +TextureClient* +CairoImage::GetTextureClient(CompositableClient *aClient) +{ + CompositableForwarder* forwarder = aClient->GetForwarder(); + RefPtr textureClient = mTextureClients.Get(forwarder->GetSerial()); + if (textureClient) { + return textureClient; + } + + RefPtr surface = GetAsSourceSurface(); + MOZ_ASSERT(surface); + + textureClient = aClient->CreateTextureClientForDrawing(surface->GetFormat(), + TEXTURE_FLAGS_DEFAULT); + MOZ_ASSERT(textureClient->AsTextureClientDrawTarget()); + if (!textureClient->AsTextureClientDrawTarget()->AllocateForSurface(surface->GetSize()) || + !textureClient->Lock(OPEN_WRITE_ONLY)) { + return nullptr; + } + + { + // We must not keep a reference to the DrawTarget after it has been unlocked. + RefPtr dt = textureClient->AsTextureClientDrawTarget()->GetAsDrawTarget(); + dt->CopySurface(surface, IntRect(IntPoint(), surface->GetSize()), IntPoint()); + } + + textureClient->Unlock(); + + mTextureClients.Put(forwarder->GetSerial(), textureClient); + return textureClient; +} + } // namespace } // namespace diff --git a/gfx/layers/ImageContainer.h b/gfx/layers/ImageContainer.h index 151e2ea89c5..fbc0e908c28 100644 --- a/gfx/layers/ImageContainer.h +++ b/gfx/layers/ImageContainer.h @@ -28,6 +28,7 @@ #include "mozilla/Atomics.h" #include "nsThreadUtils.h" #include "mozilla/gfx/2D.h" +#include "nsDataHashtable.h" #ifndef XPCOM_GLUE_AVOID_NSPR /** @@ -146,6 +147,8 @@ class ImageClient; class SharedPlanarYCbCrImage; class DeprecatedSharedPlanarYCbCrImage; class TextureClient; +class CompositableClient; +class CompositableForwarder; class SurfaceDescriptor; struct ImageBackendData @@ -165,7 +168,7 @@ public: * For use with the CompositableClient only (so that the later can * synchronize the TextureClient with the TextureHost). */ - virtual TextureClient* GetTextureClient() = 0; + virtual TextureClient* GetTextureClient(CompositableClient* aClient) = 0; }; /** @@ -905,7 +908,8 @@ protected: * device output color space. This class is very simple as all backends * have to know about how to deal with drawing a cairo image. */ -class CairoImage : public Image { +class CairoImage : public Image, + public ISharedImage { public: struct Data { gfxASurface* mDeprecatedSurface; @@ -939,9 +943,14 @@ public: return surface.forget(); } + virtual ISharedImage* AsSharedImage() { return this; } + virtual uint8_t* GetBuffer() { return nullptr; } + virtual TextureClient* GetTextureClient(CompositableClient* aClient); + gfx::IntSize GetSize() { return mSize; } - CairoImage() : Image(nullptr, ImageFormat::CAIRO_SURFACE) {} + CairoImage(); + ~CairoImage(); nsCountedRef mDeprecatedSurface; gfx::IntSize mSize; @@ -949,6 +958,7 @@ public: // mSourceSurface wraps mDeprrecatedSurface's data, therefore it should not // outlive mDeprecatedSurface nsCountedRef mSourceSurface; + nsDataHashtable > mTextureClients; }; class RemoteBitmapImage : public Image { diff --git a/gfx/layers/MacIOSurfaceImage.cpp b/gfx/layers/MacIOSurfaceImage.cpp index 259691e8602..93953b954e7 100644 --- a/gfx/layers/MacIOSurfaceImage.cpp +++ b/gfx/layers/MacIOSurfaceImage.cpp @@ -10,7 +10,7 @@ using namespace mozilla; using namespace mozilla::layers; TextureClient* -MacIOSurfaceImage::GetTextureClient() +MacIOSurfaceImage::GetTextureClient(CompositableClient* aClient) { if (!mTextureClient) { RefPtr buffer = diff --git a/gfx/layers/MacIOSurfaceImage.h b/gfx/layers/MacIOSurfaceImage.h index 652ec8fcfa3..286e59284d4 100644 --- a/gfx/layers/MacIOSurfaceImage.h +++ b/gfx/layers/MacIOSurfaceImage.h @@ -51,7 +51,7 @@ public: virtual TemporaryRef GetAsSourceSurface(); - virtual TextureClient* GetTextureClient() MOZ_OVERRIDE; + virtual TextureClient* GetTextureClient(CompositableClient* aClient) MOZ_OVERRIDE; virtual uint8_t* GetBuffer() MOZ_OVERRIDE { return nullptr; } MacIOSurfaceImage() : Image(nullptr, ImageFormat::MAC_IOSURFACE) {} diff --git a/gfx/layers/client/ImageClient.cpp b/gfx/layers/client/ImageClient.cpp index 055338907b1..1cc212942cd 100644 --- a/gfx/layers/client/ImageClient.cpp +++ b/gfx/layers/client/ImageClient.cpp @@ -145,9 +145,9 @@ ImageClientSingle::UpdateImageInternal(ImageContainer* aContainer, return true; } - if (image->AsSharedImage() && image->AsSharedImage()->GetTextureClient()) { + if (image->AsSharedImage() && image->AsSharedImage()->GetTextureClient(this)) { // fast path: no need to allocate and/or copy image data - RefPtr texture = image->AsSharedImage()->GetTextureClient(); + RefPtr texture = image->AsSharedImage()->GetTextureClient(this); if (mFrontBuffer) { diff --git a/gfx/layers/composite/CompositableHost.h b/gfx/layers/composite/CompositableHost.h index e9b64b9142b..781f49b322a 100644 --- a/gfx/layers/composite/CompositableHost.h +++ b/gfx/layers/composite/CompositableHost.h @@ -265,7 +265,6 @@ public: aLayer == mLayer || aFlags & FORCE_DETACH) { SetLayer(nullptr); - SetCompositor(nullptr); mAttached = false; mKeepAttached = false; if (mBackendData) { diff --git a/gfx/layers/ipc/CompositableForwarder.h b/gfx/layers/ipc/CompositableForwarder.h index e4cb21771be..d6d157202ee 100644 --- a/gfx/layers/ipc/CompositableForwarder.h +++ b/gfx/layers/ipc/CompositableForwarder.h @@ -48,7 +48,8 @@ class CompositableForwarder : public ISurfaceAllocator public: CompositableForwarder() - : mMultiProcess(false) + : mSerial(++sSerialCounter) + , mMultiProcess(false) {} /** @@ -246,10 +247,14 @@ public: return mTextureFactoryIdentifier; } + int32_t GetSerial() { return mSerial; } + protected: TextureFactoryIdentifier mTextureFactoryIdentifier; - bool mMultiProcess; nsTArray > mTexturesToRemove; + const int32_t mSerial; + static mozilla::Atomic sSerialCounter; + bool mMultiProcess; }; } // namespace diff --git a/gfx/layers/ipc/CompositorChild.cpp b/gfx/layers/ipc/CompositorChild.cpp index b9092f31ded..95e0a7662b1 100644 --- a/gfx/layers/ipc/CompositorChild.cpp +++ b/gfx/layers/ipc/CompositorChild.cpp @@ -28,6 +28,8 @@ namespace layers { /*static*/ CompositorChild* CompositorChild::sCompositor; +Atomic CompositableForwarder::sSerialCounter(0); + CompositorChild::CompositorChild(ClientLayerManager *aLayerManager) : mLayerManager(aLayerManager) { diff --git a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp index 5dbb520156c..9a506dbc029 100644 --- a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp +++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp @@ -63,7 +63,7 @@ DeprecatedSharedPlanarYCbCrImage::~DeprecatedSharedPlanarYCbCrImage() { } TextureClient* -SharedPlanarYCbCrImage::GetTextureClient() +SharedPlanarYCbCrImage::GetTextureClient(CompositableClient* aClient) { return mTextureClient.get(); } diff --git a/gfx/layers/ipc/SharedPlanarYCbCrImage.h b/gfx/layers/ipc/SharedPlanarYCbCrImage.h index ad42cbfcc52..f90555af59e 100644 --- a/gfx/layers/ipc/SharedPlanarYCbCrImage.h +++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.h @@ -97,7 +97,7 @@ public: ~SharedPlanarYCbCrImage(); virtual ISharedImage* AsSharedImage() MOZ_OVERRIDE { return this; } - virtual TextureClient* GetTextureClient() MOZ_OVERRIDE; + virtual TextureClient* GetTextureClient(CompositableClient* aClient) MOZ_OVERRIDE; virtual uint8_t* GetBuffer() MOZ_OVERRIDE; virtual already_AddRefed DeprecatedGetAsSurface() MOZ_OVERRIDE; diff --git a/gfx/layers/ipc/SharedRGBImage.cpp b/gfx/layers/ipc/SharedRGBImage.cpp index 77912fbe386..4fba1d463e0 100644 --- a/gfx/layers/ipc/SharedRGBImage.cpp +++ b/gfx/layers/ipc/SharedRGBImage.cpp @@ -234,7 +234,7 @@ SharedRGBImage::GetBufferSize() } TextureClient* -SharedRGBImage::GetTextureClient() +SharedRGBImage::GetTextureClient(CompositableClient* aClient) { return mTextureClient.get(); } diff --git a/gfx/layers/ipc/SharedRGBImage.h b/gfx/layers/ipc/SharedRGBImage.h index fa3d1b99380..d080c6cc7db 100644 --- a/gfx/layers/ipc/SharedRGBImage.h +++ b/gfx/layers/ipc/SharedRGBImage.h @@ -86,7 +86,7 @@ public: bool AllocateBuffer(nsIntSize aSize, gfxImageFormat aImageFormat); - TextureClient* GetTextureClient() MOZ_OVERRIDE { return nullptr; } + TextureClient* GetTextureClient(CompositableClient* aClient) MOZ_OVERRIDE { return nullptr; } protected: gfx::IntSize mSize; @@ -110,7 +110,7 @@ public: virtual ISharedImage* AsSharedImage() MOZ_OVERRIDE { return this; } - virtual TextureClient* GetTextureClient() MOZ_OVERRIDE; + virtual TextureClient* GetTextureClient(CompositableClient* aClient) MOZ_OVERRIDE; virtual uint8_t* GetBuffer() MOZ_OVERRIDE; diff --git a/gfx/thebes/gfxFT2Utils.cpp b/gfx/thebes/gfxFT2Utils.cpp index acc058e7335..28d3e2ffe32 100644 --- a/gfx/thebes/gfxFT2Utils.cpp +++ b/gfx/thebes/gfxFT2Utils.cpp @@ -81,7 +81,8 @@ gfxFT2LockedFace::GetMetrics(gfxFont::Metrics* aMetrics, gfxFloat emHeight; // Scale for vertical design metric conversion: pixels per design unit. - gfxFloat yScale; + // If this remains at 0.0, we can't use metrics from OS/2 etc. + gfxFloat yScale = 0.0; if (FT_IS_SCALABLE(mFace)) { // Prefer FT_Size_Metrics::x_scale to x_ppem as x_ppem does not // have subpixel accuracy. @@ -93,11 +94,17 @@ gfxFT2LockedFace::GetMetrics(gfxFont::Metrics* aMetrics, yScale = FLOAT_FROM_26_6(FLOAT_FROM_16_16(ftMetrics.y_scale)); emHeight = mFace->units_per_EM * yScale; } else { // Not scalable. - // FT_Size_Metrics doc says x_scale is "only relevant for scalable - // font formats". - gfxFloat emUnit = mFace->units_per_EM; - emHeight = ftMetrics.y_ppem; - yScale = emHeight / emUnit; + // FT_Face doc says units_per_EM and a bunch of following fields + // are "only relevant to scalable outlines". If it's an sfnt, + // we can get units_per_EM from the 'head' table instead; otherwise, + // we don't have a unitsPerEm value so we can't compute/use yScale. + const TT_Header* head = + static_cast(FT_Get_Sfnt_Table(mFace, ft_sfnt_head)); + if (head) { + gfxFloat emUnit = head->Units_Per_EM; + emHeight = ftMetrics.y_ppem; + yScale = emHeight / emUnit; + } } TT_OS2 *os2 = @@ -108,7 +115,7 @@ gfxFT2LockedFace::GetMetrics(gfxFont::Metrics* aMetrics, aMetrics->maxAdvance = FLOAT_FROM_26_6(ftMetrics.max_advance); gfxFloat lineHeight; - if (os2 && os2->sTypoAscender) { + if (os2 && os2->sTypoAscender && yScale > 0.0) { aMetrics->emAscent = os2->sTypoAscender * yScale; aMetrics->emDescent = -os2->sTypoDescender * yScale; FT_Short typoHeight = @@ -150,7 +157,7 @@ gfxFT2LockedFace::GetMetrics(gfxFont::Metrics* aMetrics, aMetrics->xHeight = -extents.y_bearing; aMetrics->aveCharWidth = extents.x_advance; } else { - if (os2 && os2->sxHeight) { + if (os2 && os2->sxHeight && yScale > 0.0) { aMetrics->xHeight = os2->sxHeight * yScale; } else { // CSS 2.1, section 4.3.2 Lengths: "In the cases where it is @@ -195,7 +202,7 @@ gfxFT2LockedFace::GetMetrics(gfxFont::Metrics* aMetrics, // Therefore get the underline position directly from the table // ourselves when this table exists. Use FreeType's metrics for // other (including older PostScript) fonts. - if (mFace->underline_position && mFace->underline_thickness) { + if (mFace->underline_position && mFace->underline_thickness && yScale > 0.0) { aMetrics->underlineSize = mFace->underline_thickness * yScale; TT_Postscript *post = static_cast (FT_Get_Sfnt_Table(mFace, ft_sfnt_post)); @@ -211,7 +218,7 @@ gfxFT2LockedFace::GetMetrics(gfxFont::Metrics* aMetrics, aMetrics->underlineOffset = -aMetrics->underlineSize; } - if (os2 && os2->yStrikeoutSize && os2->yStrikeoutPosition) { + if (os2 && os2->yStrikeoutSize && os2->yStrikeoutPosition && yScale > 0.0) { aMetrics->strikeoutSize = os2->yStrikeoutSize * yScale; aMetrics->strikeoutOffset = os2->yStrikeoutPosition * yScale; } else { // No strikeout info. diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index 89562e7088e..5fa2faaa709 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -575,10 +575,8 @@ GetOutlineInnerRect(nsIFrame* aFrame) (aFrame->Properties().Get(nsIFrame::OutlineInnerRectProperty())); if (savedOutlineInnerRect) return *savedOutlineInnerRect; - // FIXME (bug 599652): We probably want something narrower than either - // overflow rect here, but for now use the visual overflow in order to - // be consistent with ComputeEffectsRect in nsFrame.cpp. - return aFrame->GetVisualOverflowRect(); + NS_NOTREACHED("we should have saved a frame property"); + return nsRect(nsPoint(0, 0), aFrame->GetSize()); } void @@ -608,37 +606,22 @@ nsCSSRendering::PaintOutline(nsPresContext* aPresContext, nscolor bgColor = bgContext->GetVisitedDependentColor(eCSSProperty_background_color); - // When the outline property is set on :-moz-anonymous-block or - // :-moz-anonyomus-positioned-block pseudo-elements, it inherited that - // outline from the inline that was broken because it contained a - // block. In that case, we don't want a really wide outline if the - // block inside the inline is narrow, so union the actual contents of - // the anonymous blocks. - nsIFrame *frameForArea = aForFrame; - do { - nsIAtom *pseudoType = frameForArea->StyleContext()->GetPseudo(); - if (pseudoType != nsCSSAnonBoxes::mozAnonymousBlock && - pseudoType != nsCSSAnonBoxes::mozAnonymousPositionedBlock) - break; - // If we're done, we really want it and all its later siblings. - frameForArea = frameForArea->GetFirstPrincipalChild(); - NS_ASSERTION(frameForArea, "anonymous block with no children?"); - } while (frameForArea); - nsRect innerRect; // relative to aBorderArea.TopLeft() - if (frameForArea == aForFrame) { - innerRect = GetOutlineInnerRect(aForFrame); + nsRect innerRect; + if ( +#ifdef MOZ_XUL + aStyleContext->GetPseudoType() == nsCSSPseudoElements::ePseudo_XULTree +#else + false +#endif + ) { + // FIXME: This behavior doesn't make sense; we should switch back to + // using aBorderArea. But since this has been broken since bug + // 133165 in August of 2004, that switch should be made in its own + // patch changing only that behavior. + innerRect = aForFrame->GetVisualOverflowRect(); } else { - for (; frameForArea; frameForArea = frameForArea->GetNextSibling()) { - // The outline has already been included in aForFrame's overflow - // area, but not in those of its descendants, so we have to - // include it. Otherwise we'll end up drawing the outline inside - // the border. - nsRect r(GetOutlineInnerRect(frameForArea) + - frameForArea->GetOffsetTo(aForFrame)); - innerRect.UnionRect(innerRect, r); - } + innerRect = GetOutlineInnerRect(aForFrame); } - innerRect += aBorderArea.TopLeft(); nscoord offset = ourOutline->mOutlineOffset; innerRect.Inflate(offset, offset); diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 456ea1beb61..e6102dc3e80 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -1639,7 +1639,7 @@ nsLayoutUtils::ChangeMatrixBasis(const gfxPoint3D &aOrigin, * * @param aVal The value to constrain (in/out) */ -static void ConstrainToCoordValues(gfxFloat &aVal) +static void ConstrainToCoordValues(gfxFloat& aVal) { if (aVal <= nscoord_MIN) aVal = nscoord_MIN; @@ -1647,6 +1647,32 @@ static void ConstrainToCoordValues(gfxFloat &aVal) aVal = nscoord_MAX; } +static void ConstrainToCoordValues(gfxFloat& aStart, gfxFloat& aSize) +{ + gfxFloat max = aStart + aSize; + + // Clamp the end points to within nscoord range + ConstrainToCoordValues(aStart); + ConstrainToCoordValues(max); + + aSize = max - aStart; + // If the width if still greater than the max nscoord, then bring both + // endpoints in by the same amount until it fits. + if (aSize > nscoord_MAX) { + gfxFloat excess = aSize - nscoord_MAX; + excess /= 2; + + aStart += excess; + aSize = nscoord_MAX; + } else if (aSize < nscoord_MIN) { + gfxFloat excess = aSize - nscoord_MIN; + excess /= 2; + + aStart -= excess; + aSize = nscoord_MIN; + } +} + nsRect nsLayoutUtils::RoundGfxRectToAppRect(const gfxRect &aRect, float aFactor) { @@ -1655,10 +1681,8 @@ nsLayoutUtils::RoundGfxRectToAppRect(const gfxRect &aRect, float aFactor) scaledRect.ScaleRoundOut(aFactor); /* We now need to constrain our results to the max and min values for coords. */ - ConstrainToCoordValues(scaledRect.x); - ConstrainToCoordValues(scaledRect.y); - ConstrainToCoordValues(scaledRect.width); - ConstrainToCoordValues(scaledRect.height); + ConstrainToCoordValues(scaledRect.x, scaledRect.width); + ConstrainToCoordValues(scaledRect.y, scaledRect.height); /* Now typecast everything back. This is guaranteed to be safe. */ return nsRect(nscoord(scaledRect.X()), nscoord(scaledRect.Y()), diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index f3251bf55af..5461cec87b3 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -4976,27 +4976,6 @@ ComputeEffectsRect(nsIFrame* aFrame, const nsRect& aOverflowRect, // box-shadow r.UnionRect(r, nsLayoutUtils::GetBoxShadowRectForFrame(aFrame, aNewSize)); - const nsStyleOutline* outline = aFrame->StyleOutline(); - uint8_t outlineStyle = outline->GetOutlineStyle(); - if (outlineStyle != NS_STYLE_BORDER_STYLE_NONE) { - nscoord width; - DebugOnly result = outline->GetOutlineWidth(width); - NS_ASSERTION(result, "GetOutlineWidth had no cached outline width"); - if (width > 0) { - aFrame->Properties(). - Set(nsIFrame::OutlineInnerRectProperty(), new nsRect(r)); - - nscoord offset = outline->mOutlineOffset; - nscoord inflateBy = std::max(width + offset, 0); - // FIXME (bug 599652): We probably want outline to be drawn around - // something smaller than the visual overflow rect (perhaps the - // scrollable overflow rect is correct). When we change that, we - // need to keep this code (and the storing of properties just - // above) in sync with GetOutlineInnerRect in nsCSSRendering.cpp. - r.Inflate(inflateBy, inflateBy); - } - } - // border-image-outset. // We need to include border-image-outset because it can cause the // border image to be drawn beyond the border box. @@ -6854,6 +6833,185 @@ IsInlineFrame(nsIFrame *aFrame) return type == nsGkAtoms::inlineFrame; } +/** + * Compute the union of the border boxes of aFrame and its descendants, + * in aFrame's coordinate space (if aApplyTransform is false) or its + * post-transform coordinate space (if aApplyTransform is true). + */ +static nsRect +UnionBorderBoxes(nsIFrame* aFrame, bool aApplyTransform, + const nsSize* aSizeOverride = nullptr, + const nsOverflowAreas* aOverflowOverride = nullptr) +{ + const nsRect bounds(nsPoint(0, 0), + aSizeOverride ? *aSizeOverride : aFrame->GetSize()); + + // Start from our border-box, transformed. See comment below about + // transform of children. + nsRect u; + bool doTransform = aApplyTransform && aFrame->IsTransformed(); + if (doTransform) { + u = nsDisplayTransform::TransformRect(bounds, aFrame, + nsPoint(0, 0), &bounds); + } else { + u = bounds; + } + + // Only iterate through the children if the overflow areas suggest + // that we might need to, and if the frame doesn't clip its overflow + // anyway. + if (aOverflowOverride) { + if (!doTransform && + bounds.IsEqualEdges(aOverflowOverride->VisualOverflow()) && + bounds.IsEqualEdges(aOverflowOverride->ScrollableOverflow())) { + return u; + } + } else { + if (!doTransform && + bounds.IsEqualEdges(aFrame->GetVisualOverflowRect()) && + bounds.IsEqualEdges(aFrame->GetScrollableOverflowRect())) { + return u; + } + } + const nsStyleDisplay* disp = aFrame->StyleDisplay(); + nsIAtom* fType = aFrame->GetType(); + if (nsFrame::ShouldApplyOverflowClipping(aFrame, disp) || + fType == nsGkAtoms::scrollFrame || + fType == nsGkAtoms::svgOuterSVGFrame) { + return u; + } + + nsRect clipPropClipRect; + bool hasClipPropClip = + aFrame->GetClipPropClipRect(disp, &clipPropClipRect, bounds.Size()); + + // Iterate over all children except pop-ups. + const nsIFrame::ChildListIDs skip(nsIFrame::kPopupList | + nsIFrame::kSelectPopupList); + for (nsIFrame::ChildListIterator childLists(aFrame); + !childLists.IsDone(); childLists.Next()) { + if (skip.Contains(childLists.CurrentID())) { + continue; + } + + nsFrameList children = childLists.CurrentList(); + for (nsFrameList::Enumerator e(children); !e.AtEnd(); e.Next()) { + nsIFrame* child = e.get(); + // Note that passing |true| for aApplyTransform when + // child->Preserves3D() is incorrect if our aApplyTransform is + // false... but the opposite would be as well. This is because + // elements within a preserve-3d scene are always transformed up + // to the top of the scene. This means we don't have a + // mechanism for getting a transform up to an intermediate point + // within the scene. We choose to over-transform rather than + // under-transform because this is consistent with other + // overflow areas. + nsRect childRect = UnionBorderBoxes(child, true) + + child->GetPosition(); + + if (hasClipPropClip) { + // Intersect with the clip before transforming. + childRect.IntersectRect(childRect, clipPropClipRect); + } + + // Note that we transform each child separately according to + // aFrame's transform, and then union, which gives a different + // (smaller) result from unioning and then transforming the + // union. This doesn't match the way we handle overflow areas + // with 2-D transforms, though it does match the way we handle + // overflow areas in preserve-3d 3-D scenes. + if (doTransform && !child->Preserves3D()) { + childRect = nsDisplayTransform::TransformRect(childRect, aFrame, + nsPoint(0, 0), &bounds); + } + u.UnionRectEdges(u, childRect); + } + } + + return u; +} + +static void +ComputeAndIncludeOutlineArea(nsIFrame* aFrame, nsOverflowAreas& aOverflowAreas, + const nsSize& aNewSize) +{ + const nsStyleOutline* outline = aFrame->StyleOutline(); + if (outline->GetOutlineStyle() == NS_STYLE_BORDER_STYLE_NONE) { + return; + } + + nscoord width; + DebugOnly result = outline->GetOutlineWidth(width); + NS_ASSERTION(result, "GetOutlineWidth had no cached outline width"); + if (width <= 0) { + return; + } + + // When the outline property is set on :-moz-anonymous-block or + // :-moz-anonymous-positioned-block pseudo-elements, it inherited + // that outline from the inline that was broken because it + // contained a block. In that case, we don't want a really wide + // outline if the block inside the inline is narrow, so union the + // actual contents of the anonymous blocks. + nsIFrame *frameForArea = aFrame; + do { + nsIAtom *pseudoType = frameForArea->StyleContext()->GetPseudo(); + if (pseudoType != nsCSSAnonBoxes::mozAnonymousBlock && + pseudoType != nsCSSAnonBoxes::mozAnonymousPositionedBlock) + break; + // If we're done, we really want it and all its later siblings. + frameForArea = frameForArea->GetFirstPrincipalChild(); + NS_ASSERTION(frameForArea, "anonymous block with no children?"); + } while (frameForArea); + + // Find the union of the border boxes of all descendants, or in + // the block-in-inline case, all descendants we care about. + // + // Note that the interesting perspective-related cases are taken + // care of by the code that handles those issues for overflow + // calling FinishAndStoreOverflow again, which in turn calls this + // function again. We still need to deal with preserve-3d a bit. + nsRect innerRect; + if (frameForArea == aFrame) { + innerRect = UnionBorderBoxes(aFrame, false, &aNewSize, &aOverflowAreas); + } else { + for (; frameForArea; frameForArea = frameForArea->GetNextSibling()) { + nsRect r(UnionBorderBoxes(frameForArea, true)); + + // Adjust for offsets transforms up to aFrame's pre-transform + // (i.e., normal) coordinate space; see comments in + // UnionBorderBoxes for some of the subtlety here. + for (nsIFrame *f = frameForArea, *parent = f->GetParent(); + /* see middle of loop */; + f = parent, parent = f->GetParent()) { + r += f->GetPosition(); + if (parent == aFrame) { + break; + } + if (parent->IsTransformed() && !f->Preserves3D()) { + r = nsDisplayTransform::TransformRect(r, parent, nsPoint(0, 0)); + } + } + + innerRect.UnionRect(innerRect, r); + } + } + + aFrame->Properties().Set(nsIFrame::OutlineInnerRectProperty(), + new nsRect(innerRect)); + + nscoord offset = outline->mOutlineOffset; + nscoord inflateBy = std::max(width + offset, 0); + + // Keep this code (and the storing of properties just above) in + // sync with GetOutlineInnerRect in nsCSSRendering.cpp. + nsRect outerRect(innerRect); + outerRect.Inflate(inflateBy, inflateBy); + + nsRect& vo = aOverflowAreas.VisualOverflow(); + vo.UnionRectEdges(vo, outerRect); +} + bool nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas, nsSize aNewSize, nsSize* aOldSize) @@ -6933,6 +7091,8 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas, } } + ComputeAndIncludeOutlineArea(this, aOverflowAreas, aNewSize); + // Nothing in here should affect scrollable overflow. aOverflowAreas.VisualOverflow() = ComputeEffectsRect(this, aOverflowAreas.VisualOverflow(), aNewSize); diff --git a/layout/reftests/outline/outline-and-3d-transform-1-ref.html b/layout/reftests/outline/outline-and-3d-transform-1-ref.html new file mode 100644 index 00000000000..30fa7eabec0 --- /dev/null +++ b/layout/reftests/outline/outline-and-3d-transform-1-ref.html @@ -0,0 +1,28 @@ + +Testcase for outline around 3-D transform + + +
diff --git a/layout/reftests/outline/outline-and-3d-transform-1a.html b/layout/reftests/outline/outline-and-3d-transform-1a.html new file mode 100644 index 00000000000..6b7926c2dac --- /dev/null +++ b/layout/reftests/outline/outline-and-3d-transform-1a.html @@ -0,0 +1,40 @@ + +Testcase for outline around 3-D transform + + +
diff --git a/layout/reftests/outline/outline-and-3d-transform-1b.html b/layout/reftests/outline/outline-and-3d-transform-1b.html new file mode 100644 index 00000000000..d2e2316de69 --- /dev/null +++ b/layout/reftests/outline/outline-and-3d-transform-1b.html @@ -0,0 +1,40 @@ + +Testcase for outline around 3-D transform + + +
diff --git a/layout/reftests/outline/outline-and-3d-transform-2-ref.html b/layout/reftests/outline/outline-and-3d-transform-2-ref.html new file mode 100644 index 00000000000..93a45d8f80e --- /dev/null +++ b/layout/reftests/outline/outline-and-3d-transform-2-ref.html @@ -0,0 +1,36 @@ + +Testcase for outline around 3-D transform + + +
diff --git a/layout/reftests/outline/outline-and-3d-transform-2.html b/layout/reftests/outline/outline-and-3d-transform-2.html new file mode 100644 index 00000000000..72436697171 --- /dev/null +++ b/layout/reftests/outline/outline-and-3d-transform-2.html @@ -0,0 +1,35 @@ + +Testcase for outline around 3-D transform + + +
diff --git a/layout/reftests/outline/outline-and-box-shadow-ref.html b/layout/reftests/outline/outline-and-box-shadow-ref.html new file mode 100644 index 00000000000..0d4a9ffcf69 --- /dev/null +++ b/layout/reftests/outline/outline-and-box-shadow-ref.html @@ -0,0 +1,13 @@ + +outline and box-shadow + +

The outline should be adjacent to the background.

diff --git a/layout/reftests/outline/outline-and-box-shadow.html b/layout/reftests/outline/outline-and-box-shadow.html new file mode 100644 index 00000000000..3bb717200b4 --- /dev/null +++ b/layout/reftests/outline/outline-and-box-shadow.html @@ -0,0 +1,13 @@ + +outline and box-shadow + +

The outline should be adjacent to the background.

diff --git a/layout/reftests/outline/reftest.list b/layout/reftests/outline/reftest.list new file mode 100644 index 00000000000..7384bd4893c --- /dev/null +++ b/layout/reftests/outline/reftest.list @@ -0,0 +1,4 @@ +== outline-and-box-shadow.html outline-and-box-shadow-ref.html +== outline-and-3d-transform-1a.html outline-and-3d-transform-1-ref.html +== outline-and-3d-transform-1b.html outline-and-3d-transform-1-ref.html +== outline-and-3d-transform-2.html outline-and-3d-transform-2-ref.html diff --git a/layout/reftests/reftest.list b/layout/reftests/reftest.list index d31429ad7ec..971e76b8b83 100644 --- a/layout/reftests/reftest.list +++ b/layout/reftests/reftest.list @@ -219,6 +219,8 @@ skip-if(Android||B2G) include native-theme/reftest.list # netwerk/ skip-if(B2G) include ../../netwerk/test/reftest/reftest.list +include outline/reftest.list + # object/ skip-if(B2G) include object/reftest.list diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 6eafb5103ea..0d04b98fca1 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -1543,7 +1543,7 @@ nsStyleGradient::HasCalc() return true; } return mBgPosX.IsCalcUnit() || mBgPosY.IsCalcUnit() || mAngle.IsCalcUnit() || - mRadiusX.IsCalcUnit() || mRadiusX.IsCalcUnit(); + mRadiusX.IsCalcUnit() || mRadiusY.IsCalcUnit(); } // -------------------- diff --git a/layout/tools/reftest/reftest-analyzer.xhtml b/layout/tools/reftest/reftest-analyzer.xhtml index 6e7a07322d3..d762239d84a 100644 --- a/layout/tools/reftest/reftest-analyzer.xhtml +++ b/layout/tools/reftest/reftest-analyzer.xhtml @@ -1,6 +1,6 @@ - - + + @@ -179,7 +179,7 @@ function fileentry_changed() { var log = null; log = e.target.result; - + if (log) process_log(log); else @@ -217,7 +217,7 @@ function process_log(contents) { var state = match[1]; var random = match[2]; var url = match[3]; - var extra = match[4]; + var extra = match[4]; gTestItems.push( { pass: !state.match(/DEBUG-INFO$|FAIL$/), diff --git a/layout/tools/reftest/reftest.js b/layout/tools/reftest/reftest.js index ae057178899..a5a11cc65a6 100644 --- a/layout/tools/reftest/reftest.js +++ b/layout/tools/reftest/reftest.js @@ -1655,7 +1655,7 @@ function RecordResult(testRunTime, errorMsg, scriptResults) result += "REFTEST IMAGE 2 (REFERENCE): " + gCanvas2.toDataURL() + "\n"; } else { result += "\n"; - gDumpLog("REFTEST IMAGE: " + gCanvas1.toDataURL() + "\n"); + result += "REFTEST IMAGE: " + gCanvas1.toDataURL() + "\n"; } } else { result += "\n"; diff --git a/python/lldbutils/lldbutils/utils.py b/python/lldbutils/lldbutils/utils.py index 1484322bcb8..1370be5eb8b 100644 --- a/python/lldbutils/lldbutils/utils.py +++ b/python/lldbutils/lldbutils/utils.py @@ -19,7 +19,7 @@ def format_char(c): return "\\" elif c == 0x22: return "\\\"" - elif c == 0x39: + elif c == 0x27: return "\\'" elif c < 0x20 or c >= 0x80 and c <= 0xff: return "\\x%02x" % c