diff --git a/browser/app/nsBrowserApp.cpp b/browser/app/nsBrowserApp.cpp index 5df1289b8ccc..14f992d0540e 100644 --- a/browser/app/nsBrowserApp.cpp +++ b/browser/app/nsBrowserApp.cpp @@ -46,6 +46,10 @@ #include #endif +#ifdef XP_MACOSX +#include "MacQuirks.h" +#endif + #include #include #include @@ -208,6 +212,10 @@ int main(int argc, char* argv[]) { char exePath[MAXPATHLEN]; +#ifdef XP_MACOSX + TriggerQuirks(); +#endif + nsresult rv = mozilla::BinaryPath::Get(argv[0], exePath); if (NS_FAILED(rv)) { Output("Couldn't calculate the application directory.\n"); diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 861a635f9fee..44033e8a0576 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -4707,10 +4707,12 @@ var XULBrowserWindow = { document.documentElement.removeAttribute("disablechrome"); // Disable find commands in documents that ask for them to be disabled. - let docElt = content.document.documentElement; - let disableFind = aLocationURI && - (docElt && docElt.getAttribute("disablefastfind") == "true") && - (aLocationURI.schemeIs("about") || aLocationURI.schemeIs("chrome")); + let disableFind = false; + if (aLocationURI && + (aLocationURI.schemeIs("about") || aLocationURI.schemeIs("chrome"))) { + let docElt = content.document.documentElement; + disableFind = docElt && docElt.getAttribute("disablefastfind") == "true"; + } let findCommands = [document.getElementById("cmd_find"), document.getElementById("cmd_findAgain"), document.getElementById("cmd_findPrevious")]; diff --git a/browser/components/preferences/advanced.js b/browser/components/preferences/advanced.js index 60f2269f43d8..b12d07feec30 100644 --- a/browser/components/preferences/advanced.js +++ b/browser/components/preferences/advanced.js @@ -537,7 +537,6 @@ var gAdvancedPane = { // If it is don't show the preference at all. var installed; try { - Components.utils.reportError("0"); var wrk = Components.classes["@mozilla.org/windows-registry-key;1"] .createInstance(Components.interfaces.nsIWindowsRegKey); wrk.open(wrk.ROOT_KEY_LOCAL_MACHINE, diff --git a/client.mk b/client.mk index cbfde19ee674..e4d3ef38dcb8 100644 --- a/client.mk +++ b/client.mk @@ -294,7 +294,6 @@ $(CONFIGURES): %: %.in $(EXTRA_CONFIG_DEPS) CONFIG_STATUS_DEPS := \ $(wildcard $(CONFIGURES)) \ $(TOPSRCDIR)/allmakefiles.sh \ - $(TOPSRCDIR)/.mozconfig.mk \ $(wildcard $(TOPSRCDIR)/nsprpub/configure) \ $(wildcard $(TOPSRCDIR)/config/milestone.txt) \ $(wildcard $(TOPSRCDIR)/js/src/config/milestone.txt) \ diff --git a/configure.in b/configure.in index ffb8a333f8b6..6187de559ff2 100644 --- a/configure.in +++ b/configure.in @@ -5313,7 +5313,7 @@ then if test "$MOZ_ENABLE_GCONF" then PKG_CHECK_MODULES(MOZ_GCONF, gconf-2.0 >= $GCONF_VERSION gobject-2.0 ,[ - MOZ_GCONF_LIBS=`echo $MOZ_GCONF_LIBS | sed 's/-llinc\>//'` + MOZ_GCONF_LIBS=`$PKG_CONFIG --libs gobject-2.0` MOZ_ENABLE_GCONF=1 ],[ if test "$MOZ_ENABLE_GCONF" = "force" diff --git a/content/canvas/src/WebGLContext.cpp b/content/canvas/src/WebGLContext.cpp index d7d71618c8e1..297e36ff2072 100644 --- a/content/canvas/src/WebGLContext.cpp +++ b/content/canvas/src/WebGLContext.cpp @@ -292,11 +292,13 @@ WebGLContext::WebGLContext() WebGLMemoryReporter::AddWebGLContext(this); - mContextLost = false; - mAllowRestore = false; + mAllowRestore = true; mRobustnessTimerRunning = false; mDrawSinceRobustnessTimerSet = false; mContextRestorer = do_CreateInstance("@mozilla.org/timer;1"); + mContextStatus = ContextStable; + mContextLostErrorSet = false; + mContextLostDueToTest = false; } WebGLContext::~WebGLContext() @@ -801,7 +803,7 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* aBuilder, CanvasLayer *aOldLayer, LayerManager *aManager) { - if (mContextLost) + if (!IsContextStable()) return nsnull; if (!mResetLayer && aOldLayer && @@ -865,7 +867,7 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* aBuilder, NS_IMETHODIMP WebGLContext::GetContextAttributes(jsval *aResult) { - if (mContextLost) + if (!IsContextStable()) { *aResult = OBJECT_TO_JSVAL(NULL); return NS_OK; @@ -909,7 +911,7 @@ WebGLContext::GetContextAttributes(jsval *aResult) NS_IMETHODIMP WebGLContext::MozGetUnderlyingParamString(PRUint32 pname, nsAString& retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; retval.SetIsVoid(true); @@ -948,7 +950,7 @@ bool WebGLContext::IsExtensionSupported(WebGLExtensionID ei) // We always support this extension. isSupported = true; break; - case WebGL_WEBGL_EXT_lose_context: + case WebGL_MOZ_WEBGL_lose_context: // We always support this extension. isSupported = true; break; @@ -963,7 +965,7 @@ NS_IMETHODIMP WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval) { *retval = nsnull; - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (mDisableExtensions) { @@ -980,9 +982,9 @@ WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval) if (IsExtensionSupported(WebGL_OES_standard_derivatives)) ei = WebGL_OES_standard_derivatives; } - else if (aName.EqualsLiteral("WEBGL_EXT_lose_context")) { - if (IsExtensionSupported(WebGL_WEBGL_EXT_lose_context)) - ei = WebGL_WEBGL_EXT_lose_context; + else if (aName.EqualsLiteral("MOZ_WEBGL_lose_context")) { + if (IsExtensionSupported(WebGL_MOZ_WEBGL_lose_context)) + ei = WebGL_MOZ_WEBGL_lose_context; } if (ei != WebGLExtensionID_Max) { @@ -991,7 +993,7 @@ WebGLContext::GetExtension(const nsAString& aName, nsIWebGLExtension **retval) case WebGL_OES_standard_derivatives: mEnabledExtensions[ei] = new WebGLExtensionStandardDerivatives(this); break; - case WebGL_WEBGL_EXT_lose_context: + case WebGL_MOZ_WEBGL_lose_context: mEnabledExtensions[ei] = new WebGLExtensionLoseContext(this); break; // create an extension for any types that don't @@ -1097,10 +1099,69 @@ WebGLContext::EnsureBackbufferClearedAsNeeded() Invalidate(); } +// We use this timer for many things. Here are the things that it is activated for: +// 1) If a script is using the MOZ_WEBGL_lose_context extension. +// 2) If we are using EGL and _NOT ANGLE_, we query periodically to see if the +// CONTEXT_LOST_WEBGL error has been triggered. +// 3) If we are using ANGLE, or anything that supports ARB_robustness, query the +// GPU periodically to see if the reset status bit has been set. +// In all of these situations, we use this timer to send the script context lost +// and restored events asynchronously. For example, if it triggers a context loss, +// the webglcontextlost event will be sent to it the next time the robustness timer +// fires. +// Note that this timer mechanism is not used unless one of these 3 criteria +// are met. +// At a bare minimum, from context lost to context restores, it would take 3 +// full timer iterations: detection, webglcontextlost, webglcontextrestored. NS_IMETHODIMP WebGLContext::Notify(nsITimer* timer) { TerminateRobustnessTimer(); + // If the context has been lost and we're waiting for it to be restored, do + // that now. + if (mContextStatus == ContextLostAwaitingEvent) { + bool defaultAction; + nsContentUtils::DispatchTrustedEvent(HTMLCanvasElement()->OwnerDoc(), + (nsIDOMHTMLCanvasElement*) HTMLCanvasElement(), + NS_LITERAL_STRING("webglcontextlost"), + PR_TRUE, + PR_TRUE, + &defaultAction); + + // If the script didn't handle the event, we don't allow restores. + if (defaultAction) + mAllowRestore = false; + + // If the script handled the event and we are allowing restores, then + // mark it to be restored. Otherwise, leave it as context lost + // (unusable). + if (!defaultAction && mAllowRestore) { + ForceRestoreContext(); + // Restart the timer so that it will be restored on the next + // callback. + SetupRobustnessTimer(); + } else { + mContextStatus = ContextLost; + } + } else if (mContextStatus == ContextLostAwaitingRestore) { + // Try to restore the context. If it fails, try again later. + if (NS_FAILED(SetDimensions(mWidth, mHeight))) { + SetupRobustnessTimer(); + return NS_OK; + } + mContextStatus = ContextStable; + nsContentUtils::DispatchTrustedEvent(HTMLCanvasElement()->OwnerDoc(), + (nsIDOMHTMLCanvasElement*) HTMLCanvasElement(), + NS_LITERAL_STRING("webglcontextrestored"), + PR_TRUE, + PR_TRUE); + // Set all flags back to the state they were in before the context was + // lost. + mContextLostErrorSet = false; + mContextLostDueToTest = false; + mAllowRestore = true; + } + MaybeRestoreContext(); return NS_OK; } @@ -1108,18 +1169,25 @@ WebGLContext::Notify(nsITimer* timer) void WebGLContext::MaybeRestoreContext() { - if (mContextLost || mAllowRestore) + // Don't try to handle it if we already know it's busted. + if (mContextStatus != ContextStable || gl == nsnull) return; bool isEGL = gl->GetContextType() == GLContext::ContextTypeEGL, isANGLE = gl->IsANGLE(); + // If was lost due to a forced context loss, don't try to handle it. + // Also, we also don't try to handle if if we don't have robustness. + // Note that the code in this function is used only for situations where + // we have an actual context loss, and not a simulated one. + if (mContextLostDueToTest || + (!mHasRobustness && !isEGL)) + return; + GLContext::ContextResetARB resetStatus = GLContext::CONTEXT_NO_ERROR; if (mHasRobustness) { gl->MakeCurrent(); resetStatus = (GLContext::ContextResetARB) gl->fGetGraphicsResetStatus(); - // This call is safe as it does not actually interact with GL, so the - // context does not have to be current. } else if (isEGL) { // Simulate a ARB_robustness guilty context loss for when we // get an EGL_CONTEXT_LOST error. It may not actually be guilty, @@ -1143,10 +1211,11 @@ WebGLContext::MaybeRestoreContext() // run it again some time later. if (mDrawSinceRobustnessTimerSet) SetupRobustnessTimer(); - return; + break; case GLContext::CONTEXT_GUILTY_CONTEXT_RESET_ARB: NS_WARNING("WebGL content on the page caused the graphics card to reset; not restoring the context"); - return; + mAllowRestore = false; + break; case GLContext::CONTEXT_INNOCENT_CONTEXT_RESET_ARB: break; case GLContext::CONTEXT_UNKNOWN_CONTEXT_RESET_ARB: @@ -1156,45 +1225,25 @@ WebGLContext::MaybeRestoreContext() // This means that we can't restore it or risk restoring a guilty context. Should this ever change, // we can get rid of the whole IsANGLE() junk from GLContext.h since, as of writing, this is the // only use for it. See ANGLE issue 261. - return; + mAllowRestore = false; } break; } - - ForceRestoreContext(); } void WebGLContext::ForceLoseContext() { - TerminateRobustnessTimer(); - - mWebGLError = LOCAL_GL_CONTEXT_LOST; - - bool defaultAction; - mContextLost = true; + mContextStatus = ContextLostAwaitingEvent; + // Queue up a task to restore the event. + SetupRobustnessTimer(); DestroyResourcesAndContext(); - nsContentUtils::DispatchTrustedEvent(HTMLCanvasElement()->OwnerDoc(), - (nsIDOMHTMLCanvasElement*) HTMLCanvasElement(), - NS_LITERAL_STRING("webglcontextlost"), - PR_TRUE, - PR_TRUE, - &defaultAction); - if (defaultAction) - mAllowRestore = false; } void WebGLContext::ForceRestoreContext() { - mContextLost = false; - mAllowRestore = false; - SetDimensions(mHeight, mWidth); - nsContentUtils::DispatchTrustedEvent(HTMLCanvasElement()->OwnerDoc(), - (nsIDOMHTMLCanvasElement*) HTMLCanvasElement(), - NS_LITERAL_STRING("webglcontextrestored"), - PR_TRUE, - PR_TRUE); + mContextStatus = ContextLostAwaitingRestore; } // @@ -1372,7 +1421,7 @@ NS_INTERFACE_MAP_END_INHERITING(WebGLExtension) NS_IMETHODIMP WebGLContext::GetDrawingBufferWidth(WebGLsizei *aWidth) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *aWidth = mWidth; @@ -1383,7 +1432,7 @@ WebGLContext::GetDrawingBufferWidth(WebGLsizei *aWidth) NS_IMETHODIMP WebGLContext::GetDrawingBufferHeight(WebGLsizei *aHeight) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *aHeight = mHeight; @@ -1455,7 +1504,7 @@ NS_IMETHODIMP WebGLContext::GetSupportedExtensions(nsIVariant **retval) { *retval = nsnull; - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (mDisableExtensions) { @@ -1471,8 +1520,8 @@ WebGLContext::GetSupportedExtensions(nsIVariant **retval) extList.InsertElementAt(extList.Length(), "OES_texture_float"); if (IsExtensionSupported(WebGL_OES_standard_derivatives)) extList.InsertElementAt(extList.Length(), "OES_standard_derivatives"); - if (IsExtensionSupported(WebGL_WEBGL_EXT_lose_context)) - extList.InsertElementAt(extList.Length(), "WEBGL_EXT_lose_context"); + if (IsExtensionSupported(WebGL_MOZ_WEBGL_lose_context)) + extList.InsertElementAt(extList.Length(), "MOZ_WEBGL_lose_context"); nsresult rv; if (extList.Length() > 0) { @@ -1491,7 +1540,13 @@ WebGLContext::GetSupportedExtensions(nsIVariant **retval) NS_IMETHODIMP WebGLContext::IsContextLost(WebGLboolean *retval) { - *retval = mContextLost; + *retval = mContextStatus != ContextStable; return NS_OK; } +// Internalized version of IsContextLost. +bool +WebGLContext::IsContextStable() +{ + return mContextStatus == ContextStable; +} diff --git a/content/canvas/src/WebGLContext.h b/content/canvas/src/WebGLContext.h index 510672d9873f..da1bc821ab3e 100644 --- a/content/canvas/src/WebGLContext.h +++ b/content/canvas/src/WebGLContext.h @@ -575,10 +575,17 @@ public: return mMinCapability; } + // See the comment over WebGLContext::Notify() for more information on this. + bool ShouldEnableRobustnessTimer() { + return mHasRobustness || + IsExtensionEnabled(WebGL_MOZ_WEBGL_lose_context) || + (gl != nsnull && gl->GetContextType() == gl::GLContext::ContextTypeEGL); + } + // Sets up the GL_ARB_robustness timer if it isn't already, so that if the // driver gets restarted, the context may get reset with it. void SetupRobustnessTimer() { - if (mContextLost || (!mHasRobustness && gl->GetContextType() != gl::GLContext::ContextTypeEGL)) + if (!ShouldEnableRobustnessTimer()) return; // If the timer was already running, don't restart it here. Instead, @@ -668,11 +675,30 @@ protected: PRInt32 mGLMaxFragmentUniformVectors; PRInt32 mGLMaxVertexUniformVectors; + // Represents current status, or state, of the context. That is, is it lost + // or stable and what part of the context lost process are we currently at. + // This is used to support the WebGL spec's asyncronous nature in handling + // context loss. + enum ContextStatus { + // The context is stable; there either are none or we don't know of any. + ContextStable, + // The context has been lost, but we have not yet sent an event to the + // script informing it of this. + ContextLostAwaitingEvent, + // The context has been lost, and we have sent the script an event + // informing it of this. + ContextLost, + // The context is lost, an event has been sent to the script, and the + // script correctly handled the event. We are waiting for the context to + // be restored. + ContextLostAwaitingRestore + }; + // extensions enum WebGLExtensionID { WebGL_OES_texture_float, WebGL_OES_standard_derivatives, - WebGL_WEBGL_EXT_lose_context, + WebGL_MOZ_WEBGL_lose_context, WebGLExtensionID_Max }; nsCOMPtr mEnabledExtensions[WebGLExtensionID_Max]; @@ -805,6 +831,7 @@ protected: const GLvoid *data); void MaybeRestoreContext(); + bool IsContextStable(); void ForceLoseContext(); void ForceRestoreContext(); @@ -861,10 +888,12 @@ protected: int mBackbufferClearingStatus; nsCOMPtr mContextRestorer; - bool mContextLost; bool mAllowRestore; bool mRobustnessTimerRunning; bool mDrawSinceRobustnessTimerSet; + ContextStatus mContextStatus; + bool mContextLostErrorSet; + bool mContextLostDueToTest; public: // console logging helpers diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 5c49904584f2..54c18bbf7685 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -81,43 +81,43 @@ static WebGLenum InternalFormatForFormatAndType(WebGLenum format, WebGLenum type #define GL_SAME_METHOD_0(glname, name) \ NS_IMETHODIMP WebGLContext::name() { \ - if (mContextLost) { return NS_OK; } \ + if (!IsContextStable()) { return NS_OK; } \ MakeContextCurrent(); gl->f##glname(); return NS_OK; \ } #define GL_SAME_METHOD_1(glname, name, t1) \ NS_IMETHODIMP WebGLContext::name(t1 a1) { \ - if (mContextLost) { return NS_OK; } \ + if (!IsContextStable()) { return NS_OK; } \ MakeContextCurrent(); gl->f##glname(a1); return NS_OK; \ } #define GL_SAME_METHOD_2(glname, name, t1, t2) \ NS_IMETHODIMP WebGLContext::name(t1 a1, t2 a2) { \ - if (mContextLost) { return NS_OK; } \ + if (!IsContextStable()) { return NS_OK; } \ MakeContextCurrent(); gl->f##glname(a1,a2); return NS_OK; \ } #define GL_SAME_METHOD_3(glname, name, t1, t2, t3) \ NS_IMETHODIMP WebGLContext::name(t1 a1, t2 a2, t3 a3) { \ - if (mContextLost) { return NS_OK; } \ + if (!IsContextStable()) { return NS_OK; } \ MakeContextCurrent(); gl->f##glname(a1,a2,a3); return NS_OK; \ } #define GL_SAME_METHOD_4(glname, name, t1, t2, t3, t4) \ NS_IMETHODIMP WebGLContext::name(t1 a1, t2 a2, t3 a3, t4 a4) { \ - if (mContextLost) { return NS_OK; } \ + if (!IsContextStable()) { return NS_OK; } \ MakeContextCurrent(); gl->f##glname(a1,a2,a3,a4); return NS_OK; \ } #define GL_SAME_METHOD_5(glname, name, t1, t2, t3, t4, t5) \ NS_IMETHODIMP WebGLContext::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) { \ - if (mContextLost) { return NS_OK; } \ + if (!IsContextStable()) { return NS_OK; } \ MakeContextCurrent(); gl->f##glname(a1,a2,a3,a4,a5); return NS_OK; \ } #define GL_SAME_METHOD_6(glname, name, t1, t2, t3, t4, t5, t6) \ NS_IMETHODIMP WebGLContext::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) { \ - if (mContextLost) { return NS_OK; } \ + if (!IsContextStable()) { return NS_OK; } \ MakeContextCurrent(); gl->f##glname(a1,a2,a3,a4,a5,a6); return NS_OK; \ } @@ -131,7 +131,7 @@ NS_IMETHODIMP WebGLContext::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) { \ NS_IMETHODIMP WebGLContext::ActiveTexture(WebGLenum texture) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (texture < LOCAL_GL_TEXTURE0 || texture >= LOCAL_GL_TEXTURE0 + mBound2DTextures.Length()) @@ -147,7 +147,7 @@ WebGLContext::ActiveTexture(WebGLenum texture) NS_IMETHODIMP WebGLContext::AttachShader(nsIWebGLProgram *pobj, nsIWebGLShader *shobj) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; // if pobj or shobj are null/not specified, it's an error @@ -177,7 +177,7 @@ WebGLContext::AttachShader(nsIWebGLProgram *pobj, nsIWebGLShader *shobj) NS_IMETHODIMP WebGLContext::BindAttribLocation(nsIWebGLProgram *pobj, WebGLuint location, const nsAString& name) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; WebGLuint progname; @@ -337,7 +337,7 @@ GL_SAME_METHOD_4(BlendColor, BlendColor, WebGLfloat, WebGLfloat, WebGLfloat, Web NS_IMETHODIMP WebGLContext::BlendEquation(WebGLenum mode) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!ValidateBlendEquationEnum(mode, "blendEquation: mode")) @@ -350,7 +350,7 @@ NS_IMETHODIMP WebGLContext::BlendEquation(WebGLenum mode) NS_IMETHODIMP WebGLContext::BlendEquationSeparate(WebGLenum modeRGB, WebGLenum modeAlpha) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!ValidateBlendEquationEnum(modeRGB, "blendEquationSeparate: modeRGB") || @@ -364,7 +364,7 @@ NS_IMETHODIMP WebGLContext::BlendEquationSeparate(WebGLenum modeRGB, WebGLenum m NS_IMETHODIMP WebGLContext::BlendFunc(WebGLenum sfactor, WebGLenum dfactor) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!ValidateBlendFuncSrcEnum(sfactor, "blendFunc: sfactor") || @@ -383,7 +383,7 @@ NS_IMETHODIMP WebGLContext::BlendFuncSeparate(WebGLenum srcRGB, WebGLenum dstRGB, WebGLenum srcAlpha, WebGLenum dstAlpha) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!ValidateBlendFuncSrcEnum(srcRGB, "blendFuncSeparate: srcRGB") || @@ -431,7 +431,7 @@ GLenum WebGLContext::CheckedBufferData(GLenum target, NS_IMETHODIMP WebGLContext::BufferData(PRInt32 dummy) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; // this should never be called @@ -442,7 +442,7 @@ WebGLContext::BufferData(PRInt32 dummy) NS_IMETHODIMP WebGLContext::BufferData_null() { - if (mContextLost) + if (!IsContextStable()) return NS_OK; // see http://www.khronos.org/bugzilla/show_bug.cgi?id=386 @@ -453,7 +453,7 @@ WebGLContext::BufferData_null() NS_IMETHODIMP WebGLContext::BufferData_size(WebGLenum target, WebGLsizei size, WebGLenum usage) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; WebGLBuffer *boundBuffer = NULL; @@ -494,7 +494,7 @@ WebGLContext::BufferData_size(WebGLenum target, WebGLsizei size, WebGLenum usage NS_IMETHODIMP WebGLContext::BufferData_buf(WebGLenum target, JSObject *wb, WebGLenum usage) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; WebGLBuffer *boundBuffer = NULL; @@ -535,7 +535,7 @@ WebGLContext::BufferData_buf(WebGLenum target, JSObject *wb, WebGLenum usage) NS_IMETHODIMP WebGLContext::BufferData_array(WebGLenum target, JSObject *wa, WebGLenum usage) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; WebGLBuffer *boundBuffer = NULL; @@ -576,7 +576,7 @@ WebGLContext::BufferData_array(WebGLenum target, JSObject *wa, WebGLenum usage) NS_IMETHODIMP WebGLContext::BufferSubData(PRInt32) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; return NS_ERROR_FAILURE; @@ -585,7 +585,7 @@ WebGLContext::BufferSubData(PRInt32) NS_IMETHODIMP WebGLContext::BufferSubData_null() { - if (mContextLost) + if (!IsContextStable()) return NS_OK; return NS_OK; // see http://www.khronos.org/bugzilla/show_bug.cgi?id=386 @@ -594,7 +594,7 @@ WebGLContext::BufferSubData_null() NS_IMETHODIMP WebGLContext::BufferSubData_buf(GLenum target, WebGLsizei byteOffset, JSObject *wb) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; WebGLBuffer *boundBuffer = NULL; @@ -634,7 +634,7 @@ WebGLContext::BufferSubData_buf(GLenum target, WebGLsizei byteOffset, JSObject * NS_IMETHODIMP WebGLContext::BufferSubData_array(WebGLenum target, WebGLsizei byteOffset, JSObject *wa) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; WebGLBuffer *boundBuffer = NULL; @@ -674,7 +674,7 @@ WebGLContext::BufferSubData_array(WebGLenum target, WebGLsizei byteOffset, JSObj NS_IMETHODIMP WebGLContext::CheckFramebufferStatus(WebGLenum target, WebGLenum *retval) { - if (mContextLost) + if (!IsContextStable()) { *retval = LOCAL_GL_FRAMEBUFFER_UNSUPPORTED; return NS_OK; @@ -697,7 +697,7 @@ WebGLContext::CheckFramebufferStatus(WebGLenum target, WebGLenum *retval) NS_IMETHODIMP WebGLContext::Clear(PRUint32 mask) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; MakeContextCurrent(); @@ -739,7 +739,7 @@ WebGLContext::Clear(PRUint32 mask) NS_IMETHODIMP WebGLContext::ClearColor(WebGLfloat r, WebGLfloat g, WebGLfloat b, WebGLfloat a) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; MakeContextCurrent(); @@ -754,7 +754,7 @@ WebGLContext::ClearColor(WebGLfloat r, WebGLfloat g, WebGLfloat b, WebGLfloat a) NS_IMETHODIMP WebGLContext::ClearDepth(WebGLfloat v) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; MakeContextCurrent(); @@ -766,7 +766,7 @@ WebGLContext::ClearDepth(WebGLfloat v) NS_IMETHODIMP WebGLContext::ClearStencil(WebGLint v) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; MakeContextCurrent(); @@ -778,7 +778,7 @@ WebGLContext::ClearStencil(WebGLint v) NS_IMETHODIMP WebGLContext::ColorMask(WebGLboolean r, WebGLboolean g, WebGLboolean b, WebGLboolean a) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; MakeContextCurrent(); @@ -890,7 +890,7 @@ WebGLContext::CopyTexImage2D(WebGLenum target, WebGLsizei height, WebGLint border) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; switch (target) { @@ -995,7 +995,7 @@ WebGLContext::CopyTexSubImage2D(WebGLenum target, WebGLsizei width, WebGLsizei height) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; switch (target) { @@ -1062,7 +1062,7 @@ WebGLContext::CopyTexSubImage2D(WebGLenum target, NS_IMETHODIMP WebGLContext::CreateProgram(nsIWebGLProgram **retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *retval = nsnull; @@ -1076,7 +1076,7 @@ WebGLContext::CreateProgram(nsIWebGLProgram **retval) NS_IMETHODIMP WebGLContext::CreateShader(WebGLenum type, nsIWebGLShader **retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *retval = nsnull; @@ -1096,7 +1096,7 @@ WebGLContext::CreateShader(WebGLenum type, nsIWebGLShader **retval) NS_IMETHODIMP WebGLContext::CullFace(WebGLenum face) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!ValidateFaceEnum(face, "cullFace")) @@ -1110,7 +1110,7 @@ WebGLContext::CullFace(WebGLenum face) NS_IMETHODIMP WebGLContext::DeleteBuffer(nsIWebGLBuffer *bobj) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; WebGLuint bufname; @@ -1140,7 +1140,7 @@ WebGLContext::DeleteBuffer(nsIWebGLBuffer *bobj) NS_IMETHODIMP WebGLContext::DeleteFramebuffer(nsIWebGLFramebuffer *fbobj) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; WebGLFramebuffer *fbuf; @@ -1163,7 +1163,7 @@ WebGLContext::DeleteFramebuffer(nsIWebGLFramebuffer *fbobj) NS_IMETHODIMP WebGLContext::DeleteRenderbuffer(nsIWebGLRenderbuffer *rbobj) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; WebGLRenderbuffer *rbuf; @@ -1189,7 +1189,7 @@ WebGLContext::DeleteRenderbuffer(nsIWebGLRenderbuffer *rbobj) NS_IMETHODIMP WebGLContext::DeleteTexture(nsIWebGLTexture *tobj) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; WebGLTexture *tex; @@ -1222,7 +1222,7 @@ WebGLContext::DeleteTexture(nsIWebGLTexture *tobj) NS_IMETHODIMP WebGLContext::DeleteProgram(nsIWebGLProgram *pobj) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; WebGLuint progname; @@ -1242,7 +1242,7 @@ WebGLContext::DeleteProgram(nsIWebGLProgram *pobj) NS_IMETHODIMP WebGLContext::DeleteShader(nsIWebGLShader *sobj) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; WebGLuint shadername; @@ -1262,7 +1262,7 @@ WebGLContext::DeleteShader(nsIWebGLShader *sobj) NS_IMETHODIMP WebGLContext::DetachShader(nsIWebGLProgram *pobj, nsIWebGLShader *shobj) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; WebGLuint progname, shadername; @@ -1284,7 +1284,7 @@ WebGLContext::DetachShader(nsIWebGLProgram *pobj, nsIWebGLShader *shobj) NS_IMETHODIMP WebGLContext::DepthFunc(WebGLenum func) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!ValidateComparisonEnum(func, "depthFunc")) @@ -1298,7 +1298,7 @@ WebGLContext::DepthFunc(WebGLenum func) NS_IMETHODIMP WebGLContext::DepthMask(WebGLboolean b) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; MakeContextCurrent(); @@ -1310,7 +1310,7 @@ WebGLContext::DepthMask(WebGLboolean b) NS_IMETHODIMP WebGLContext::DepthRange(WebGLfloat zNear, WebGLfloat zFar) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (zNear > zFar) @@ -1324,7 +1324,7 @@ WebGLContext::DepthRange(WebGLfloat zNear, WebGLfloat zFar) NS_IMETHODIMP WebGLContext::DisableVertexAttribArray(WebGLuint index) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!ValidateAttribIndex(index, "disableVertexAttribArray")) @@ -1550,7 +1550,7 @@ WebGLContext::UnbindFakeBlackTextures() NS_IMETHODIMP WebGLContext::DrawArrays(GLenum mode, WebGLint first, WebGLsizei count) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!ValidateDrawModeEnum(mode, "drawArrays: mode")) @@ -1611,7 +1611,7 @@ WebGLContext::DrawArrays(GLenum mode, WebGLint first, WebGLsizei count) NS_IMETHODIMP WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, WebGLint byteOffset) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!ValidateDrawModeEnum(mode, "drawElements: mode")) @@ -1721,7 +1721,7 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, Web NS_IMETHODIMP WebGLContext::Enable(WebGLenum cap) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!ValidateCapabilityEnum(cap, "enable")) @@ -1743,7 +1743,7 @@ NS_IMETHODIMP WebGLContext::Enable(WebGLenum cap) NS_IMETHODIMP WebGLContext::Disable(WebGLenum cap) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!ValidateCapabilityEnum(cap, "disable")) @@ -1766,7 +1766,7 @@ NS_IMETHODIMP WebGLContext::Disable(WebGLenum cap) NS_IMETHODIMP WebGLContext::EnableVertexAttribArray(WebGLuint index) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!ValidateAttribIndex(index, "enableVertexAttribArray")) @@ -1783,7 +1783,7 @@ WebGLContext::EnableVertexAttribArray(WebGLuint index) NS_IMETHODIMP WebGLContext::FramebufferRenderbuffer(WebGLenum target, WebGLenum attachment, WebGLenum rbtarget, nsIWebGLRenderbuffer *rbobj) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!mBoundFramebuffer) @@ -1799,7 +1799,7 @@ WebGLContext::FramebufferTexture2D(WebGLenum target, nsIWebGLTexture *tobj, WebGLint level) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (mBoundFramebuffer) @@ -1815,7 +1815,7 @@ GL_SAME_METHOD_0(Finish, Finish) NS_IMETHODIMP WebGLContext::FrontFace(WebGLenum mode) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; switch (mode) { @@ -1835,7 +1835,7 @@ WebGLContext::FrontFace(WebGLenum mode) NS_IMETHODIMP WebGLContext::GetActiveAttrib(nsIWebGLProgram *pobj, PRUint32 index, nsIWebGLActiveInfo **retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *retval = nsnull; @@ -1870,7 +1870,7 @@ WebGLContext::GetActiveAttrib(nsIWebGLProgram *pobj, PRUint32 index, nsIWebGLAct NS_IMETHODIMP WebGLContext::GenerateMipmap(WebGLenum target) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!ValidateTextureTargetEnum(target, "generateMipmap")) @@ -1899,7 +1899,7 @@ WebGLContext::GenerateMipmap(WebGLenum target) NS_IMETHODIMP WebGLContext::GetActiveUniform(nsIWebGLProgram *pobj, PRUint32 index, nsIWebGLActiveInfo **retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *retval = nsnull; @@ -1955,7 +1955,7 @@ WebGLContext::GetActiveUniform(nsIWebGLProgram *pobj, PRUint32 index, nsIWebGLAc NS_IMETHODIMP WebGLContext::GetAttachedShaders(nsIWebGLProgram *pobj, nsIVariant **retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *retval = nsnull; @@ -1998,7 +1998,7 @@ WebGLContext::GetAttribLocation(nsIWebGLProgram *pobj, const nsAString& name, PRInt32 *retval) { - if (mContextLost) + if (!IsContextStable()) { *retval = -1; return NS_OK; @@ -2021,7 +2021,7 @@ WebGLContext::GetAttribLocation(nsIWebGLProgram *pobj, NS_IMETHODIMP WebGLContext::GetParameter(PRUint32 pname, nsIVariant **retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *retval = nsnull; @@ -2334,7 +2334,7 @@ WebGLContext::GetParameter(PRUint32 pname, nsIVariant **retval) NS_IMETHODIMP WebGLContext::GetBufferParameter(WebGLenum target, WebGLenum pname, nsIVariant **retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *retval = nsnull; @@ -2371,7 +2371,7 @@ WebGLContext::GetBufferParameter(WebGLenum target, WebGLenum pname, nsIVariant * NS_IMETHODIMP WebGLContext::GetFramebufferAttachmentParameter(WebGLenum target, WebGLenum attachment, WebGLenum pname, nsIVariant **retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *retval = nsnull; @@ -2452,7 +2452,7 @@ WebGLContext::GetFramebufferAttachmentParameter(WebGLenum target, WebGLenum atta NS_IMETHODIMP WebGLContext::GetRenderbufferParameter(WebGLenum target, WebGLenum pname, nsIVariant **retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *retval = nsnull; @@ -2503,7 +2503,7 @@ WebGLContext::GetRenderbufferParameter(WebGLenum target, WebGLenum pname, nsIVar NS_IMETHODIMP WebGLContext::CreateBuffer(nsIWebGLBuffer **retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *retval = nsnull; @@ -2517,7 +2517,7 @@ WebGLContext::CreateBuffer(nsIWebGLBuffer **retval) NS_IMETHODIMP WebGLContext::CreateTexture(nsIWebGLTexture **retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *retval = nsnull; @@ -2533,9 +2533,12 @@ WebGLContext::CreateTexture(nsIWebGLTexture **retval) NS_IMETHODIMP WebGLContext::GetError(WebGLenum *_retval) { - if (!mContextLost) { + if (mContextStatus == ContextStable) { MakeContextCurrent(); UpdateWebGLErrorAndClearGLError(); + } else if (!mContextLostErrorSet) { + mWebGLError = LOCAL_GL_CONTEXT_LOST; + mContextLostErrorSet = true; } *_retval = mWebGLError; @@ -2547,7 +2550,7 @@ WebGLContext::GetError(WebGLenum *_retval) NS_IMETHODIMP WebGLContext::GetProgramParameter(nsIWebGLProgram *pobj, PRUint32 pname, nsIVariant **retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *retval = nsnull; @@ -2612,7 +2615,7 @@ WebGLContext::GetProgramParameter(nsIWebGLProgram *pobj, PRUint32 pname, nsIVari NS_IMETHODIMP WebGLContext::GetProgramInfoLog(nsIWebGLProgram *pobj, nsAString& retval) { - if (mContextLost) + if (!IsContextStable()) { retval.SetIsVoid(true); return NS_OK; @@ -2740,7 +2743,7 @@ nsresult WebGLContext::TexParameter_base(WebGLenum target, WebGLenum pname, NS_IMETHODIMP WebGLContext::TexParameterf(WebGLenum target, WebGLenum pname, WebGLfloat param) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; return TexParameter_base(target, pname, nsnull, ¶m); @@ -2749,7 +2752,7 @@ WebGLContext::TexParameterf(WebGLenum target, WebGLenum pname, WebGLfloat param) NS_IMETHODIMP WebGLContext::TexParameteri(WebGLenum target, WebGLenum pname, WebGLint param) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; return TexParameter_base(target, pname, ¶m, nsnull); @@ -2758,7 +2761,7 @@ WebGLContext::TexParameteri(WebGLenum target, WebGLenum pname, WebGLint param) NS_IMETHODIMP WebGLContext::GetTexParameter(WebGLenum target, WebGLenum pname, nsIVariant **retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *retval = nsnull; @@ -2799,7 +2802,7 @@ WebGLContext::GetTexParameter(WebGLenum target, WebGLenum pname, nsIVariant **re NS_IMETHODIMP WebGLContext::GetUniform(nsIWebGLProgram *pobj, nsIWebGLUniformLocation *ploc, nsIVariant **retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *retval = nsnull; @@ -2921,7 +2924,7 @@ WebGLContext::GetUniform(nsIWebGLProgram *pobj, nsIWebGLUniformLocation *ploc, n NS_IMETHODIMP WebGLContext::GetUniformLocation(nsIWebGLProgram *pobj, const nsAString& name, nsIWebGLUniformLocation **retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *retval = nsnull; @@ -2948,7 +2951,7 @@ WebGLContext::GetUniformLocation(nsIWebGLProgram *pobj, const nsAString& name, n NS_IMETHODIMP WebGLContext::GetVertexAttrib(WebGLuint index, WebGLenum pname, nsIVariant **retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *retval = nsnull; @@ -3022,7 +3025,7 @@ NS_IMETHODIMP WebGLContext::GetVertexAttribOffset(WebGLuint index, WebGLenum pname, WebGLuint *retval) { *retval = 0; - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!ValidateAttribIndex(index, "getVertexAttribOffset")) @@ -3038,7 +3041,7 @@ WebGLContext::GetVertexAttribOffset(WebGLuint index, WebGLenum pname, WebGLuint NS_IMETHODIMP WebGLContext::Hint(WebGLenum target, WebGLenum mode) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; bool isValid = false; @@ -3061,7 +3064,7 @@ WebGLContext::Hint(WebGLenum target, WebGLenum mode) NS_IMETHODIMP WebGLContext::IsBuffer(nsIWebGLBuffer *bobj, WebGLboolean *retval) { - if (mContextLost) + if (!IsContextStable()) { *retval = false; return NS_OK; @@ -3079,7 +3082,7 @@ WebGLContext::IsBuffer(nsIWebGLBuffer *bobj, WebGLboolean *retval) NS_IMETHODIMP WebGLContext::IsFramebuffer(nsIWebGLFramebuffer *fbobj, WebGLboolean *retval) { - if (mContextLost) + if (!IsContextStable()) { *retval = false; return NS_OK; @@ -3097,7 +3100,7 @@ WebGLContext::IsFramebuffer(nsIWebGLFramebuffer *fbobj, WebGLboolean *retval) NS_IMETHODIMP WebGLContext::IsProgram(nsIWebGLProgram *pobj, WebGLboolean *retval) { - if (mContextLost) + if (!IsContextStable()) { *retval = false; return NS_OK; @@ -3113,7 +3116,7 @@ WebGLContext::IsProgram(nsIWebGLProgram *pobj, WebGLboolean *retval) NS_IMETHODIMP WebGLContext::IsRenderbuffer(nsIWebGLRenderbuffer *rbobj, WebGLboolean *retval) { - if (mContextLost) + if (!IsContextStable()) { *retval = false; return NS_OK; @@ -3131,7 +3134,7 @@ WebGLContext::IsRenderbuffer(nsIWebGLRenderbuffer *rbobj, WebGLboolean *retval) NS_IMETHODIMP WebGLContext::IsShader(nsIWebGLShader *sobj, WebGLboolean *retval) { - if (mContextLost) + if (!IsContextStable()) { *retval = false; return NS_OK; @@ -3147,7 +3150,7 @@ WebGLContext::IsShader(nsIWebGLShader *sobj, WebGLboolean *retval) NS_IMETHODIMP WebGLContext::IsTexture(nsIWebGLTexture *tobj, WebGLboolean *retval) { - if (mContextLost) + if (!IsContextStable()) { *retval = false; return NS_OK; @@ -3165,7 +3168,7 @@ WebGLContext::IsTexture(nsIWebGLTexture *tobj, WebGLboolean *retval) NS_IMETHODIMP WebGLContext::IsEnabled(WebGLenum cap, WebGLboolean *retval) { - if (mContextLost) + if (!IsContextStable()) { *retval = false; return NS_OK; @@ -3186,7 +3189,7 @@ GL_SAME_METHOD_1(LineWidth, LineWidth, WebGLfloat) NS_IMETHODIMP WebGLContext::LinkProgram(nsIWebGLProgram *pobj) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; GLuint progname; @@ -3221,7 +3224,7 @@ WebGLContext::LinkProgram(nsIWebGLProgram *pobj) NS_IMETHODIMP WebGLContext::PixelStorei(WebGLenum pname, WebGLint param) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; switch (pname) { @@ -3264,7 +3267,7 @@ GL_SAME_METHOD_2(PolygonOffset, PolygonOffset, WebGLfloat, WebGLfloat) NS_IMETHODIMP WebGLContext::ReadPixels(PRInt32) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; return NS_ERROR_FAILURE; @@ -3493,7 +3496,7 @@ NS_IMETHODIMP WebGLContext::ReadPixels_array(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height, WebGLenum format, WebGLenum type, JSObject *pixels) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; return ReadPixels_base(x, y, width, height, format, type, pixels); @@ -3502,7 +3505,7 @@ WebGLContext::ReadPixels_array(WebGLint x, WebGLint y, WebGLsizei width, WebGLsi NS_IMETHODIMP WebGLContext::RenderbufferStorage(WebGLenum target, WebGLenum internalformat, WebGLsizei width, WebGLsizei height) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!mBoundRenderbuffer || !mBoundRenderbuffer->GLName()) @@ -3583,7 +3586,7 @@ GL_SAME_METHOD_2(SampleCoverage, SampleCoverage, WebGLfloat, WebGLboolean) NS_IMETHODIMP WebGLContext::Scissor(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (width < 0 || height < 0) @@ -3597,7 +3600,7 @@ WebGLContext::Scissor(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei heigh NS_IMETHODIMP WebGLContext::StencilFunc(WebGLenum func, WebGLint ref, WebGLuint mask) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!ValidateComparisonEnum(func, "stencilFunc: func")) @@ -3616,7 +3619,7 @@ WebGLContext::StencilFunc(WebGLenum func, WebGLint ref, WebGLuint mask) NS_IMETHODIMP WebGLContext::StencilFuncSeparate(WebGLenum face, WebGLenum func, WebGLint ref, WebGLuint mask) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!ValidateFaceEnum(face, "stencilFuncSeparate: face") || @@ -3648,7 +3651,7 @@ WebGLContext::StencilFuncSeparate(WebGLenum face, WebGLenum func, WebGLint ref, NS_IMETHODIMP WebGLContext::StencilMask(WebGLuint mask) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; mStencilWriteMaskFront = mask; @@ -3662,7 +3665,7 @@ WebGLContext::StencilMask(WebGLuint mask) NS_IMETHODIMP WebGLContext::StencilMaskSeparate(WebGLenum face, WebGLuint mask) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!ValidateFaceEnum(face, "stencilMaskSeparate: face")) @@ -3689,7 +3692,7 @@ WebGLContext::StencilMaskSeparate(WebGLenum face, WebGLuint mask) NS_IMETHODIMP WebGLContext::StencilOp(WebGLenum sfail, WebGLenum dpfail, WebGLenum dppass) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!ValidateStencilOpEnum(sfail, "stencilOp: sfail") || @@ -3705,7 +3708,7 @@ WebGLContext::StencilOp(WebGLenum sfail, WebGLenum dpfail, WebGLenum dppass) NS_IMETHODIMP WebGLContext::StencilOpSeparate(WebGLenum face, WebGLenum sfail, WebGLenum dpfail, WebGLenum dppass) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!ValidateFaceEnum(face, "stencilOpSeparate: face") || @@ -4023,7 +4026,7 @@ WebGLContext::name(PRInt32) { \ NS_IMETHODIMP \ WebGLContext::name##_array(nsIWebGLUniformLocation *ploc, JSObject *wa) \ { \ - if (mContextLost) \ + if (!IsContextStable()) \ return NS_OK; \ OBTAIN_UNIFORM_LOCATION(#name ": location") \ if (!wa || JS_GetTypedArrayType(wa) != js::TypedArray::arrayType) \ @@ -4043,7 +4046,7 @@ WebGLContext::name(PRInt32) { \ NS_IMETHODIMP \ WebGLContext::name##_array(nsIWebGLUniformLocation *ploc, WebGLboolean transpose, JSObject *wa) \ { \ - if (mContextLost) \ + if (!IsContextStable()) \ return NS_OK; \ OBTAIN_UNIFORM_LOCATION(#name ": location") \ if (!wa || JS_GetTypedArrayType(wa) != js::TypedArray::arrayType) \ @@ -4059,7 +4062,7 @@ WebGLContext::name##_array(nsIWebGLUniformLocation *ploc, WebGLboolean transpose #define SIMPLE_METHOD_UNIFORM_1(glname, name, t1) \ NS_IMETHODIMP WebGLContext::name(nsIWebGLUniformLocation *ploc, t1 a1) { \ - if (mContextLost) \ + if (!IsContextStable()) \ return NS_OK; \ OBTAIN_UNIFORM_LOCATION(#name ": location") \ MakeContextCurrent(); gl->f##glname(location, a1); return NS_OK; \ @@ -4067,7 +4070,7 @@ NS_IMETHODIMP WebGLContext::name(nsIWebGLUniformLocation *ploc, t1 a1) { \ #define SIMPLE_METHOD_UNIFORM_2(glname, name, t1, t2) \ NS_IMETHODIMP WebGLContext::name(nsIWebGLUniformLocation *ploc, t1 a1, t2 a2) { \ - if (mContextLost) \ + if (!IsContextStable()) \ return NS_OK; \ OBTAIN_UNIFORM_LOCATION(#name ": location") \ MakeContextCurrent(); gl->f##glname(location, a1, a2); return NS_OK; \ @@ -4075,7 +4078,7 @@ NS_IMETHODIMP WebGLContext::name(nsIWebGLUniformLocation *ploc, t1 a1, t2 a2) { #define SIMPLE_METHOD_UNIFORM_3(glname, name, t1, t2, t3) \ NS_IMETHODIMP WebGLContext::name(nsIWebGLUniformLocation *ploc, t1 a1, t2 a2, t3 a3) { \ - if (mContextLost) \ + if (!IsContextStable()) \ return NS_OK; \ OBTAIN_UNIFORM_LOCATION(#name ": location") \ MakeContextCurrent(); gl->f##glname(location, a1, a2, a3); return NS_OK; \ @@ -4083,7 +4086,7 @@ NS_IMETHODIMP WebGLContext::name(nsIWebGLUniformLocation *ploc, t1 a1, t2 a2, t3 #define SIMPLE_METHOD_UNIFORM_4(glname, name, t1, t2, t3, t4) \ NS_IMETHODIMP WebGLContext::name(nsIWebGLUniformLocation *ploc, t1 a1, t2 a2, t3 a3, t4 a4) { \ - if (mContextLost) \ + if (!IsContextStable()) \ return NS_OK; \ OBTAIN_UNIFORM_LOCATION(#name ": location") \ MakeContextCurrent(); gl->f##glname(location, a1, a2, a3, a4); return NS_OK; \ @@ -4116,7 +4119,7 @@ SIMPLE_MATRIX_METHOD_UNIFORM(UniformMatrix4fv, 4, TYPE_FLOAT32, WebGLfloat) NS_IMETHODIMP WebGLContext::VertexAttrib1f(PRUint32 index, WebGLfloat x0) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; MakeContextCurrent(); @@ -4138,7 +4141,7 @@ WebGLContext::VertexAttrib1f(PRUint32 index, WebGLfloat x0) NS_IMETHODIMP WebGLContext::VertexAttrib2f(PRUint32 index, WebGLfloat x0, WebGLfloat x1) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; MakeContextCurrent(); @@ -4160,7 +4163,7 @@ WebGLContext::VertexAttrib2f(PRUint32 index, WebGLfloat x0, WebGLfloat x1) NS_IMETHODIMP WebGLContext::VertexAttrib3f(PRUint32 index, WebGLfloat x0, WebGLfloat x1, WebGLfloat x2) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; MakeContextCurrent(); @@ -4183,7 +4186,7 @@ NS_IMETHODIMP WebGLContext::VertexAttrib4f(PRUint32 index, WebGLfloat x0, WebGLfloat x1, WebGLfloat x2, WebGLfloat x3) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; MakeContextCurrent(); @@ -4210,7 +4213,7 @@ WebGLContext::name(PRInt32) { \ NS_IMETHODIMP \ WebGLContext::name##_array(WebGLuint idx, JSObject *wa) \ { \ - if (mContextLost) \ + if (!IsContextStable()) \ return NS_OK; \ if (!wa || JS_GetTypedArrayType(wa) != js::TypedArray::arrayType) \ return ErrorInvalidOperation(#name ": array must be " #arrayType); \ @@ -4239,7 +4242,7 @@ SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib4fv, 4, TYPE_FLOAT32, WebGLfloat) NS_IMETHODIMP WebGLContext::UseProgram(nsIWebGLProgram *pobj) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; WebGLProgram *prog; @@ -4263,7 +4266,7 @@ WebGLContext::UseProgram(nsIWebGLProgram *pobj) NS_IMETHODIMP WebGLContext::ValidateProgram(nsIWebGLProgram *pobj) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; WebGLuint progname; @@ -4286,7 +4289,7 @@ WebGLContext::ValidateProgram(nsIWebGLProgram *pobj) NS_IMETHODIMP WebGLContext::CreateFramebuffer(nsIWebGLFramebuffer **retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *retval = 0; @@ -4300,7 +4303,7 @@ WebGLContext::CreateFramebuffer(nsIWebGLFramebuffer **retval) NS_IMETHODIMP WebGLContext::CreateRenderbuffer(nsIWebGLRenderbuffer **retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *retval = 0; @@ -4314,7 +4317,7 @@ WebGLContext::CreateRenderbuffer(nsIWebGLRenderbuffer **retval) NS_IMETHODIMP WebGLContext::Viewport(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (width < 0 || height < 0) @@ -4328,7 +4331,7 @@ WebGLContext::Viewport(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei heig NS_IMETHODIMP WebGLContext::CompileShader(nsIWebGLShader *sobj) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; WebGLShader *shader; @@ -4448,7 +4451,7 @@ WebGLContext::CompileShader(nsIWebGLShader *sobj) NS_IMETHODIMP WebGLContext::GetShaderParameter(nsIWebGLShader *sobj, WebGLenum pname, nsIVariant **retval) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; *retval = nsnull; @@ -4499,7 +4502,7 @@ WebGLContext::GetShaderParameter(nsIWebGLShader *sobj, WebGLenum pname, nsIVaria NS_IMETHODIMP WebGLContext::GetShaderInfoLog(nsIWebGLShader *sobj, nsAString& retval) { - if (mContextLost) + if (!IsContextStable()) { retval.SetIsVoid(true); return NS_OK; @@ -4544,7 +4547,7 @@ NS_IMETHODIMP WebGLContext::GetShaderPrecisionFormat(WebGLenum shadertype, WebGLenum precisiontype, nsIWebGLShaderPrecisionFormat **retval) { *retval = nsnull; - if (mContextLost) + if (!IsContextStable()) return NS_OK; switch (shadertype) { @@ -4582,7 +4585,7 @@ WebGLContext::GetShaderPrecisionFormat(WebGLenum shadertype, WebGLenum precision NS_IMETHODIMP WebGLContext::GetShaderSource(nsIWebGLShader *sobj, nsAString& retval) { - if (mContextLost) + if (!IsContextStable()) { retval.SetIsVoid(true); return NS_OK; @@ -4601,7 +4604,7 @@ WebGLContext::GetShaderSource(nsIWebGLShader *sobj, nsAString& retval) NS_IMETHODIMP WebGLContext::ShaderSource(nsIWebGLShader *sobj, const nsAString& source) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; WebGLShader *shader; @@ -4629,7 +4632,7 @@ WebGLContext::VertexAttribPointer(WebGLuint index, WebGLint size, WebGLenum type WebGLboolean normalized, WebGLsizei stride, WebGLsizeiptr byteOffset) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (mBoundArrayBuffer == nsnull) @@ -4705,7 +4708,7 @@ WebGLContext::VertexAttribPointer(WebGLuint index, WebGLint size, WebGLenum type NS_IMETHODIMP WebGLContext::TexImage2D(PRInt32) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; return NS_ERROR_FAILURE; @@ -4901,7 +4904,7 @@ WebGLContext::TexImage2D_array(WebGLenum target, WebGLint level, WebGLenum inter WebGLenum format, WebGLenum type, JSObject *pixels) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; return TexImage2D_base(target, level, internalformat, width, height, 0, border, format, type, @@ -4917,7 +4920,7 @@ WebGLContext::TexImage2D_imageData(WebGLenum target, WebGLint level, WebGLenum i WebGLenum format, WebGLenum type, JSObject *pixels) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; return TexImage2D_base(target, level, internalformat, width, height, 4*width, border, format, type, @@ -4931,7 +4934,7 @@ NS_IMETHODIMP WebGLContext::TexImage2D_dom(WebGLenum target, WebGLint level, WebGLenum internalformat, WebGLenum format, GLenum type, nsIDOMElement *elt) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; nsRefPtr isurf; @@ -4954,7 +4957,7 @@ WebGLContext::TexImage2D_dom(WebGLenum target, WebGLint level, WebGLenum interna NS_IMETHODIMP WebGLContext::TexSubImage2D(PRInt32) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; return NS_ERROR_FAILURE; @@ -5082,7 +5085,7 @@ WebGLContext::TexSubImage2D_array(WebGLenum target, WebGLint level, WebGLenum format, WebGLenum type, JSObject *pixels) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!pixels) @@ -5102,7 +5105,7 @@ WebGLContext::TexSubImage2D_imageData(WebGLenum target, WebGLint level, WebGLenum format, WebGLenum type, JSObject *pixels) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; if (!pixels) @@ -5121,7 +5124,7 @@ WebGLContext::TexSubImage2D_dom(WebGLenum target, WebGLint level, WebGLenum format, WebGLenum type, nsIDOMElement *elt) { - if (mContextLost) + if (!IsContextStable()) return NS_OK; nsRefPtr isurf; @@ -5145,11 +5148,10 @@ WebGLContext::TexSubImage2D_dom(WebGLenum target, WebGLint level, bool WebGLContext::LoseContext() { - if (mContextLost) { + if (!IsContextStable()) return false; - } - mAllowRestore = true; + mContextLostDueToTest = true; ForceLoseContext(); return true; @@ -5158,7 +5160,7 @@ WebGLContext::LoseContext() bool WebGLContext::RestoreContext() { - if (!mContextLost || !mAllowRestore) { + if (IsContextStable() || !mAllowRestore) { return false; } diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp index 134bd73c3a2d..62af780742c7 100644 --- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp @@ -1195,7 +1195,7 @@ nsCanvasRenderingContext2DAzure::Redraw(const mgfx::Rect &r) nsSVGEffects::InvalidateDirectRenderingObservers(HTMLCanvasElement()); - gfxRect tmpR = GFXRect(r); + gfxRect tmpR = ThebesRect(r); HTMLCanvasElement()->InvalidateCanvasContent(&tmpR); return; diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 36fae4e0e91b..8e16dc41c302 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -4683,15 +4683,6 @@ nsDOMClassInfo::HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext *cx, return NS_ERROR_UNEXPECTED; } -NS_IMETHODIMP -nsDOMClassInfo::Trace(nsIXPConnectWrappedNative *wrapper, JSTracer *trc, - JSObject *obj) -{ - NS_WARNING("nsDOMClassInfo::Trace Don't call me!"); - - return NS_ERROR_UNEXPECTED; -} - NS_IMETHODIMP nsDOMClassInfo::Equality(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, const jsval &val, bool *bp) diff --git a/dom/plugins/ipc/interpose/plugin_child_quirks.mm b/dom/plugins/ipc/interpose/plugin_child_quirks.mm index f5fdadddf0e2..3897ad949d0e 100644 --- a/dom/plugins/ipc/interpose/plugin_child_quirks.mm +++ b/dom/plugins/ipc/interpose/plugin_child_quirks.mm @@ -37,10 +37,6 @@ * * ***** END LICENSE BLOCK ***** */ -// This file is a copy and paste from existing methods from -// libxul. This is intentional because this interpose -// library does not link with libxul. - #include #include #import "CoreFoundation/CoreFoundation.h" @@ -49,9 +45,6 @@ #define PRInt32 int32_t #define PRUint32 uint32_t -PRInt32 -NS_CompareVersions(const char *A, const char *B); - #include "MacQuirks.h" int static_init() { @@ -59,189 +52,3 @@ int static_init() { return 0; } int run = static_init(); - -struct VersionPart { - PRInt32 numA; - - const char *strB; // NOT null-terminated, can be a null pointer - PRUint32 strBlen; - - PRInt32 numC; - - char *extraD; // null-terminated -}; - -/** - * Parse a version part into a number and "extra text". - * - * @returns A pointer to the next versionpart, or null if none. - */ -static char* -ParseVP(char *part, VersionPart &result) -{ - char *dot; - - result.numA = 0; - result.strB = NULL; - result.strBlen = 0; - result.numC = 0; - result.extraD = NULL; - - if (!part) - return part; - - dot = strchr(part, '.'); - if (dot) - *dot = '\0'; - - if (part[0] == '*' && part[1] == '\0') { - result.numA = INT32_MAX; - result.strB = ""; - } - else { - result.numA = strtol(part, const_cast(&result.strB), 10); - } - - if (!*result.strB) { - result.strB = NULL; - result.strBlen = 0; - } - else { - if (result.strB[0] == '+') { - static const char kPre[] = "pre"; - - ++result.numA; - result.strB = kPre; - result.strBlen = sizeof(kPre) - 1; - } - else { - const char *numstart = strpbrk(result.strB, "0123456789+-"); - if (!numstart) { - result.strBlen = strlen(result.strB); - } - else { - result.strBlen = numstart - result.strB; - - result.numC = strtol(numstart, &result.extraD, 10); - if (!*result.extraD) - result.extraD = NULL; - } - } - } - - if (dot) { - ++dot; - - if (!*dot) - dot = NULL; - } - - return dot; -} - - -// compare two null-terminated strings, which may be null pointers -static PRInt32 -ns_strcmp(const char *str1, const char *str2) -{ - // any string is *before* no string - if (!str1) - return str2 != 0; - - if (!str2) - return -1; - - return strcmp(str1, str2); -} - -// compare two length-specified string, which may be null pointers -static PRInt32 -ns_strnncmp(const char *str1, PRUint32 len1, const char *str2, PRUint32 len2) -{ - // any string is *before* no string - if (!str1) - return str2 != 0; - - if (!str2) - return -1; - - for (; len1 && len2; --len1, --len2, ++str1, ++str2) { - if (*str1 < *str2) - return -1; - - if (*str1 > *str2) - return 1; - } - - if (len1 == 0) - return len2 == 0 ? 0 : -1; - - return 1; -} - -// compare two PRInt32 -static PRInt32 -ns_cmp(PRInt32 n1, PRInt32 n2) -{ - if (n1 < n2) - return -1; - - return n1 != n2; -} - -/** - * Compares two VersionParts - */ -static PRInt32 -CompareVP(VersionPart &v1, VersionPart &v2) -{ - PRInt32 r = ns_cmp(v1.numA, v2.numA); - if (r) - return r; - - r = ns_strnncmp(v1.strB, v1.strBlen, v2.strB, v2.strBlen); - if (r) - return r; - - r = ns_cmp(v1.numC, v2.numC); - if (r) - return r; - - return ns_strcmp(v1.extraD, v2.extraD); -} - -PRInt32 -NS_CompareVersions(const char *A, const char *B) -{ - char *A2 = strdup(A); - if (!A2) - return 1; - - char *B2 = strdup(B); - if (!B2) { - free(A2); - return 1; - } - - PRInt32 result; - char *a = A2, *b = B2; - - do { - VersionPart va, vb; - - a = ParseVP(a, va); - b = ParseVP(b, vb); - - result = CompareVP(va, vb); - if (result) - break; - - } while (a || b); - - free(A2); - free(B2); - - return result; -} - - diff --git a/extensions/gio/nsGIOProtocolHandler.cpp b/extensions/gio/nsGIOProtocolHandler.cpp index 9347b6e0ab74..e8f153db6792 100644 --- a/extensions/gio/nsGIOProtocolHandler.cpp +++ b/extensions/gio/nsGIOProtocolHandler.cpp @@ -238,7 +238,7 @@ class nsGIOInputStream : public nsIInputStream void nsGIOInputStream::SetMountResult(MountOperationResult result, gint error_code) { - mozilla::MonitorAutoEnter mon(mMonitorMountInProgress); + mozilla::MonitorAutoLock mon(mMonitorMountInProgress); mMountRes = result; mMountErrorCode = error_code; mon.Notify(); @@ -263,7 +263,7 @@ nsGIOInputStream::MountVolume() { NULL, mount_enclosing_volume_finished, this); - mozilla::MonitorAutoEnter mon(mMonitorMountInProgress); + mozilla::MonitorAutoLock mon(mMonitorMountInProgress); /* Waiting for finish of mount operation thread */ while (mMountRes == MOUNT_OPERATION_IN_PROGRESS) mon.Wait(); diff --git a/gfx/2d/Logging.h b/gfx/2d/Logging.h index 44b3f143db2a..f5e52052409c 100644 --- a/gfx/2d/Logging.h +++ b/gfx/2d/Logging.h @@ -43,6 +43,7 @@ #include #include "Point.h" +#include "Matrix.h" #ifdef WIN32 #include @@ -115,6 +116,9 @@ public: { mMessage << "(" << aSize.width << "x" << aSize.height << ")"; return *this; } Log &operator <<(const IntSize &aSize) { mMessage << "(" << aSize.width << "x" << aSize.height << ")"; return *this; } + Log &operator<<(const Matrix& aMatrix) + { mMessage << "[ " << aMatrix._11 << " " << aMatrix._12 << " ; " << aMatrix._21 << " " << aMatrix._22 << " ; " << aMatrix._31 << " " << aMatrix._32 << " ]"; return *this; } + private: diff --git a/gfx/2d/Matrix.h b/gfx/2d/Matrix.h index e38b15672b62..b0193cfae186 100644 --- a/gfx/2d/Matrix.h +++ b/gfx/2d/Matrix.h @@ -73,6 +73,16 @@ public: return retPoint; } + Size operator *(const Size &aSize) const + { + Size retSize; + + retSize.width = aSize.width * _11 + aSize.height * _21; + retSize.height = aSize.width * _12 + aSize.height * _22; + + return retSize; + } + Rect TransformBounds(const Rect& rect) const; // Apply a scale to this matrix. This scale will be applied -before- the @@ -144,6 +154,21 @@ public: return resultMatrix; } + /* Returns true if the other matrix is fuzzy-equal to this matrix. + * Note that this isn't a cheap comparison! + */ + bool operator==(const Matrix& other) const + { + return FuzzyEqual(_11, other._11) && FuzzyEqual(_12, other._12) && + FuzzyEqual(_21, other._21) && FuzzyEqual(_22, other._22) && + FuzzyEqual(_31, other._31) && FuzzyEqual(_32, other._32); + } + + bool operator!=(const Matrix& other) const + { + return !(*this == other); + } + /* Returns true if the matrix is a rectilinear transformation (i.e. * grid-aligned rectangles are transformed to grid-aligned rectangles) */ @@ -156,6 +181,16 @@ public: return false; } + + /* Returns true if the matrix is an identity matrix. + */ + bool IsIdentity() const + { + return _11 == 1.0f && _12 == 0.0f && + _21 == 0.0f && _22 == 1.0f && + _31 == 0.0f && _32 == 0.0f; + } + private: static bool FuzzyEqual(Float aV1, Float aV2) { // XXX - Check if fabs does the smart thing and just negates the sign bit. diff --git a/gfx/layers/basic/BasicLayers.cpp b/gfx/layers/basic/BasicLayers.cpp index ac6cd825063d..e1a84903307b 100644 --- a/gfx/layers/basic/BasicLayers.cpp +++ b/gfx/layers/basic/BasicLayers.cpp @@ -609,6 +609,11 @@ IntersectWithClip(const nsIntRegion& aRegion, gfxContext* aContext) static void SetAntialiasingFlags(Layer* aLayer, gfxContext* aTarget) { + if (!aTarget->IsCairo()) { + // Azure targets don't contain antialiasing flags at this point. + return; + } + nsRefPtr surface = aTarget->CurrentSurface(); if (surface->GetContentType() != gfxASurface::CONTENT_COLOR_ALPHA) { // Destination doesn't have alpha channel; no need to set any special flags @@ -754,6 +759,9 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext, } } + if (BasicManager()->IsTransactionIncomplete()) + return; + if (!IsHidden()) { AutoSetOperator setOperator(aContext, GetOperator()); mBuffer.DrawTo(this, aContext, opacity); @@ -930,14 +938,16 @@ BasicImageLayer::PaintContext(gfxPattern* aPattern, // outside the bounds of the video image. gfxPattern::GraphicsExtend extend = gfxPattern::EXTEND_PAD; - // PAD is slow with X11 and Quartz surfaces, so prefer speed over correctness - // and use NONE. - nsRefPtr target = aContext->CurrentSurface(); - gfxASurface::gfxSurfaceType type = target->GetType(); - if (type == gfxASurface::SurfaceTypeXlib || - type == gfxASurface::SurfaceTypeXcb || - type == gfxASurface::SurfaceTypeQuartz) { - extend = gfxPattern::EXTEND_NONE; + if (aContext->IsCairo()) { + // PAD is slow with X11 and Quartz surfaces, so prefer speed over correctness + // and use NONE. + nsRefPtr target = aContext->CurrentSurface(); + gfxASurface::gfxSurfaceType type = target->GetType(); + if (type == gfxASurface::SurfaceTypeXlib || + type == gfxASurface::SurfaceTypeXcb || + type == gfxASurface::SurfaceTypeQuartz) { + extend = gfxPattern::EXTEND_NONE; + } } if (!aTileSourceRect) { @@ -1334,7 +1344,8 @@ already_AddRefed BasicLayerManager::PushGroupWithCachedSurface(gfxContext *aTarget, gfxASurface::gfxContentType aContent) { - if (mCachedSurfaceInUse) { + if (mCachedSurfaceInUse || !aTarget->IsCairo()) { + // We can't cache Azure DrawTargets at this point. aTarget->PushGroup(aContent); nsRefPtr result = aTarget; return result.forget(); @@ -1360,7 +1371,7 @@ BasicLayerManager::PopGroupToSourceWithCachedSurface(gfxContext *aTarget, gfxCon if (!aTarget) return; nsRefPtr current = aPushed->CurrentSurface(); - if (mCachedSurface.IsSurface(current)) { + if (aTarget->IsCairo() && mCachedSurface.IsSurface(current)) { gfxContextMatrixAutoSaveRestore saveMatrix(aTarget); aTarget->IdentityMatrix(); aTarget->SetSource(current); @@ -1849,17 +1860,20 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget, bool pushedTargetOpaqueRect = false; nsRefPtr currentSurface = aTarget->CurrentSurface(); - const gfxRect& targetOpaqueRect = currentSurface->GetOpaqueRect(); - - // Try to annotate currentSurface with a region of pixels that have been - // (or will be) painted opaque, if no such region is currently set. const nsIntRect& bounds = visibleRegion.GetBounds(); - if (targetOpaqueRect.IsEmpty() && visibleRegion.GetNumRects() == 1 && - (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) && - !transform.HasNonAxisAlignedTransform()) { - currentSurface->SetOpaqueRect( - aTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height))); - pushedTargetOpaqueRect = true; + + if (aTarget->IsCairo()) { + const gfxRect& targetOpaqueRect = currentSurface->GetOpaqueRect(); + + // Try to annotate currentSurface with a region of pixels that have been + // (or will be) painted opaque, if no such region is currently set. + if (targetOpaqueRect.IsEmpty() && visibleRegion.GetNumRects() == 1 && + (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) && + !transform.HasNonAxisAlignedTransform()) { + currentSurface->SetOpaqueRect( + aTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height))); + pushedTargetOpaqueRect = true; + } } nsRefPtr groupTarget; diff --git a/gfx/layers/basic/BasicLayers.h b/gfx/layers/basic/BasicLayers.h index c1c50847e2b4..c5406ccafaf5 100644 --- a/gfx/layers/basic/BasicLayers.h +++ b/gfx/layers/basic/BasicLayers.h @@ -165,6 +165,7 @@ public: void ClearCachedResources(); void SetTransactionIncomplete() { mTransactionIncomplete = true; } + bool IsTransactionIncomplete() { return mTransactionIncomplete; } already_AddRefed PushGroupForLayer(gfxContext* aContext, Layer* aLayer, const nsIntRegion& aRegion, diff --git a/gfx/layers/d3d10/ThebesLayerD3D10.cpp b/gfx/layers/d3d10/ThebesLayerD3D10.cpp index a37673cddc79..8505abbe8d45 100644 --- a/gfx/layers/d3d10/ThebesLayerD3D10.cpp +++ b/gfx/layers/d3d10/ThebesLayerD3D10.cpp @@ -54,6 +54,11 @@ #include "ReadbackLayer.h" #include "ReadbackProcessor.h" +#include "mozilla/Preferences.h" +#include "mozilla/gfx/2D.h" + +using namespace mozilla::gfx; + namespace mozilla { namespace layers { @@ -189,7 +194,8 @@ ThebesLayerD3D10::Validate(ReadbackProcessor *aReadback) SurfaceMode mode = GetSurfaceMode(); if (mode == SURFACE_COMPONENT_ALPHA && - (!mParent || !mParent->SupportsComponentAlphaChildren())) { + (gfxPlatform::UseAzureContentDrawing() || + !mParent || !mParent->SupportsComponentAlphaChildren())) { mode = SURFACE_SINGLE_CHANNEL_ALPHA; } // If we have a transform that requires resampling of our texture, then @@ -352,11 +358,13 @@ static void FillSurface(gfxASurface* aSurface, const nsIntRegion& aRegion, const nsIntPoint& aOffset, const gfxRGBA& aColor) { - nsRefPtr ctx = new gfxContext(aSurface); - ctx->Translate(-gfxPoint(aOffset.x, aOffset.y)); - gfxUtils::PathFromRegion(ctx, aRegion); - ctx->SetColor(aColor); - ctx->Fill(); + if (aSurface) { + nsRefPtr ctx = new gfxContext(aSurface); + ctx->Translate(-gfxPoint(aOffset.x, aOffset.y)); + gfxUtils::PathFromRegion(ctx, aRegion); + ctx->SetColor(aColor); + ctx->Fill(); + } } void @@ -364,7 +372,7 @@ ThebesLayerD3D10::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode) { nsIntRect visibleRect = mVisibleRegion.GetBounds(); - if (!mD2DSurface) { + if (!mD2DSurface && !mDrawTarget) { return; } @@ -383,7 +391,13 @@ ThebesLayerD3D10::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode) destinationSurface = mD2DSurface; } - nsRefPtr context = new gfxContext(destinationSurface); + nsRefPtr context; + + if (mDrawTarget) { + context = new gfxContext(mDrawTarget); + } else { + context = new gfxContext(destinationSurface); + } nsIntRegionRectIterator iter(aRegion); context->Translate(gfxPoint(-visibleRect.x, -visibleRect.y)); @@ -391,16 +405,21 @@ ThebesLayerD3D10::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode) const nsIntRect *iterRect; while ((iterRect = iter.Next())) { context->Rectangle(gfxRect(iterRect->x, iterRect->y, iterRect->width, iterRect->height)); + if (mDrawTarget) { + mDrawTarget->ClearRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height)); + } } context->Clip(); - if (aMode == SURFACE_SINGLE_CHANNEL_ALPHA) { + if (!mDrawTarget && aMode == SURFACE_SINGLE_CHANNEL_ALPHA) { context->SetOperator(gfxContext::OPERATOR_CLEAR); context->Paint(); context->SetOperator(gfxContext::OPERATOR_OVER); } - mD2DSurface->SetSubpixelAntialiasingEnabled(!(mContentFlags & CONTENT_COMPONENT_ALPHA)); + if (mD2DSurface) { + mD2DSurface->SetSubpixelAntialiasingEnabled(!(mContentFlags & CONTENT_COMPONENT_ALPHA)); + } LayerManagerD3D10::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo(); cbInfo.Callback(this, context, aRegion, nsIntRegion(), cbInfo.CallbackData); @@ -433,15 +452,25 @@ ThebesLayerD3D10::CreateNewTextures(const gfxIntSize &aSize, SurfaceMode aMode) NS_WARNING("Failed to create shader resource view for ThebesLayerD3D10."); } - mD2DSurface = new gfxD2DSurface(mTexture, aMode != SURFACE_SINGLE_CHANNEL_ALPHA ? - gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA); + if (!gfxPlatform::UseAzureContentDrawing()) { + mD2DSurface = new gfxD2DSurface(mTexture, aMode != SURFACE_SINGLE_CHANNEL_ALPHA ? + gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA); - if (!mD2DSurface || mD2DSurface->CairoStatus()) { - NS_WARNING("Failed to create surface for ThebesLayerD3D10."); - mD2DSurface = nsnull; - return; + if (!mD2DSurface || mD2DSurface->CairoStatus()) { + NS_WARNING("Failed to create surface for ThebesLayerD3D10."); + mD2DSurface = NULL; + return; + } + } else { + mDrawTarget = Factory::CreateDrawTargetForD3D10Texture(mTexture, aMode != SURFACE_SINGLE_CHANNEL_ALPHA ? + FORMAT_B8G8R8X8 : FORMAT_B8G8R8A8); + + if (!mDrawTarget) { + NS_WARNING("Failed to create DrawTarget for ThebesLayerD3D10."); + mDrawTarget = nsnull; + return; + } } - } if (aMode == SURFACE_COMPONENT_ALPHA && !mTextureOnWhite) { diff --git a/gfx/layers/d3d10/ThebesLayerD3D10.h b/gfx/layers/d3d10/ThebesLayerD3D10.h index 5b3f03bfb332..4ab8161df45f 100644 --- a/gfx/layers/d3d10/ThebesLayerD3D10.h +++ b/gfx/layers/d3d10/ThebesLayerD3D10.h @@ -86,6 +86,8 @@ private: /* This contains the thebes surface */ nsRefPtr mD2DSurface; + mozilla::RefPtr mDrawTarget; + /* This contains the thebes surface for our render-on-white texture */ nsRefPtr mD2DSurfaceOnWhite; diff --git a/gfx/src/nsDeviceContext.cpp b/gfx/src/nsDeviceContext.cpp index f80def5c3117..bf7e9ea4d8de 100644 --- a/gfx/src/nsDeviceContext.cpp +++ b/gfx/src/nsDeviceContext.cpp @@ -44,6 +44,7 @@ #include "nsIView.h" #include "nsIWidget.h" +#include "mozilla/Attributes.h" #include "mozilla/Services.h" #include "mozilla/Preferences.h" #include "nsIServiceManager.h" @@ -91,7 +92,7 @@ static nsSystemFontsAndroid *gSystemFonts = nsnull; using namespace mozilla; using mozilla::services::GetObserverService; -class nsFontCache : public nsIObserver +class nsFontCache MOZ_FINAL : public nsIObserver { public: nsFontCache() { MOZ_COUNT_CTOR(nsFontCache); } diff --git a/gfx/src/nsRenderingContext.cpp b/gfx/src/nsRenderingContext.cpp index 26a02912bdad..b5590c08e47d 100644 --- a/gfx/src/nsRenderingContext.cpp +++ b/gfx/src/nsRenderingContext.cpp @@ -125,9 +125,9 @@ nsRenderingContext::IntersectClip(const nsRect& aRect) gfxRect clipRect(GFX_RECT_FROM_TWIPS_RECT(aRect)); if (mThebes->UserToDevicePixelSnapped(clipRect, true)) { gfxMatrix mat(mThebes->CurrentMatrix()); - mThebes->IdentityMatrix(); + mat.Invert(); + clipRect = mat.Transform(clipRect); mThebes->Rectangle(clipRect); - mThebes->SetMatrix(mat); } else { mThebes->Rectangle(clipRect); } diff --git a/gfx/thebes/gfx2DGlue.h b/gfx/thebes/gfx2DGlue.h index 82c70b8ebd1a..ad0d2bac0a15 100644 --- a/gfx/thebes/gfx2DGlue.h +++ b/gfx/thebes/gfx2DGlue.h @@ -1,6 +1,9 @@ #include "gfxRect.h" +#include "gfxMatrix.h" +#include "gfxContext.h" #include "mozilla/gfx/Rect.h" +#include "mozilla/gfx/2D.h" namespace mozilla { namespace gfx { @@ -19,11 +22,154 @@ inline Rect ToRect(const gfxRect &aRect) Float(aRect.width), Float(aRect.height)); } -inline gfxRect GFXRect(const Rect &aRect) +inline Color ToColor(const gfxRGBA &aRGBA) +{ + return Color(Float(aRGBA.r), Float(aRGBA.g), + Float(aRGBA.b), Float(aRGBA.a)); +} + +inline Matrix ToMatrix(const gfxMatrix &aMatrix) +{ + return Matrix(Float(aMatrix.xx), Float(aMatrix.yx), Float(aMatrix.xy), + Float(aMatrix.yy), Float(aMatrix.x0), Float(aMatrix.y0)); +} + +inline Point ToPoint(const gfxPoint &aPoint) +{ + return Point(Float(aPoint.x), Float(aPoint.y)); +} + +inline Size ToSize(const gfxSize &aSize) +{ + return Size(Float(aSize.width), Float(aSize.height)); +} + +inline Filter ToFilter(gfxPattern::GraphicsFilter aFilter) +{ + switch (aFilter) { + case gfxPattern::FILTER_NEAREST: + return FILTER_POINT; + default: + return FILTER_LINEAR; + } +} + +inline gfxPattern::GraphicsFilter ThebesFilter(Filter aFilter) +{ + switch (aFilter) { + case FILTER_POINT: + return gfxPattern::FILTER_NEAREST; + default: + return gfxPattern::FILTER_BEST; + } +} + +inline ExtendMode ToExtendMode(gfxPattern::GraphicsExtend aExtend) +{ + switch (aExtend) { + case gfxPattern::EXTEND_REPEAT: + return EXTEND_REPEAT; + case gfxPattern::EXTEND_REFLECT: + return EXTEND_REFLECT; + default: + return EXTEND_CLAMP; + } +} + +inline gfxPattern::GraphicsExtend ThebesExtend(ExtendMode aExtend) +{ + switch (aExtend) { + case EXTEND_REPEAT: + return gfxPattern::EXTEND_REPEAT; + case EXTEND_REFLECT: + return gfxPattern::EXTEND_REFLECT; + default: + return gfxPattern::EXTEND_PAD; + } +} + +inline gfxPoint ThebesPoint(const Point &aPoint) +{ + return gfxPoint(aPoint.x, aPoint.y); +} + +inline gfxSize ThebesSize(const Size &aSize) +{ + return gfxSize(aSize.width, aSize.height); +} + +inline gfxRect ThebesRect(const Rect &aRect) { return gfxRect(aRect.x, aRect.y, aRect.width, aRect.height); } +inline gfxRGBA ThebesRGBA(const Color &aColor) +{ + return gfxRGBA(aColor.r, aColor.g, aColor.b, aColor.a); +} + +inline gfxContext::GraphicsLineCap ThebesLineCap(CapStyle aStyle) +{ + switch (aStyle) { + case CAP_BUTT: + return gfxContext::LINE_CAP_BUTT; + case CAP_ROUND: + return gfxContext::LINE_CAP_ROUND; + case CAP_SQUARE: + return gfxContext::LINE_CAP_SQUARE; + default: + return gfxContext::LINE_CAP_BUTT; + } +} + +inline CapStyle ToCapStyle(gfxContext::GraphicsLineCap aStyle) +{ + switch (aStyle) { + case gfxContext::LINE_CAP_BUTT: + return CAP_BUTT; + case gfxContext::LINE_CAP_ROUND: + return CAP_ROUND; + case gfxContext::LINE_CAP_SQUARE: + return CAP_SQUARE; + default: + return CAP_BUTT; + } +} + +inline gfxContext::GraphicsLineJoin ThebesLineJoin(JoinStyle aStyle) +{ + switch (aStyle) { + case JOIN_MITER: + return gfxContext::LINE_JOIN_MITER; + case JOIN_BEVEL: + return gfxContext::LINE_JOIN_BEVEL; + case JOIN_ROUND: + return gfxContext::LINE_JOIN_ROUND; + default: + return gfxContext::LINE_JOIN_MITER; + } +} + +inline JoinStyle ToJoinStyle(gfxContext::GraphicsLineJoin aStyle) +{ + switch (aStyle) { + case gfxContext::LINE_JOIN_MITER: + return JOIN_MITER; + case gfxContext::LINE_JOIN_BEVEL: + return JOIN_BEVEL; + case gfxContext::LINE_JOIN_ROUND: + return JOIN_ROUND; + default: + return JOIN_MITER; + } +} + +inline gfxMatrix ThebesMatrix(const Matrix &aMatrix) +{ + return gfxMatrix(aMatrix._11, aMatrix._12, aMatrix._21, + aMatrix._22, aMatrix._31, aMatrix._32); +} + inline gfxASurface::gfxContentType ContentForFormat(const SurfaceFormat &aFormat) { switch (aFormat) { @@ -31,10 +177,75 @@ inline gfxASurface::gfxContentType ContentForFormat(const SurfaceFormat &aFormat return gfxASurface::CONTENT_COLOR; case FORMAT_A8: return gfxASurface::CONTENT_ALPHA; + case FORMAT_B8G8R8A8: default: return gfxASurface::CONTENT_COLOR_ALPHA; } } +inline SurfaceFormat FormatForContent(gfxASurface::gfxContentType aContent) +{ + switch (aContent) { + case gfxASurface::CONTENT_COLOR: + return FORMAT_B8G8R8X8; + case gfxASurface::CONTENT_ALPHA: + return FORMAT_A8; + default: + return FORMAT_B8G8R8A8; + } +} + +inline CompositionOp CompositionOpForOp(gfxContext::GraphicsOperator aOp) +{ + switch (aOp) { + case gfxContext::OPERATOR_ADD: + return OP_ADD; + case gfxContext::OPERATOR_ATOP: + return OP_ATOP; + case gfxContext::OPERATOR_IN: + return OP_IN; + case gfxContext::OPERATOR_OUT: + return OP_OUT; + case gfxContext::OPERATOR_SOURCE: + return OP_SOURCE; + case gfxContext::OPERATOR_DEST_IN: + return OP_DEST_IN; + case gfxContext::OPERATOR_DEST_OUT: + return OP_DEST_OUT; + case gfxContext::OPERATOR_DEST_ATOP: + return OP_DEST_ATOP; + case gfxContext::OPERATOR_XOR: + return OP_XOR; + default: + return OP_OVER; + } +} + +inline gfxContext::GraphicsOperator ThebesOp(CompositionOp aOp) +{ + switch (aOp) { + case OP_ADD: + return gfxContext::OPERATOR_ADD; + case OP_ATOP: + return gfxContext::OPERATOR_ATOP; + case OP_IN: + return gfxContext::OPERATOR_IN; + case OP_OUT: + return gfxContext::OPERATOR_OUT; + case OP_SOURCE: + return gfxContext::OPERATOR_SOURCE; + case OP_DEST_IN: + return gfxContext::OPERATOR_DEST_IN; + case OP_DEST_OUT: + return gfxContext::OPERATOR_DEST_OUT; + case OP_DEST_ATOP: + return gfxContext::OPERATOR_DEST_ATOP; + case OP_XOR: + return gfxContext::OPERATOR_XOR; + default: + return gfxContext::OPERATOR_OVER; + } +} + } } diff --git a/gfx/thebes/gfxContext.cpp b/gfx/thebes/gfxContext.cpp index aac7fd8affee..81c3e08e9b19 100644 --- a/gfx/thebes/gfxContext.cpp +++ b/gfx/thebes/gfxContext.cpp @@ -56,28 +56,102 @@ #include "gfxPlatform.h" #include "gfxTeeSurface.h" -gfxContext::gfxContext(gfxASurface *surface) : - mSurface(surface) -{ - MOZ_COUNT_CTOR(gfxContext); +using namespace mozilla; +using namespace mozilla::gfx; - mCairo = cairo_create(surface->CairoSurface()); - mFlags = surface->GetDefaultContextFlags(); - if (mSurface->GetRotateForLandscape()) { - // Rotate page 90 degrees to draw landscape page on portrait paper - gfxIntSize size = mSurface->GetSize(); - Translate(gfxPoint(0, size.width)); - gfxMatrix matrix(0, -1, - 1, 0, - 0, 0); - Multiply(matrix); +/* This class lives on the stack and allows gfxContext users to easily, and + * performantly get a gfx::Pattern to use for drawing in their current context. + */ +class GeneralPattern +{ +public: + GeneralPattern(gfxContext *aContext) : mContext(aContext), mPattern(NULL) {} + ~GeneralPattern() { if (mPattern) { mPattern->~Pattern(); } } + + operator mozilla::gfx::Pattern&() + { + gfxContext::AzureState &state = mContext->CurrentState(); + + if (state.pattern) { + return *state.pattern->GetPattern(mContext->mDT); + } else if (state.sourceSurface) { + mPattern = new (mSurfacePattern.addr()) + SurfacePattern(state.sourceSurface, EXTEND_CLAMP, state.surfTransform); + return *mPattern; + } else { + mPattern = new (mColorPattern.addr()) + ColorPattern(state.color); + return *mPattern; } + } + +private: + union { + mozilla::AlignedStorage2 mColorPattern; + mozilla::AlignedStorage2 mSurfacePattern; + }; + + gfxContext *mContext; + Pattern *mPattern; +}; + +gfxContext::gfxContext(gfxASurface *surface) + : mSurface(surface) + , mRefCairo(NULL) +{ + MOZ_COUNT_CTOR(gfxContext); + + mCairo = cairo_create(surface->CairoSurface()); + mFlags = surface->GetDefaultContextFlags(); + if (mSurface->GetRotateForLandscape()) { + // Rotate page 90 degrees to draw landscape page on portrait paper + gfxIntSize size = mSurface->GetSize(); + Translate(gfxPoint(0, size.width)); + gfxMatrix matrix(0, -1, + 1, 0, + 0, 0); + Multiply(matrix); + } } + +gfxContext::gfxContext(DrawTarget *aTarget) + : mPathIsRect(false) + , mTransformChanged(false) + , mCairo(NULL) + , mRefCairo(NULL) + , mSurface(NULL) + , mFlags(0) + , mDT(aTarget) + , mOriginalDT(aTarget) +{ + MOZ_COUNT_CTOR(gfxContext); + + mStateStack.SetLength(1); + CurrentState().drawTarget = mDT; + mDT->SetTransform(Matrix()); +} + gfxContext::~gfxContext() { + if (mCairo) { cairo_destroy(mCairo); + } + if (mRefCairo) { + cairo_destroy(mRefCairo); + } + if (mDT) { + for (int i = mStateStack.Length() - 1; i >= 0; i--) { + for (unsigned int c = 0; c < mStateStack[i].pushedClips.Length(); c++) { + mDT->PopClip(); + } - MOZ_COUNT_DTOR(gfxContext); + if (mStateStack[i].clipWasReset) { + break; + } + } + mDT->Flush(); + } + MOZ_COUNT_DTOR(gfxContext); } gfxASurface * @@ -89,6 +163,7 @@ gfxContext::OriginalSurface() already_AddRefed gfxContext::CurrentSurface(gfxFloat *dx, gfxFloat *dy) { + if (mCairo) { cairo_surface_t *s = cairo_get_group_target(mCairo); if (s == mSurface->CairoSurface()) { if (dx && dy) @@ -101,107 +176,229 @@ gfxContext::CurrentSurface(gfxFloat *dx, gfxFloat *dy) if (dx && dy) cairo_surface_get_device_offset(s, dx, dy); return gfxASurface::Wrap(s); + } else { + if (dx && dy) { + *dx = *dy = 0; + } + // An Azure context doesn't have a surface backing it. + return NULL; + } +} + +cairo_t * +gfxContext::GetCairo() +{ + if (mCairo) { + return mCairo; + } + + if (mRefCairo) { + // Set transform! + return mRefCairo; + } + + mRefCairo = cairo_create(gfxPlatform::GetPlatform()->ScreenReferenceSurface()->CairoSurface()); + + return mRefCairo; } void gfxContext::Save() { + if (mCairo) { cairo_save(mCairo); + } else { + CurrentState().transform = mDT->GetTransform(); + mStateStack.AppendElement(AzureState(CurrentState())); + CurrentState().clipWasReset = false; + CurrentState().pushedClips.Clear(); + } } void gfxContext::Restore() { + if (mCairo) { cairo_restore(mCairo); + } else { + for (unsigned int c = 0; c < CurrentState().pushedClips.Length(); c++) { + mDT->PopClip(); + } + + if (CurrentState().clipWasReset && + CurrentState().drawTarget == mStateStack[mStateStack.Length() - 2].drawTarget) { + PushClipsToDT(mDT); + } + + mStateStack.RemoveElementAt(mStateStack.Length() - 1); + + if (mPathBuilder || mPath || mPathIsRect) { + mTransformChanged = true; + mPathTransform = mDT->GetTransform(); + } + + mDT = CurrentState().drawTarget; + mDT->SetTransform(CurrentState().transform); + } } // drawing void gfxContext::NewPath() { + if (mCairo) { cairo_new_path(mCairo); + } else { + mPath = NULL; + mPathBuilder = NULL; + mPathIsRect = false; + mTransformChanged = false; + } } void gfxContext::ClosePath() { + if (mCairo) { cairo_close_path(mCairo); + } else { + EnsurePathBuilder(); + mPathBuilder->Close(); + } } already_AddRefed gfxContext::CopyPath() const { + if (mCairo) { nsRefPtr path = new gfxPath(cairo_copy_path(mCairo)); return path.forget(); + } else { + // XXX - This is not yet supported for Azure. + return NULL; + } } void gfxContext::AppendPath(gfxPath* path) { + if (mCairo) { if (path->mPath->status == CAIRO_STATUS_SUCCESS && path->mPath->num_data != 0) cairo_append_path(mCairo, path->mPath); + } else { + // XXX - This is not yet supported for Azure. + return; + } } gfxPoint -gfxContext::CurrentPoint() const +gfxContext::CurrentPoint() { + if (mCairo) { double x, y; cairo_get_current_point(mCairo, &x, &y); return gfxPoint(x, y); + } else { + EnsurePathBuilder(); + return ThebesPoint(mPathBuilder->CurrentPoint()); + } } void gfxContext::Stroke() { + if (mCairo) { cairo_stroke_preserve(mCairo); + } else { + AzureState &state = CurrentState(); + if (mPathIsRect) { + mDT->StrokeRect(mRect, GeneralPattern(this), + state.strokeOptions, + DrawOptions(1.0f, GetOp(), state.aaMode)); + } else { + EnsurePath(); + + mDT->Stroke(mPath, GeneralPattern(this), state.strokeOptions, + DrawOptions(1.0f, GetOp(), state.aaMode)); + } + } } void gfxContext::Fill() { + if (mCairo) { cairo_fill_preserve(mCairo); + } else { + FillAzure(1.0f); + } } void gfxContext::FillWithOpacity(gfxFloat aOpacity) { - // This method exists in the hope that one day cairo gets a direct - // API for this, and then we would change this method to use that - // API instead. - if (aOpacity != 1.0) { - gfxContextAutoSaveRestore saveRestore(this); - Clip(); - Paint(aOpacity); + if (mCairo) { + // This method exists in the hope that one day cairo gets a direct + // API for this, and then we would change this method to use that + // API instead. + if (aOpacity != 1.0) { + gfxContextAutoSaveRestore saveRestore(this); + Clip(); + Paint(aOpacity); + } else { + Fill(); + } } else { - Fill(); + FillAzure(Float(aOpacity)); } } void gfxContext::MoveTo(const gfxPoint& pt) { + if (mCairo) { cairo_move_to(mCairo, pt.x, pt.y); + } else { + EnsurePathBuilder(); + mPathBuilder->MoveTo(ToPoint(pt)); + } } void gfxContext::NewSubPath() { + if (mCairo) { cairo_new_sub_path(mCairo); + } else { + // XXX - This has no users, we should kill it, it should be equivelant to a + // MoveTo to the path's current point. + } } void gfxContext::LineTo(const gfxPoint& pt) { + if (mCairo) { cairo_line_to(mCairo, pt.x, pt.y); + } else { + EnsurePathBuilder(); + mPathBuilder->LineTo(ToPoint(pt)); + } } void gfxContext::CurveTo(const gfxPoint& pt1, const gfxPoint& pt2, const gfxPoint& pt3) { + if (mCairo) { cairo_curve_to(mCairo, pt1.x, pt1.y, pt2.x, pt2.y, pt3.x, pt3.y); + } else { + EnsurePathBuilder(); + mPathBuilder->BezierTo(ToPoint(pt1), ToPoint(pt2), ToPoint(pt3)); + } } void gfxContext::QuadraticCurveTo(const gfxPoint& pt1, const gfxPoint& pt2) { + if (mCairo) { double cx, cy; cairo_get_current_point(mCairo, &cx, &cy); cairo_curve_to(mCairo, @@ -211,27 +408,47 @@ gfxContext::QuadraticCurveTo(const gfxPoint& pt1, const gfxPoint& pt2) (pt1.y * 2.0 + pt2.y) / 3.0, pt2.x, pt2.y); + } else { + EnsurePathBuilder(); + mPathBuilder->QuadraticBezierTo(ToPoint(pt1), ToPoint(pt2)); + } } void gfxContext::Arc(const gfxPoint& center, gfxFloat radius, gfxFloat angle1, gfxFloat angle2) { + if (mCairo) { cairo_arc(mCairo, center.x, center.y, radius, angle1, angle2); + } else { + EnsurePathBuilder(); + mPathBuilder->Arc(ToPoint(center), Float(radius), Float(angle1), Float(angle2)); + } } void gfxContext::NegativeArc(const gfxPoint& center, gfxFloat radius, gfxFloat angle1, gfxFloat angle2) { + if (mCairo) { cairo_arc_negative(mCairo, center.x, center.y, radius, angle1, angle2); + } else { + EnsurePathBuilder(); + mPathBuilder->Arc(ToPoint(center), Float(radius), Float(angle2), Float(angle1)); + } } void gfxContext::Line(const gfxPoint& start, const gfxPoint& end) { + if (mCairo) { MoveTo(start); LineTo(end); + } else { + EnsurePathBuilder(); + mPathBuilder->MoveTo(ToPoint(start)); + mPathBuilder->LineTo(ToPoint(end)); + } } // XXX snapToPixels is only valid when snapping for filled @@ -241,6 +458,7 @@ gfxContext::Line(const gfxPoint& start, const gfxPoint& end) void gfxContext::Rectangle(const gfxRect& rect, bool snapToPixels) { + if (mCairo) { if (snapToPixels) { gfxRect snappedRect(rect); @@ -257,21 +475,50 @@ gfxContext::Rectangle(const gfxRect& rect, bool snapToPixels) } cairo_rectangle(mCairo, rect.X(), rect.Y(), rect.Width(), rect.Height()); + } else { + Rect rec = ToRect(rect); + + if (snapToPixels) { + gfxRect newRect(rect); + if (UserToDevicePixelSnapped(newRect, PR_TRUE)) { + gfxMatrix mat = ThebesMatrix(mDT->GetTransform()); + mat.Invert(); + + // We need the user space rect. + rec = ToRect(mat.TransformBounds(newRect)); + } + } + + if (!mPathBuilder && !mPathIsRect) { + mPathIsRect = true; + mRect = rec; + return; + } else if (!mPathBuilder) { + EnsurePathBuilder(); + } + + mPathBuilder->MoveTo(rec.TopLeft()); + mPathBuilder->LineTo(rec.TopRight()); + mPathBuilder->LineTo(rec.BottomRight()); + mPathBuilder->LineTo(rec.BottomLeft()); + mPathBuilder->Close(); + } } void gfxContext::Ellipse(const gfxPoint& center, const gfxSize& dimensions) { - gfxSize halfDim = dimensions / 2.0; - gfxRect r(center - gfxPoint(halfDim.width, halfDim.height), dimensions); - gfxCornerSizes c(halfDim, halfDim, halfDim, halfDim); + gfxSize halfDim = dimensions / 2.0; + gfxRect r(center - gfxPoint(halfDim.width, halfDim.height), dimensions); + gfxCornerSizes c(halfDim, halfDim, halfDim, halfDim); - RoundedRectangle (r, c); + RoundedRectangle (r, c); } void gfxContext::Polygon(const gfxPoint *points, PRUint32 numPoints) { + if (mCairo) { if (numPoints == 0) return; @@ -279,11 +526,24 @@ gfxContext::Polygon(const gfxPoint *points, PRUint32 numPoints) for (PRUint32 i = 1; i < numPoints; ++i) { cairo_line_to(mCairo, points[i].x, points[i].y); } + } else { + if (numPoints == 0) { + return; + } + + EnsurePathBuilder(); + + mPathBuilder->MoveTo(ToPoint(points[0])); + for (PRUint32 i = 1; i < numPoints; i++) { + mPathBuilder->LineTo(ToPoint(points[i])); + } + } } void gfxContext::DrawSurface(gfxASurface *surface, const gfxSize& size) { + if (mCairo) { cairo_save(mCairo); cairo_set_source_surface(mCairo, surface->CairoSurface(), 0, 0); cairo_new_path(mCairo); @@ -293,108 +553,205 @@ gfxContext::DrawSurface(gfxASurface *surface, const gfxSize& size) cairo_fill(mCairo); cairo_restore(mCairo); + } else { + RefPtr surf = + gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mDT, surface); + + Rect rect(0, 0, Float(size.width), Float(size.height)); + rect.Intersect(Rect(0, 0, Float(surf->GetSize().width), Float(surf->GetSize().height))); + + // XXX - Should fix pixel snapping. + mDT->DrawSurface(surf, rect, rect); + } } // transform stuff void gfxContext::Translate(const gfxPoint& pt) { + if (mCairo) { cairo_translate(mCairo, pt.x, pt.y); + } else { + MOZ_ASSERT(!mPathBuilder); + + Matrix newMatrix = mDT->GetTransform(); + mDT->SetTransform(newMatrix.Translate(Float(pt.x), Float(pt.y))); + } } void gfxContext::Scale(gfxFloat x, gfxFloat y) { + if (mCairo) { cairo_scale(mCairo, x, y); + } else { + MOZ_ASSERT(!mPathBuilder); + + Matrix newMatrix = mDT->GetTransform(); + mDT->SetTransform(newMatrix.Scale(Float(x), Float(y))); + } } void gfxContext::Rotate(gfxFloat angle) { + if (mCairo) { cairo_rotate(mCairo, angle); + } else { + MOZ_ASSERT(!mPathBuilder); + + Matrix rotation = Matrix::Rotation(Float(angle)); + mDT->SetTransform(rotation * mDT->GetTransform()); + } } void gfxContext::Multiply(const gfxMatrix& matrix) { + if (mCairo) { const cairo_matrix_t& mat = reinterpret_cast(matrix); cairo_transform(mCairo, &mat); + } else { + MOZ_ASSERT(!mPathBuilder); + + mDT->SetTransform(ToMatrix(matrix) * mDT->GetTransform()); + } } void gfxContext::SetMatrix(const gfxMatrix& matrix) { + if (mCairo) { const cairo_matrix_t& mat = reinterpret_cast(matrix); cairo_set_matrix(mCairo, &mat); + } else { + MOZ_ASSERT(!mPathBuilder); + + mDT->SetTransform(ToMatrix(matrix)); + } } void gfxContext::IdentityMatrix() { + if (mCairo) { cairo_identity_matrix(mCairo); + } else { + MOZ_ASSERT(!mPathBuilder); + + mDT->SetTransform(Matrix()); + } } gfxMatrix gfxContext::CurrentMatrix() const { + if (mCairo) { cairo_matrix_t mat; cairo_get_matrix(mCairo, &mat); return gfxMatrix(*reinterpret_cast(&mat)); + } else { + return ThebesMatrix(mDT->GetTransform()); + } } void gfxContext::NudgeCurrentMatrixToIntegers() { + if (mCairo) { cairo_matrix_t mat; cairo_get_matrix(mCairo, &mat); gfxMatrix(*reinterpret_cast(&mat)).NudgeToIntegers(); cairo_set_matrix(mCairo, &mat); + } else { + gfxMatrix matrix = ThebesMatrix(mTransform); + matrix.NudgeToIntegers(); + mTransform = ToMatrix(matrix); + } } gfxPoint gfxContext::DeviceToUser(const gfxPoint& point) const { + if (mCairo) { gfxPoint ret = point; cairo_device_to_user(mCairo, &ret.x, &ret.y); return ret; + } else { + Matrix matrix = mDT->GetTransform(); + + matrix.Invert(); + + return ThebesPoint(matrix * ToPoint(point)); + } } gfxSize gfxContext::DeviceToUser(const gfxSize& size) const { + if (mCairo) { gfxSize ret = size; cairo_device_to_user_distance(mCairo, &ret.width, &ret.height); return ret; + } else { + Matrix matrix = mDT->GetTransform(); + + matrix.Invert(); + + return ThebesSize(matrix * ToSize(size)); + } } gfxRect gfxContext::DeviceToUser(const gfxRect& rect) const { + if (mCairo) { gfxRect ret = rect; cairo_device_to_user(mCairo, &ret.x, &ret.y); cairo_device_to_user_distance(mCairo, &ret.width, &ret.height); return ret; + } else { + Matrix matrix = mDT->GetTransform(); + + matrix.Invert(); + + return ThebesRect(matrix.TransformBounds(ToRect(rect))); + } } gfxPoint gfxContext::UserToDevice(const gfxPoint& point) const { + if (mCairo) { gfxPoint ret = point; cairo_user_to_device(mCairo, &ret.x, &ret.y); return ret; + } else { + return ThebesPoint(mDT->GetTransform() * ToPoint(point)); + } } gfxSize gfxContext::UserToDevice(const gfxSize& size) const { + if (mCairo) { gfxSize ret = size; cairo_user_to_device_distance(mCairo, &ret.width, &ret.height); return ret; + } else { + const Matrix &matrix = mDT->GetTransform(); + + gfxSize newSize = size; + newSize.width = newSize.width * matrix._11 + newSize.height * matrix._12; + newSize.height = newSize.width * matrix._21 + newSize.height * matrix._22; + return newSize; + } } gfxRect gfxContext::UserToDevice(const gfxRect& rect) const { + if (mCairo) { double xmin = rect.X(), ymin = rect.Y(), xmax = rect.XMost(), ymax = rect.YMost(); double x[3], y[3]; @@ -414,184 +771,255 @@ gfxContext::UserToDevice(const gfxRect& rect) const } return gfxRect(xmin, ymin, xmax - xmin, ymax - ymin); + } else { + const Matrix &matrix = mDT->GetTransform(); + return ThebesRect(matrix.TransformBounds(ToRect(rect))); + } } bool gfxContext::UserToDevicePixelSnapped(gfxRect& rect, bool ignoreScale) const { - if (GetFlags() & FLAG_DISABLE_SNAPPING) - return false; + if (GetFlags() & FLAG_DISABLE_SNAPPING) + return false; - // if we're not at 1.0 scale, don't snap, unless we're - // ignoring the scale. If we're not -just- a scale, - // never snap. - const gfxFloat epsilon = 0.0000001; + // if we're not at 1.0 scale, don't snap, unless we're + // ignoring the scale. If we're not -just- a scale, + // never snap. + const gfxFloat epsilon = 0.0000001; #define WITHIN_E(a,b) (fabs((a)-(b)) < epsilon) + if (mCairo) { cairo_matrix_t mat; cairo_get_matrix(mCairo, &mat); if (!ignoreScale && (!WITHIN_E(mat.xx,1.0) || !WITHIN_E(mat.yy,1.0) || - !WITHIN_E(mat.xy,0.0) || !WITHIN_E(mat.yx,0.0))) + !WITHIN_E(mat.xy,0.0) || !WITHIN_E(mat.yx,0.0))) return false; + } else { + Matrix mat = mDT->GetTransform(); + if (!ignoreScale && + (!WITHIN_E(mat._11,1.0) || !WITHIN_E(mat._22,1.0) || + !WITHIN_E(mat._12,0.0) || !WITHIN_E(mat._21,0.0))) + return false; + } #undef WITHIN_E - gfxPoint p1 = UserToDevice(rect.TopLeft()); - gfxPoint p2 = UserToDevice(rect.TopRight()); - gfxPoint p3 = UserToDevice(rect.BottomRight()); + gfxPoint p1 = UserToDevice(rect.TopLeft()); + gfxPoint p2 = UserToDevice(rect.TopRight()); + gfxPoint p3 = UserToDevice(rect.BottomRight()); - // Check that the rectangle is axis-aligned. For an axis-aligned rectangle, - // two opposite corners define the entire rectangle. So check if - // the axis-aligned rectangle with opposite corners p1 and p3 - // define an axis-aligned rectangle whose other corners are p2 and p4. - // We actually only need to check one of p2 and p4, since an affine - // transform maps parallelograms to parallelograms. - if (p2 == gfxPoint(p1.x, p3.y) || p2 == gfxPoint(p3.x, p1.y)) { - p1.Round(); - p3.Round(); + // Check that the rectangle is axis-aligned. For an axis-aligned rectangle, + // two opposite corners define the entire rectangle. So check if + // the axis-aligned rectangle with opposite corners p1 and p3 + // define an axis-aligned rectangle whose other corners are p2 and p4. + // We actually only need to check one of p2 and p4, since an affine + // transform maps parallelograms to parallelograms. + if (p2 == gfxPoint(p1.x, p3.y) || p2 == gfxPoint(p3.x, p1.y)) { + p1.Round(); + p3.Round(); - rect.MoveTo(gfxPoint(NS_MIN(p1.x, p3.x), NS_MIN(p1.y, p3.y))); - rect.SizeTo(gfxSize(NS_MAX(p1.x, p3.x) - rect.X(), - NS_MAX(p1.y, p3.y) - rect.Y())); - return true; - } + rect.MoveTo(gfxPoint(NS_MIN(p1.x, p3.x), NS_MIN(p1.y, p3.y))); + rect.SizeTo(gfxSize(NS_MAX(p1.x, p3.x) - rect.X(), + NS_MAX(p1.y, p3.y) - rect.Y())); + return true; + } - return false; + return false; } bool gfxContext::UserToDevicePixelSnapped(gfxPoint& pt, bool ignoreScale) const { - if (GetFlags() & FLAG_DISABLE_SNAPPING) - return false; + if (GetFlags() & FLAG_DISABLE_SNAPPING) + return false; - // if we're not at 1.0 scale, don't snap, unless we're - // ignoring the scale. If we're not -just- a scale, - // never snap. + // if we're not at 1.0 scale, don't snap, unless we're + // ignoring the scale. If we're not -just- a scale, + // never snap. + const gfxFloat epsilon = 0.0000001; +#define WITHIN_E(a,b) (fabs((a)-(b)) < epsilon) + if (mCairo) { cairo_matrix_t mat; cairo_get_matrix(mCairo, &mat); - if ((!ignoreScale && (mat.xx != 1.0 || mat.yy != 1.0)) || - (mat.xy != 0.0 || mat.yx != 0.0)) + if (!ignoreScale && + (!WITHIN_E(mat.xx,1.0) || !WITHIN_E(mat.yy,1.0) || + !WITHIN_E(mat.xy,0.0) || !WITHIN_E(mat.yx,0.0))) return false; + } else { + Matrix mat = mDT->GetTransform(); + if (!ignoreScale && + (!WITHIN_E(mat._11,1.0) || !WITHIN_E(mat._22,1.0) || + !WITHIN_E(mat._12,0.0) || !WITHIN_E(mat._21,0.0))) + return false; + } +#undef WITHIN_E - pt = UserToDevice(pt); - pt.Round(); - return true; + pt = UserToDevice(pt); + pt.Round(); + return true; } void gfxContext::PixelSnappedRectangleAndSetPattern(const gfxRect& rect, gfxPattern *pattern) { - gfxRect r(rect); + gfxRect r(rect); - // Bob attempts to pixel-snap the rectangle, and returns true if - // the snapping succeeds. If it does, we need to set up an - // identity matrix, because the rectangle given back is in device - // coordinates. - // - // We then have to call a translate to dr.pos afterwards, to make - // sure the image lines up in the right place with our pixel - // snapped rectangle. - // - // If snapping wasn't successful, we just translate to where the - // pattern would normally start (in app coordinates) and do the - // same thing. - - gfxMatrix mat = CurrentMatrix(); - if (UserToDevicePixelSnapped(r)) { - IdentityMatrix(); - } - - Translate(r.TopLeft()); - r.MoveTo(gfxPoint(0, 0)); - Rectangle(r); - SetPattern(pattern); - - SetMatrix(mat); + // Bob attempts to pixel-snap the rectangle, and returns true if + // the snapping succeeds. If it does, we need to set up an + // identity matrix, because the rectangle given back is in device + // coordinates. + // + // We then have to call a translate to dr.pos afterwards, to make + // sure the image lines up in the right place with our pixel + // snapped rectangle. + // + // If snapping wasn't successful, we just translate to where the + // pattern would normally start (in app coordinates) and do the + // same thing. + Rectangle(r, true); + SetPattern(pattern); } void gfxContext::SetAntialiasMode(AntialiasMode mode) { + if (mCairo) { if (mode == MODE_ALIASED) { cairo_set_antialias(mCairo, CAIRO_ANTIALIAS_NONE); } else if (mode == MODE_COVERAGE) { cairo_set_antialias(mCairo, CAIRO_ANTIALIAS_DEFAULT); } + } else { + if (mode == MODE_ALIASED) { + CurrentState().aaMode = AA_NONE; + } else if (mode == MODE_COVERAGE) { + CurrentState().aaMode = AA_SUBPIXEL; + } + } } gfxContext::AntialiasMode gfxContext::CurrentAntialiasMode() const { + if (mCairo) { cairo_antialias_t aa = cairo_get_antialias(mCairo); if (aa == CAIRO_ANTIALIAS_NONE) return MODE_ALIASED; return MODE_COVERAGE; + } else { + if (CurrentState().aaMode == AA_NONE) { + return MODE_ALIASED; + } + return MODE_COVERAGE; + } } void gfxContext::SetDash(gfxLineType ltype) { - static double dash[] = {5.0, 5.0}; - static double dot[] = {1.0, 1.0}; + static double dash[] = {5.0, 5.0}; + static double dot[] = {1.0, 1.0}; - switch (ltype) { - case gfxLineDashed: - SetDash(dash, 2, 0.0); - break; - case gfxLineDotted: - SetDash(dot, 2, 0.0); - break; - case gfxLineSolid: - default: - SetDash(nsnull, 0, 0.0); - break; - } + switch (ltype) { + case gfxLineDashed: + SetDash(dash, 2, 0.0); + break; + case gfxLineDotted: + SetDash(dot, 2, 0.0); + break; + case gfxLineSolid: + default: + SetDash(nsnull, 0, 0.0); + break; + } } void gfxContext::SetDash(gfxFloat *dashes, int ndash, gfxFloat offset) { + if (mCairo) { cairo_set_dash(mCairo, dashes, ndash, offset); + } else { + AzureState &state = CurrentState(); + + state.dashPattern.SetLength(ndash); + for (int i = 0; i < ndash; i++) { + state.dashPattern[i] = Float(dashes[i]); + } + state.strokeOptions.mDashLength = ndash; + state.strokeOptions.mDashOffset = Float(offset); + state.strokeOptions.mDashPattern = ndash ? state.dashPattern.Elements() : NULL; + } } bool gfxContext::CurrentDash(FallibleTArray& dashes, gfxFloat* offset) const { + if (mCairo) { int count = cairo_get_dash_count(mCairo); if (count <= 0 || !dashes.SetLength(count)) { return false; } cairo_get_dash(mCairo, dashes.Elements(), offset); return true; + } else { + const AzureState &state = CurrentState(); + int count = state.strokeOptions.mDashLength; + + if (count <= 0 || !dashes.SetLength(count)) { + return false; + } + + for (int i = 0; i < count; i++) { + dashes[i] = state.dashPattern[i]; + } + + *offset = state.strokeOptions.mDashOffset; + + return true; + } } gfxFloat gfxContext::CurrentDashOffset() const { + if (mCairo) { if (cairo_get_dash_count(mCairo) <= 0) { return 0.0; } gfxFloat offset; cairo_get_dash(mCairo, NULL, &offset); return offset; + } else { + return CurrentState().strokeOptions.mDashOffset; + } } void gfxContext::SetLineWidth(gfxFloat width) { + if (mCairo) { cairo_set_line_width(mCairo, width); + } else { + CurrentState().strokeOptions.mLineWidth = Float(width); + } } gfxFloat gfxContext::CurrentLineWidth() const { + if (mCairo) { return cairo_get_line_width(mCairo); + } else { + return CurrentState().strokeOptions.mLineWidth; + } } void gfxContext::SetOperator(GraphicsOperator op) { + if (mCairo) { if (mFlags & FLAG_SIMPLIFY_OPERATORS) { if (op != OPERATOR_SOURCE && op != OPERATOR_CLEAR && @@ -600,105 +1028,218 @@ gfxContext::SetOperator(GraphicsOperator op) } cairo_set_operator(mCairo, (cairo_operator_t)op); + } else { + if (op == OPERATOR_CLEAR) { + CurrentState().opIsClear = true; + return; + } + CurrentState().opIsClear = false; + CurrentState().op = CompositionOpForOp(op); + } } gfxContext::GraphicsOperator gfxContext::CurrentOperator() const { + if (mCairo) { return (GraphicsOperator)cairo_get_operator(mCairo); + } else { + return ThebesOp(CurrentState().op); + } } void gfxContext::SetLineCap(GraphicsLineCap cap) { + if (mCairo) { cairo_set_line_cap(mCairo, (cairo_line_cap_t)cap); + } else { + CurrentState().strokeOptions.mLineCap = ToCapStyle(cap); + } } gfxContext::GraphicsLineCap gfxContext::CurrentLineCap() const { + if (mCairo) { return (GraphicsLineCap)cairo_get_line_cap(mCairo); + } else { + return ThebesLineCap(CurrentState().strokeOptions.mLineCap); + } } void gfxContext::SetLineJoin(GraphicsLineJoin join) { + if (mCairo) { cairo_set_line_join(mCairo, (cairo_line_join_t)join); + } else { + CurrentState().strokeOptions.mLineJoin = ToJoinStyle(join); + } } gfxContext::GraphicsLineJoin gfxContext::CurrentLineJoin() const { + if (mCairo) { return (GraphicsLineJoin)cairo_get_line_join(mCairo); + } else { + return ThebesLineJoin(CurrentState().strokeOptions.mLineJoin); + } } void gfxContext::SetMiterLimit(gfxFloat limit) { + if (mCairo) { cairo_set_miter_limit(mCairo, limit); + } else { + CurrentState().strokeOptions.mMiterLimit = Float(limit); + } } gfxFloat gfxContext::CurrentMiterLimit() const { + if (mCairo) { return cairo_get_miter_limit(mCairo); + } else { + return CurrentState().strokeOptions.mMiterLimit; + } } void gfxContext::SetFillRule(FillRule rule) { + if (mCairo) { cairo_set_fill_rule(mCairo, (cairo_fill_rule_t)rule); + } else { + CurrentState().fillRule = rule == FILL_RULE_WINDING ? FILL_WINDING : FILL_EVEN_ODD; + } } gfxContext::FillRule gfxContext::CurrentFillRule() const { + if (mCairo) { return (FillRule)cairo_get_fill_rule(mCairo); + } else { + return FILL_RULE_WINDING; + } } // clipping void gfxContext::Clip(const gfxRect& rect) { + if (mCairo) { cairo_new_path(mCairo); cairo_rectangle(mCairo, rect.X(), rect.Y(), rect.Width(), rect.Height()); cairo_clip(mCairo); + } else { + AzureState::PushedClip clip = { NULL, ToRect(rect), mDT->GetTransform() }; + CurrentState().pushedClips.AppendElement(clip); + mDT->PushClipRect(ToRect(rect)); + NewPath(); + } } void gfxContext::Clip() { + if (mCairo) { cairo_clip_preserve(mCairo); + } else { + if (mPathIsRect && !mTransformChanged) { + AzureState::PushedClip clip = { NULL, mRect, mDT->GetTransform() }; + CurrentState().pushedClips.AppendElement(clip); + mDT->PushClipRect(mRect); + } else { + EnsurePath(); + mDT->PushClip(mPath); + AzureState::PushedClip clip = { mPath, Rect(), mDT->GetTransform() }; + CurrentState().pushedClips.AppendElement(clip); + } + } } void gfxContext::ResetClip() { + if (mCairo) { cairo_reset_clip(mCairo); + } else { + for (int i = mStateStack.Length() - 1; i >= 0; i--) { + for (unsigned int c = 0; c < mStateStack[i].pushedClips.Length(); c++) { + mDT->PopClip(); + } + + if (mStateStack[i].clipWasReset) { + break; + } + } + CurrentState().pushedClips.Clear(); + CurrentState().clipWasReset = true; + } } void gfxContext::UpdateSurfaceClip() { + if (mCairo) { NewPath(); // we paint an empty rectangle to ensure the clip is propagated to // the destination surface SetDeviceColor(gfxRGBA(0,0,0,0)); Rectangle(gfxRect(0,1,1,0)); Fill(); + } } gfxRect gfxContext::GetClipExtents() { + if (mCairo) { double xmin, ymin, xmax, ymax; cairo_clip_extents(mCairo, &xmin, &ymin, &xmax, &ymax); return gfxRect(xmin, ymin, xmax - xmin, ymax - ymin); + } else { + unsigned int lastReset = 0; + for (int i = mStateStack.Length() - 1; i > 0; i--) { + if (mStateStack[i].clipWasReset) { + lastReset = i; + } + } + + Rect rect(0, 0, Float(mDT->GetSize().width), Float(mDT->GetSize().height)); + for (unsigned int i = lastReset; i < mStateStack.Length(); i++) { + for (unsigned int c = 0; c < mStateStack[i].pushedClips.Length(); c++) { + AzureState::PushedClip &clip = mStateStack[i].pushedClips[c]; + if (clip.path) { + Rect bounds = clip.path->GetBounds(clip.transform); + rect.IntersectRect(rect, bounds); + } else { + rect.IntersectRect(rect, clip.transform.TransformBounds(clip.rect)); + } + } + } + + if (rect.width == 0 || rect.height == 0) { + return gfxRect(0, 0, 0, 0); + } + + Matrix mat = mDT->GetTransform(); + mat.Invert(); + rect = mat.TransformBounds(rect); + + return ThebesRect(rect); + } } bool gfxContext::ClipContainsRect(const gfxRect& aRect) { + if (mCairo) { cairo_rectangle_list_t *clip = cairo_copy_clip_rectangle_list(mCairo); @@ -715,8 +1256,40 @@ gfxContext::ClipContainsRect(const gfxRect& aRect) } } - cairo_rectangle_list_destroy(clip); - return result; + cairo_rectangle_list_destroy(clip); + return result; + } else { + unsigned int lastReset = 0; + for (int i = mStateStack.Length() - 2; i > 0; i--) { + if (mStateStack[i].clipWasReset) { + lastReset = i; + } + } + + bool result = true; + + // Since we always return false when the clip list contains a + // non-rectangular clip or a non-rectilinear transform, our 'total' clip + // is always a rectangle if we hit the end of this function. + Rect clipBounds(0, 0, Float(mDT->GetSize().width), Float(mDT->GetSize().height)); + + for (unsigned int i = lastReset; i < mStateStack.Length(); i++) { + for (unsigned int c = 0; c < mStateStack[i].pushedClips.Length(); c++) { + AzureState::PushedClip &clip = mStateStack[i].pushedClips[c]; + if (clip.path || !clip.transform.IsRectilinear()) { + // Cairo behavior is we return false if the clip contains a non- + // rectangle. + return false; + } else { + Rect clipRect = mTransform.TransformBounds(clip.rect); + + clipBounds.IntersectRect(clipBounds, clipRect); + } + } + } + + return clipBounds.Contains(ToRect(aRect)); + } } // rendering sources @@ -724,6 +1297,7 @@ gfxContext::ClipContainsRect(const gfxRect& aRect) void gfxContext::SetColor(const gfxRGBA& c) { + if (mCairo) { if (gfxPlatform::GetCMSMode() == eCMSMode_All) { gfxRGBA cms; @@ -735,40 +1309,88 @@ gfxContext::SetColor(const gfxRGBA& c) } else cairo_set_source_rgba(mCairo, c.r, c.g, c.b, c.a); + } else { + CurrentState().pattern = NULL; + CurrentState().sourceSurface = NULL; + + if (gfxPlatform::GetCMSMode() == eCMSMode_All) { + + gfxRGBA cms; + gfxPlatform::TransformPixel(c, cms, gfxPlatform::GetCMSRGBTransform()); + + // Use the original alpha to avoid unnecessary float->byte->float + // conversion errors + CurrentState().color = ToColor(cms); + } + else + CurrentState().color = ToColor(c); + } } void gfxContext::SetDeviceColor(const gfxRGBA& c) { + if (mCairo) { cairo_set_source_rgba(mCairo, c.r, c.g, c.b, c.a); + } else { + CurrentState().pattern = NULL; + CurrentState().sourceSurface = NULL; + CurrentState().color = ToColor(c); + } } bool gfxContext::GetDeviceColor(gfxRGBA& c) { + if (mCairo) { return cairo_pattern_get_rgba(cairo_get_source(mCairo), &c.r, &c.g, &c.b, &c.a) == CAIRO_STATUS_SUCCESS; + } else { + if (CurrentState().sourceSurface) { + return false; + } + if (CurrentState().pattern) { + gfxRGBA color; + return CurrentState().pattern->GetSolidColor(c); + } + + c = ThebesRGBA(CurrentState().color); + return true; + } } void gfxContext::SetSource(gfxASurface *surface, const gfxPoint& offset) { + if (mCairo) { NS_ASSERTION(surface->GetAllowUseAsSource(), "Surface not allowed to be used as source!"); cairo_set_source_surface(mCairo, surface->CairoSurface(), offset.x, offset.y); + } else { + CurrentState().surfTransform = Matrix(1.0f, 0, 0, 1.0f, Float(offset.x), Float(offset.y)); + CurrentState().pattern = NULL; + CurrentState().sourceSurface = + gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mDT, surface); + } } void gfxContext::SetPattern(gfxPattern *pattern) { + if (mCairo) { cairo_set_source(mCairo, pattern->CairoPattern()); + } else { + CurrentState().sourceSurface = NULL; + CurrentState().pattern = pattern; + } } already_AddRefed gfxContext::GetPattern() { + if (mCairo) { cairo_pattern_t *pat = cairo_get_source(mCairo); NS_ASSERTION(pat, "I was told this couldn't be null"); @@ -780,6 +1402,19 @@ gfxContext::GetPattern() NS_IF_ADDREF(wrapper); return wrapper; + } else { + nsRefPtr pat; + + AzureState &state = CurrentState(); + if (state.pattern) { + pat = state.pattern; + } else if (state.sourceSurface) { + NS_ASSERTION(false, "Ugh, this isn't good."); + } else { + pat = new gfxPattern(ThebesRGBA(state.color)); + } + return pat.forget(); + } } @@ -788,19 +1423,49 @@ gfxContext::GetPattern() void gfxContext::Mask(gfxPattern *pattern) { + if (mCairo) { cairo_mask(mCairo, pattern->CairoPattern()); + } else { + mDT->Mask(GeneralPattern(this), *pattern->GetPattern(mDT), DrawOptions(1.0f, CurrentState().op, CurrentState().aaMode)); + } } void gfxContext::Mask(gfxASurface *surface, const gfxPoint& offset) { + if (mCairo) { cairo_mask_surface(mCairo, surface->CairoSurface(), offset.x, offset.y); + } else { + RefPtr sourceSurf = + gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mDT, surface); + + gfxPoint pt = surface->GetDeviceOffset(); + mDT->Mask(GeneralPattern(this), + SurfacePattern(sourceSurf, EXTEND_CLAMP, + Matrix(1.0f, 0, 0, 1.0f, Float(offset.x - pt.x), Float(offset.y - pt.y))), + DrawOptions(1.0f, CurrentState().op, CurrentState().aaMode)); + } } void gfxContext::Paint(gfxFloat alpha) { + if (mCairo) { cairo_paint_with_alpha(mCairo, alpha); + } else { + AzureState &state = CurrentState(); + + Matrix mat = mDT->GetTransform(); + mat.Invert(); + Rect paintRect = mat.TransformBounds(Rect(Point(0, 0), Size(mDT->GetSize()))); + + if (state.opIsClear) { + mDT->ClearRect(paintRect); + } else { + mDT->FillRect(paintRect, GeneralPattern(this), + DrawOptions(Float(alpha), GetOp())); + } + } } // groups @@ -808,17 +1473,30 @@ gfxContext::Paint(gfxFloat alpha) void gfxContext::PushGroup(gfxASurface::gfxContentType content) { + if (mCairo) { cairo_push_group_with_content(mCairo, (cairo_content_t) content); + } else { + RefPtr newDT = + mDT->CreateSimilarDrawTarget(mDT->GetSize(), FormatForContent(content)); + + Save(); + + CurrentState().drawTarget = newDT; + + PushClipsToDT(newDT); + newDT->SetTransform(mDT->GetTransform()); + mDT = newDT; + } } static gfxRect GetRoundOutDeviceClipExtents(gfxContext* aCtx) { - gfxContextMatrixAutoSaveRestore save(aCtx); - aCtx->IdentityMatrix(); - gfxRect r = aCtx->GetClipExtents(); - r.RoundOut(); - return r; + gfxContextMatrixAutoSaveRestore save(aCtx); + aCtx->IdentityMatrix(); + gfxRect r = aCtx->GetClipExtents(); + r.RoundOut(); + return r; } /** @@ -837,6 +1515,7 @@ CopySurface(gfxASurface* aSrc, gfxASurface* aDest, const gfxPoint& aTranslation) void gfxContext::PushGroupAndCopyBackground(gfxASurface::gfxContentType content) { + if (mCairo) { if (content == gfxASurface::CONTENT_COLOR_ALPHA && !(GetFlags() & FLAG_DISABLE_COPY_BACKGROUND)) { nsRefPtr s = CurrentSurface(); @@ -865,73 +1544,133 @@ gfxContext::PushGroupAndCopyBackground(gfxASurface::gfxContentType content) } } cairo_push_group_with_content(mCairo, (cairo_content_t) content); + } else { + RefPtr source = mDT->Snapshot(); + PushGroup(content); + Rect surfRect(0, 0, Float(mDT->GetSize().width), Float(mDT->GetSize().height)); + mDT->DrawSurface(source, surfRect, surfRect); + } } already_AddRefed gfxContext::PopGroup() { + if (mCairo) { cairo_pattern_t *pat = cairo_pop_group(mCairo); gfxPattern *wrapper = new gfxPattern(pat); cairo_pattern_destroy(pat); NS_IF_ADDREF(wrapper); return wrapper; + } else { + RefPtr src = mDT->Snapshot(); + + Restore(); + + Matrix mat = mDT->GetTransform(); + mat.Invert(); + nsRefPtr pat = new gfxPattern(src, mat); + + return pat.forget(); + } } void gfxContext::PopGroupToSource() { + if (mCairo) { cairo_pop_group_to_source(mCairo); + } else { + RefPtr src = mDT->Snapshot(); + Restore(); + CurrentState().sourceSurface = src; + CurrentState().pattern = NULL; + + Matrix mat = mDT->GetTransform(); + mat.Invert(); + CurrentState().surfTransform = mat; + } } bool gfxContext::PointInFill(const gfxPoint& pt) { + if (mCairo) { return cairo_in_fill(mCairo, pt.x, pt.y); + } else { + return mPath->ContainsPoint(ToPoint(pt), mTransform); + } } bool gfxContext::PointInStroke(const gfxPoint& pt) { + if (mCairo) { return cairo_in_stroke(mCairo, pt.x, pt.y); + } else { + // XXX - Used by SVG, needs fixing. + return PR_FALSE; + } } gfxRect gfxContext::GetUserPathExtent() { + if (mCairo) { double xmin, ymin, xmax, ymax; cairo_path_extents(mCairo, &xmin, &ymin, &xmax, &ymax); return gfxRect(xmin, ymin, xmax - xmin, ymax - ymin); + } else { + return ThebesRect(mPath->GetBounds()); + } } gfxRect gfxContext::GetUserFillExtent() { + if (mCairo) { double xmin, ymin, xmax, ymax; cairo_fill_extents(mCairo, &xmin, &ymin, &xmax, &ymax); return gfxRect(xmin, ymin, xmax - xmin, ymax - ymin); + } else { + return ThebesRect(mPath->GetBounds()); + } } gfxRect gfxContext::GetUserStrokeExtent() { + if (mCairo) { double xmin, ymin, xmax, ymax; cairo_stroke_extents(mCairo, &xmin, &ymin, &xmax, &ymax); return gfxRect(xmin, ymin, xmax - xmin, ymax - ymin); + } else { + return ThebesRect(mPath->GetStrokedBounds(CurrentState().strokeOptions, mTransform)); + } } already_AddRefed gfxContext::GetFlattenedPath() { + if (mCairo) { gfxFlattenedPath *path = new gfxFlattenedPath(cairo_copy_path_flat(mCairo)); NS_IF_ADDREF(path); return path; + } else { + // XXX - Used by SVG, needs fixing. + return NULL; + } } bool gfxContext::HasError() { - return cairo_status(mCairo) != CAIRO_STATUS_SUCCESS; + if (mCairo) { + return cairo_status(mCairo) != CAIRO_STATUS_SUCCESS; + } else { + // As far as this is concerned, an Azure context is never in error. + return PR_FALSE; + } } void @@ -1008,6 +1747,8 @@ gfxContext::RoundedRectangle(const gfxRect& rect, // For the various corners and for each axis, the sign of this // constant changes, or it might be 0 -- it's multiplied by the // appropriate multiplier from the list before using. + + if (mCairo) { const gfxFloat alpha = 0.55191497064665766025; typedef struct { gfxFloat a, b; } twoFloats; @@ -1066,6 +1807,65 @@ gfxContext::RoundedRectangle(const gfxRect& rect, } cairo_close_path (mCairo); + } else { + EnsurePathBuilder(); + + const gfxFloat alpha = 0.55191497064665766025; + + typedef struct { gfxFloat a, b; } twoFloats; + + twoFloats cwCornerMults[4] = { { -1, 0 }, + { 0, -1 }, + { +1, 0 }, + { 0, +1 } }; + twoFloats ccwCornerMults[4] = { { +1, 0 }, + { 0, -1 }, + { -1, 0 }, + { 0, +1 } }; + + twoFloats *cornerMults = draw_clockwise ? cwCornerMults : ccwCornerMults; + + gfxPoint pc, p0, p1, p2, p3; + + if (draw_clockwise) + mPathBuilder->MoveTo(Point(Float(rect.X() + corners[NS_CORNER_TOP_LEFT].width), Float(rect.Y()))); + else + mPathBuilder->MoveTo(Point(Float(rect.X() + rect.Width() - corners[NS_CORNER_TOP_RIGHT].width), Float(rect.Y()))); + + NS_FOR_CSS_CORNERS(i) { + // the corner index -- either 1 2 3 0 (cw) or 0 3 2 1 (ccw) + mozilla::css::Corner c = mozilla::css::Corner(draw_clockwise ? ((i+1) % 4) : ((4-i) % 4)); + + // i+2 and i+3 respectively. These are used to index into the corner + // multiplier table, and were deduced by calculating out the long form + // of each corner and finding a pattern in the signs and values. + int i2 = (i+2) % 4; + int i3 = (i+3) % 4; + + pc = rect.AtCorner(c); + + if (corners[c].width > 0.0 && corners[c].height > 0.0) { + p0.x = pc.x + cornerMults[i].a * corners[c].width; + p0.y = pc.y + cornerMults[i].b * corners[c].height; + + p3.x = pc.x + cornerMults[i3].a * corners[c].width; + p3.y = pc.y + cornerMults[i3].b * corners[c].height; + + p1.x = p0.x + alpha * cornerMults[i2].a * corners[c].width; + p1.y = p0.y + alpha * cornerMults[i2].b * corners[c].height; + + p2.x = p3.x - alpha * cornerMults[i3].a * corners[c].width; + p2.y = p3.y - alpha * cornerMults[i3].b * corners[c].height; + + mPathBuilder->LineTo(ToPoint(p0)); + mPathBuilder->BezierTo(ToPoint(p1), ToPoint(p2), ToPoint(p3)); + } else { + mPathBuilder->LineTo(ToPoint(pc)); + } + } + + mPathBuilder->Close(); + } } #ifdef MOZ_DUMP_PAINTING @@ -1102,3 +1902,158 @@ gfxContext::CopyAsDataURL() } } #endif + +void +gfxContext::EnsurePath() +{ + if (mPathBuilder) { + mPath = mPathBuilder->Finish(); + mPathBuilder = NULL; + } + + if (mPath) { + if (mTransformChanged) { + Matrix mat = mDT->GetTransform(); + mat.Invert(); + mat = mPathTransform * mat; + mPathBuilder = mPath->TransformedCopyToBuilder(mat, CurrentState().fillRule); + mPath = mPathBuilder->Finish(); + mPathBuilder = NULL; + + mTransformChanged = false; + } + + if (CurrentState().fillRule == mPath->GetFillRule()) { + return; + } + + mPathBuilder = mPath->CopyToBuilder(CurrentState().fillRule); + + mPath = mPathBuilder->Finish(); + mPathBuilder = NULL; + return; + } + + EnsurePathBuilder(); + mPath = mPathBuilder->Finish(); + mPathBuilder = NULL; +} + +void +gfxContext::EnsurePathBuilder() +{ + if (mPathBuilder) { + return; + } + + if (mPath) { + mPathBuilder = mPath->CopyToBuilder(CurrentState().fillRule); + mPath = NULL; + } + + mPathBuilder = mDT->CreatePathBuilder(CurrentState().fillRule); + + if (mPathIsRect && !mTransformChanged) { + mPathBuilder->MoveTo(mRect.TopLeft()); + mPathBuilder->LineTo(mRect.TopRight()); + mPathBuilder->LineTo(mRect.BottomRight()); + mPathBuilder->LineTo(mRect.BottomLeft()); + mPathBuilder->Close(); + } else if (mPathIsRect) { + mTransformChanged = false; + Matrix mat = mDT->GetTransform(); + mat.Invert(); + mat = mPathTransform * mat; + mPathBuilder->MoveTo(mat * mRect.TopLeft()); + mPathBuilder->LineTo(mat * mRect.TopRight()); + mPathBuilder->LineTo(mat * mRect.BottomRight()); + mPathBuilder->LineTo(mat * mRect.BottomLeft()); + mPathBuilder->Close(); + } + + mPathIsRect = false; +} + +void +gfxContext::FillAzure(Float aOpacity) +{ + AzureState &state = CurrentState(); + + CompositionOp op = GetOp(); + + if (mPathIsRect && !mTransformChanged) { + if (state.opIsClear) { + mDT->ClearRect(mRect); + } else if (op == OP_SOURCE) { + // Emulate cairo operator source which is bound by mask! + mDT->ClearRect(mRect); + mDT->FillRect(mRect, GeneralPattern(this), DrawOptions(aOpacity)); + } else { + mDT->FillRect(mRect, GeneralPattern(this), DrawOptions(aOpacity, op, state.aaMode)); + } + } else { + EnsurePath(); + + NS_ASSERTION(!state.opIsClear, "We shouldn't be clearing complex paths!"); + + mDT->Fill(mPath, GeneralPattern(this), DrawOptions(aOpacity, op, state.aaMode)); + } +} + +void +gfxContext::PushClipsToDT(DrawTarget *aDT) +{ + // Tricky, we have to restore all clips -since the last time- the clip + // was reset. If we didn't reset the clip, just popping the clips we + // added was fine. + unsigned int lastReset = 0; + for (int i = mStateStack.Length() - 2; i > 0; i--) { + if (mStateStack[i].clipWasReset) { + lastReset = i; + } + } + + // Don't need to save the old transform, we'll be setting a new one soon! + + // Push all clips from the last state on the stack where the clip was + // reset to the clip before ours. + for (unsigned int i = lastReset; i < mStateStack.Length() - 1; i++) { + for (unsigned int c = 0; c < mStateStack[i].pushedClips.Length(); c++) { + aDT->SetTransform(mStateStack[i].pushedClips[c].transform); + if (mStateStack[i].pushedClips[c].path) { + aDT->PushClip(mStateStack[i].pushedClips[c].path); + } else { + aDT->PushClipRect(mStateStack[i].pushedClips[c].rect); + } + } + } +} + +CompositionOp +gfxContext::GetOp() +{ + if (CurrentState().op != OP_SOURCE) { + return CurrentState().op; + } + + AzureState &state = CurrentState(); + if (state.pattern) { + if (state.pattern->IsOpaque()) { + return OP_OVER; + } else { + return OP_SOURCE; + } + } else if (state.sourceSurface) { + if (state.sourceSurface->GetFormat() == FORMAT_B8G8R8X8) { + return OP_OVER; + } else { + return OP_SOURCE; + } + } else { + if (state.color.a > 0.999) { + return OP_OVER; + } else { + return OP_SOURCE; + } + } +} diff --git a/gfx/thebes/gfxContext.h b/gfx/thebes/gfxContext.h index bb20f1683eb9..53d05576b26c 100644 --- a/gfx/thebes/gfxContext.h +++ b/gfx/thebes/gfxContext.h @@ -49,6 +49,9 @@ #include "gfxPattern.h" #include "gfxPath.h" #include "nsISupportsImpl.h" +#include "nsTArray.h" + +#include "mozilla/gfx/2D.h" typedef struct _cairo cairo_t; template class FallibleTArray; @@ -75,6 +78,12 @@ public: * Initialize this context from a surface. */ gfxContext(gfxASurface *surface); + + /** + * Initialize this context from a DrawTarget. + */ + gfxContext(mozilla::gfx::DrawTarget *aTarget); + ~gfxContext(); /** @@ -97,7 +106,9 @@ public: * Return the raw cairo_t object. * XXX this should go away at some point. */ - cairo_t *GetCairo() { return mCairo; } + cairo_t *GetCairo(); + + mozilla::gfx::DrawTarget *GetDrawTarget() { return mDT; } /** * Returns true if the cairo context is in an error state. @@ -174,7 +185,7 @@ public: /** * Returns the current point in the current path. */ - gfxPoint CurrentPoint() const; + gfxPoint CurrentPoint(); /** * Draws a line from the current point to pt. @@ -681,6 +692,8 @@ public: void ClearFlag(PRInt32 aFlag) { mFlags &= ~aFlag; } PRInt32 GetFlags() const { return mFlags; } + bool IsCairo() const { return !mDT; } + #ifdef MOZ_DUMP_PAINTING /** * Debug functions to encode the current surface as a PNG and export it. @@ -703,11 +716,79 @@ public: #endif private: - cairo_t *mCairo; - nsRefPtr mSurface; - PRInt32 mFlags; -}; + friend class GeneralPattern; + typedef mozilla::gfx::Matrix Matrix; + typedef mozilla::gfx::DrawTarget DrawTarget; + typedef mozilla::gfx::Color Color; + typedef mozilla::gfx::StrokeOptions StrokeOptions; + typedef mozilla::gfx::Float Float; + typedef mozilla::gfx::Rect Rect; + typedef mozilla::gfx::CompositionOp CompositionOp; + typedef mozilla::gfx::Path Path; + typedef mozilla::gfx::PathBuilder PathBuilder; + typedef mozilla::gfx::SourceSurface SourceSurface; + + struct AzureState { + AzureState() + : op(mozilla::gfx::OP_OVER) + , opIsClear(false) + , color(0, 0, 0, 1.0f) + , clipWasReset(false) + , fillRule(mozilla::gfx::FILL_WINDING) + , aaMode(mozilla::gfx::AA_SUBPIXEL) + {} + + mozilla::gfx::CompositionOp op; + bool opIsClear; + Color color; + nsRefPtr pattern; + mozilla::RefPtr sourceSurface; + Matrix surfTransform; + Matrix transform; + struct PushedClip { + mozilla::RefPtr path; + Rect rect; + Matrix transform; + }; + nsTArray pushedClips; + nsTArray dashPattern; + bool clipWasReset; + mozilla::gfx::FillRule fillRule; + StrokeOptions strokeOptions; + mozilla::RefPtr drawTarget; + mozilla::RefPtr parentTarget; + mozilla::gfx::AntialiasMode aaMode; + }; + + // This ensures mPath contains a valid path (in user space!) + void EnsurePath(); + // This ensures mPathBuilder contains a valid PathBuilder (in user space!) + void EnsurePathBuilder(); + void FillAzure(mozilla::gfx::Float aOpacity); + void PushClipsToDT(mozilla::gfx::DrawTarget *aDT); + CompositionOp GetOp(); + + bool mPathIsRect; + bool mTransformChanged; + Matrix mPathTransform; + Rect mRect; + mozilla::RefPtr mPathBuilder; + mozilla::RefPtr mPath; + Matrix mTransform; + nsTArray mStateStack; + + AzureState &CurrentState() { return mStateStack[mStateStack.Length() - 1]; } + const AzureState &CurrentState() const { return mStateStack[mStateStack.Length() - 1]; } + + cairo_t *mCairo; + cairo_t *mRefCairo; + nsRefPtr mSurface; + PRInt32 mFlags; + + mozilla::RefPtr mDT; + mozilla::RefPtr mOriginalDT; +}; /** * Sentry helper class for functions with multiple return points that need to @@ -844,6 +925,9 @@ public: { if (aDisable) { mSurface = aContext->CurrentSurface(); + if (!mSurface) { + return; + } mSubpixelAntialiasingEnabled = mSurface->GetSubpixelAntialiasingEnabled(); mSurface->SetSubpixelAntialiasingEnabled(false); } diff --git a/gfx/thebes/gfxDrawable.cpp b/gfx/thebes/gfxDrawable.cpp index ea9bf29dd1b1..6812d672e607 100644 --- a/gfx/thebes/gfxDrawable.cpp +++ b/gfx/thebes/gfxDrawable.cpp @@ -72,6 +72,13 @@ PreparePatternForUntiledDrawing(gfxPattern* aPattern, gfxASurface *currentTarget, const gfxPattern::GraphicsFilter aDefaultFilter) { + if (!currentTarget) { + // This happens if we're dealing with an Azure target. + aPattern->SetExtend(gfxPattern::EXTEND_PAD); + aPattern->SetFilter(aDefaultFilter); + return; + } + // In theory we can handle this using cairo's EXTEND_PAD, // but implementation limitations mean we have to consult // the surface type. diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index 5342e602cd24..5ee46b115c0a 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -76,7 +76,10 @@ #include "nsCRT.h" +#include + using namespace mozilla; +using namespace mozilla::gfx; gfxFontCache *gfxFontCache::gGlobalCache = nsnull; @@ -1149,6 +1152,45 @@ struct GlyphBuffer { #undef GLYPH_BUFFER_SIZE }; +struct GlyphBufferAzure { +#define GLYPH_BUFFER_SIZE (2048/sizeof(Glyph)) + Glyph mGlyphBuffer[GLYPH_BUFFER_SIZE]; + unsigned int mNumGlyphs; + + GlyphBufferAzure() + : mNumGlyphs(0) { } + + Glyph *AppendGlyph() { + return &mGlyphBuffer[mNumGlyphs++]; + } + + void Flush(DrawTarget *aDT, Pattern &aPattern, ScaledFont *aFont, + bool aDrawToPath, bool aReverse, bool aFinish = false) + { + // Ensure there's enough room for a glyph to be added to the buffer + if (!aFinish && mNumGlyphs < GLYPH_BUFFER_SIZE || !mNumGlyphs) { + return; + } + + if (aReverse) { + Glyph *begin = &mGlyphBuffer[0]; + Glyph *end = &mGlyphBuffer[mNumGlyphs]; + std::reverse(begin, end); + } + + NS_ASSERTION(!aDrawToPath, "Not supported yet."); + + gfx::GlyphBuffer buf; + buf.mGlyphs = mGlyphBuffer; + buf.mNumGlyphs = mNumGlyphs; + + aDT->FillGlyphs(aFont, buf, aPattern); + + mNumGlyphs = 0; + } +#undef GLYPH_BUFFER_SIZE +}; + // Bug 674909. When synthetic bolding text by drawing twice, need to // render using a pixel offset in device pixels, otherwise text // doesn't appear bolded, it appears as if a bad text shadow exists @@ -1206,137 +1248,308 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd, double x = aPt->x; double y = aPt->y; - bool success = SetupCairoFont(aContext); - if (NS_UNLIKELY(!success)) - return; - - GlyphBuffer glyphs; - cairo_glyph_t *glyph; cairo_t *cr = aContext->GetCairo(); + RefPtr dt = aContext->GetDrawTarget(); - if (aSpacing) { - x += direction*aSpacing[0].mBefore; - } - for (i = aStart; i < aEnd; ++i) { - const gfxTextRun::CompressedGlyph *glyphData = &charGlyphs[i]; - if (glyphData->IsSimpleGlyph()) { - glyph = glyphs.AppendGlyph(); - glyph->index = glyphData->GetSimpleGlyph(); - double advance = glyphData->GetSimpleAdvance(); - // Perhaps we should put a scale in the cairo context instead of - // doing this scaling here... - // Multiplying by the reciprocal may introduce tiny error here, - // but we assume cairo is going to round coordinates at some stage - // and this is faster - double glyphX; - if (isRTL) { - x -= advance; - glyphX = x; - } else { - glyphX = x; - x += advance; - } - glyph->x = ToDeviceUnits(glyphX, devUnitsPerAppUnit); - glyph->y = ToDeviceUnits(y, devUnitsPerAppUnit); - glyphs.Flush(cr, aDrawToPath, isRTL); + RefPtr scaledFont; + + gfxRGBA color; + ColorPattern colPat(Color(0, 0, 0, 0)); + + if (aContext->IsCairo()) { + bool success = SetupCairoFont(aContext); + if (NS_UNLIKELY(!success)) + return; + + ::GlyphBuffer glyphs; + cairo_glyph_t *glyph; + + if (aSpacing) { + x += direction*aSpacing[0].mBefore; + } + for (i = aStart; i < aEnd; ++i) { + const gfxTextRun::CompressedGlyph *glyphData = &charGlyphs[i]; + if (glyphData->IsSimpleGlyph()) { + glyph = glyphs.AppendGlyph(); + glyph->index = glyphData->GetSimpleGlyph(); + double advance = glyphData->GetSimpleAdvance(); + // Perhaps we should put a scale in the cairo context instead of + // doing this scaling here... + // Multiplying by the reciprocal may introduce tiny error here, + // but we assume cairo is going to round coordinates at some stage + // and this is faster + double glyphX; + if (isRTL) { + x -= advance; + glyphX = x; + } else { + glyphX = x; + x += advance; + } + glyph->x = ToDeviceUnits(glyphX, devUnitsPerAppUnit); + glyph->y = ToDeviceUnits(y, devUnitsPerAppUnit); + glyphs.Flush(cr, aDrawToPath, isRTL); - // synthetic bolding by multi-striking with 1-pixel offsets - // at least once, more if there's room (large font sizes) - if (IsSyntheticBold()) { - double strikeOffset = synBoldOnePixelOffset; - PRInt32 strikeCount = strikes; - do { - cairo_glyph_t *doubleglyph; - doubleglyph = glyphs.AppendGlyph(); - doubleglyph->index = glyph->index; - doubleglyph->x = - ToDeviceUnits(glyphX + strikeOffset * appUnitsPerDevUnit, - devUnitsPerAppUnit); - doubleglyph->y = glyph->y; - strikeOffset += synBoldOnePixelOffset; - glyphs.Flush(cr, aDrawToPath, isRTL); - } while (--strikeCount > 0); - } - } else { - PRUint32 glyphCount = glyphData->GetGlyphCount(); - if (glyphCount > 0) { - const gfxTextRun::DetailedGlyph *details = - aTextRun->GetDetailedGlyphs(i); - NS_ASSERTION(details, "detailedGlyph should not be missing!"); - for (PRUint32 j = 0; j < glyphCount; ++j, ++details) { - double advance = details->mAdvance; - if (glyphData->IsMissing()) { - // default ignorable characters will have zero advance width. - // we don't have to draw the hexbox for them - if (!aDrawToPath && advance > 0) { - double glyphX = x; - if (isRTL) { - glyphX -= advance; - } - gfxPoint pt(ToDeviceUnits(glyphX, devUnitsPerAppUnit), - ToDeviceUnits(y, devUnitsPerAppUnit)); - gfxFloat advanceDevUnits = ToDeviceUnits(advance, devUnitsPerAppUnit); - gfxFloat height = GetMetrics().maxAscent; - gfxRect glyphRect(pt.x, pt.y - height, advanceDevUnits, height); - gfxFontMissingGlyphs::DrawMissingGlyph(aContext, - glyphRect, - details->mGlyphID); - } - } else { - glyph = glyphs.AppendGlyph(); - glyph->index = details->mGlyphID; - double glyphX = x + details->mXOffset; - if (isRTL) { - glyphX -= advance; - } - glyph->x = ToDeviceUnits(glyphX, devUnitsPerAppUnit); - glyph->y = ToDeviceUnits(y + details->mYOffset, devUnitsPerAppUnit); - glyphs.Flush(cr, aDrawToPath, isRTL); + // synthetic bolding by multi-striking with 1-pixel offsets + // at least once, more if there's room (large font sizes) + if (IsSyntheticBold()) { + double strikeOffset = synBoldOnePixelOffset; + PRInt32 strikeCount = strikes; + do { + cairo_glyph_t *doubleglyph; + doubleglyph = glyphs.AppendGlyph(); + doubleglyph->index = glyph->index; + doubleglyph->x = + ToDeviceUnits(glyphX + strikeOffset * appUnitsPerDevUnit, + devUnitsPerAppUnit); + doubleglyph->y = glyph->y; + strikeOffset += synBoldOnePixelOffset; + glyphs.Flush(cr, aDrawToPath, isRTL); + } while (--strikeCount > 0); + } + } else { + PRUint32 glyphCount = glyphData->GetGlyphCount(); + if (glyphCount > 0) { + const gfxTextRun::DetailedGlyph *details = + aTextRun->GetDetailedGlyphs(i); + NS_ASSERTION(details, "detailedGlyph should not be missing!"); + for (PRUint32 j = 0; j < glyphCount; ++j, ++details) { + double advance = details->mAdvance; + if (glyphData->IsMissing()) { + // default ignorable characters will have zero advance width. + // we don't have to draw the hexbox for them + if (!aDrawToPath && advance > 0) { + double glyphX = x; + if (isRTL) { + glyphX -= advance; + } + gfxPoint pt(ToDeviceUnits(glyphX, devUnitsPerAppUnit), + ToDeviceUnits(y, devUnitsPerAppUnit)); + gfxFloat advanceDevUnits = ToDeviceUnits(advance, devUnitsPerAppUnit); + gfxFloat height = GetMetrics().maxAscent; + gfxRect glyphRect(pt.x, pt.y - height, advanceDevUnits, height); + gfxFontMissingGlyphs::DrawMissingGlyph(aContext, + glyphRect, + details->mGlyphID); + } + } else { + glyph = glyphs.AppendGlyph(); + glyph->index = details->mGlyphID; + double glyphX = x + details->mXOffset; + if (isRTL) { + glyphX -= advance; + } + glyph->x = ToDeviceUnits(glyphX, devUnitsPerAppUnit); + glyph->y = ToDeviceUnits(y + details->mYOffset, devUnitsPerAppUnit); + glyphs.Flush(cr, aDrawToPath, isRTL); - if (IsSyntheticBold()) { - double strikeOffset = synBoldOnePixelOffset; - PRInt32 strikeCount = strikes; - do { - cairo_glyph_t *doubleglyph; - doubleglyph = glyphs.AppendGlyph(); - doubleglyph->index = glyph->index; - doubleglyph->x = - ToDeviceUnits(glyphX + strikeOffset * - appUnitsPerDevUnit, - devUnitsPerAppUnit); - doubleglyph->y = glyph->y; - strikeOffset += synBoldOnePixelOffset; - glyphs.Flush(cr, aDrawToPath, isRTL); - } while (--strikeCount > 0); - } - } - x += direction*advance; - } - } + if (IsSyntheticBold()) { + double strikeOffset = synBoldOnePixelOffset; + PRInt32 strikeCount = strikes; + do { + cairo_glyph_t *doubleglyph; + doubleglyph = glyphs.AppendGlyph(); + doubleglyph->index = glyph->index; + doubleglyph->x = + ToDeviceUnits(glyphX + strikeOffset * + appUnitsPerDevUnit, + devUnitsPerAppUnit); + doubleglyph->y = glyph->y; + strikeOffset += synBoldOnePixelOffset; + glyphs.Flush(cr, aDrawToPath, isRTL); + } while (--strikeCount > 0); + } + } + x += direction*advance; + } + } + } + + if (aSpacing) { + double space = aSpacing[i - aStart].mAfter; + if (i + 1 < aEnd) { + space += aSpacing[i + 1 - aStart].mBefore; + } + x += direction*space; + } + } + + if (gfxFontTestStore::CurrentStore()) { + /* This assumes that the tests won't have anything that results + * in more than GLYPH_BUFFER_SIZE glyphs. Do this before we + * flush, since that'll blow away the num_glyphs. + */ + gfxFontTestStore::CurrentStore()->AddItem(GetName(), + glyphs.mGlyphBuffer, + glyphs.mNumGlyphs); + } + + // draw any remaining glyphs + glyphs.Flush(cr, aDrawToPath, isRTL, true); + + } else { + if (aDrawToPath) { + // This should never be reached with azure! + NS_ERROR("Attempt at drawing to a Path to an Azure gfxContext."); + return; + } + + scaledFont = + gfxPlatform::GetPlatform()->GetScaledFontForFont(this); + + if (!scaledFont || !aContext->GetDeviceColor(color)) { + return; + } + + colPat.mColor = ToColor(color); + + GlyphBufferAzure glyphs; + Glyph *glyph; + + Matrix mat, matInv; + Matrix oldMat = dt->GetTransform(); + + if (mScaledFont) { + cairo_matrix_t matrix; + cairo_scaled_font_get_font_matrix(mScaledFont, &matrix); + if (matrix.xy != 0) { + // If this matrix applies a skew, which can happen when drawing + // oblique fonts, we will set the DrawTarget matrix to apply the + // skew. We'll need to move the glyphs by the inverse of the skew to + // get the glyphs positioned correctly in the new device space + // though, since the font matrix should only be applied to drawing + // the glyphs, and not to their position. + mat = ToMatrix(*reinterpret_cast(&matrix)); + + mat._11 = mat._22 = 1.0; + mat._21 /= mAdjustedSize; + + dt->SetTransform(mat * oldMat); + + matInv = mat; + matInv.Invert(); } + } - if (aSpacing) { - double space = aSpacing[i - aStart].mAfter; - if (i + 1 < aEnd) { - space += aSpacing[i + 1 - aStart].mBefore; - } - x += direction*space; - } + if (aSpacing) { + x += direction*aSpacing[0].mBefore; + } + for (i = aStart; i < aEnd; ++i) { + const gfxTextRun::CompressedGlyph *glyphData = &charGlyphs[i]; + if (glyphData->IsSimpleGlyph()) { + glyph = glyphs.AppendGlyph(); + glyph->mIndex = glyphData->GetSimpleGlyph(); + double advance = glyphData->GetSimpleAdvance(); + // Perhaps we should put a scale in the cairo context instead of + // doing this scaling here... + // Multiplying by the reciprocal may introduce tiny error here, + // but we assume cairo is going to round coordinates at some stage + // and this is faster + double glyphX; + if (isRTL) { + x -= advance; + glyphX = x; + } else { + glyphX = x; + x += advance; + } + glyph->mPosition.x = ToDeviceUnits(glyphX, devUnitsPerAppUnit); + glyph->mPosition.y = ToDeviceUnits(y, devUnitsPerAppUnit); + glyph->mPosition = matInv * glyph->mPosition; + glyphs.Flush(dt, colPat, scaledFont, aDrawToPath, isRTL); + + // synthetic bolding by multi-striking with 1-pixel offsets + // at least once, more if there's room (large font sizes) + if (IsSyntheticBold()) { + double strikeOffset = synBoldOnePixelOffset; + PRInt32 strikeCount = strikes; + do { + Glyph *doubleglyph; + doubleglyph = glyphs.AppendGlyph(); + doubleglyph->mIndex = glyph->mIndex; + doubleglyph->mPosition.x = + ToDeviceUnits(glyphX + strikeOffset * appUnitsPerDevUnit, + devUnitsPerAppUnit); + doubleglyph->mPosition.y = glyph->mPosition.y; + doubleglyph->mPosition = matInv * doubleglyph->mPosition; + strikeOffset += synBoldOnePixelOffset; + glyphs.Flush(dt, colPat, scaledFont, aDrawToPath, isRTL); + } while (--strikeCount > 0); + } + } else { + PRUint32 glyphCount = glyphData->GetGlyphCount(); + if (glyphCount > 0) { + const gfxTextRun::DetailedGlyph *details = + aTextRun->GetDetailedGlyphs(i); + NS_ASSERTION(details, "detailedGlyph should not be missing!"); + for (PRUint32 j = 0; j < glyphCount; ++j, ++details) { + double advance = details->mAdvance; + if (glyphData->IsMissing()) { + // default ignorable characters will have zero advance width. + // we don't have to draw the hexbox for them + if (!aDrawToPath && advance > 0) { + double glyphX = x; + if (isRTL) { + glyphX -= advance; + } + gfxPoint pt(ToDeviceUnits(glyphX, devUnitsPerAppUnit), + ToDeviceUnits(y, devUnitsPerAppUnit)); + gfxFloat advanceDevUnits = ToDeviceUnits(advance, devUnitsPerAppUnit); + gfxFloat height = GetMetrics().maxAscent; + gfxRect glyphRect(pt.x, pt.y - height, advanceDevUnits, height); + gfxFontMissingGlyphs::DrawMissingGlyph(aContext, + glyphRect, + details->mGlyphID); + } + } else { + glyph = glyphs.AppendGlyph(); + glyph->mIndex = details->mGlyphID; + double glyphX = x + details->mXOffset; + if (isRTL) { + glyphX -= advance; + } + glyph->mPosition.x = ToDeviceUnits(glyphX, devUnitsPerAppUnit); + glyph->mPosition.y = ToDeviceUnits(y + details->mYOffset, devUnitsPerAppUnit); + glyph->mPosition = matInv * glyph->mPosition; + glyphs.Flush(dt, colPat, scaledFont, aDrawToPath, isRTL); + + if (IsSyntheticBold()) { + double strikeOffset = synBoldOnePixelOffset; + PRInt32 strikeCount = strikes; + do { + Glyph *doubleglyph; + doubleglyph = glyphs.AppendGlyph(); + doubleglyph->mIndex = glyph->mIndex; + doubleglyph->mPosition.x = + ToDeviceUnits(glyphX + strikeOffset * + appUnitsPerDevUnit, + devUnitsPerAppUnit); + doubleglyph->mPosition.y = glyph->mPosition.y; + strikeOffset += synBoldOnePixelOffset; + doubleglyph->mPosition = matInv * doubleglyph->mPosition; + glyphs.Flush(dt, colPat, scaledFont, aDrawToPath, isRTL); + } while (--strikeCount > 0); + } + } + x += direction*advance; + } + } + } + + if (aSpacing) { + double space = aSpacing[i - aStart].mAfter; + if (i + 1 < aEnd) { + space += aSpacing[i + 1 - aStart].mBefore; + } + x += direction*space; + } + } + + glyphs.Flush(dt, colPat, scaledFont, aDrawToPath, isRTL, true); + + dt->SetTransform(oldMat); } - if (gfxFontTestStore::CurrentStore()) { - /* This assumes that the tests won't have anything that results - * in more than GLYPH_BUFFER_SIZE glyphs. Do this before we - * flush, since that'll blow away the num_glyphs. - */ - gfxFontTestStore::CurrentStore()->AddItem(GetName(), - glyphs.mGlyphBuffer, - glyphs.mNumGlyphs); - } - - // draw any remaining glyphs - glyphs.Flush(cr, aDrawToPath, isRTL, true); - *aPt = gfxPoint(x, y); } diff --git a/gfx/thebes/gfxPattern.cpp b/gfx/thebes/gfxPattern.cpp index da0d1ea32b39..4320584a1b13 100644 --- a/gfx/thebes/gfxPattern.cpp +++ b/gfx/thebes/gfxPattern.cpp @@ -42,24 +42,32 @@ #include "cairo.h" +#include + +using namespace mozilla::gfx; + gfxPattern::gfxPattern(cairo_pattern_t *aPattern) + : mGfxPattern(NULL) { mPattern = cairo_pattern_reference(aPattern); } gfxPattern::gfxPattern(const gfxRGBA& aColor) + : mGfxPattern(NULL) { mPattern = cairo_pattern_create_rgba(aColor.r, aColor.g, aColor.b, aColor.a); } // from another surface gfxPattern::gfxPattern(gfxASurface *surface) + : mGfxPattern(NULL) { mPattern = cairo_pattern_create_for_surface(surface->CairoSurface()); } // linear gfxPattern::gfxPattern(gfxFloat x0, gfxFloat y0, gfxFloat x1, gfxFloat y1) + : mGfxPattern(NULL) { mPattern = cairo_pattern_create_linear(x0, y0, x1, y1); } @@ -67,14 +75,28 @@ gfxPattern::gfxPattern(gfxFloat x0, gfxFloat y0, gfxFloat x1, gfxFloat y1) // radial gfxPattern::gfxPattern(gfxFloat cx0, gfxFloat cy0, gfxFloat radius0, gfxFloat cx1, gfxFloat cy1, gfxFloat radius1) + : mGfxPattern(NULL) { mPattern = cairo_pattern_create_radial(cx0, cy0, radius0, cx1, cy1, radius1); } +// Azure +gfxPattern::gfxPattern(SourceSurface *aSurface, const Matrix &aTransform) + : mPattern(NULL) + , mGfxPattern(NULL) + , mSourceSurface(aSurface) + , mTransform(aTransform) +{ +} + gfxPattern::~gfxPattern() { cairo_pattern_destroy(mPattern); + + if (mGfxPattern) { + mGfxPattern->~Pattern(); + } } cairo_pattern_t * @@ -86,6 +108,8 @@ gfxPattern::CairoPattern() void gfxPattern::AddColorStop(gfxFloat offset, const gfxRGBA& c) { + if (mPattern) { + mStops = NULL; if (gfxPlatform::GetCMSMode() == eCMSMode_All) { gfxRGBA cms; gfxPlatform::TransformPixel(c, cms, gfxPlatform::GetCMSRGBTransform()); @@ -97,26 +121,159 @@ gfxPattern::AddColorStop(gfxFloat offset, const gfxRGBA& c) } else cairo_pattern_add_color_stop_rgba(mPattern, offset, c.r, c.g, c.b, c.a); + } } void gfxPattern::SetMatrix(const gfxMatrix& matrix) { + if (mPattern) { cairo_matrix_t mat = *reinterpret_cast(&matrix); cairo_pattern_set_matrix(mPattern, &mat); + } else { + mTransform = ToMatrix(matrix); + } } gfxMatrix gfxPattern::GetMatrix() const { + if (mPattern) { cairo_matrix_t mat; cairo_pattern_get_matrix(mPattern, &mat); return gfxMatrix(*reinterpret_cast(&mat)); + } else { + return ThebesMatrix(mTransform); + } +} + +Pattern* +gfxPattern::GetPattern(mozilla::gfx::DrawTarget *aTarget) +{ + if (!mPattern) { + mGfxPattern = new (mSurfacePattern.addr()) + SurfacePattern(mSourceSurface, EXTEND_CLAMP, mTransform); + return mGfxPattern; + } + + GraphicsExtend extend = (GraphicsExtend)cairo_pattern_get_extend(mPattern); + + switch (cairo_pattern_get_type(mPattern)) { + case CAIRO_PATTERN_TYPE_SURFACE: + { + GraphicsFilter filter = (GraphicsFilter)cairo_pattern_get_filter(mPattern); + cairo_matrix_t mat; + cairo_pattern_get_matrix(mPattern, &mat); + gfxMatrix matrix(*reinterpret_cast(&mat)); + + cairo_surface_t *surf = NULL; + cairo_pattern_get_surface(mPattern, &surf); + + if (!mSourceSurface) { + nsRefPtr gfxSurf = gfxASurface::Wrap(surf); + mSourceSurface = + gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(aTarget, gfxSurf); + } + + if (mSourceSurface) { + Matrix newMat = ToMatrix(matrix); + newMat.Invert(); + double x, y; + cairo_surface_get_device_offset(surf, &x, &y); + newMat.Translate(-x, -y); + mGfxPattern = new (mSurfacePattern.addr()) + SurfacePattern(mSourceSurface, ToExtendMode(extend), newMat, ToFilter(filter)); + return mGfxPattern; + } + break; + } + case CAIRO_PATTERN_TYPE_LINEAR: + { + double x1, y1, x2, y2; + cairo_pattern_get_linear_points(mPattern, &x1, &y1, &x2, &y2); + if (!mStops) { + int count = 0; + cairo_pattern_get_color_stop_count(mPattern, &count); + + std::vector stops; + + for (int i = 0; i < count; i++) { + GradientStop stop; + double r, g, b, a, offset; + cairo_pattern_get_color_stop_rgba(mPattern, i, &offset, &r, &g, &b, &a); + + stop.offset = offset; + stop.color = Color(Float(r), Float(g), Float(b), Float(a)); + stops.push_back(stop); + } + + mStops = aTarget->CreateGradientStops(&stops.front(), count, ToExtendMode(extend)); + } + + if (mStops) { + cairo_matrix_t mat; + cairo_pattern_get_matrix(mPattern, &mat); + gfxMatrix matrix(*reinterpret_cast(&mat)); + + Matrix newMat = ToMatrix(matrix); + newMat.Invert(); + + mGfxPattern = new (mLinearGradientPattern.addr()) + LinearGradientPattern(Point(x1, y1), Point(x2, y2), mStops, newMat); + + return mGfxPattern; + } + break; + } + case CAIRO_PATTERN_TYPE_RADIAL: + { + if (!mStops) { + int count = 0; + cairo_pattern_get_color_stop_count(mPattern, &count); + + std::vector stops; + + for (int i = 0; i < count; i++) { + GradientStop stop; + double r, g, b, a, offset; + cairo_pattern_get_color_stop_rgba(mPattern, i, &offset, &r, &g, &b, &a); + + stop.offset = offset; + stop.color = Color(Float(r), Float(g), Float(b), Float(a)); + stops.push_back(stop); + } + + mStops = aTarget->CreateGradientStops(&stops.front(), count, ToExtendMode(extend)); + } + + if (mStops) { + cairo_matrix_t mat; + cairo_pattern_get_matrix(mPattern, &mat); + gfxMatrix matrix(*reinterpret_cast(&mat)); + + Matrix newMat = ToMatrix(matrix); + newMat.Invert(); + + double x1, y1, x2, y2, r1, r2; + cairo_pattern_get_radial_circles(mPattern, &x1, &y1, &r1, &x2, &y2, &r2); + mGfxPattern = new (mRadialGradientPattern.addr()) + RadialGradientPattern(Point(x1, y1), Point(x2, y2), r1, r2, mStops, newMat); + + return mGfxPattern; + } + break; + } + } + + new (mColorPattern.addr()) ColorPattern(Color(0, 0, 0, 0)); + return mColorPattern.addr(); } void gfxPattern::SetExtend(GraphicsExtend extend) { + if (mPattern) { + mStops = NULL; if (extend == EXTEND_PAD_EDGE) { if (cairo_pattern_get_type(mPattern) == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_t *surf = NULL; @@ -144,24 +301,66 @@ gfxPattern::SetExtend(GraphicsExtend extend) } cairo_pattern_set_extend(mPattern, (cairo_extend_t)extend); + } else { + // This is always a surface pattern and will default to EXTEND_PAD + // for EXTEND_PAD_EDGE. + mExtend = ToExtendMode(extend); + } +} + +bool +gfxPattern::IsOpaque() +{ + if (mPattern) { + switch (cairo_pattern_get_type(mPattern)) { + case CAIRO_PATTERN_TYPE_SURFACE: + { + cairo_surface_t *surf = NULL; + cairo_pattern_get_surface(mPattern, &surf); + + if (cairo_surface_get_content(surf) == CAIRO_CONTENT_COLOR) { + return true; + } + } + } + + return false; + } + + if (mSourceSurface->GetFormat() == FORMAT_B8G8R8X8) { + return true; + } + return false; } gfxPattern::GraphicsExtend gfxPattern::Extend() const { + if (mPattern) { return (GraphicsExtend)cairo_pattern_get_extend(mPattern); + } else { + return ThebesExtend(mExtend); + } } void gfxPattern::SetFilter(GraphicsFilter filter) { + if (mPattern) { cairo_pattern_set_filter(mPattern, (cairo_filter_t)filter); + } else { + mFilter = ToFilter(filter); + } } gfxPattern::GraphicsFilter gfxPattern::Filter() const { + if (mPattern) { return (GraphicsFilter)cairo_pattern_get_filter(mPattern); + } else { + return ThebesFilter(mFilter); + } } bool @@ -177,22 +376,39 @@ gfxPattern::GetSolidColor(gfxRGBA& aColor) already_AddRefed gfxPattern::GetSurface() { + if (mPattern) { cairo_surface_t *surf = nsnull; if (cairo_pattern_get_surface (mPattern, &surf) != CAIRO_STATUS_SUCCESS) return nsnull; return gfxASurface::Wrap(surf); + } else { + // We should never be trying to get the surface off an Azure gfx Pattern. + NS_ERROR("Attempt to get surface off an Azure gfxPattern!"); + return NULL; + } } gfxPattern::GraphicsPatternType gfxPattern::GetType() const { + if (mPattern) { return (GraphicsPatternType) cairo_pattern_get_type(mPattern); + } else { + // We should never be trying to get the type off an Azure gfx Pattern. + MOZ_ASSERT(0); + return PATTERN_SURFACE; + } } int gfxPattern::CairoStatus() { + if (mPattern) { return cairo_pattern_status(mPattern); + } else { + // An Azure pattern as this point is never in error status. + return CAIRO_STATUS_SUCCESS; + } } diff --git a/gfx/thebes/gfxPattern.h b/gfx/thebes/gfxPattern.h index 95d088cdf8b2..1d4aae573273 100644 --- a/gfx/thebes/gfxPattern.h +++ b/gfx/thebes/gfxPattern.h @@ -44,6 +44,8 @@ #include "gfxMatrix.h" #include "nsISupportsImpl.h" #include "nsAutoPtr.h" +#include "mozilla/gfx/2D.h" +#include "mozilla/Util.h" class gfxContext; class gfxASurface; @@ -61,6 +63,8 @@ public: gfxPattern(gfxFloat x0, gfxFloat y0, gfxFloat x1, gfxFloat y1); // linear gfxPattern(gfxFloat cx0, gfxFloat cy0, gfxFloat radius0, gfxFloat cx1, gfxFloat cy1, gfxFloat radius1); // radial + gfxPattern(mozilla::gfx::SourceSurface *aSurface, + const mozilla::gfx::Matrix &aTransform); // Azure virtual ~gfxPattern(); cairo_pattern_t *CairoPattern(); @@ -69,6 +73,9 @@ public: void SetMatrix(const gfxMatrix& matrix); gfxMatrix GetMatrix() const; + mozilla::gfx::Pattern *GetPattern(mozilla::gfx::DrawTarget *aTarget); + bool IsOpaque(); + enum GraphicsExtend { EXTEND_NONE, EXTEND_REPEAT, @@ -120,6 +127,21 @@ public: protected: cairo_pattern_t *mPattern; + + union { + mozilla::AlignedStorage2 mColorPattern; + mozilla::AlignedStorage2 mLinearGradientPattern; + mozilla::AlignedStorage2 mRadialGradientPattern; + mozilla::AlignedStorage2 mSurfacePattern; + }; + + mozilla::gfx::Pattern *mGfxPattern; + + mozilla::RefPtr mSourceSurface; + mozilla::gfx::Matrix mTransform; + mozilla::RefPtr mStops; + mozilla::gfx::ExtendMode mExtend; + mozilla::gfx::Filter mFilter; }; #endif /* GFX_PATTERN_H */ diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 2f286ac3b4b3..799807a2cad5 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -976,6 +976,21 @@ gfxPlatform::AppendPrefLang(eFontPrefLang aPrefLangs[], PRUint32& aLen, eFontPre } } +bool +gfxPlatform::UseAzureContentDrawing() +{ + static bool sAzureContentDrawingEnabled; + static bool sAzureContentDrawingPrefCached = false; + + if (!sAzureContentDrawingPrefCached) { + sAzureContentDrawingPrefCached = true; + mozilla::Preferences::AddBoolVarCache(&sAzureContentDrawingEnabled, + "gfx.content.azure.enabled"); + } + + return sAzureContentDrawingEnabled; +} + eCMSMode gfxPlatform::GetCMSMode() { diff --git a/gfx/thebes/gfxPlatform.h b/gfx/thebes/gfxPlatform.h index bb7bb9445b34..2e0e942088f1 100644 --- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -356,6 +356,9 @@ public: // helper method to add a pref lang to an array, if not already in array static void AppendPrefLang(eFontPrefLang aPrefLangs[], PRUint32& aLen, eFontPrefLang aAddLang); + + // helper method to indicate if we want to use Azure content drawing + static bool UseAzureContentDrawing(); /** * Are we going to try color management? diff --git a/gfx/thebes/gfxUserFontSet.cpp b/gfx/thebes/gfxUserFontSet.cpp index ddc70573823b..13563eb1f97d 100644 --- a/gfx/thebes/gfxUserFontSet.cpp +++ b/gfx/thebes/gfxUserFontSet.cpp @@ -74,7 +74,8 @@ gfxProxyFontEntry::gfxProxyFontEntry(const nsTArray& aFontFaceSr PRUint32 aLanguageOverride, gfxSparseBitSet *aUnicodeRanges) : gfxFontEntry(NS_LITERAL_STRING("Proxy"), aFamily), - mLoadingState(NOT_LOADING) + mLoadingState(NOT_LOADING), + mUnsupportedFormat(false) { mIsProxy = true; mSrcList = aFontFaceSrcList; @@ -605,6 +606,7 @@ gfxUserFontSet::LoadNext(gfxProxyFontEntry *aProxyEntry) if (aProxyEntry->mLoadingState == gfxProxyFontEntry::NOT_LOADING) { aProxyEntry->mLoadingState = gfxProxyFontEntry::LOADING_STARTED; + aProxyEntry->mUnsupportedFormat = false; } else { // we were already loading; move to the next source, // but don't reset state - if we've already timed out, @@ -664,14 +666,20 @@ gfxUserFontSet::LoadNext(gfxProxyFontEntry *aProxyEntry) nsIScriptError::errorFlag, rv); } } else { - LogMessage(aProxyEntry, "format not supported", - nsIScriptError::warningFlag); + // We don't log a warning to the web console yet, + // as another source may load successfully + aProxyEntry->mUnsupportedFormat = true; } } aProxyEntry->mSrcIndex++; } + if (aProxyEntry->mUnsupportedFormat) { + LogMessage(aProxyEntry, "no supported format found", + nsIScriptError::warningFlag); + } + // all src's failed; mark this entry as unusable (so fallback will occur) LOG(("userfonts (%p) failed all src for (%s)\n", this, NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get())); diff --git a/gfx/thebes/gfxUserFontSet.h b/gfx/thebes/gfxUserFontSet.h index 100a0a297dc8..7b549bc1c95c 100644 --- a/gfx/thebes/gfxUserFontSet.h +++ b/gfx/thebes/gfxUserFontSet.h @@ -297,6 +297,7 @@ public: LOADING_FAILED // failed to load any source: use fallback }; LoadingState mLoadingState; + bool mUnsupportedFormat; nsTArray mSrcList; PRUint32 mSrcIndex; // index of loading src item diff --git a/gfx/thebes/gfxUtils.cpp b/gfx/thebes/gfxUtils.cpp index ac1073839d23..621126d67fa5 100644 --- a/gfx/thebes/gfxUtils.cpp +++ b/gfx/thebes/gfxUtils.cpp @@ -297,11 +297,11 @@ struct NS_STACK_CLASS AutoCairoPixmanBugWorkaround AutoCairoPixmanBugWorkaround(gfxContext* aContext, const gfxMatrix& aDeviceSpaceToImageSpace, const gfxRect& aFill, - const gfxASurface::gfxSurfaceType& aSurfaceType) + const gfxASurface* aSurface) : mContext(aContext), mSucceeded(true), mPushedGroup(false) { // Quartz's limits for matrix are much larger than pixman - if (aSurfaceType == gfxASurface::SurfaceTypeQuartz) + if (!aSurface || aSurface->GetType() == gfxASurface::SurfaceTypeQuartz) return; if (!IsSafeImageTransformComponent(aDeviceSpaceToImageSpace.xx) || @@ -381,12 +381,11 @@ gfxUtils::DrawPixelSnapped(gfxContext* aContext, bool doTile = !aImageRect.Contains(aSourceRect); nsRefPtr currentTarget = aContext->CurrentSurface(); - gfxASurface::gfxSurfaceType surfaceType = currentTarget->GetType(); gfxMatrix deviceSpaceToImageSpace = DeviceToImageTransform(aContext, aUserSpaceToImageSpace); AutoCairoPixmanBugWorkaround workaround(aContext, deviceSpaceToImageSpace, - aFill, surfaceType); + aFill, currentTarget); if (!workaround.Succeeded()) return; diff --git a/gfx/thebes/gfxWindowsNativeDrawing.cpp b/gfx/thebes/gfxWindowsNativeDrawing.cpp index 7510ba191e9a..24943c92dc37 100644 --- a/gfx/thebes/gfxWindowsNativeDrawing.cpp +++ b/gfx/thebes/gfxWindowsNativeDrawing.cpp @@ -69,8 +69,13 @@ HDC gfxWindowsNativeDrawing::BeginNativeDrawing() { if (mRenderState == RENDER_STATE_INIT) { - nsRefPtr surf = mContext->CurrentSurface(&mDeviceOffset.x, &mDeviceOffset.y); - if (!surf || surf->CairoStatus()) + nsRefPtr surf; + + if (mContext->GetCairo()) { + surf = mContext->CurrentSurface(&mDeviceOffset.x, &mDeviceOffset.y); + } + + if (surf && surf->CairoStatus()) return nsnull; gfxMatrix m = mContext->CurrentMatrix(); @@ -84,11 +89,12 @@ gfxWindowsNativeDrawing::BeginNativeDrawing() // if this is a native win32 surface, we don't have to // redirect rendering to our own HDC; in some cases, // we may be able to use the HDC from the surface directly. - if ((surf->GetType() == gfxASurface::SurfaceTypeWin32 || - surf->GetType() == gfxASurface::SurfaceTypeWin32Printing) && - (surf->GetContentType() == gfxASurface::CONTENT_COLOR || - (surf->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA && - (mNativeDrawFlags & CAN_DRAW_TO_COLOR_ALPHA)))) + if (surf && + ((surf->GetType() == gfxASurface::SurfaceTypeWin32 || + surf->GetType() == gfxASurface::SurfaceTypeWin32Printing) && + (surf->GetContentType() == gfxASurface::CONTENT_COLOR || + (surf->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA && + (mNativeDrawFlags & CAN_DRAW_TO_COLOR_ALPHA))))) { // grab the DC. This can fail if there is a complex clipping path, // in which case we'll have to fall back. @@ -208,11 +214,15 @@ gfxWindowsNativeDrawing::BeginNativeDrawing() bool gfxWindowsNativeDrawing::IsDoublePass() { + if (!mContext->IsCairo()) { + return true; + } + nsRefPtr surf = mContext->CurrentSurface(&mDeviceOffset.x, &mDeviceOffset.y); if (!surf || surf->CairoStatus()) return false; if (surf->GetType() != gfxASurface::SurfaceTypeWin32 && - surf->GetType() != gfxASurface::SurfaceTypeWin32Printing) { + surf->GetType() != gfxASurface::SurfaceTypeWin32Printing) { return true; } if ((surf->GetContentType() != gfxASurface::CONTENT_COLOR || diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index dda5b04054ea..beb7b336978c 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -2583,7 +2583,8 @@ RasterImage::Draw(gfxContext *aContext, mFrameDecodeFlags = DECODE_FLAGS_DEFAULT; } - if (!mDecoded) { + // We use !mDecoded && mHasSourceData to mean discarded. + if (!mDecoded && mHasSourceData) { mDrawStartTime = TimeStamp::Now(); } @@ -2838,10 +2839,10 @@ imgDecodeWorker::Run() mDecodeTime += decodeLatency; // Flush invalidations _after_ we've written everything we're going to. - // Furthermore, if this is a redecode, we don't want to do progressive + // Furthermore, if we have all of the data, we don't want to do progressive // display at all. In that case, let Decoder::PostFrameStop() do the // flush once the whole frame is ready. - if (!image->mHasBeenDecoded) { + if (!image->mHasSourceData) { image->mInDecoder = true; image->mDecoder->FlushInvalidations(); image->mInDecoder = false; diff --git a/ipc/chromium/src/base/dir_reader_posix.h b/ipc/chromium/src/base/dir_reader_posix.h index f591ae05783b..9a34492aaccd 100644 --- a/ipc/chromium/src/base/dir_reader_posix.h +++ b/ipc/chromium/src/base/dir_reader_posix.h @@ -18,7 +18,7 @@ // seems worse than falling back to enumerating all file descriptors so we will // probably never implement this on the Mac. -#if defined(OS_LINUX) +#if defined(OS_LINUX) && !defined(OS_OPENBSD) #include "base/dir_reader_linux.h" #else #include "base/dir_reader_fallback.h" @@ -26,7 +26,7 @@ namespace base { -#if defined(OS_LINUX) +#if defined(OS_LINUX) && !defined(OS_OPENBSD) typedef DirReaderLinux DirReaderPosix; #else typedef DirReaderFallback DirReaderPosix; diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index c355677f5712..b6dae76c4031 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -629,17 +629,23 @@ GetAvailableChunkList(JSCompartment *comp) inline void Chunk::addToAvailableList(JSCompartment *comp) { - Chunk **listHeadp = GetAvailableChunkList(comp); + insertToAvailableList(GetAvailableChunkList(comp)); +} + +inline void +Chunk::insertToAvailableList(Chunk **insertPoint) +{ + JS_ASSERT(hasAvailableArenas()); JS_ASSERT(!info.prevp); JS_ASSERT(!info.next); - info.prevp = listHeadp; - Chunk *head = *listHeadp; - if (head) { - JS_ASSERT(head->info.prevp == listHeadp); - head->info.prevp = &info.next; + info.prevp = insertPoint; + Chunk *insertBefore = *insertPoint; + if (insertBefore) { + JS_ASSERT(insertBefore->info.prevp == insertPoint); + insertBefore->info.prevp = &info.next; } - info.next = head; - *listHeadp = this; + info.next = insertBefore; + *insertPoint = this; } inline void @@ -2243,6 +2249,22 @@ DecommitArenasFromAvailableList(JSRuntime *rt, Chunk **availableListHeadp) * * We decommit from the tail of the list to minimize interference with the * main thread that may start to allocate things at this point. + * + * The arena that is been decommitted outside the GC lock must not be + * available for allocations either via the free list or via the + * decommittedArenas bitmap. For that we just fetch the arena from the + * free list before the decommit pretending as it was allocated. If this + * arena also is the single free arena in the chunk, then we must remove + * from the available list before we release the lock so the allocation + * thread would not see chunks with no free arenas on the available list. + * + * After we retake the lock, we mark the arena as free and decommitted if + * the decommit was successful. We must also add the chunk back to the + * available list if we removed it previously or when the main thread + * have allocated all remaining free arenas in the chunk. + * + * We also must make sure that the aheader is not accessed again after we + * decommit the arena. */ JS_ASSERT(chunk->info.prevp == availableListHeadp); while (Chunk *next = chunk->info.next) { @@ -2252,27 +2274,23 @@ DecommitArenasFromAvailableList(JSRuntime *rt, Chunk **availableListHeadp) for (;;) { while (chunk->info.numArenasFreeCommitted != 0) { - /* - * The arena that is been decommitted outside the GC lock must not - * be available for allocations either via the free list or via - * the decommittedArenas bitmap. For that we just fetch the arena - * from the free list before the decommit and then mark it as free - * and decommitted when we retake the GC lock. However, if this - * arena also is the single free arena in the chunk, then during - * the decommit the allocation thread may find the chunk as - * present on the available list yet having no arenas to allocate. - * To avoid complications in this case we decommit inside the lock. - * - * We also must make sure that the aheader is not accessed again - * after we decommit the arena. - */ ArenaHeader *aheader = chunk->fetchNextFreeArena(rt); + + Chunk **savedPrevp = chunk->info.prevp; + if (!chunk->hasAvailableArenas()) + chunk->removeFromAvailableList(); + size_t arenaIndex = Chunk::arenaIndex(aheader->arenaAddress()); bool ok; { - Maybe maybayUnlock; - if (chunk->hasAvailableArenas()) - maybayUnlock.construct(rt); + /* + * If the main thread waits for the decommit to finish, skip + * potentially expensive unlock/lock pair on the contested + * lock. + */ + Maybe maybeUnlock; + if (!rt->gcRunning) + maybeUnlock.construct(rt); ok = DecommitMemory(aheader->getArena(), ArenaSize); } @@ -2282,6 +2300,26 @@ DecommitArenasFromAvailableList(JSRuntime *rt, Chunk **availableListHeadp) } else { chunk->addArenaToFreeList(rt, aheader); } + JS_ASSERT(chunk->hasAvailableArenas()); + JS_ASSERT(!chunk->unused()); + if (chunk->info.numArenasFree == 1) { + /* + * Put the chunk back to the available list either at the + * point where it was before to preserve the available list + * that we enumerate, or, when the allocation thread has fully + * used all the previous chunks, at the beginning of the + * available list. + */ + Chunk **insertPoint = savedPrevp; + if (savedPrevp != availableListHeadp) { + Chunk *prev = Chunk::fromPointerToNext(savedPrevp); + if (!prev->hasAvailableArenas()) + insertPoint = availableListHeadp; + } + chunk->insertToAvailableList(insertPoint); + } else { + JS_ASSERT(chunk->info.prevp); + } if (rt->gcChunkAllocationSinceLastGC) { /* @@ -2293,8 +2331,8 @@ DecommitArenasFromAvailableList(JSRuntime *rt, Chunk **availableListHeadp) } /* - * prevp becomes null when the allocator thread consumed all chunks from - * the available list. + * chunk->info.prevp becomes null when the allocator thread consumed + * all chunks from the available list. */ JS_ASSERT_IF(chunk->info.prevp, *chunk->info.prevp == chunk); if (chunk->info.prevp == availableListHeadp || !chunk->info.prevp) diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 8b3fe9d0442a..f3b8e2f15219 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -739,6 +739,7 @@ struct Chunk { } inline void addToAvailableList(JSCompartment *compartment); + inline void insertToAvailableList(Chunk **insertPoint); inline void removeFromAvailableList(); ArenaHeader *allocateArena(JSCompartment *comp, AllocKind kind); @@ -760,9 +761,14 @@ struct Chunk { */ Chunk *getPrevious() { JS_ASSERT(info.prevp); - uintptr_t prevAddress = reinterpret_cast(info.prevp); - JS_ASSERT((prevAddress & ChunkMask) == offsetof(Chunk, info.next)); - return reinterpret_cast(prevAddress - offsetof(Chunk, info.next)); + return fromPointerToNext(info.prevp); + } + + /* Get the chunk from a pointer to its info.next field. */ + static Chunk *fromPointerToNext(Chunk **nextFieldPtr) { + uintptr_t addr = reinterpret_cast(nextFieldPtr); + JS_ASSERT((addr & ChunkMask) == offsetof(Chunk, info.next)); + return reinterpret_cast(addr - offsetof(Chunk, info.next)); } private: diff --git a/js/src/jsscopeinlines.h b/js/src/jsscopeinlines.h index 255a3a9c7bc6..c5a785a4f2cb 100644 --- a/js/src/jsscopeinlines.h +++ b/js/src/jsscopeinlines.h @@ -86,11 +86,11 @@ BaseShape::BaseShape(Class *clasp, JSObject *parent, uint32_t objectFlags, this->rawGetter = rawGetter; this->rawSetter = rawSetter; if ((attrs & JSPROP_GETTER) && rawGetter) { - flags |= HAS_GETTER_OBJECT; + this->flags |= HAS_GETTER_OBJECT; JSObject::writeBarrierPost(this->getterObj, &this->getterObj); } if ((attrs & JSPROP_SETTER) && rawSetter) { - flags |= HAS_SETTER_OBJECT; + this->flags |= HAS_SETTER_OBJECT; JSObject::writeBarrierPost(this->setterObj, &this->setterObj); } } @@ -104,6 +104,12 @@ BaseShape::BaseShape(const StackBaseShape &base) this->flags = base.flags; this->rawGetter = base.rawGetter; this->rawSetter = base.rawSetter; + if ((base.flags & HAS_GETTER_OBJECT) && base.rawGetter) { + JSObject::writeBarrierPost(this->getterObj, &this->getterObj); + } + if ((base.flags & HAS_SETTER_OBJECT) && base.rawSetter) { + JSObject::writeBarrierPost(this->setterObj, &this->setterObj); + } } inline bool diff --git a/js/xpconnect/idl/nsIXPCScriptable.idl b/js/xpconnect/idl/nsIXPCScriptable.idl index 6d623705c015..367f60506187 100644 --- a/js/xpconnect/idl/nsIXPCScriptable.idl +++ b/js/xpconnect/idl/nsIXPCScriptable.idl @@ -41,8 +41,6 @@ #include "nsISupports.idl" #include "nsIXPConnect.idl" -[ptr] native JSTracerPtr(JSTracer); - %{ C++ #define NS_SUCCESS_I_DID_SOMETHING \ (NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCONNECT,1)) @@ -73,7 +71,7 @@ * to *_retval unless they want to return PR_FALSE. */ -[uuid(a40ce52e-2d8c-400f-9af2-f8784a656070)] +[uuid(fca22e1e-a2bf-456e-83db-f73e8de0f7c5)] interface nsIXPCScriptable : nsISupports { /* bitflags used for 'flags' (only 32 bits available!) */ @@ -94,7 +92,6 @@ interface nsIXPCScriptable : nsISupports const PRUint32 WANT_CALL = 1 << 13; const PRUint32 WANT_CONSTRUCT = 1 << 14; const PRUint32 WANT_HASINSTANCE = 1 << 15; - const PRUint32 WANT_TRACE = 1 << 16; const PRUint32 USE_JSSTUB_FOR_ADDPROPERTY = 1 << 17; const PRUint32 USE_JSSTUB_FOR_DELPROPERTY = 1 << 18; const PRUint32 USE_JSSTUB_FOR_SETPROPERTY = 1 << 19; @@ -104,7 +101,6 @@ interface nsIXPCScriptable : nsISupports const PRUint32 CLASSINFO_INTERFACES_ONLY = 1 << 23; const PRUint32 ALLOW_PROP_MODS_DURING_RESOLVE = 1 << 24; const PRUint32 ALLOW_PROP_MODS_TO_PROTOTYPE = 1 << 25; - const PRUint32 DONT_SHARE_PROTOTYPE = 1 << 26; const PRUint32 DONT_REFLECT_INTERFACE_NAMES = 1 << 27; const PRUint32 WANT_EQUALITY = 1 << 28; const PRUint32 WANT_OUTER_OBJECT = 1 << 29; @@ -181,9 +177,6 @@ interface nsIXPCScriptable : nsISupports in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out boolean bp); - void trace(in nsIXPConnectWrappedNative wrapper, - in JSTracerPtr trc, in JSObjectPtr obj); - boolean equality(in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val); diff --git a/js/xpconnect/idl/nsIXPConnect.idl b/js/xpconnect/idl/nsIXPConnect.idl index 7aba1189cc50..04a58b17316e 100644 --- a/js/xpconnect/idl/nsIXPConnect.idl +++ b/js/xpconnect/idl/nsIXPConnect.idl @@ -392,7 +392,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } } %} -[uuid(07661008-5505-4784-a612-89f7dc2144da)] +[uuid(241e6db3-e018-4d99-b976-c782a05f9c77)] interface nsIXPConnect : nsISupports { %{ C++ @@ -658,17 +658,6 @@ interface nsIXPConnect : nsISupports jsval variantToJS(in JSContextPtr ctx, in JSObjectPtr scope, in nsIVariant value); nsIVariant JSToVariant(in JSContextPtr ctx, in jsval value); - /** - * Restore an old prototype for wrapped natives of type - * aClassInfo. This should be used only when restoring an old - * scope into a state close to where it was prior to - * being reinitialized. - */ - void restoreWrappedNativePrototype(in JSContextPtr aJSContext, - in JSObjectPtr aScope, - in nsIClassInfo aClassInfo, - in nsIXPConnectJSObjectHolder aPrototype); - /** * Create a sandbox for evaluating code in isolation using * evalInSandboxObject(). diff --git a/js/xpconnect/public/xpc_map_end.h b/js/xpconnect/public/xpc_map_end.h index f4f1649b497b..dbec27a605d5 100644 --- a/js/xpconnect/public/xpc_map_end.h +++ b/js/xpconnect/public/xpc_map_end.h @@ -109,9 +109,6 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::GetScriptableFlags(PRUint32 *aFlags) #ifdef XPC_MAP_WANT_HASINSTANCE nsIXPCScriptable::WANT_HASINSTANCE | #endif -#ifdef XPC_MAP_WANT_TRACE - nsIXPCScriptable::WANT_TRACE | -#endif #ifdef XPC_MAP_WANT_EQUALITY nsIXPCScriptable::WANT_EQUALITY | #endif @@ -208,11 +205,6 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::HasInstance(nsIXPConnectWrappedNative *wrapper, {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;} #endif -#ifndef XPC_MAP_WANT_TRACE -NS_IMETHODIMP XPC_MAP_CLASSNAME::Trace(nsIXPConnectWrappedNative *wrapper, JSTracer *trc, JSObject * obj) - {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;} -#endif - #ifndef XPC_MAP_WANT_EQUALITY NS_IMETHODIMP XPC_MAP_CLASSNAME::Equality(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, const jsval &val, bool *bp) {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;} @@ -297,10 +289,6 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::PostCreatePrototype(JSContext *cx, JSObject *pr #undef XPC_MAP_WANT_HASINSTANCE #endif -#ifdef XPC_MAP_WANT_TRACE -#undef XPC_MAP_WANT_TRACE -#endif - #ifdef XPC_MAP_WANT_EQUALITY #undef XPC_MAP_WANT_EQUALITY #endif diff --git a/js/xpconnect/src/XPCWrappedNative.cpp b/js/xpconnect/src/XPCWrappedNative.cpp index e843f8edb374..a829ad9fada4 100644 --- a/js/xpconnect/src/XPCWrappedNative.cpp +++ b/js/xpconnect/src/XPCWrappedNative.cpp @@ -527,8 +527,7 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx, // wrapper is actually created, but before JS code can see it. if (info && !isClassInfo) { - proto = XPCWrappedNativeProto::GetNewOrUsed(ccx, Scope, info, &sciProto, - false, isGlobal); + proto = XPCWrappedNativeProto::GetNewOrUsed(ccx, Scope, info, &sciProto, isGlobal); if (!proto) return NS_ERROR_FAILURE; @@ -1028,15 +1027,13 @@ XPCWrappedNative::GatherScriptableCreateInfo(nsISupports* obj, NS_ASSERTION(!(sciWrapper.GetFlags().DontEnumStaticProps() && !sciProto.GetFlags().DontEnumStaticProps() && - sciProto.GetCallback() && - !sciProto.GetFlags().DontSharePrototype()), + sciProto.GetCallback()), "Can't set DONT_ENUM_STATIC_PROPS on an instance scriptable " "without also setting it on the class scriptable (if present and shared)"); NS_ASSERTION(!(sciWrapper.GetFlags().DontEnumQueryInterface() && !sciProto.GetFlags().DontEnumQueryInterface() && - sciProto.GetCallback() && - !sciProto.GetFlags().DontSharePrototype()), + sciProto.GetCallback()), "Can't set DONT_ENUM_QUERY_INTERFACE on an instance scriptable " "without also setting it on the class scriptable (if present and shared)"); @@ -1047,29 +1044,20 @@ XPCWrappedNative::GatherScriptableCreateInfo(nsISupports* obj, NS_ASSERTION(!(sciWrapper.GetFlags().ClassInfoInterfacesOnly() && !sciProto.GetFlags().ClassInfoInterfacesOnly() && - sciProto.GetCallback() && - !sciProto.GetFlags().DontSharePrototype()), + sciProto.GetCallback()), "Can't set CLASSINFO_INTERFACES_ONLY on an instance scriptable " "without also setting it on the class scriptable (if present and shared)"); NS_ASSERTION(!(sciWrapper.GetFlags().AllowPropModsDuringResolve() && !sciProto.GetFlags().AllowPropModsDuringResolve() && - sciProto.GetCallback() && - !sciProto.GetFlags().DontSharePrototype()), + sciProto.GetCallback()), "Can't set ALLOW_PROP_MODS_DURING_RESOLVE on an instance scriptable " "without also setting it on the class scriptable (if present and shared)"); NS_ASSERTION(!(sciWrapper.GetFlags().AllowPropModsToPrototype() && !sciProto.GetFlags().AllowPropModsToPrototype() && - sciProto.GetCallback() && - !sciProto.GetFlags().DontSharePrototype()), - "Can't set ALLOW_PROP_MODS_TO_PROTOTYPE on an instance scriptable " - "without also setting it on the class scriptable (if present and shared)"); - - NS_ASSERTION(!(sciWrapper.GetFlags().DontSharePrototype() && - !sciProto.GetFlags().DontSharePrototype() && sciProto.GetCallback()), - "Can't set DONT_SHARE_PROTOTYPE on an instance scriptable " + "Can't set ALLOW_PROP_MODS_TO_PROTOTYPE on an instance scriptable " "without also setting it on the class scriptable (if present and shared)"); return sciWrapper; @@ -1101,13 +1089,6 @@ XPCWrappedNative::Init(XPCCallContext& ccx, if (!mScriptableInfo) return false; - - // If we have a one-off proto, then it should share our scriptable. - // This allows the proto's JSClass callbacks to do the right things - // (like respecting the DONT_ENUM_STATIC_PROPS flag) w/o requiring - // scriptable objects to have an nsIClassInfo. - if (HasProto() && !HasSharedProto()) - GetProto()->SetScriptableInfo(mScriptableInfo); } } XPCNativeScriptableInfo* si = mScriptableInfo; @@ -1502,7 +1483,6 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx, XPCWrappedNativeProto::GetNewOrUsed(ccx, aNewScope, oldProto->GetClassInfo(), &ci, - !oldProto->IsShared(), (info->GetJSClass()->flags & JSCLASS_IS_GLOBAL), oldProto->GetOffsetsMasked()); if (!newProto) { @@ -3035,7 +3015,6 @@ NS_IMETHODIMP XPCWrappedNative::RefreshPrototype() newProto = XPCWrappedNativeProto::GetNewOrUsed(ccx, oldProto->GetScope(), oldProto->GetClassInfo(), &ci, - !oldProto->IsShared(), (info->GetJSClass()->flags & JSCLASS_IS_GLOBAL), oldProto->GetOffsetsMasked()); if (!newProto) @@ -3724,7 +3703,7 @@ ConstructSlimWrapper(XPCCallContext &ccx, JSBool isGlobal = false; xpcproto = XPCWrappedNativeProto::GetNewOrUsed(ccx, xpcScope, classInfoHelper, &sciProto, - false, isGlobal); + isGlobal); if (!xpcproto) return false; diff --git a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp index 55e951256547..df5f821b932d 100644 --- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp +++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp @@ -688,7 +688,7 @@ TraceForValidWrapper(JSTracer *trc, XPCWrappedNative* wrapper) } static void -MarkWrappedNative(JSTracer *trc, JSObject *obj, bool helper) +MarkWrappedNative(JSTracer *trc, JSObject *obj) { JSObject *obj2; @@ -698,20 +698,17 @@ MarkWrappedNative(JSTracer *trc, JSObject *obj, bool helper) XPCWrappedNative::GetWrappedNativeOfJSObject(nsnull, obj, nsnull, &obj2); if (wrapper) { - if (wrapper->IsValid()) { - if (helper) - wrapper->GetScriptableCallback()->Trace(wrapper, trc, obj); + if (wrapper->IsValid()) TraceForValidWrapper(trc, wrapper); - } } else if (obj2) { GetSlimWrapperProto(obj2)->TraceJS(trc); } } static void -XPC_WN_Shared_Trace(JSTracer *trc, JSObject *obj) +XPC_WN_NoHelper_Trace(JSTracer *trc, JSObject *obj) { - MarkWrappedNative(trc, obj, false); + MarkWrappedNative(trc, obj); } static JSBool @@ -840,7 +837,7 @@ js::Class XPC_WN_NoHelper_JSClass = { nsnull, // construct nsnull, // xdrObject; nsnull, // hasInstance - XPC_WN_Shared_Trace, // trace + XPC_WN_NoHelper_Trace, // trace // ClassExtension { @@ -1065,12 +1062,6 @@ XPC_WN_Helper_Finalize(JSContext *cx, JSObject *obj) wrapper->FlatJSObjectFinalized(cx); } -static void -XPC_WN_Helper_Trace(JSTracer *trc, JSObject *obj) -{ - MarkWrappedNative(trc, obj, true); -} - static JSBool XPC_WN_Helper_NewResolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp) @@ -1501,10 +1492,7 @@ XPCNativeScriptableShared::PopulateJSClass(JSBool isGlobal) if (mFlags.WantHasInstance()) mJSClass.base.hasInstance = XPC_WN_Helper_HasInstance; - if (mFlags.WantTrace()) - mJSClass.base.trace = XPC_WN_Helper_Trace; - else - mJSClass.base.trace = XPC_WN_Shared_Trace; + mJSClass.base.trace = XPC_WN_NoHelper_Trace; if (mFlags.WantOuterObject()) mJSClass.base.ext.outerObject = XPC_WN_OuterObject; diff --git a/js/xpconnect/src/XPCWrappedNativeProto.cpp b/js/xpconnect/src/XPCWrappedNativeProto.cpp index 8fe3ff66335d..84b1b3c9e252 100644 --- a/js/xpconnect/src/XPCWrappedNativeProto.cpp +++ b/js/xpconnect/src/XPCWrappedNativeProto.cpp @@ -38,7 +38,7 @@ * * ***** END LICENSE BLOCK ***** */ -/* Possibly shared proto object for XPCWrappedNative. */ +/* Shared proto object for XPCWrappedNative. */ #include "xpcprivate.h" @@ -152,13 +152,11 @@ XPCWrappedNativeProto::JSProtoObjectFinalized(JSContext *cx, JSObject *obj) // Map locking is not necessary since we are running gc. - if (IsShared()) { - // Only remove this proto from the map if it is the one in the map. - ClassInfo2WrappedNativeProtoMap* map = - GetScope()->GetWrappedNativeProtoMap(ClassIsMainThreadOnly()); - if (map->Find(mClassInfo) == this) - map->Remove(mClassInfo); - } + // Only remove this proto from the map if it is the one in the map. + ClassInfo2WrappedNativeProtoMap* map = + GetScope()->GetWrappedNativeProtoMap(ClassIsMainThreadOnly()); + if (map->Find(mClassInfo) == this) + map->Remove(mClassInfo); GetRuntime()->GetDetachedWrappedNativeProtoMap()->Remove(this); GetRuntime()->GetDyingWrappedNativeProtoMap()->Add(this); @@ -191,67 +189,48 @@ XPCWrappedNativeProto::SystemIsBeingShutDown(JSContext* cx) // static XPCWrappedNativeProto* XPCWrappedNativeProto::GetNewOrUsed(XPCCallContext& ccx, - XPCWrappedNativeScope* Scope, - nsIClassInfo* ClassInfo, - const XPCNativeScriptableCreateInfo* ScriptableCreateInfo, - JSBool ForceNoSharing, + XPCWrappedNativeScope* scope, + nsIClassInfo* classInfo, + const XPCNativeScriptableCreateInfo* scriptableCreateInfo, JSBool isGlobal, QITableEntry* offsets) { - NS_ASSERTION(Scope, "bad param"); - NS_ASSERTION(ClassInfo, "bad param"); + NS_ASSERTION(scope, "bad param"); + NS_ASSERTION(classInfo, "bad param"); AutoMarkingWrappedNativeProtoPtr proto(ccx); ClassInfo2WrappedNativeProtoMap* map = nsnull; XPCLock* lock = nsnull; - JSBool shared; uint32_t ciFlags; - if (NS_FAILED(ClassInfo->GetFlags(&ciFlags))) + if (NS_FAILED(classInfo->GetFlags(&ciFlags))) ciFlags = 0; - if (ciFlags & XPC_PROTO_DONT_SHARE) { - NS_ERROR("reserved flag set!"); - ciFlags &= ~XPC_PROTO_DONT_SHARE; - } - - if (ForceNoSharing || (ciFlags & nsIClassInfo::PLUGIN_OBJECT) || - (ScriptableCreateInfo && - ScriptableCreateInfo->GetFlags().DontSharePrototype())) { - ciFlags |= XPC_PROTO_DONT_SHARE; - shared = false; - } else { - shared = true; - } - - if (shared) { - JSBool mainThreadOnly = !!(ciFlags & nsIClassInfo::MAIN_THREAD_ONLY); - map = Scope->GetWrappedNativeProtoMap(mainThreadOnly); - lock = mainThreadOnly ? nsnull : Scope->GetRuntime()->GetMapLock(); - { // scoped lock - XPCAutoLock al(lock); - proto = map->Find(ClassInfo); - if (proto) - return proto; - } + JSBool mainThreadOnly = !!(ciFlags & nsIClassInfo::MAIN_THREAD_ONLY); + map = scope->GetWrappedNativeProtoMap(mainThreadOnly); + lock = mainThreadOnly ? nsnull : scope->GetRuntime()->GetMapLock(); + { // scoped lock + XPCAutoLock al(lock); + proto = map->Find(classInfo); + if (proto) + return proto; } AutoMarkingNativeSetPtr set(ccx); - set = XPCNativeSet::GetNewOrUsed(ccx, ClassInfo); + set = XPCNativeSet::GetNewOrUsed(ccx, classInfo); if (!set) return nsnull; - proto = new XPCWrappedNativeProto(Scope, ClassInfo, ciFlags, set, offsets); + proto = new XPCWrappedNativeProto(scope, classInfo, ciFlags, set, offsets); - if (!proto || !proto->Init(ccx, isGlobal, ScriptableCreateInfo)) { + if (!proto || !proto->Init(ccx, isGlobal, scriptableCreateInfo)) { delete proto.get(); return nsnull; } - if (shared) { // scoped lock XPCAutoLock al(lock); - map->Add(ClassInfo, proto); + map->Add(classInfo, proto); } return proto; diff --git a/js/xpconnect/src/XPCWrappedNativeScope.cpp b/js/xpconnect/src/XPCWrappedNativeScope.cpp index 9dde4a2e9839..5fe75e9d882e 100644 --- a/js/xpconnect/src/XPCWrappedNativeScope.cpp +++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp @@ -559,11 +559,10 @@ struct ShutdownData { ShutdownData(JSContext* acx) : cx(acx), wrapperCount(0), - sharedProtoCount(0), nonSharedProtoCount(0) {} + protoCount(0) {} JSContext* cx; int wrapperCount; - int sharedProtoCount; - int nonSharedProtoCount; + int protoCount; }; static JSDHashOperator @@ -574,8 +573,6 @@ WrappedNativeShutdownEnumerator(JSDHashTable *table, JSDHashEntryHdr *hdr, XPCWrappedNative* wrapper = ((Native2WrappedNativeMap::Entry*)hdr)->value; if (wrapper->IsValid()) { - if (wrapper->HasProto() && !wrapper->HasSharedProto()) - data->nonSharedProtoCount++; wrapper->SystemIsBeingShutDown(data->cx); data->wrapperCount++; } @@ -589,7 +586,7 @@ WrappedNativeProtoShutdownEnumerator(JSDHashTable *table, JSDHashEntryHdr *hdr, ShutdownData* data = (ShutdownData*) arg; ((ClassInfo2WrappedNativeProtoMap::Entry*)hdr)->value-> SystemIsBeingShutDown(data->cx); - data->sharedProtoCount++; + data->protoCount++; return JS_DHASH_REMOVE; } @@ -648,10 +645,9 @@ XPCWrappedNativeScope::SystemIsBeingShutDown(JSContext* cx) if (data.wrapperCount) printf("deleting nsXPConnect with %d live XPCWrappedNatives\n", data.wrapperCount); - if (data.sharedProtoCount + data.nonSharedProtoCount) - printf("deleting nsXPConnect with %d live XPCWrappedNativeProtos (%d shared)\n", - data.sharedProtoCount + data.nonSharedProtoCount, - data.sharedProtoCount); + if (data.protoCount) + printf("deleting nsXPConnect with %d live XPCWrappedNativeProtos\n", + data.protoCount); if (liveScopeCount) printf("deleting nsXPConnect with %d live XPCWrappedNativeScopes\n", liveScopeCount); @@ -814,16 +810,6 @@ WNProtoSecPolicyClearer(JSDHashTable *table, JSDHashEntryHdr *hdr, return JS_DHASH_NEXT; } -static JSDHashOperator -WNSecPolicyClearer(JSDHashTable *table, JSDHashEntryHdr *hdr, - uint32_t number, void *arg) -{ - XPCWrappedNative* wrapper = ((Native2WrappedNativeMap::Entry*)hdr)->value; - if (wrapper->HasProto() && !wrapper->HasSharedProto()) - *(wrapper->GetProto()->GetSecurityInfoAddr()) = nsnull; - return JS_DHASH_NEXT; -} - // static nsresult XPCWrappedNativeScope::ClearAllWrappedNativeSecurityPolicies(XPCCallContext& ccx) @@ -834,7 +820,6 @@ XPCWrappedNativeScope::ClearAllWrappedNativeSecurityPolicies(XPCCallContext& ccx for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) { cur->mWrappedNativeProtoMap->Enumerate(WNProtoSecPolicyClearer, nsnull); cur->mMainThreadWrappedNativeProtoMap->Enumerate(WNProtoSecPolicyClearer, nsnull); - cur->mWrappedNativeMap->Enumerate(WNSecPolicyClearer, nsnull); } DEBUG_TrackScopeTraversal(); diff --git a/js/xpconnect/src/nsXPConnect.cpp b/js/xpconnect/src/nsXPConnect.cpp index c78ac67e90f4..751370375c04 100644 --- a/js/xpconnect/src/nsXPConnect.cpp +++ b/js/xpconnect/src/nsXPConnect.cpp @@ -2061,97 +2061,6 @@ nsXPConnect::ClearAllWrappedNativeSecurityPolicies() return XPCWrappedNativeScope::ClearAllWrappedNativeSecurityPolicies(ccx); } -/* void restoreWrappedNativePrototype (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsIClassInfo aClassInfo, in nsIXPConnectJSObjectHolder aPrototype); */ -NS_IMETHODIMP -nsXPConnect::RestoreWrappedNativePrototype(JSContext * aJSContext, - JSObject * aScope, - nsIClassInfo * aClassInfo, - nsIXPConnectJSObjectHolder * aPrototype) -{ - XPCCallContext ccx(NATIVE_CALLER, aJSContext); - if (!ccx.IsValid()) - return UnexpectedFailure(NS_ERROR_FAILURE); - - if (!aClassInfo || !aPrototype) - return UnexpectedFailure(NS_ERROR_INVALID_ARG); - - JSObject *protoJSObject; - nsresult rv = aPrototype->GetJSObject(&protoJSObject); - if (NS_FAILED(rv)) - return UnexpectedFailure(rv); - - if (!IS_PROTO_CLASS(js::GetObjectClass(protoJSObject))) - return UnexpectedFailure(NS_ERROR_INVALID_ARG); - - XPCWrappedNativeScope* scope = - XPCWrappedNativeScope::FindInJSObjectScope(ccx, aScope); - if (!scope) - return UnexpectedFailure(NS_ERROR_FAILURE); - - XPCWrappedNativeProto *proto = - (XPCWrappedNativeProto*)xpc_GetJSPrivate(protoJSObject); - if (!proto) - return UnexpectedFailure(NS_ERROR_FAILURE); - - if (scope != proto->GetScope()) { - NS_ERROR("Attempt to reset prototype to a prototype from a" - "different scope!"); - - return UnexpectedFailure(NS_ERROR_INVALID_ARG); - } - - XPCNativeScriptableInfo *si = proto->GetScriptableInfo(); - - if (si && si->GetFlags().DontSharePrototype()) - return UnexpectedFailure(NS_ERROR_INVALID_ARG); - - ClassInfo2WrappedNativeProtoMap* map = - scope->GetWrappedNativeProtoMap(proto->ClassIsMainThreadOnly()); - XPCLock* lock = GetRuntime()->GetMapLock(); - - { // scoped lock - XPCAutoLock al(lock); - - XPCWrappedNativeProtoMap* detachedMap = - GetRuntime()->GetDetachedWrappedNativeProtoMap(); - - // If we're replacing an old proto, make sure to put it on the - // map of detached wrapped native protos so that the old proto - // gets properly cleaned up, especially during shutdown. - XPCWrappedNativeProto *oldProto = map->Find(aClassInfo); - if (oldProto) { - detachedMap->Add(oldProto); - - // ClassInfo2WrappedNativeProtoMap doesn't ever replace - // entries in the map, so now since we know there's an - // entry for aClassInfo in the map we have to remove it to - // be able to add the new one. - map->Remove(aClassInfo); - - // This code should do the right thing even if we're - // restoring the current proto, but warn in that case - // since doing that is pointless. - NS_ASSERTION(proto != oldProto, - "Restoring current prototype, fix caller!"); - } - - map->Add(aClassInfo, proto); - - // Remove the prototype from the map of detached wrapped - // native prototypes now that the prototype is part of a scope - // again. - detachedMap->Remove(proto); - } - - // The global in this scope didn't change, but a prototype did - // (most likely the global object's prototype), which means the - // scope needs to get a chance to update its cached - // Object.prototype pointers etc. - scope->SetGlobal(ccx, aScope); - - return NS_OK; -} - NS_IMETHODIMP nsXPConnect::CreateSandbox(JSContext *cx, nsIPrincipal *principal, nsIXPConnectJSObjectHolder **_retval) @@ -2222,8 +2131,7 @@ nsXPConnect::GetWrappedNativePrototype(JSContext * aJSContext, AutoMarkingWrappedNativeProtoPtr proto(ccx); proto = XPCWrappedNativeProto::GetNewOrUsed(ccx, scope, aClassInfo, - &sciProto, false, - OBJ_IS_NOT_GLOBAL); + &sciProto, OBJ_IS_NOT_GLOBAL); if (!proto) return UnexpectedFailure(NS_ERROR_FAILURE); diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index 0456727d4d33..6664bbafc23c 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -2013,7 +2013,6 @@ public: JSBool WantCall() GET_IT(WANT_CALL) JSBool WantConstruct() GET_IT(WANT_CONSTRUCT) JSBool WantHasInstance() GET_IT(WANT_HASINSTANCE) - JSBool WantTrace() GET_IT(WANT_TRACE) JSBool WantEquality() GET_IT(WANT_EQUALITY) JSBool WantOuterObject() GET_IT(WANT_OUTER_OBJECT) JSBool UseJSStubForAddProperty() GET_IT(USE_JSSTUB_FOR_ADDPROPERTY) @@ -2025,7 +2024,6 @@ public: JSBool ClassInfoInterfacesOnly() GET_IT(CLASSINFO_INTERFACES_ONLY) JSBool AllowPropModsDuringResolve() GET_IT(ALLOW_PROP_MODS_DURING_RESOLVE) JSBool AllowPropModsToPrototype() GET_IT(ALLOW_PROP_MODS_TO_PROTOTYPE) - JSBool DontSharePrototype() GET_IT(DONT_SHARE_PROTOTYPE) JSBool DontReflectInterfaceNames() GET_IT(DONT_REFLECT_INTERFACE_NAMES) JSBool UseStubEqualityHook() GET_IT(USE_STUB_EQUALITY_HOOK) @@ -2195,7 +2193,7 @@ private: }; /***********************************************/ -// XPCWrappedNativeProto hold the additional (potentially shared) wrapper data +// XPCWrappedNativeProto hold the additional shared wrapper data // for XPCWrappedNative whose native objects expose nsIClassInfo. #define UNKNOWN_OFFSETS ((QITableEntry*)1) @@ -2205,10 +2203,9 @@ class XPCWrappedNativeProto public: static XPCWrappedNativeProto* GetNewOrUsed(XPCCallContext& ccx, - XPCWrappedNativeScope* Scope, - nsIClassInfo* ClassInfo, - const XPCNativeScriptableCreateInfo* ScriptableCreateInfo, - JSBool ForceNoSharing, + XPCWrappedNativeScope* scope, + nsIClassInfo* classInfo, + const XPCNativeScriptableCreateInfo* scriptableCreateInfo, JSBool isGlobal, QITableEntry* offsets = UNKNOWN_OFFSETS); @@ -2283,11 +2280,6 @@ public: #undef GET_IT -#define XPC_PROTO_DONT_SHARE JS_BIT(31) // only high bit of 32 is set - - JSBool - IsShared() const {return !(mClassInfoFlags & XPC_PROTO_DONT_SHARE);} - XPCLock* GetLock() const {return ClassIsThreadSafe() ? GetRuntime()->GetMapLock() : nsnull;} @@ -2575,10 +2567,6 @@ public: GetClassInfo() const {return IsValid() && HasProto() ? GetProto()->GetClassInfo() : nsnull;} - JSBool - HasSharedProto() const {return IsValid() && HasProto() && - GetProto()->IsShared();} - JSBool HasMutatedSet() const {return IsValid() && (!HasProto() || diff --git a/layout/base/nsCSSRenderingBorders.cpp b/layout/base/nsCSSRenderingBorders.cpp index dfad48b0cf2b..e533d0143e8e 100644 --- a/layout/base/nsCSSRenderingBorders.cpp +++ b/layout/base/nsCSSRenderingBorders.cpp @@ -1088,15 +1088,16 @@ nsCSSBorderRenderer::CreateCornerGradient(mozilla::css::Corner aCorner, float gradientOffset; - if (mContext->OriginalSurface()->GetType() == gfxASurface::SurfaceTypeD2D || - mContext->OriginalSurface()->GetType() == gfxASurface::SurfaceTypeQuartz) + if (mContext->IsCairo() && + (mContext->OriginalSurface()->GetType() == gfxASurface::SurfaceTypeD2D || + mContext->OriginalSurface()->GetType() == gfxASurface::SurfaceTypeQuartz)) { // On quarz this doesn't do exactly the right thing, but it does do what // most other browsers do and doing the 'right' thing seems to be // hard with the quartz cairo backend. gradientOffset = 0; } else { - // When cairo does the gradient drawing this gives us pretty nice behavior! + // When cairo/Azure does the gradient drawing this gives us pretty nice behavior! gradientOffset = 0.25 / sqrt(pow(mBorderWidths[cornerHeight[aCorner]], 2) + pow(mBorderWidths[cornerHeight[aCorner]], 2)); } diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index ae69c9064bab..6fd82c98b0ba 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -4336,7 +4336,7 @@ public: nsChangeHint mChangeHint; }; -class LayerActivityTracker : public nsExpirationTracker { +class LayerActivityTracker MOZ_FINAL : public nsExpirationTracker { public: // 75-100ms is a good timeout period. We use 4 generations of 25ms each. enum { GENERATION_MS = 100 }; diff --git a/layout/mathml/nsMathMLmunderoverFrame.cpp b/layout/mathml/nsMathMLmunderoverFrame.cpp index 593e204026cb..c26d7cf80ef8 100644 --- a/layout/mathml/nsMathMLmunderoverFrame.cpp +++ b/layout/mathml/nsMathMLmunderoverFrame.cpp @@ -24,6 +24,8 @@ * David J. Fiddes * Shyjan Mahamud * Pierre Phaneuf + * Jonathan Hage + * Frederic Wang * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -529,7 +531,22 @@ nsMathMLmunderoverFrame::Place(nsRenderingContext& aRenderingContext, overDelta2 = 0; } - nscoord dxBase, dxOver = 0, dxUnder = 0; + nscoord dxBase = 0, dxOver = 0, dxUnder = 0; + nsAutoString valueAlign; + enum { + center, + left, + right + } alignPosition = center; + + if (GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::align, + valueAlign)) { + if (valueAlign.EqualsLiteral("left")) { + alignPosition = left; + } else if (valueAlign.EqualsLiteral("right")) { + alignPosition = right; + } + } ////////// // pass 1, do what does: attach the overscript on the base @@ -545,13 +562,24 @@ nsMathMLmunderoverFrame::Place(nsRenderingContext& aRenderingContext, if (NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)) { mBoundingMetrics.width = bmBase.width; - dxOver += correction + (mBoundingMetrics.width - overWidth)/2; + if (alignPosition == center) { + dxOver += correction; + } } else { mBoundingMetrics.width = NS_MAX(bmBase.width, overWidth); - dxOver += correction/2 + (mBoundingMetrics.width - overWidth)/2; + if (alignPosition == center) { + dxOver += correction/2; + } + } + + if (alignPosition == center) { + dxOver += (mBoundingMetrics.width - overWidth)/2; + dxBase = (mBoundingMetrics.width - bmBase.width)/2; + } else if (alignPosition == right) { + dxOver += mBoundingMetrics.width - overWidth; + dxBase = mBoundingMetrics.width - bmBase.width; } - dxBase = (mBoundingMetrics.width - bmBase.width)/2; mBoundingMetrics.ascent = bmBase.ascent + overDelta1 + bmOver.ascent + bmOver.descent; @@ -574,8 +602,6 @@ nsMathMLmunderoverFrame::Place(nsRenderingContext& aRenderingContext, overSize.ascent + bmOver.descent + overDelta1 + bmBase.ascent); ascentAnonymousBase = NS_MAX(ascentAnonymousBase, baseSize.ascent); - GetItalicCorrection(bmAnonymousBase, correction); - // Width of non-spacing marks is zero so use left and right bearing. nscoord underWidth = bmUnder.width; if (!underWidth) { @@ -584,13 +610,19 @@ nsMathMLmunderoverFrame::Place(nsRenderingContext& aRenderingContext, } nscoord maxWidth = NS_MAX(bmAnonymousBase.width, underWidth); - if (NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags)) { - dxUnder += (maxWidth - underWidth)/2;; + if (alignPosition == center && + !NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags)) { + GetItalicCorrection(bmAnonymousBase, correction); + dxUnder += -correction/2; } - else { - dxUnder += -correction/2 + (maxWidth - underWidth)/2; + nscoord dxAnonymousBase = 0; + if (alignPosition == center) { + dxUnder += (maxWidth - underWidth)/2; + dxAnonymousBase = (maxWidth - bmAnonymousBase.width)/2; + } else if (alignPosition == right) { + dxUnder += maxWidth - underWidth; + dxAnonymousBase = maxWidth - bmAnonymousBase.width; } - nscoord dxAnonymousBase = (maxWidth - bmAnonymousBase.width)/2; // adjust the offsets of the real base and overscript since their // final offsets should be relative to us... diff --git a/layout/reftests/mathml/munder-mover-align-accent-false-ref.html b/layout/reftests/mathml/munder-mover-align-accent-false-ref.html new file mode 100644 index 000000000000..b691c57b5b4d --- /dev/null +++ b/layout/reftests/mathml/munder-mover-align-accent-false-ref.html @@ -0,0 +1,224 @@ + + + +

Test with accent="false"

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
movermunder
+ Over + < + Base + + + + Over + > + Base + + + + Over + < + Base + + + + Over + > + Base +
+ align="left" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ align="right" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ align="center" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+
Under & Over
+ + + + + + +
        +
Base
+ + + + + + +
+ + diff --git a/layout/reftests/mathml/munder-mover-align-accent-false.html b/layout/reftests/mathml/munder-mover-align-accent-false.html new file mode 100644 index 000000000000..34efa9958439 --- /dev/null +++ b/layout/reftests/mathml/munder-mover-align-accent-false.html @@ -0,0 +1,176 @@ + + + +

Test with accent="false"

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
movermunder
+ Over + < + Base + + + + Over + > + Base + + + + Over + < + Base + + + + Over + > + Base +
+ align="left" + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ align="right" + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ align="center" + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+
Under & Over
+ + + + + + +
        +
Base
+ + + + + + +
+ + diff --git a/layout/reftests/mathml/munder-mover-align-accent-true-ref.html b/layout/reftests/mathml/munder-mover-align-accent-true-ref.html new file mode 100644 index 000000000000..94fb4898726b --- /dev/null +++ b/layout/reftests/mathml/munder-mover-align-accent-true-ref.html @@ -0,0 +1,224 @@ + + + +

Test with accent="true"

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
movermunder
+ Over + < + Base + + + + Over + > + Base + + + + Over + < + Base + + + + Over + > + Base +
+ align="left" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ align="right" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ align="center" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+
Under & Over
+ + + + + + +
        +
Base
+ + + + + + +
+ + diff --git a/layout/reftests/mathml/munder-mover-align-accent-true.html b/layout/reftests/mathml/munder-mover-align-accent-true.html new file mode 100644 index 000000000000..9c66f9817333 --- /dev/null +++ b/layout/reftests/mathml/munder-mover-align-accent-true.html @@ -0,0 +1,176 @@ + + + +

Test with accent="true"

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
movermunder
+ Over + < + Base + + + + Over + > + Base + + + + Over + < + Base + + + + Over + > + Base +
+ align="left" + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ align="right" + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ align="center" + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+
Under & Over
+ + + + + + +
        +
Base
+ + + + + + +
+ + diff --git a/layout/reftests/mathml/munderover-align-accent-false-ref.html b/layout/reftests/mathml/munderover-align-accent-false-ref.html new file mode 100644 index 000000000000..e500ce29d3be --- /dev/null +++ b/layout/reftests/mathml/munderover-align-accent-false-ref.html @@ -0,0 +1,274 @@ + + + +

Test with accent="false"

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
munderover
+ Over + < + Base + < + Under + + + + Over + > + Base + > + Under + + + + Over = Under + < + Base + + + Over = Under + > + Base +
+ align="left" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ align="right" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ align="center" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+
Under & Over
+ + + + + + +
        +
Base
+ + + + + + +
+ + diff --git a/layout/reftests/mathml/munderover-align-accent-false.html b/layout/reftests/mathml/munderover-align-accent-false.html new file mode 100644 index 000000000000..1dd316c5c825 --- /dev/null +++ b/layout/reftests/mathml/munderover-align-accent-false.html @@ -0,0 +1,190 @@ + + + +

Test with accent="false"

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
munderover
+ Over + < + Base + < + Under + + + + Over + > + Base + > + Under + + + + Over = Under + < + Base + + + Over = Under + > + Base +
+ align="left" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ align="right" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ align="center" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+
Under & Over
+ + + + + + +
        +
Base
+ + + + + + +
+ + diff --git a/layout/reftests/mathml/munderover-align-accent-true-ref.html b/layout/reftests/mathml/munderover-align-accent-true-ref.html new file mode 100644 index 000000000000..2ca5eb30454f --- /dev/null +++ b/layout/reftests/mathml/munderover-align-accent-true-ref.html @@ -0,0 +1,274 @@ + + + +

Test with accent="true"

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
munderover
+ Over + < + Base + < + Under + + + + Over + > + Base + > + Under + + + + Over = Under + < + Base + + + Over = Under + > + Base +
+ align="left" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ align="right" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ align="center" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+
Under & Over
+ + + + + + +
        +
Base
+ + + + + + +
+ + diff --git a/layout/reftests/mathml/munderover-align-accent-true.html b/layout/reftests/mathml/munderover-align-accent-true.html new file mode 100644 index 000000000000..d2f2795f20ae --- /dev/null +++ b/layout/reftests/mathml/munderover-align-accent-true.html @@ -0,0 +1,190 @@ + + + +

Test with accent="true"

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
munderover
+ Over + < + Base + < + Under + + + + Over + > + Base + > + Under + + + + Over = Under + < + Base + + + Over = Under + > + Base +
+ align="left" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ align="right" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ align="center" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+
Under & Over
+ + + + + + +
        +
Base
+ + + + + + +
+ + diff --git a/layout/reftests/mathml/reftest.list b/layout/reftests/mathml/reftest.list index 00060c7a8f19..35e616d204bf 100644 --- a/layout/reftests/mathml/reftest.list +++ b/layout/reftests/mathml/reftest.list @@ -87,6 +87,10 @@ fails == mstyle-5.xhtml mstyle-5-ref.xhtml # See bug 569125#c29 == mpadded-6.html mpadded-6-ref.html == math-display.html math-display-ref.html == scriptlevel-movablelimits-1.html scriptlevel-movablelimits-1-ref.html +== munderover-align-accent-false.html munderover-align-accent-false-ref.html +== munderover-align-accent-true.html munderover-align-accent-true-ref.html +== munder-mover-align-accent-true.html munder-mover-align-accent-true-ref.html +== munder-mover-align-accent-false.html munder-mover-align-accent-false-ref.html == mfrac-linethickness-1.xhtml mfrac-linethickness-1-ref.xhtml == mathml-negativespace.html mathml-negativespace-ref.html != link-1.xhtml link-ref.xhtml diff --git a/layout/style/nsFontFaceLoader.cpp b/layout/style/nsFontFaceLoader.cpp index fca6fe3763a3..08aa5e2acee0 100644 --- a/layout/style/nsFontFaceLoader.cpp +++ b/layout/style/nsFontFaceLoader.cpp @@ -727,10 +727,14 @@ nsUserFontSet::LogMessage(gfxProxyFontEntry *aProxy, NS_ConvertUTF16toUTF8 familyName(aProxy->FamilyName()); nsCAutoString fontURI; - if (aProxy->mSrcList[aProxy->mSrcIndex].mURI) { - aProxy->mSrcList[aProxy->mSrcIndex].mURI->GetSpec(fontURI); + if (aProxy->mSrcIndex == aProxy->mSrcList.Length()) { + fontURI.AppendLiteral("(end of source list)"); } else { - fontURI.AppendLiteral("(invalid URI)"); + if (aProxy->mSrcList[aProxy->mSrcIndex].mURI) { + aProxy->mSrcList[aProxy->mSrcIndex].mURI->GetSpec(fontURI); + } else { + fontURI.AppendLiteral("(invalid URI)"); + } } char weightKeywordBuf[8]; // plenty to sprintf() a PRUint16 diff --git a/layout/svg/base/src/nsSVGUtils.cpp b/layout/svg/base/src/nsSVGUtils.cpp index 55bf278924cd..0b36603b7ff3 100644 --- a/layout/svg/base/src/nsSVGUtils.cpp +++ b/layout/svg/base/src/nsSVGUtils.cpp @@ -89,8 +89,11 @@ #include "gfxUtils.h" #include "mozilla/Preferences.h" +#include "mozilla/gfx/2D.h" + using namespace mozilla; using namespace mozilla::dom; +using namespace mozilla::gfx; // c = n / 255 // (c <= 0.0031308 ? c * 12.92 : 1.055 * pow(c, 1 / 2.4) - 0.055) * 255 + 0.5 @@ -1214,12 +1217,32 @@ nsSVGUtils::CompositeSurfaceMatrix(gfxContext *aContext, { if (aCTM.IsSingular()) return; + + if (aContext->IsCairo()) { + aContext->Save(); + aContext->Multiply(aCTM); + aContext->SetSource(aSurface); + aContext->Paint(aOpacity); + aContext->Restore(); + } else { + DrawTarget *dt = aContext->GetDrawTarget(); + Matrix oldMat = dt->GetTransform(); + RefPtr surf = + gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, aSurface); + dt->SetTransform(oldMat * ToMatrix(aCTM)); - aContext->Save(); - aContext->Multiply(aCTM); - aContext->SetSource(aSurface); - aContext->Paint(aOpacity); - aContext->Restore(); + gfxSize size = aSurface->GetSize(); + NS_ASSERTION(size.width >= 0 && size.height >= 0, "Failure to get size for aSurface."); + + gfxPoint pt = aSurface->GetDeviceOffset(); + + dt->FillRect(Rect(-pt.x, -pt.y, size.width, size.height), + SurfacePattern(surf, EXTEND_CLAMP, + Matrix(1.0f, 0, 0, 1.0f, -pt.x, -pt.y)), + DrawOptions(aOpacity)); + + dt->SetTransform(oldMat); + } } void diff --git a/mobile/android/base/gfx/WidgetTileLayer.java b/mobile/android/base/gfx/WidgetTileLayer.java index f77fda204239..652db0264bdc 100644 --- a/mobile/android/base/gfx/WidgetTileLayer.java +++ b/mobile/android/base/gfx/WidgetTileLayer.java @@ -50,6 +50,7 @@ import javax.microedition.khronos.opengles.GL10; * Encapsulates the logic needed to draw the single-tiled Gecko texture */ public class WidgetTileLayer extends Layer { + private static final String LOGTAG = "WidgetTileLayer"; private int[] mTextureIDs; private CairoImage mImage; @@ -110,7 +111,16 @@ public class WidgetTileLayer extends Layer { 0); float top = viewport.height() - (bounds.top + bounds.height()); + + // There may be errors from a previous GL call, so clear them first because + // we want to check for one below + while (GLES11.glGetError() != GLES11.GL_NO_ERROR); + GLES11Ext.glDrawTexfOES(bounds.left, top, 0.0f, bounds.width(), bounds.height()); + int error = GLES11.glGetError(); + if (error != GLES11.GL_NO_ERROR) { + Log.i(LOGTAG, "Failed to draw texture: " + error); + } } } diff --git a/mobile/android/base/ui/PanZoomController.java b/mobile/android/base/ui/PanZoomController.java index 596511b8fae1..0a969ba87291 100644 --- a/mobile/android/base/ui/PanZoomController.java +++ b/mobile/android/base/ui/PanZoomController.java @@ -487,7 +487,7 @@ public class PanZoomController } mX.setFlingState(Axis.FlingStates.PANNING); mY.setFlingState(Axis.FlingStates.PANNING); - mX.displace(); mY.displace(); + mX.displace(mOverridePanning); mY.displace(mOverridePanning); updatePosition(); } @@ -497,7 +497,7 @@ public class PanZoomController mX.disableSnap = mY.disableSnap = mOverridePanning; - mX.displace(); mY.displace(); + mX.displace(mOverridePanning); mY.displace(mOverridePanning); updatePosition(); stopAnimationTimer(); @@ -670,7 +670,7 @@ public class PanZoomController /* If we're still flinging in any direction, update the origin. */ if (flingingX || flingingY) { - mX.displace(); mY.displace(); + mX.displace(mOverridePanning); mY.displace(mOverridePanning); updatePosition(); /* @@ -849,8 +849,8 @@ public class PanZoomController } // Performs displacement of the viewport position according to the current velocity. - public void displace() { - if (locked || !scrollable()) + public void displace(boolean panningOverridden) { + if (!panningOverridden && (locked || !scrollable())) return; if (mFlingState == FlingStates.PANNING) diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 85910fef322f..232a418de7ad 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -2106,6 +2106,16 @@ var BrowserEventHandler = { cwu.sendMouseEventToWindow(aName, Math.round(aX), Math.round(aY), aButton, 1, 0, true); }, + _hasScrollableOverflow: function(elem) { + var win = elem.ownerDocument.defaultView; + if (!win) + return false; + var computedStyle = win.getComputedStyle(elem); + if (!computedStyle) + return false; + return computedStyle.overflow == 'auto' || computedStyle.overflow == 'scroll'; + }, + _findScrollableElement: function(elem, checkElem) { // Walk the DOM tree until we find a scrollable element let scrollable = false; @@ -2119,8 +2129,7 @@ var BrowserEventHandler = { if (checkElem) { if (((elem.scrollHeight > elem.clientHeight) || (elem.scrollWidth > elem.clientWidth)) && - (elem.style.overflow == 'auto' || - elem.style.overflow == 'scroll' || + (this._hasScrollableOverflow(elem) || elem.mozMatchesSelector("html, body, textarea")) || (elem instanceof HTMLSelectElement && (elem.size > 1 || elem.multiple))) { scrollable = true; diff --git a/mobile/android/chrome/content/downloads.js b/mobile/android/chrome/content/downloads.js index 9184832d23f7..8decf3d72299 100644 --- a/mobile/android/chrome/content/downloads.js +++ b/mobile/android/chrome/content/downloads.js @@ -133,9 +133,9 @@ var Downloads = { this._dlmgr = Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManager); this._progressAlert = new AlertDownloadProgressListener(); this._dlmgr.addListener(this._progressAlert); - - NativeWindow.toast.show(Strings.browser.GetStringFromName("alertDownloadsToast"), "long"); } + + NativeWindow.toast.show(Strings.browser.GetStringFromName("alertDownloadsToast"), "long"); } else if (aTopic == "dl-done") { msgKey = "alertDownloadsDone"; } diff --git a/mobile/xul/chrome/content/common-ui.js b/mobile/xul/chrome/content/common-ui.js index ac8d552d53ba..5528510fc99f 100644 --- a/mobile/xul/chrome/content/common-ui.js +++ b/mobile/xul/chrome/content/common-ui.js @@ -1176,8 +1176,7 @@ var FullScreenVideo = { try { this.screen = null; let screenManager = Cc["@mozilla.org/gfx/screenmanager;1"].getService(Ci.nsIScreenManager); - let screen = screenManager.primaryScreen.QueryInterface(Ci.nsIScreen_MOZILLA_2_0_BRANCH); - this.screen = screen; + this.screen = screenManager.primaryScreen; } catch (e) {} // The screen does not support brightness locks }, diff --git a/netwerk/protocol/file/nsFileProtocolHandler.cpp b/netwerk/protocol/file/nsFileProtocolHandler.cpp index 1f1d70789579..70daa3073a60 100644 --- a/netwerk/protocol/file/nsFileProtocolHandler.cpp +++ b/netwerk/protocol/file/nsFileProtocolHandler.cpp @@ -96,10 +96,6 @@ NS_IMPL_THREADSAFE_ISUPPORTS3(nsFileProtocolHandler, NS_IMETHODIMP nsFileProtocolHandler::ReadURLFile(nsIFile* aFile, nsIURI** aURI) { -// IUniformResourceLocator isn't supported by VC5 (bless its little heart) -#if _MSC_VER < 1200 - return NS_ERROR_NOT_AVAILABLE; -#else nsAutoString path; nsresult rv = aFile->GetPath(path); if (NS_FAILED(rv)) @@ -139,8 +135,6 @@ nsFileProtocolHandler::ReadURLFile(nsIFile* aFile, nsIURI** aURI) urlLink->Release(); } return rv; - -#endif //_MSC_VER < 1200 } #elif defined(XP_OS2) diff --git a/netwerk/protocol/ftp/nsFtpConnectionThread.cpp b/netwerk/protocol/ftp/nsFtpConnectionThread.cpp index 34c9998c3f73..78d34a7150ad 100644 --- a/netwerk/protocol/ftp/nsFtpConnectionThread.cpp +++ b/netwerk/protocol/ftp/nsFtpConnectionThread.cpp @@ -1706,6 +1706,13 @@ nsFtpState::Init(nsFtpChannel *channel) nsresult rv; nsCAutoString path; nsCOMPtr url = do_QueryInterface(mChannel->URI()); + + nsCString host; + url->GetAsciiHost(host); + if (host.IsEmpty()) { + return NS_ERROR_MALFORMED_URI; + } + if (url) { rv = url->GetFilePath(path); } else { diff --git a/netwerk/protocol/websocket/WebSocketChannel.cpp b/netwerk/protocol/websocket/WebSocketChannel.cpp index 0959f406d25e..5442eceface2 100644 --- a/netwerk/protocol/websocket/WebSocketChannel.cpp +++ b/netwerk/protocol/websocket/WebSocketChannel.cpp @@ -2373,7 +2373,8 @@ WebSocketChannel::SendMsgCommon(const nsACString *aMsg, bool aIsBinary, return NS_ERROR_NOT_CONNECTED; } - if (aLength > mMaxMessageSize) { + NS_ABORT_IF_FALSE(mMaxMessageSize >= 0, "max message size negative"); + if (aLength > static_cast(mMaxMessageSize)) { LOG(("WebSocketChannel:: Error: message too big\n")); return NS_ERROR_FILE_TOO_BIG; } diff --git a/toolkit/components/places/Database.cpp b/toolkit/components/places/Database.cpp index 72cbb8b989bb..06b00c36369f 100644 --- a/toolkit/components/places/Database.cpp +++ b/toolkit/components/places/Database.cpp @@ -728,7 +728,12 @@ Database::InitSchema(bool* aDatabaseMigrated) NS_ENSURE_SUCCESS(rv, rv); } - // Firefox 11 uses schema version 14. + if (currentSchemaVersion < 16) { + rv = MigrateV16Up(); + NS_ENSURE_SUCCESS(rv, rv); + } + + // Firefox 11 uses schema version 16. // Schema Upgrades must add migration code here. @@ -1545,6 +1550,8 @@ Database::MigrateV13Up() nsresult Database::MigrateV14Up() { + MOZ_ASSERT(NS_IsMainThread()); + // For existing profiles, we may not have a moz_favicons.guid column. // Add it here. We want it to be unique, but ALTER TABLE doesn't allow // a uniqueness constraint, so the index must be created separately. @@ -1560,17 +1567,18 @@ Database::MigrateV14Up() )); NS_ENSURE_SUCCESS(rv, rv); - // Generate GUIDs for our existing favicons. - rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( - "UPDATE moz_favicons " - "SET guid = GENERATE_GUID()" - )); - NS_ENSURE_SUCCESS(rv, rv); - - // And now we can make the column unique. rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_FAVICONS_GUID); NS_ENSURE_SUCCESS(rv, rv); } + + // Generate GUID for any favicon missing it. + rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "UPDATE moz_favicons " + "SET guid = GENERATE_GUID() " + "WHERE guid ISNULL " + )); + NS_ENSURE_SUCCESS(rv, rv); + return NS_OK; } @@ -1600,6 +1608,23 @@ Database::MigrateV15Up() return NS_OK; } +nsresult +Database::MigrateV16Up() +{ + MOZ_ASSERT(NS_IsMainThread()); + + // Due to Bug 715268 downgraded and then upgraded profiles may lack favicons + // guids, so fillup any missing ones. + nsresult rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "UPDATE moz_favicons " + "SET guid = GENERATE_GUID() " + "WHERE guid ISNULL " + )); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + void Database::Shutdown() { @@ -1632,7 +1657,7 @@ Database::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData) { - NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread"); + MOZ_ASSERT(NS_IsMainThread()); if (strcmp(aTopic, TOPIC_PROFILE_CHANGE_TEARDOWN) == 0) { // Tests simulating shutdown may cause multiple notifications. @@ -1678,27 +1703,38 @@ Database::Observe(nsISupports *aSubject, #ifdef DEBUG { // Sanity check for missing guids. + bool haveNullGuids = false; nsCOMPtr stmt; + nsresult rv = mMainConn->CreateStatement(NS_LITERAL_CSTRING( "SELECT 1 " "FROM moz_places " "WHERE guid IS NULL " - "UNION ALL " + ), getter_AddRefs(stmt)); + NS_ENSURE_SUCCESS(rv, rv); + rv = stmt->ExecuteStep(&haveNullGuids); + NS_ENSURE_SUCCESS(rv, rv); + MOZ_ASSERT(!haveNullGuids && "Found a page without a GUID!"); + + rv = mMainConn->CreateStatement(NS_LITERAL_CSTRING( "SELECT 1 " "FROM moz_bookmarks " "WHERE guid IS NULL " - "UNION ALL " + ), getter_AddRefs(stmt)); + NS_ENSURE_SUCCESS(rv, rv); + rv = stmt->ExecuteStep(&haveNullGuids); + NS_ENSURE_SUCCESS(rv, rv); + MOZ_ASSERT(!haveNullGuids && "Found a bookmark without a GUID!"); + + rv = mMainConn->CreateStatement(NS_LITERAL_CSTRING( "SELECT 1 " "FROM moz_favicons " "WHERE guid IS NULL " ), getter_AddRefs(stmt)); NS_ENSURE_SUCCESS(rv, rv); - - bool haveNullGuids; rv = stmt->ExecuteStep(&haveNullGuids); NS_ENSURE_SUCCESS(rv, rv); - NS_ASSERTION(!haveNullGuids, - "Someone added an entry without adding a GUID!"); + MOZ_ASSERT(!haveNullGuids && "Found a favicon without a GUID!"); } #endif diff --git a/toolkit/components/places/Database.h b/toolkit/components/places/Database.h index 20da36e1c05d..82df715c4422 100644 --- a/toolkit/components/places/Database.h +++ b/toolkit/components/places/Database.h @@ -47,7 +47,7 @@ // This is the schema version. Update it at any schema change and add a // corresponding migrateVxx method below. -#define DATABASE_SCHEMA_VERSION 15 +#define DATABASE_SCHEMA_VERSION 16 // Fired after Places inited. #define TOPIC_PLACES_INIT_COMPLETE "places-init-complete" @@ -298,6 +298,7 @@ protected: nsresult MigrateV13Up(); nsresult MigrateV14Up(); nsresult MigrateV15Up(); + nsresult MigrateV16Up(); nsresult UpdateBookmarkRootTitles(); nsresult CheckAndUpdateGUIDs(); diff --git a/toolkit/components/places/tests/head_common.js b/toolkit/components/places/tests/head_common.js index 24d671f6ee23..0b0d6d082370 100644 --- a/toolkit/components/places/tests/head_common.js +++ b/toolkit/components/places/tests/head_common.js @@ -35,7 +35,7 @@ * * ***** END LICENSE BLOCK ***** */ -const CURRENT_SCHEMA_VERSION = 15; +const CURRENT_SCHEMA_VERSION = 16; const NS_APP_USER_PROFILE_50_DIR = "ProfD"; const NS_APP_PROFILE_DIR_STARTUP = "ProfDS"; diff --git a/toolkit/components/places/tests/migration/places_v10_from_v11.sqlite b/toolkit/components/places/tests/migration/places_v10_from_v14.sqlite similarity index 97% rename from toolkit/components/places/tests/migration/places_v10_from_v11.sqlite rename to toolkit/components/places/tests/migration/places_v10_from_v14.sqlite index e3f9ef4463fb..810416564845 100644 Binary files a/toolkit/components/places/tests/migration/places_v10_from_v11.sqlite and b/toolkit/components/places/tests/migration/places_v10_from_v14.sqlite differ diff --git a/toolkit/components/places/tests/migration/test_current_from_v10_migrated_from_v11.js b/toolkit/components/places/tests/migration/test_current_from_v10_migrated_from_v14.js similarity index 98% rename from toolkit/components/places/tests/migration/test_current_from_v10_migrated_from_v11.js rename to toolkit/components/places/tests/migration/test_current_from_v10_migrated_from_v14.js index 6386ecc9d4ac..038a94a08f81 100644 --- a/toolkit/components/places/tests/migration/test_current_from_v10_migrated_from_v11.js +++ b/toolkit/components/places/tests/migration/test_current_from_v10_migrated_from_v14.js @@ -2,7 +2,7 @@ http://creativecommons.org/publicdomain/zero/1.0/ */ /** - * This file tests migration invariants from a database with schema version 11 + * This file tests migration invariants from a database with schema version 14 * that was then downgraded to a database with a schema version 10. Places * should then migrate this database to one with the current schema version. */ @@ -127,6 +127,6 @@ function test_final_state() function run_test() { - setPlacesDatabase("places_v10_from_v11.sqlite"); + setPlacesDatabase("places_v10_from_v14.sqlite"); run_next_test(); } diff --git a/toolkit/components/places/tests/migration/xpcshell.ini b/toolkit/components/places/tests/migration/xpcshell.ini index b38c198b0292..6722a8be386d 100644 --- a/toolkit/components/places/tests/migration/xpcshell.ini +++ b/toolkit/components/places/tests/migration/xpcshell.ini @@ -3,7 +3,7 @@ head = head_migration.js tail = [test_current_from_v10.js] -[test_current_from_v10_migrated_from_v11.js] +[test_current_from_v10_migrated_from_v14.js] [test_database_from_alpha.js] [test_database_from_v6_no_frecency.js] [test_database_from_v6_no_indices.js] diff --git a/toolkit/mozapps/extensions/content/extensions.js b/toolkit/mozapps/extensions/content/extensions.js index 8cd2d0511a1c..85297dfdc2d3 100644 --- a/toolkit/mozapps/extensions/content/extensions.js +++ b/toolkit/mozapps/extensions/content/extensions.js @@ -963,8 +963,7 @@ var gViewController = { return true; }, doCommand: function(aAddon) { - if (gViewController.currentViewObj == gListView && - aAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE) { + if (aAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE) { gViewController.commands.cmd_showItemDetails.doCommand(aAddon); return; } diff --git a/toolkit/mozapps/extensions/content/setting.xml b/toolkit/mozapps/extensions/content/setting.xml index ac6d5535b18b..337e570bbc01 100644 --- a/toolkit/mozapps/extensions/content/setting.xml +++ b/toolkit/mozapps/extensions/content/setting.xml @@ -50,7 +50,7 @@ - + @@ -170,8 +170,8 @@ - - + + @@ -207,8 +207,8 @@ - - + + @@ -270,8 +270,8 @@ - - + + @@ -306,8 +306,8 @@ - - + + @@ -320,8 +320,8 @@ - - + + @@ -358,8 +358,8 @@ - - + + @@ -395,8 +395,8 @@ - - + + @@ -476,8 +476,8 @@ - - + + diff --git a/toolkit/mozapps/extensions/test/browser/Makefile.in b/toolkit/mozapps/extensions/test/browser/Makefile.in index b04d28f0541c..41c6e0c06033 100644 --- a/toolkit/mozapps/extensions/test/browser/Makefile.in +++ b/toolkit/mozapps/extensions/test/browser/Makefile.in @@ -72,6 +72,7 @@ _MAIN_TEST_FILES = \ browser_bug610764.js \ browser_bug618502.js \ browser_bug679604.js \ + browser_bug714593.js \ browser_details.js \ browser_discovery.js \ browser_dragdrop.js \ diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug714593.js b/toolkit/mozapps/extensions/test/browser/browser_bug714593.js new file mode 100644 index 000000000000..02e1e72298d4 --- /dev/null +++ b/toolkit/mozapps/extensions/test/browser/browser_bug714593.js @@ -0,0 +1,141 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Tests that installed addons in the search view load inline prefs properly + +const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; +const NO_MATCH_URL = TESTROOT + "browser_searching_empty.xml"; + +var gManagerWindow; +var gCategoryUtilities; +var gProvider; + +function test() { + // Turn on searching for this test + Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15); + + waitForExplicitFinish(); + + gProvider = new MockProvider(); + + gProvider.createAddons([{ + id: "inlinesettings2@tests.mozilla.org", + name: "Inline Settings (Regular)", + version: "1", + optionsURL: CHROMEROOT + "options.xul", + optionsType: AddonManager.OPTIONS_TYPE_INLINE + }]); + + open_manager("addons://list/extension", function(aWindow) { + gManagerWindow = aWindow; + gCategoryUtilities = new CategoryUtilities(gManagerWindow); + run_next_test(); + }); +} + +function end_test() { + close_manager(gManagerWindow, finish); +} + +/* + * Checks whether or not the Add-ons Manager is currently searching + * + * @param aExpectedSearching + * The expected isSearching state + */ +function check_is_searching(aExpectedSearching) { + var loading = gManagerWindow.document.getElementById("search-loading"); + is(!is_hidden(loading), aExpectedSearching, + "Search throbber should be showing iff currently searching"); +} + +/* + * Completes a search + * + * @param aQuery + * The query to search for + * @param aFinishImmediately + * Boolean representing whether or not the search is expected to + * finish immediately + * @param aCallback + * The callback to call when the search is done + * @param aCategoryType + * The expected selected category after the search is done. + * Optional and defaults to "search" + */ +function search(aQuery, aFinishImmediately, aCallback, aCategoryType) { + // Point search to the correct xml test file + Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS, NO_MATCH_URL); + + aCategoryType = aCategoryType ? aCategoryType : "search"; + + var searchBox = gManagerWindow.document.getElementById("header-search"); + searchBox.value = aQuery; + + EventUtils.synthesizeMouseAtCenter(searchBox, { }, gManagerWindow); + EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow); + + var finishImmediately = true; + wait_for_view_load(gManagerWindow, function() { + is(gCategoryUtilities.selectedCategory, aCategoryType, "Expected category view should be selected"); + is(gCategoryUtilities.isTypeVisible("search"), aCategoryType == "search", + "Search category should only be visible if it is the current view"); + is(finishImmediately, aFinishImmediately, "Search should finish immediately only if expected"); + + aCallback(); + }); + + finishImmediately = false + if (!aFinishImmediately) + check_is_searching(true); +} + +/* + * Get item for a specific add-on by name + * + * @param aName + * The name of the add-on to search for + * @return Row of add-on if found, null otherwise + */ +function get_addon_item(aName) { + var id = aName + "@tests.mozilla.org"; + var list = gManagerWindow.document.getElementById("search-list"); + var rows = list.getElementsByTagName("richlistitem"); + for (var i = 0; i < rows.length; i++) { + var row = rows[i]; + if (row.mAddon && row.mAddon.id == id) + return row; + } + + return null; +} + +add_test(function() { + search("settings", false, function() { + var localFilter = gManagerWindow.document.getElementById("search-filter-local"); + EventUtils.synthesizeMouseAtCenter(localFilter, { }, gManagerWindow); + + var item = get_addon_item("inlinesettings2"); + // Force the XBL binding to apply. + item.clientTop; + var button = gManagerWindow.document.getAnonymousElementByAttribute(item, "anonid", "preferences-btn"); + is_element_visible(button, "Preferences button should be visible"); + + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + is(gManagerWindow.gViewController.currentViewObj, gManagerWindow.gDetailView, "View should have changed to detail"); + + var searchCategory = gManagerWindow.document.getElementById("category-search"); + EventUtils.synthesizeMouseAtCenter(searchCategory, { }, gManagerWindow); + wait_for_view_load(gManagerWindow, function() { + is(gManagerWindow.gViewController.currentViewObj, gManagerWindow.gSearchView, "View should have changed back to search"); + + // Reset filter to remote to avoid breaking later tests. + var remoteFilter = gManagerWindow.document.getElementById("search-filter-remote"); + EventUtils.synthesizeMouseAtCenter(remoteFilter, { }, gManagerWindow); + run_next_test(); + }); + }); + }); +}); diff --git a/toolkit/system/gnome/nsGConfService.cpp b/toolkit/system/gnome/nsGConfService.cpp index 44beaa7b6153..b07b0ea0d225 100644 --- a/toolkit/system/gnome/nsGConfService.cpp +++ b/toolkit/system/gnome/nsGConfService.cpp @@ -36,24 +36,93 @@ * * ***** END LICENSE BLOCK ***** */ +#include "mozilla/Util.h" #include "nsGConfService.h" #include "nsStringAPI.h" #include "nsCOMPtr.h" #include "nsComponentManagerUtils.h" #include "nsISupportsPrimitives.h" #include "nsIMutableArray.h" +#include "prlink.h" #include +using namespace mozilla; + +#define GCONF_FUNCTIONS \ + FUNC(gconf_client_get_default, GConfClient*, (void)) \ + FUNC(gconf_client_get_bool, gboolean, (GConfClient*, const gchar*, GError**)) \ + FUNC(gconf_client_get_string, gchar*, (GConfClient*, const gchar*, GError**)) \ + FUNC(gconf_client_get_int, gint, (GConfClient*, const gchar*, GError**)) \ + FUNC(gconf_client_get_float, gdouble, (GConfClient*, const gchar*, GError**)) \ + FUNC(gconf_client_get_list, GSList*, (GConfClient*, const gchar*, GConfValueType, GError**)) \ + FUNC(gconf_client_set_bool, gboolean, (GConfClient*, const gchar*, gboolean, GError**)) \ + FUNC(gconf_client_set_string, gboolean, (GConfClient*, const gchar*, const gchar*, GError**)) \ + FUNC(gconf_client_set_int, gboolean, (GConfClient*, const gchar*, gint, GError**)) \ + FUNC(gconf_client_set_float, gboolean, (GConfClient*, const gchar*, gdouble, GError**)) \ + FUNC(gconf_client_unset, gboolean, (GConfClient*, const gchar*, GError**)) + +#define FUNC(name, type, params) \ + typedef type (*_##name##_fn) params; \ + static _##name##_fn _##name; + +GCONF_FUNCTIONS + +#undef FUNC + +#define gconf_client_get_default _gconf_client_get_default +#define gconf_client_get_bool _gconf_client_get_bool +#define gconf_client_get_string _gconf_client_get_string +#define gconf_client_get_int _gconf_client_get_int +#define gconf_client_get_float _gconf_client_get_float +#define gconf_client_get_list _gconf_client_get_list +#define gconf_client_set_bool _gconf_client_set_bool +#define gconf_client_set_string _gconf_client_set_string +#define gconf_client_set_int _gconf_client_set_int +#define gconf_client_set_float _gconf_client_set_float +#define gconf_client_unset _gconf_client_unset + +static PRLibrary *gconfLib = nsnull; + +typedef void (*nsGConfFunc)(); +struct nsGConfDynamicFunction { + const char *functionName; + nsGConfFunc *function; +}; + nsGConfService::~nsGConfService() { if (mClient) g_object_unref(mClient); + + // We don't unload gconf here because liborbit uses atexit(). In addition to + // this, it's not a good idea to unload any gobject based library, as it + // leaves types registered in glib's type system } nsresult nsGConfService::Init() { +#define FUNC(name, type, params) { #name, (nsGConfFunc *)&_##name }, + static const nsGConfDynamicFunction kGConfSymbols[] = { + GCONF_FUNCTIONS + }; +#undef FUNC + + if (!gconfLib) { + gconfLib = PR_LoadLibrary("libgconf-2.so.4"); + if (!gconfLib) + return NS_ERROR_FAILURE; + } + + for (PRUint32 i = 0; i < ArrayLength(kGConfSymbols); i++) { + *kGConfSymbols[i].function = + PR_FindFunctionSymbol(gconfLib, kGConfSymbols[i].functionName); + if (!*kGConfSymbols[i].function) { + return NS_ERROR_FAILURE; + } + } + mClient = gconf_client_get_default(); return mClient ? NS_OK : NS_ERROR_FAILURE; } diff --git a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp index f49836a87a96..f24b9b9d4a55 100644 --- a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp +++ b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp @@ -456,7 +456,8 @@ nsUnixSystemProxySettings::GetProxyFromGSettings(const nsACString& aScheme, rv = mGSettings->GetCollectionForSchema(NS_LITERAL_CSTRING("org.gnome.system.proxy"), getter_AddRefs(proxy_settings)); - NS_ENSURE_SUCCESS(rv, rv); + if (NS_FAILED(rv)) + return rv; nsCString proxyMode; rv = proxy_settings->GetString(NS_LITERAL_CSTRING("mode"), proxyMode); diff --git a/toolkit/xre/MacQuirks.h b/toolkit/xre/MacQuirks.h index c3060ad824c8..b8d6b13767f0 100644 --- a/toolkit/xre/MacQuirks.h +++ b/toolkit/xre/MacQuirks.h @@ -47,6 +47,197 @@ #include "CoreServices/CoreServices.h" #include "Carbon/Carbon.h" +// This file is a copy and paste from existing methods from +// libxul. This is intentional because this interpose +// library does not link with libxul. + +struct VersionPart { + PRInt32 numA; + + const char *strB; // NOT null-terminated, can be a null pointer + PRUint32 strBlen; + + PRInt32 numC; + + char *extraD; // null-terminated +}; + +/** + * Parse a version part into a number and "extra text". + * + * @returns A pointer to the next versionpart, or null if none. + */ +static char* +ParseVP(char *part, VersionPart &result) +{ + char *dot; + + result.numA = 0; + result.strB = NULL; + result.strBlen = 0; + result.numC = 0; + result.extraD = NULL; + + if (!part) + return part; + + dot = strchr(part, '.'); + if (dot) + *dot = '\0'; + + if (part[0] == '*' && part[1] == '\0') { + result.numA = INT32_MAX; + result.strB = ""; + } + else { + result.numA = strtol(part, const_cast(&result.strB), 10); + } + + if (!*result.strB) { + result.strB = NULL; + result.strBlen = 0; + } + else { + if (result.strB[0] == '+') { + static const char kPre[] = "pre"; + + ++result.numA; + result.strB = kPre; + result.strBlen = sizeof(kPre) - 1; + } + else { + const char *numstart = strpbrk(result.strB, "0123456789+-"); + if (!numstart) { + result.strBlen = strlen(result.strB); + } + else { + result.strBlen = numstart - result.strB; + + result.numC = strtol(numstart, &result.extraD, 10); + if (!*result.extraD) + result.extraD = NULL; + } + } + } + + if (dot) { + ++dot; + + if (!*dot) + dot = NULL; + } + + return dot; +} + + +// compare two null-terminated strings, which may be null pointers +static PRInt32 +ns_strcmp(const char *str1, const char *str2) +{ + // any string is *before* no string + if (!str1) + return str2 != 0; + + if (!str2) + return -1; + + return strcmp(str1, str2); +} + +// compare two length-specified string, which may be null pointers +static PRInt32 +ns_strnncmp(const char *str1, PRUint32 len1, const char *str2, PRUint32 len2) +{ + // any string is *before* no string + if (!str1) + return str2 != 0; + + if (!str2) + return -1; + + for (; len1 && len2; --len1, --len2, ++str1, ++str2) { + if (*str1 < *str2) + return -1; + + if (*str1 > *str2) + return 1; + } + + if (len1 == 0) + return len2 == 0 ? 0 : -1; + + return 1; +} + +// compare two PRInt32 +static PRInt32 +ns_cmp(PRInt32 n1, PRInt32 n2) +{ + if (n1 < n2) + return -1; + + return n1 != n2; +} + +/** + * Compares two VersionParts + */ +static PRInt32 +CompareVP(VersionPart &v1, VersionPart &v2) +{ + PRInt32 r = ns_cmp(v1.numA, v2.numA); + if (r) + return r; + + r = ns_strnncmp(v1.strB, v1.strBlen, v2.strB, v2.strBlen); + if (r) + return r; + + r = ns_cmp(v1.numC, v2.numC); + if (r) + return r; + + return ns_strcmp(v1.extraD, v2.extraD); +} + +/* this is intentionally not static so that we don't end up making copies + * anywhere */ +PRInt32 +NS_CompareVersions(const char *A, const char *B) +{ + char *A2 = strdup(A); + if (!A2) + return 1; + + char *B2 = strdup(B); + if (!B2) { + free(A2); + return 1; + } + + PRInt32 result; + char *a = A2, *b = B2; + + do { + VersionPart va, vb; + + a = ParseVP(a, va); + b = ParseVP(b, vb); + + result = CompareVP(va, vb); + if (result) + break; + + } while (a || b); + + free(A2); + free(B2); + + return result; +} + + static void TriggerQuirks() { diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 627e89d6073c..10d687c344d8 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -69,7 +69,6 @@ #ifdef XP_MACOSX #include "nsVersionComparator.h" -#include "MacQuirks.h" #include "MacLaunchHelper.h" #include "MacApplicationDelegate.h" #include "MacAutoreleasePool.h" @@ -2594,10 +2593,6 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData) NS_BREAK(); #endif -#ifdef XP_MACOSX - TriggerQuirks(); -#endif - // see bug 639842 // it's very important to fire this process BEFORE we set up error handling. // indeed, this process is expected to be crashy, and we don't want the user to see its crashes. diff --git a/toolkit/xre/nsEmbedFunctions.cpp b/toolkit/xre/nsEmbedFunctions.cpp index 8c24bba2e821..8337b710dda7 100644 --- a/toolkit/xre/nsEmbedFunctions.cpp +++ b/toolkit/xre/nsEmbedFunctions.cpp @@ -79,7 +79,6 @@ #include "mozilla/Omnijar.h" #if defined(XP_MACOSX) #include "nsVersionComparator.h" -#include "MacQuirks.h" #include "chrome/common/mach_ipc_mac.h" #endif #include "nsX11ErrorHandler.h" @@ -314,10 +313,6 @@ XRE_InitChildProcess(int aArgc, NS_ENSURE_ARG_POINTER(aArgv); NS_ENSURE_ARG_POINTER(aArgv[0]); -#ifdef XP_MACOSX - TriggerQuirks(); -#endif - sChildProcessType = aProcess; // Complete 'task_t' exchange for Mac OS X. This structure has the same size diff --git a/widget/android/AndroidDirectTexture.cpp b/widget/android/AndroidDirectTexture.cpp index 5a118e4bf4c8..80d06dba51d2 100644 --- a/widget/android/AndroidDirectTexture.cpp +++ b/widget/android/AndroidDirectTexture.cpp @@ -126,6 +126,9 @@ AndroidDirectTexture::Reallocate(PRUint32 aWidth, PRUint32 aHeight, gfxASurface: bool result = mBackBuffer->Reallocate(aWidth, aHeight, aFormat); if (result) { mPendingReallocBuffer = mFrontBuffer; + + mWidth = aWidth; + mHeight = aHeight; } return result; diff --git a/widget/android/AndroidGraphicBuffer.cpp b/widget/android/AndroidGraphicBuffer.cpp index 97ab7b806a55..510a243a41dc 100644 --- a/widget/android/AndroidGraphicBuffer.cpp +++ b/widget/android/AndroidGraphicBuffer.cpp @@ -234,6 +234,11 @@ private: namespace mozilla { +static void clearGLError() +{ + while (glGetError() != GL_NO_ERROR); +} + static bool ensureNoGLError(const char* name) { bool result = true; @@ -298,11 +303,11 @@ AndroidGraphicBuffer::DestroyBuffer() } bool -AndroidGraphicBuffer::EnsureBufferCreated(PRUint32 aWidth, PRUint32 aHeight, PRUint32 aUsage, gfxImageFormat aFormat) +AndroidGraphicBuffer::EnsureBufferCreated() { if (!mHandle) { mHandle = malloc(GRAPHIC_BUFFER_SIZE); - sGLFunctions.fGraphicBufferCtor(mHandle, mWidth, mHeight, GetAndroidFormat(aFormat), GetAndroidUsage(aUsage)); + sGLFunctions.fGraphicBufferCtor(mHandle, mWidth, mHeight, GetAndroidFormat(mFormat), GetAndroidUsage(mUsage)); } return true; @@ -315,7 +320,7 @@ AndroidGraphicBuffer::EnsureInitialized() return false; } - EnsureBufferCreated(mWidth, mHeight, mUsage, mFormat); + EnsureBufferCreated(); return true; } @@ -358,19 +363,19 @@ AndroidGraphicBuffer::Reallocate(PRUint32 aWidth, PRUint32 aHeight, gfxImageForm if (!EnsureInitialized()) return false; + mWidth = aWidth; + mHeight = aHeight; + mFormat = aFormat; + // Sometimes GraphicBuffer::reallocate just doesn't work. In those cases we'll just allocate a brand // new buffer. If reallocate fails once, never try it again. if (!gTryRealloc || sGLFunctions.fGraphicBufferReallocate(mHandle, aWidth, aHeight, GetAndroidFormat(aFormat)) != 0) { DestroyBuffer(); - EnsureBufferCreated(aWidth, aHeight, mUsage, aFormat); + EnsureBufferCreated(); gTryRealloc = false; } - mWidth = aWidth; - mHeight = aHeight; - mFormat = aFormat; - return true; } @@ -443,6 +448,7 @@ AndroidGraphicBuffer::Bind() return false; } + clearGLError(); sGLFunctions.fImageTargetTexture2DOES(GL_TEXTURE_2D, mEGLImage); return ensureNoGLError("glEGLImageTargetTexture2DOES"); } diff --git a/widget/android/AndroidGraphicBuffer.h b/widget/android/AndroidGraphicBuffer.h index 961c7e29d3bf..4a2ffd0ec7ba 100644 --- a/widget/android/AndroidGraphicBuffer.h +++ b/widget/android/AndroidGraphicBuffer.h @@ -86,7 +86,7 @@ private: bool EnsureEGLImage(); void DestroyBuffer(); - bool EnsureBufferCreated(PRUint32 aWidth, PRUint32 aHeight, PRUint32 aUsage, gfxASurface::gfxImageFormat aFormat); + bool EnsureBufferCreated(); PRUint32 GetAndroidUsage(PRUint32 aUsage); PRUint32 GetAndroidFormat(gfxASurface::gfxImageFormat aFormat); diff --git a/widget/android/nsScreenManagerAndroid.cpp b/widget/android/nsScreenManagerAndroid.cpp index 2a006b57f353..079b6dc66338 100644 --- a/widget/android/nsScreenManagerAndroid.cpp +++ b/widget/android/nsScreenManagerAndroid.cpp @@ -42,8 +42,6 @@ using namespace mozilla; -NS_IMPL_ISUPPORTS2(nsScreenAndroid, nsIScreen, nsIScreen_MOZILLA_2_0_BRANCH) - nsScreenAndroid::nsScreenAndroid(void *nativeScreen) { } diff --git a/widget/android/nsScreenManagerAndroid.h b/widget/android/nsScreenManagerAndroid.h index 9907155cacc6..e2ce02e71d08 100644 --- a/widget/android/nsScreenManagerAndroid.h +++ b/widget/android/nsScreenManagerAndroid.h @@ -41,23 +41,23 @@ #include "nsCOMPtr.h" +#include "nsBaseScreen.h" #include "nsIScreenManager.h" -#include "nsIScreen.h" #include "WidgetUtils.h" -class nsScreenAndroid - : public nsIScreen - , public mozilla::widget::BrightnessLockingWidget +class nsScreenAndroid : public nsBaseScreen { public: nsScreenAndroid(void *nativeScreen); ~nsScreenAndroid(); - NS_DECL_ISUPPORTS - NS_DECL_NSISCREEN + NS_IMETHOD GetRect(PRInt32* aLeft, PRInt32* aTop, PRInt32* aWidth, PRInt32* aHeight); + NS_IMETHOD GetAvailRect(PRInt32* aLeft, PRInt32* aTop, PRInt32* aWidth, PRInt32* aHeight); + NS_IMETHOD GetPixelDepth(PRInt32* aPixelDepth); + NS_IMETHOD GetColorDepth(PRInt32* aColorDepth); protected: - void ApplyMinimumBrightness(PRUint32 aBrightness); + virtual void ApplyMinimumBrightness(PRUint32 aBrightness) MOZ_OVERRIDE; }; class nsScreenManagerAndroid : diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index 377788e1b65f..1454756dff3f 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -1191,9 +1191,8 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae) nsAutoString metadata; unsigned char *bits = NULL; if (sHasDirectTexture) { - if ((sDirectTexture->Width() != gAndroidBounds.width || - sDirectTexture->Height() != gAndroidBounds.height) && - gAndroidBounds.width != 0 && gAndroidBounds.height != 0) { + if (sDirectTexture->Width() != gAndroidBounds.width || + sDirectTexture->Height() != gAndroidBounds.height) { sDirectTexture->Reallocate(gAndroidBounds.width, gAndroidBounds.height); } diff --git a/widget/cocoa/nsScreenCocoa.h b/widget/cocoa/nsScreenCocoa.h index e3df1582d75d..60d275170f8f 100644 --- a/widget/cocoa/nsScreenCocoa.h +++ b/widget/cocoa/nsScreenCocoa.h @@ -41,17 +41,18 @@ #import -#include "nsIScreen.h" +#include "nsBaseScreen.h" -class nsScreenCocoa : public nsIScreen +class nsScreenCocoa : public nsBaseScreen { public: nsScreenCocoa (NSScreen *screen); ~nsScreenCocoa (); - NS_DECL_ISUPPORTS - - NS_DECL_NSISCREEN + NS_IMETHOD GetRect(PRInt32* aLeft, PRInt32* aTop, PRInt32* aWidth, PRInt32* aHeight); + NS_IMETHOD GetAvailRect(PRInt32* aLeft, PRInt32* aTop, PRInt32* aWidth, PRInt32* aHeight); + NS_IMETHOD GetPixelDepth(PRInt32* aPixelDepth); + NS_IMETHOD GetColorDepth(PRInt32* aColorDepth); NSScreen *CocoaScreen() { return mScreen; } diff --git a/widget/cocoa/nsScreenCocoa.mm b/widget/cocoa/nsScreenCocoa.mm index d6742a087711..ee3eb798b96e 100644 --- a/widget/cocoa/nsScreenCocoa.mm +++ b/widget/cocoa/nsScreenCocoa.mm @@ -40,8 +40,6 @@ #include "nsObjCExceptions.h" #include "nsCocoaUtils.h" -NS_IMPL_ISUPPORTS1(nsScreenCocoa, nsIScreen) - nsScreenCocoa::nsScreenCocoa (NSScreen *screen) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; diff --git a/widget/gonk/nsScreenManagerGonk.cpp b/widget/gonk/nsScreenManagerGonk.cpp index 1a7744acd29e..130942490d86 100644 --- a/widget/gonk/nsScreenManagerGonk.cpp +++ b/widget/gonk/nsScreenManagerGonk.cpp @@ -41,8 +41,6 @@ using namespace mozilla; -NS_IMPL_ISUPPORTS2(nsScreenGonk, nsIScreen, nsIScreen) - nsScreenGonk::nsScreenGonk(void *nativeScreen) { } @@ -64,16 +62,14 @@ nsScreenGonk::GetRect(PRInt32 *outLeft, PRInt32 *outTop, return NS_OK; } - NS_IMETHODIMP nsScreenGonk::GetAvailRect(PRInt32 *outLeft, PRInt32 *outTop, - PRInt32 *outWidth, PRInt32 *outHeight) + PRInt32 *outWidth, PRInt32 *outHeight) { return GetRect(outLeft, outTop, outWidth, outHeight); } - NS_IMETHODIMP nsScreenGonk::GetPixelDepth(PRInt32 *aPixelDepth) { @@ -83,7 +79,6 @@ nsScreenGonk::GetPixelDepth(PRInt32 *aPixelDepth) return NS_OK; } - NS_IMETHODIMP nsScreenGonk::GetColorDepth(PRInt32 *aColorDepth) { diff --git a/widget/gonk/nsScreenManagerGonk.h b/widget/gonk/nsScreenManagerGonk.h index cb6d2a61037e..e99562c8629e 100644 --- a/widget/gonk/nsScreenManagerGonk.h +++ b/widget/gonk/nsScreenManagerGonk.h @@ -41,18 +41,19 @@ #include "nsCOMPtr.h" +#include "nsBaseScreen.h" #include "nsIScreenManager.h" -#include "nsIScreen.h" -#include "WidgetUtils.h" -class nsScreenGonk : public nsIScreen +class nsScreenGonk : public nsBaseScreen { public: - nsScreenGonk(void *nativeScreen); + nsScreenGonk(void* nativeScreen); ~nsScreenGonk(); - NS_DECL_ISUPPORTS - NS_DECL_NSISCREEN + NS_IMETHOD GetRect(PRInt32* aLeft, PRInt32* aTop, PRInt32* aWidth, PRInt32* aHeight); + NS_IMETHOD GetAvailRect(PRInt32* aLeft, PRInt32* aTop, PRInt32* aWidth, PRInt32* aHeight); + NS_IMETHOD GetPixelDepth(PRInt32* aPixelDepth); + NS_IMETHOD GetColorDepth(PRInt32* aColorDepth); }; class nsScreenManagerGonk : public nsIScreenManager diff --git a/widget/gtk2/nsScreenGtk.cpp b/widget/gtk2/nsScreenGtk.cpp index 68c6e659f840..ca69cf19fccc 100644 --- a/widget/gtk2/nsScreenGtk.cpp +++ b/widget/gtk2/nsScreenGtk.cpp @@ -58,10 +58,6 @@ nsScreenGtk :: ~nsScreenGtk() } -// addref, release, QI -NS_IMPL_ISUPPORTS1(nsScreenGtk, nsIScreen) - - NS_IMETHODIMP nsScreenGtk :: GetRect(PRInt32 *outLeft, PRInt32 *outTop, PRInt32 *outWidth, PRInt32 *outHeight) { diff --git a/widget/gtk2/nsScreenGtk.h b/widget/gtk2/nsScreenGtk.h index 258e6a2c7d5b..9bf285f97484 100644 --- a/widget/gtk2/nsScreenGtk.h +++ b/widget/gtk2/nsScreenGtk.h @@ -38,7 +38,7 @@ #ifndef nsScreenGtk_h___ #define nsScreenGtk_h___ -#include "nsIScreen.h" +#include "nsBaseScreen.h" #include "nsRect.h" #include "gdk/gdk.h" #ifdef MOZ_X11 @@ -56,14 +56,16 @@ typedef struct { //------------------------------------------------------------------------ -class nsScreenGtk : public nsIScreen +class nsScreenGtk : public nsBaseScreen { public: nsScreenGtk(); ~nsScreenGtk(); - NS_DECL_ISUPPORTS - NS_DECL_NSISCREEN + NS_IMETHOD GetRect(PRInt32* aLeft, PRInt32* aTop, PRInt32* aWidth, PRInt32* aHeight); + NS_IMETHOD GetAvailRect(PRInt32* aLeft, PRInt32* aTop, PRInt32* aWidth, PRInt32* aHeight); + NS_IMETHOD GetPixelDepth(PRInt32* aPixelDepth); + NS_IMETHOD GetColorDepth(PRInt32* aColorDepth); void Init(GdkWindow *aRootWindow); #ifdef MOZ_X11 diff --git a/widget/nsIScreen.idl b/widget/nsIScreen.idl index 1acca42629cd..633cd45fe57c 100644 --- a/widget/nsIScreen.idl +++ b/widget/nsIScreen.idl @@ -38,24 +38,9 @@ #include "nsISupports.idl" - -[scriptable, uuid(f728830e-1dd1-11b2-9598-fb9f414f2465)] +[scriptable, uuid(498dcd6c-94a2-4c32-8c77-531b583dff37)] interface nsIScreen : nsISupports { - void GetRect ( out long left, out long top, out long width, out long height ); - void GetAvailRect ( out long left, out long top, out long width, out long height ); - - readonly attribute long pixelDepth; - readonly attribute long colorDepth; -}; - - -%{ C++ - -%} - -[scriptable, uuid(f7c93d20-c4e4-4628-b343-cb5530b04f15)] -interface nsIScreen_MOZILLA_2_0_BRANCH : nsISupports { /** * Levels of brightness for the screen, from off to full brightness. */ @@ -65,6 +50,9 @@ interface nsIScreen_MOZILLA_2_0_BRANCH : nsISupports { /* The number of different brightness levels */ const unsigned long BRIGHTNESS_LEVELS = 2; + void GetRect(out long left, out long top, out long width, out long height); + void GetAvailRect(out long left, out long top, out long width, out long height); + /** * Locks the minimum brightness of the screen, forcing it to be at * least as bright as a certain brightness level. Each call to this @@ -82,5 +70,7 @@ interface nsIScreen_MOZILLA_2_0_BRANCH : nsISupports { * @param brightness A brightness level, one of the above constants. */ void unlockMinimumBrightness(in unsigned long brightness); + + readonly attribute long pixelDepth; + readonly attribute long colorDepth; }; - diff --git a/widget/os2/nsScreenOS2.cpp b/widget/os2/nsScreenOS2.cpp index 74b47e7bb740..cd8a408a48cc 100644 --- a/widget/os2/nsScreenOS2.cpp +++ b/widget/os2/nsScreenOS2.cpp @@ -51,10 +51,6 @@ nsScreenOS2 :: ~nsScreenOS2() } -// addref, release, QI -NS_IMPL_ISUPPORTS1(nsScreenOS2, nsIScreen) - - NS_IMETHODIMP nsScreenOS2 :: GetRect(PRInt32 *outLeft, PRInt32 *outTop, PRInt32 *outWidth, PRInt32 *outHeight) { diff --git a/widget/os2/nsScreenOS2.h b/widget/os2/nsScreenOS2.h index b7e70fec7ddb..47a4b378f19b 100644 --- a/widget/os2/nsScreenOS2.h +++ b/widget/os2/nsScreenOS2.h @@ -38,7 +38,7 @@ #ifndef nsScreenOS2_h___ #define nsScreenOS2_h___ -#include "nsIScreen.h" +#include "nsBaseScreen.h" #define INCL_WIN #define INCL_DOS @@ -46,14 +46,16 @@ //------------------------------------------------------------------------ -class nsScreenOS2 : public nsIScreen +class nsScreenOS2 : public nsBaseScreen { public: nsScreenOS2 ( ); virtual ~nsScreenOS2(); - NS_DECL_ISUPPORTS - NS_DECL_NSISCREEN + NS_IMETHOD GetRect(PRInt32* aLeft, PRInt32* aTop, PRInt32* aWidth, PRInt32* aHeight); + NS_IMETHOD GetAvailRect(PRInt32* aLeft, PRInt32* aTop, PRInt32* aWidth, PRInt32* aHeight); + NS_IMETHOD GetPixelDepth(PRInt32* aPixelDepth); + NS_IMETHOD GetColorDepth(PRInt32* aColorDepth); private: diff --git a/widget/qt/nsScreenQt.cpp b/widget/qt/nsScreenQt.cpp index eb3e6419b4e6..97f532d74ee0 100644 --- a/widget/qt/nsScreenQt.cpp +++ b/widget/qt/nsScreenQt.cpp @@ -79,13 +79,6 @@ nsScreenQt::~nsScreenQt() #endif } -// addref, release, QI -#ifdef MOZ_ENABLE_QMSYSTEM2 -NS_IMPL_ISUPPORTS2(nsScreenQt, nsIScreen, nsIScreen_MOZILLA_2_0_BRANCH) -#else -NS_IMPL_ISUPPORTS1(nsScreenQt, nsIScreen) -#endif - NS_IMETHODIMP nsScreenQt::GetRect(PRInt32 *outLeft,PRInt32 *outTop, PRInt32 *outWidth,PRInt32 *outHeight) diff --git a/widget/qt/nsScreenQt.h b/widget/qt/nsScreenQt.h index e5bf5733ae81..18292eda7931 100644 --- a/widget/qt/nsScreenQt.h +++ b/widget/qt/nsScreenQt.h @@ -41,10 +41,9 @@ #ifndef nsScreenQt_h___ #define nsScreenQt_h___ -#include "nsIScreen.h" +#include "nsBaseScreen.h" #ifdef MOZ_ENABLE_QMSYSTEM2 -#include "WidgetUtils.h" namespace MeeGo { class QmDisplayState; @@ -54,20 +53,20 @@ namespace MeeGo //------------------------------------------------------------------------ -class nsScreenQt : public nsIScreen -#ifdef MOZ_ENABLE_QMSYSTEM2 - , public mozilla::widget::BrightnessLockingWidget -#endif +class nsScreenQt : public nsBaseScreen { public: nsScreenQt (int aScreen); virtual ~nsScreenQt(); - NS_DECL_ISUPPORTS - NS_DECL_NSISCREEN + NS_IMETHOD GetRect(PRInt32* aLeft, PRInt32* aTop, PRInt32* aWidth, PRInt32* aHeight); + NS_IMETHOD GetAvailRect(PRInt32* aLeft, PRInt32* aTop, PRInt32* aWidth, PRInt32* aHeight); + NS_IMETHOD GetPixelDepth(PRInt32* aPixelDepth); + NS_IMETHOD GetColorDepth(PRInt32* aColorDepth); #ifdef MOZ_ENABLE_QMSYSTEM2 - void ApplyMinimumBrightness(PRUint32 aType); +protected: + virtual void ApplyMinimumBrightness(PRUint32 aType) MOZ_OVERRIDE; private: MeeGo::QmDisplayState* mDisplayState; #endif diff --git a/widget/shared/WidgetUtils.cpp b/widget/shared/WidgetUtils.cpp index 133a475cc1ef..fc5a78fb9a61 100644 --- a/widget/shared/WidgetUtils.cpp +++ b/widget/shared/WidgetUtils.cpp @@ -80,54 +80,5 @@ WidgetUtils::DOMWindowToWidget(nsIDOMWindow *aDOMWindow) return widget.forget(); } -// class BrightnessLockingWidget - -BrightnessLockingWidget::BrightnessLockingWidget() -{ - for (PRUint32 i = 0; i < nsIScreen_MOZILLA_2_0_BRANCH::BRIGHTNESS_LEVELS; i++) - mBrightnessLocks[i] = 0; -} - -NS_IMETHODIMP -BrightnessLockingWidget::LockMinimumBrightness(PRUint32 aBrightness) -{ - NS_ABORT_IF_FALSE( - aBrightness < nsIScreen_MOZILLA_2_0_BRANCH::BRIGHTNESS_LEVELS, - "Invalid brightness level to lock"); - mBrightnessLocks[aBrightness]++; - NS_ABORT_IF_FALSE(mBrightnessLocks[aBrightness] > 0, - "Overflow after locking brightness level"); - - CheckMinimumBrightness(); - - return NS_OK; -} - -NS_IMETHODIMP -BrightnessLockingWidget::UnlockMinimumBrightness(PRUint32 aBrightness) -{ - NS_ABORT_IF_FALSE( - aBrightness < nsIScreen_MOZILLA_2_0_BRANCH::BRIGHTNESS_LEVELS, - "Invalid brightness level to lock"); - NS_ABORT_IF_FALSE(mBrightnessLocks[aBrightness] > 0, - "Unlocking a brightness level with no corresponding lock"); - mBrightnessLocks[aBrightness]--; - - CheckMinimumBrightness(); - - return NS_OK; -} - -void -BrightnessLockingWidget::CheckMinimumBrightness() -{ - PRUint32 brightness = nsIScreen_MOZILLA_2_0_BRANCH::BRIGHTNESS_LEVELS; - for (PRUint32 i = 0; i < nsIScreen_MOZILLA_2_0_BRANCH::BRIGHTNESS_LEVELS; i++) - if (mBrightnessLocks[i] > 0) - brightness = i; - - ApplyMinimumBrightness(brightness); -} - } // namespace widget } // namespace mozilla diff --git a/widget/shared/WidgetUtils.h b/widget/shared/WidgetUtils.h index 32800caa647d..8ab96732d439 100644 --- a/widget/shared/WidgetUtils.h +++ b/widget/shared/WidgetUtils.h @@ -45,7 +45,6 @@ #include "nsIWidget.h" #include "nsPIDOMWindow.h" #include "nsIDOMWindow.h" -#include "nsIScreen.h" namespace mozilla { namespace widget { @@ -61,46 +60,6 @@ public: static already_AddRefed DOMWindowToWidget(nsIDOMWindow *aDOMWindow); }; -/** - * Simple management of screen brightness locks. This abstract base class - * allows all widget implementations to share brightness locking code. - */ -class BrightnessLockingWidget : public nsIScreen_MOZILLA_2_0_BRANCH -{ -public: - BrightnessLockingWidget(); - - NS_IMETHOD LockMinimumBrightness(PRUint32 aBrightness); - NS_IMETHOD UnlockMinimumBrightness(PRUint32 aBrightness); - -protected: - /** - * Manually set the current level of brightness locking. This is called after - * we determine, based on the current active locks, what the strongest - * lock is. You should normally not call this function - it will be - * called automatically by this class. - * - * Each widget implementation should implement this in a way that - * makes sense there. This is normally the only function that - * contains widget-specific code. - * - * @param aBrightness The current brightness level to set. If this is - * nsIScreen_MOZILLA_2_0_BRANCH::BRIGHTNESS_LEVELS - * (an impossible value for a brightness level to be), - * then that signifies that there is no current - * minimum brightness level, and the screen can shut off. - */ - virtual void ApplyMinimumBrightness(PRUint32 aBrightness) = 0; - - /** - * Checks what the minimum brightness value is, and calls - * ApplyMinimumBrightness. - */ - void CheckMinimumBrightness(); - - PRUint32 mBrightnessLocks[nsIScreen_MOZILLA_2_0_BRANCH::BRIGHTNESS_LEVELS]; -}; - } // namespace widget } // namespace mozilla diff --git a/widget/windows/nsScreenManagerWin.cpp b/widget/windows/nsScreenManagerWin.cpp index 3e4748c98177..da4064ddf29d 100644 --- a/widget/windows/nsScreenManagerWin.cpp +++ b/widget/windows/nsScreenManagerWin.cpp @@ -35,16 +35,6 @@ * * ***** END LICENSE BLOCK ***** */ -// -// We have to do this in order to have access to the multiple-monitor -// APIs that are only defined when WINVER is >= 0x0500. Don't worry, -// these won't actually be called unless they are present. -// -#undef WINVER -#define WINVER 0x0500 -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0500 - #include "nsScreenManagerWin.h" #include "nsScreenWin.h" @@ -78,7 +68,7 @@ NS_IMPL_ISUPPORTS1(nsScreenManagerWin, nsIScreenManager) // screen. This should change when a multi-monitor impl is done. // nsIScreen* -nsScreenManagerWin :: CreateNewScreenObject ( void* inScreen ) +nsScreenManagerWin :: CreateNewScreenObject ( HMONITOR inScreen ) { nsIScreen* retScreen = nsnull; @@ -93,7 +83,7 @@ nsScreenManagerWin :: CreateNewScreenObject ( void* inScreen ) } // for each screen. retScreen = new nsScreenWin(inScreen); - mScreenList.AppendElement ( ScreenListItem ( (HMONITOR)inScreen, retScreen ) ); + mScreenList.AppendElement ( ScreenListItem ( inScreen, retScreen ) ); NS_IF_ADDREF(retScreen); return retScreen; @@ -120,7 +110,7 @@ nsScreenManagerWin :: ScreenForRect ( PRInt32 inLeft, PRInt32 inTop, PRInt32 inW RECT globalWindowBounds = { inLeft, inTop, inLeft + inWidth, inTop + inHeight }; - void* genScreen = ::MonitorFromRect( &globalWindowBounds, MONITOR_DEFAULTTOPRIMARY ); + HMONITOR genScreen = ::MonitorFromRect( &globalWindowBounds, MONITOR_DEFAULTTOPRIMARY ); *outScreen = CreateNewScreenObject ( genScreen ); // addrefs diff --git a/widget/windows/nsScreenManagerWin.h b/widget/windows/nsScreenManagerWin.h index 08d34db307ae..9b71730bbf3a 100644 --- a/widget/windows/nsScreenManagerWin.h +++ b/widget/windows/nsScreenManagerWin.h @@ -69,7 +69,7 @@ public: private: - nsIScreen* CreateNewScreenObject ( void* inScreen ) ; + nsIScreen* CreateNewScreenObject ( HMONITOR inScreen ) ; PRUint32 mNumberOfScreens; diff --git a/widget/windows/nsScreenWin.cpp b/widget/windows/nsScreenWin.cpp index e6c58a944170..a3f926ebb79f 100644 --- a/widget/windows/nsScreenWin.cpp +++ b/widget/windows/nsScreenWin.cpp @@ -35,20 +35,10 @@ * * ***** END LICENSE BLOCK ***** */ -// -// We have to do this in order to have access to the multiple-monitor -// APIs that are only defined when WINVER is >= 0x0500. Don't worry, -// these won't actually be called unless they are present. -// -#undef WINVER -#define WINVER 0x0500 -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0500 - #include "nsScreenWin.h" -nsScreenWin :: nsScreenWin ( void* inScreen ) +nsScreenWin :: nsScreenWin ( HMONITOR inScreen ) : mScreen(inScreen) { #ifdef DEBUG @@ -70,19 +60,14 @@ nsScreenWin :: ~nsScreenWin() } -// addref, release, QI -NS_IMPL_ISUPPORTS1(nsScreenWin, nsIScreen) - - NS_IMETHODIMP nsScreenWin :: GetRect(PRInt32 *outLeft, PRInt32 *outTop, PRInt32 *outWidth, PRInt32 *outHeight) { BOOL success = FALSE; -#if _MSC_VER >= 1200 if ( mScreen ) { MONITORINFO info; info.cbSize = sizeof(MONITORINFO); - success = ::GetMonitorInfoW( (HMONITOR)mScreen, &info ); + success = ::GetMonitorInfoW( mScreen, &info ); if ( success ) { *outLeft = info.rcMonitor.left; *outTop = info.rcMonitor.top; @@ -90,7 +75,6 @@ nsScreenWin :: GetRect(PRInt32 *outLeft, PRInt32 *outTop, PRInt32 *outWidth, PRI *outHeight = info.rcMonitor.bottom - info.rcMonitor.top; } } -#endif if (!success) { HDC hDCScreen = ::GetDC(nsnull); NS_ASSERTION(hDCScreen,"GetDC Failure"); @@ -111,11 +95,10 @@ nsScreenWin :: GetAvailRect(PRInt32 *outLeft, PRInt32 *outTop, PRInt32 *outWidth { BOOL success = FALSE; -#if _MSC_VER >= 1200 if ( mScreen ) { MONITORINFO info; info.cbSize = sizeof(MONITORINFO); - success = ::GetMonitorInfoW( (HMONITOR)mScreen, &info ); + success = ::GetMonitorInfoW( mScreen, &info ); if ( success ) { *outLeft = info.rcWork.left; *outTop = info.rcWork.top; @@ -123,7 +106,6 @@ nsScreenWin :: GetAvailRect(PRInt32 *outLeft, PRInt32 *outTop, PRInt32 *outWidth *outHeight = info.rcWork.bottom - info.rcWork.top; } } -#endif if (!success) { RECT workArea; ::SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0); diff --git a/widget/windows/nsScreenWin.h b/widget/windows/nsScreenWin.h index 5eb01d16381e..09da53d818d0 100644 --- a/widget/windows/nsScreenWin.h +++ b/widget/windows/nsScreenWin.h @@ -39,22 +39,24 @@ #define nsScreenWin_h___ #include -#include "nsIScreen.h" +#include "nsBaseScreen.h" //------------------------------------------------------------------------ -class nsScreenWin : public nsIScreen +class nsScreenWin : public nsBaseScreen { public: - nsScreenWin ( void* inScreen ); + nsScreenWin ( HMONITOR inScreen ); ~nsScreenWin(); - NS_DECL_ISUPPORTS - NS_DECL_NSISCREEN + NS_IMETHOD GetRect(PRInt32* aLeft, PRInt32* aTop, PRInt32* aWidth, PRInt32* aHeight); + NS_IMETHOD GetAvailRect(PRInt32* aLeft, PRInt32* aTop, PRInt32* aWidth, PRInt32* aHeight); + NS_IMETHOD GetPixelDepth(PRInt32* aPixelDepth); + NS_IMETHOD GetColorDepth(PRInt32* aColorDepth); private: - void* mScreen; // a |HMONITOR|, can't use this type in header file though. + HMONITOR mScreen; }; #endif // nsScreenWin_h___ diff --git a/widget/xpwidgets/Makefile.in b/widget/xpwidgets/Makefile.in index 05695d898c6e..481e93ad4db4 100644 --- a/widget/xpwidgets/Makefile.in +++ b/widget/xpwidgets/Makefile.in @@ -57,6 +57,7 @@ DEFINES += \ CPPSRCS = \ nsBaseAppShell.cpp \ + nsBaseScreen.cpp \ nsBaseWidget.cpp \ nsTransferable.cpp \ nsHTMLFormatConverter.cpp \ diff --git a/widget/xpwidgets/nsBaseScreen.cpp b/widget/xpwidgets/nsBaseScreen.cpp new file mode 100644 index 000000000000..2d3f46d90a5f --- /dev/null +++ b/widget/xpwidgets/nsBaseScreen.cpp @@ -0,0 +1,92 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: sw=2 ts=8 et : + */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Code. + * + * The Initial Developer of the Original Code is + * The Mozilla Foundation + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Jones + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsBaseScreen.h" + +NS_IMPL_ISUPPORTS1(nsBaseScreen, nsIScreen) + +nsBaseScreen::nsBaseScreen() +{ + for (PRUint32 i = 0; i < nsIScreen::BRIGHTNESS_LEVELS; i++) + mBrightnessLocks[i] = 0; +} + +nsBaseScreen::~nsBaseScreen() { } + +NS_IMETHODIMP +nsBaseScreen::LockMinimumBrightness(PRUint32 aBrightness) +{ + NS_ABORT_IF_FALSE( + aBrightness < nsIScreen::BRIGHTNESS_LEVELS, + "Invalid brightness level to lock"); + mBrightnessLocks[aBrightness]++; + NS_ABORT_IF_FALSE(mBrightnessLocks[aBrightness] > 0, + "Overflow after locking brightness level"); + + CheckMinimumBrightness(); + + return NS_OK; +} + +NS_IMETHODIMP +nsBaseScreen::UnlockMinimumBrightness(PRUint32 aBrightness) +{ + NS_ABORT_IF_FALSE( + aBrightness < nsIScreen::BRIGHTNESS_LEVELS, + "Invalid brightness level to lock"); + NS_ABORT_IF_FALSE(mBrightnessLocks[aBrightness] > 0, + "Unlocking a brightness level with no corresponding lock"); + mBrightnessLocks[aBrightness]--; + + CheckMinimumBrightness(); + + return NS_OK; +} + +void +nsBaseScreen::CheckMinimumBrightness() +{ + PRUint32 brightness = nsIScreen::BRIGHTNESS_LEVELS; + for (PRUint32 i = 0; i < nsIScreen::BRIGHTNESS_LEVELS; i++) + if (mBrightnessLocks[i] > 0) + brightness = i; + + ApplyMinimumBrightness(brightness); +} diff --git a/widget/xpwidgets/nsBaseScreen.h b/widget/xpwidgets/nsBaseScreen.h new file mode 100644 index 000000000000..0834065e5376 --- /dev/null +++ b/widget/xpwidgets/nsBaseScreen.h @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: sw=2 ts=8 et : + */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Code. + * + * The Initial Developer of the Original Code is + * The Mozilla Foundation + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Jones + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsBaseScreen_h +#define nsBaseScreen_h + +#include "mozilla/Attributes.h" +#include "nsIScreen.h" + +class nsBaseScreen : public nsIScreen +{ +public: + nsBaseScreen(); + virtual ~nsBaseScreen(); + + NS_DECL_ISUPPORTS + + // nsIScreen interface + + /** + * Simple management of screen brightness locks. This abstract base class + * allows all widget implementations to share brightness locking code. + */ + NS_IMETHOD LockMinimumBrightness(PRUint32 aBrightness); + NS_IMETHOD UnlockMinimumBrightness(PRUint32 aBrightness); + +protected: + /** + * Manually set the current level of brightness locking. This is called after + * we determine, based on the current active locks, what the strongest + * lock is. You should normally not call this function - it will be + * called automatically by this class. + * + * Each widget implementation should implement this in a way that + * makes sense there. This is normally the only function that + * contains widget-specific code. + * + * The default implementation does nothing. + * + * @param aBrightness The current brightness level to set. If this is + * nsIScreen_MOZILLA_2_0_BRANCH::BRIGHTNESS_LEVELS + * (an impossible value for a brightness level to be), + * then that signifies that there is no current + * minimum brightness level, and the screen can shut off. + */ + virtual void ApplyMinimumBrightness(PRUint32 aBrightness) { } + +private: + /** + * Checks what the minimum brightness value is, and calls + * ApplyMinimumBrightness. + */ + void CheckMinimumBrightness(); + + PRUint32 mBrightnessLocks[nsIScreen::BRIGHTNESS_LEVELS]; +}; + +#endif // nsBaseScreen_h diff --git a/xpcom/base/nsAutoRef.h b/xpcom/base/nsAutoRef.h index f211372f72d5..0dd5d9e49d51 100644 --- a/xpcom/base/nsAutoRef.h +++ b/xpcom/base/nsAutoRef.h @@ -87,7 +87,7 @@ template class nsReturningRef; * // Specializing nsAutoRefTraits describes how to manage file * // descriptors, so that nsAutoRef provides automatic closing of * // its file descriptor on destruction. - * NS_SPECIALIZE_TEMPLATE + * template <> * class nsAutoRefTraits { * public: * // The file descriptor is held in an int. @@ -431,7 +431,7 @@ public: * // integral typedefs, a new unique possibly-incomplete class may need to be * // declared. * - * NS_SPECIALIZE_TEMPLATE + * template <> * class nsAutoRefTraits * { * // Specializations must provide a typedef for RawRef, describing the @@ -477,14 +477,14 @@ template class nsAutoRefTraits; * * Examples of use: * - * NS_SPECIALIZE_TEMPLATE + * template <> * class nsAutoRefTraits : public nsPointerRefTraits * { * public: * static void Release(PRFileDesc *ptr) { PR_Close(ptr); } * }; * - * NS_SPECIALIZE_TEMPLATE + * template <> * class nsAutoRefTraits : public nsPointerRefTraits * { * public: diff --git a/xpcom/base/nscore.h b/xpcom/base/nscore.h index 21721621229b..353626c3e8cd 100644 --- a/xpcom/base/nscore.h +++ b/xpcom/base/nscore.h @@ -244,7 +244,7 @@ typedef size_t(*nsMallocSizeOfFun)(const void *p, size_t computedSize); */ #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) # define MOZ_DEPRECATED __attribute__((deprecated)) -#elif defined(_MSC_VER) && (_MSC_VER >= 1300) +#elif defined(_MSC_VER) # define MOZ_DEPRECATED __declspec(deprecated) #else # define MOZ_DEPRECATED @@ -330,7 +330,7 @@ typedef size_t(*nsMallocSizeOfFun)(const void *p, size_t computedSize); #ifdef NS_NO_VTABLE #undef NS_NO_VTABLE #endif -#if defined(_MSC_VER) && _MSC_VER >= 1100 +#if defined(_MSC_VER) #define NS_NO_VTABLE __declspec(novtable) #else #define NS_NO_VTABLE @@ -373,7 +373,7 @@ typedef PRUint32 nsrefcnt; /* Casting macros for hiding C++ features from older compilers */ /* under VC++ (Windows), we don't have autoconf yet */ -#if defined(_MSC_VER) && (_MSC_VER>=1100) +#if defined(_MSC_VER) #define HAVE_CPP_2BYTE_WCHAR_T #endif diff --git a/xpcom/io/nsLinebreakConverter.cpp b/xpcom/io/nsLinebreakConverter.cpp index f7abaf46ab68..43396e437270 100644 --- a/xpcom/io/nsLinebreakConverter.cpp +++ b/xpcom/io/nsLinebreakConverter.cpp @@ -41,14 +41,6 @@ #include "nsCRT.h" -#if defined(XP_WIN) && defined(_MSC_VER) && (_MSC_VER <= 1100) -#define LOSER_CHAR_CAST(t) (char *)(t) -#define LOSER_UNICHAR_CAST(t) (PRUnichar *)(t) -#else -#define LOSER_CHAR_CAST(t) (t) -#define LOSER_UNICHAR_CAST(t) (t) -#endif - /*---------------------------------------------------------------------------- GetLinebreakString @@ -342,9 +334,9 @@ char* nsLinebreakConverter::ConvertLineBreaks(const char* aSrc, char* resultString; if (aSrcBreaks == eLinebreakAny) - resultString = ConvertUnknownBreaks(LOSER_CHAR_CAST(aSrc), sourceLen, GetLinebreakString(aDestBreaks)); + resultString = ConvertUnknownBreaks(aSrc, sourceLen, GetLinebreakString(aDestBreaks)); else - resultString = ConvertBreaks(LOSER_CHAR_CAST(aSrc), sourceLen, GetLinebreakString(aSrcBreaks), GetLinebreakString(aDestBreaks)); + resultString = ConvertBreaks(aSrc, sourceLen, GetLinebreakString(aSrcBreaks), GetLinebreakString(aDestBreaks)); if (outLen) *outLen = sourceLen; @@ -413,9 +405,9 @@ PRUnichar* nsLinebreakConverter::ConvertUnicharLineBreaks(const PRUnichar* aSrc, PRUnichar* resultString; if (aSrcBreaks == eLinebreakAny) - resultString = ConvertUnknownBreaks(LOSER_UNICHAR_CAST(aSrc), bufLen, GetLinebreakString(aDestBreaks)); + resultString = ConvertUnknownBreaks(aSrc, bufLen, GetLinebreakString(aDestBreaks)); else - resultString = ConvertBreaks(LOSER_UNICHAR_CAST(aSrc), bufLen, GetLinebreakString(aSrcBreaks), GetLinebreakString(aDestBreaks)); + resultString = ConvertBreaks(aSrc, bufLen, GetLinebreakString(aSrcBreaks), GetLinebreakString(aDestBreaks)); if (outLen) *outLen = bufLen; diff --git a/xpcom/io/nsLocalFileWin.h b/xpcom/io/nsLocalFileWin.h index 78b557852fae..ec1051d1ebc4 100644 --- a/xpcom/io/nsLocalFileWin.h +++ b/xpcom/io/nsLocalFileWin.h @@ -52,13 +52,6 @@ #include "nsIClassInfoImpl.h" #include "windows.h" - -// For older version (<6.0) of the VC Compiler -#if (_MSC_VER == 1100) -#include -DEFINE_OLEGUID(IID_IPersistFile, 0x0000010BL, 0, 0); -#endif - #include "shlobj.h" #include