Merge last clean PGO changeset from mozilla-inbound to mozilla-central

This commit is contained in:
Marco Bonardo 2012-01-05 15:52:19 +01:00
commit 2b6c8bb207
114 changed files with 5161 additions and 1314 deletions

View File

@ -46,6 +46,10 @@
#include <sys/resource.h>
#endif
#ifdef XP_MACOSX
#include "MacQuirks.h"
#endif
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
@ -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");

View File

@ -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")];

View File

@ -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,

View File

@ -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) \

View File

@ -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"

View File

@ -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;
}

View File

@ -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<WebGLExtension> 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<nsITimer> mContextRestorer;
bool mContextLost;
bool mAllowRestore;
bool mRobustnessTimerRunning;
bool mDrawSinceRobustnessTimerSet;
ContextStatus mContextStatus;
bool mContextLostErrorSet;
bool mContextLostDueToTest;
public:
// console logging helpers

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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)

View File

@ -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 <sys/types.h>
#include <sys/sysctl.h>
#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<char**>(&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;
}

View File

@ -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();

View File

@ -43,6 +43,7 @@
#include <stdio.h>
#include "Point.h"
#include "Matrix.h"
#ifdef WIN32
#include <windows.h>
@ -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:

View File

@ -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.

View File

@ -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<gfxASurface> 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<gfxASurface> 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<gfxASurface> 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<gfxContext>
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<gfxContext> result = aTarget;
return result.forget();
@ -1360,7 +1371,7 @@ BasicLayerManager::PopGroupToSourceWithCachedSurface(gfxContext *aTarget, gfxCon
if (!aTarget)
return;
nsRefPtr<gfxASurface> 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<gfxASurface> 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<gfxContext> groupTarget;

View File

@ -165,6 +165,7 @@ public:
void ClearCachedResources();
void SetTransactionIncomplete() { mTransactionIncomplete = true; }
bool IsTransactionIncomplete() { return mTransactionIncomplete; }
already_AddRefed<gfxContext> PushGroupForLayer(gfxContext* aContext, Layer* aLayer,
const nsIntRegion& aRegion,

View File

@ -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<gfxContext> ctx = new gfxContext(aSurface);
ctx->Translate(-gfxPoint(aOffset.x, aOffset.y));
gfxUtils::PathFromRegion(ctx, aRegion);
ctx->SetColor(aColor);
ctx->Fill();
if (aSurface) {
nsRefPtr<gfxContext> 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<gfxContext> context = new gfxContext(destinationSurface);
nsRefPtr<gfxContext> 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) {

View File

@ -86,6 +86,8 @@ private:
/* This contains the thebes surface */
nsRefPtr<gfxASurface> mD2DSurface;
mozilla::RefPtr<mozilla::gfx::DrawTarget> mDrawTarget;
/* This contains the thebes surface for our render-on-white texture */
nsRefPtr<gfxASurface> mD2DSurfaceOnWhite;

View File

@ -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); }

View File

@ -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);
}

View File

@ -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;
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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 <typename T> 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<gfxASurface> 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<gfxPattern> pattern;
mozilla::RefPtr<SourceSurface> sourceSurface;
Matrix surfTransform;
Matrix transform;
struct PushedClip {
mozilla::RefPtr<Path> path;
Rect rect;
Matrix transform;
};
nsTArray<PushedClip> pushedClips;
nsTArray<Float> dashPattern;
bool clipWasReset;
mozilla::gfx::FillRule fillRule;
StrokeOptions strokeOptions;
mozilla::RefPtr<DrawTarget> drawTarget;
mozilla::RefPtr<DrawTarget> 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<PathBuilder> mPathBuilder;
mozilla::RefPtr<Path> mPath;
Matrix mTransform;
nsTArray<AzureState> mStateStack;
AzureState &CurrentState() { return mStateStack[mStateStack.Length() - 1]; }
const AzureState &CurrentState() const { return mStateStack[mStateStack.Length() - 1]; }
cairo_t *mCairo;
cairo_t *mRefCairo;
nsRefPtr<gfxASurface> mSurface;
PRInt32 mFlags;
mozilla::RefPtr<DrawTarget> mDT;
mozilla::RefPtr<DrawTarget> 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);
}

View File

@ -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.

View File

@ -76,7 +76,10 @@
#include "nsCRT.h"
#include <algorithm>
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<DrawTarget> 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> 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<gfxMatrix*>(&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);
}

View File

@ -42,24 +42,32 @@
#include "cairo.h"
#include <vector>
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<const cairo_matrix_t*>(&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<gfxMatrix*>(&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<gfxMatrix*>(&mat));
cairo_surface_t *surf = NULL;
cairo_pattern_get_surface(mPattern, &surf);
if (!mSourceSurface) {
nsRefPtr<gfxASurface> 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<GradientStop> 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<gfxMatrix*>(&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<GradientStop> 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<gfxMatrix*>(&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<gfxASurface>
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;
}
}

View File

@ -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<mozilla::gfx::ColorPattern> mColorPattern;
mozilla::AlignedStorage2<mozilla::gfx::LinearGradientPattern> mLinearGradientPattern;
mozilla::AlignedStorage2<mozilla::gfx::RadialGradientPattern> mRadialGradientPattern;
mozilla::AlignedStorage2<mozilla::gfx::SurfacePattern> mSurfacePattern;
};
mozilla::gfx::Pattern *mGfxPattern;
mozilla::RefPtr<mozilla::gfx::SourceSurface> mSourceSurface;
mozilla::gfx::Matrix mTransform;
mozilla::RefPtr<mozilla::gfx::GradientStops> mStops;
mozilla::gfx::ExtendMode mExtend;
mozilla::gfx::Filter mFilter;
};
#endif /* GFX_PATTERN_H */

View File

@ -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()
{

View File

@ -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?

View File

@ -74,7 +74,8 @@ gfxProxyFontEntry::gfxProxyFontEntry(const nsTArray<gfxFontFaceSrc>& 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()));

View File

@ -297,6 +297,7 @@ public:
LOADING_FAILED // failed to load any source: use fallback
};
LoadingState mLoadingState;
bool mUnsupportedFormat;
nsTArray<gfxFontFaceSrc> mSrcList;
PRUint32 mSrcIndex; // index of loading src item

View File

@ -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<gfxASurface> 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;

View File

@ -69,8 +69,13 @@ HDC
gfxWindowsNativeDrawing::BeginNativeDrawing()
{
if (mRenderState == RENDER_STATE_INIT) {
nsRefPtr<gfxASurface> surf = mContext->CurrentSurface(&mDeviceOffset.x, &mDeviceOffset.y);
if (!surf || surf->CairoStatus())
nsRefPtr<gfxASurface> 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<gfxASurface> 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 ||

View File

@ -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;

View File

@ -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;

View File

@ -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<AutoUnlockGC> 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<AutoUnlockGC> 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)

View File

@ -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<uintptr_t>(info.prevp);
JS_ASSERT((prevAddress & ChunkMask) == offsetof(Chunk, info.next));
return reinterpret_cast<Chunk *>(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<uintptr_t>(nextFieldPtr);
JS_ASSERT((addr & ChunkMask) == offsetof(Chunk, info.next));
return reinterpret_cast<Chunk *>(addr - offsetof(Chunk, info.next));
}
private:

View File

@ -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

View File

@ -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);

View File

@ -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().

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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);

View File

@ -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() ||

View File

@ -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));
}

View File

@ -4336,7 +4336,7 @@ public:
nsChangeHint mChangeHint;
};
class LayerActivityTracker : public nsExpirationTracker<LayerActivity,4> {
class LayerActivityTracker MOZ_FINAL : public nsExpirationTracker<LayerActivity,4> {
public:
// 75-100ms is a good timeout period. We use 4 generations of 25ms each.
enum { GENERATION_MS = 100 };

View File

@ -24,6 +24,8 @@
* David J. Fiddes <D.J.Fiddes@hw.ac.uk>
* Shyjan Mahamud <mahamud@cs.cmu.edu>
* Pierre Phaneuf <pp@ludusdesign.com>
* Jonathan Hage <hage.jonathan@gmail.com>
* Frederic Wang <fred.wang@free.fr>
*
* 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 <mover> 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...

View File

@ -0,0 +1,224 @@
<html>
<head><title></title></head>
<body>
<h2> Test with accent="false" </h2>
<table border="1">
<tr>
<td align="center"></td>
<th colspan="2">mover</th>
<th colspan="2">munder</th>
</tr>
<tr>
<td align="center"></td>
<td align="center"><mrow>
<mi>Over</mi>
<mo>&lt;</mo>
<mi>Base</mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over</mi>
<mo>&gt;</mo>
<mi>Base</mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over</mi>
<mo>&lt;</mo>
<mi>Base</mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over</mi>
<mo>&gt;</mo>
<mi>Base</mi>
</mrow></td>
</tr>
<tr>
<th>
align="left"
</th>
<td align="center">
<math>
<mover>
<mspace height="15px" width="75px" mathbackground="blue"/>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
</mrow>
</mover>
</math>
</td>
<td align="center">
<math>
<mover>
<mrow>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<munder>
<mspace height="15px" width="75px" mathbackground="blue"/>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
</mrow>
</munder>
</math>
</td>
<td align="center">
<math>
<munder>
<mrow>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
</munder>
</math>
</td>
</tr>
<tr>
<th>
align="right"
</th>
<td align="center">
<math>
<mover>
<mspace height="15px" width="75px" mathbackground="blue"/>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
</mover>
</math>
</td>
<td align="center">
<math>
<mover>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<munder>
<mspace height="15px" width="75px" mathbackground="blue"/>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
</munder>
</math>
</td>
<td align="center">
<math>
<munder>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
</munder>
</math>
</td>
</tr>
<tr>
<th>
align="center"
</th>
<td align="center">
<math>
<mover>
<mspace height="15px" width="75px" mathbackground="blue"/>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
</mrow>
</mover>
</math>
</td>
<td align="center">
<math>
<mover>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<munder>
<mspace height="15px" width="75px" mathbackground="blue"/>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
</mrow>
</munder>
</math>
</td>
<td align="center">
<math>
<munder>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
</munder>
</math>
</td>
</tr>
</table>
<table>
<tr>
<th>
<h5>Under & Over</h5>
<math>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
</math>
</th>
<th>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>
<th>
<h5>Base</h5>
<math>
<mrow>
<mspace height="15px" width="25px" mathbackground="blue"/>
</mrow>
</math>
</th>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,176 @@
<html>
<head><title></title></head>
<body>
<h2> Test with accent="false" </h2>
<table border="1">
<tr>
<td align="center"></td>
<th colspan="2">mover</th>
<th colspan="2">munder</th>
</tr>
<tr>
<td align="center"></td>
<td align="center"><mrow>
<mi>Over</mi>
<mo>&lt;</mo>
<mi>Base</mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over</mi>
<mo>&gt;</mo>
<mi>Base</mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over</mi>
<mo>&lt;</mo>
<mi>Base</mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over</mi>
<mo>&gt;</mo>
<mi>Base</mi>
</mrow></td>
</tr>
<tr>
<th>
align="left"
</th>
<td align="center">
<math>
<mover align="left">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<mover align="left">
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<munder align="left">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</munder>
</math>
</td>
<td align="center">
<math>
<munder align="left">
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munder>
</math>
</td>
</tr>
<tr>
<th>
align="right"
</th>
<td align="center">
<math>
<mover align="right">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<mover align="right">
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<munder align="right">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</munder>
</math>
</td>
<td align="center">
<math>
<munder align="right">
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munder>
</math>
</td>
</tr>
<tr>
<th>
align="center"
</th>
<td align="center">
<math>
<mover align="center">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<mover align="center">
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<munder align="center">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</munder>
</math>
</td>
<td align="center">
<math>
<munder align="center">
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munder>
</math>
</td>
</tr>
</table>
<table>
<tr>
<th>
<h5>Under & Over</h5>
<math>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
</math>
</th>
<th>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>
<th>
<h5>Base</h5>
<math>
<mrow>
<mspace height="15px" width="25px" mathbackground="blue"/>
</mrow>
</math>
</th>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,224 @@
<html>
<head><title></title></head>
<body>
<h2> Test with accent="true" </h2>
<table border="1">
<tr>
<td align="center"></td>
<th colspan="2">mover</th>
<th colspan="2">munder</th>
</tr>
<tr>
<td align="center"></td>
<td align="center"><mrow>
<mi>Over</mi>
<mo>&lt;</mo>
<mi>Base</mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over</mi>
<mo>&gt;</mo>
<mi>Base</mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over</mi>
<mo>&lt;</mo>
<mi>Base</mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over</mi>
<mo>&gt;</mo>
<mi>Base</mi>
</mrow></td>
</tr>
<tr>
<th>
align="left"
</th>
<td align="center">
<math>
<mover accent="true">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
</mrow>
</mover>
</math>
</td>
<td align="center">
<math>
<mover accent="true">
<mrow>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<munder accentunder="true">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
</mrow>
</munder>
</math>
</td>
<td align="center">
<math>
<munder accentunder="true">
<mrow>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
</munder>
</math>
</td>
</tr>
<tr>
<th>
align="right"
</th>
<td align="center">
<math>
<mover accent="true">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
</mover>
</math>
</td>
<td align="center">
<math>
<mover accent="true">
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<munder accentunder="true">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
</munder>
</math>
</td>
<td align="center">
<math>
<munder accentunder="true">
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
</munder>
</math>
</td>
</tr>
<tr>
<th>
align="center"
</th>
<td align="center">
<math>
<mover accent="true">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
</mrow>
</mover>
</math>
</td>
<td align="center">
<math>
<mover accent="true">
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<munder accentunder="true">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
</mrow>
</munder>
</math>
</td>
<td align="center">
<math>
<munder accentunder="true">
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
</munder>
</math>
</td>
</tr>
</table>
<table>
<tr>
<th>
<h5>Under & Over</h5>
<math>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
</math>
</th>
<th>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>
<th>
<h5>Base</h5>
<math>
<mrow>
<mspace height="15px" width="25px" mathbackground="blue"/>
</mrow>
</math>
</th>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,176 @@
<html>
<head><title></title></head>
<body>
<h2> Test with accent="true" </h2>
<table border="1">
<tr>
<td align="center"></td>
<th colspan="2">mover</th>
<th colspan="2">munder</th>
</tr>
<tr>
<td align="center"></td>
<td align="center"><mrow>
<mi>Over</mi>
<mo>&lt;</mo>
<mi>Base</mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over</mi>
<mo>&gt;</mo>
<mi>Base</mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over</mi>
<mo>&lt;</mo>
<mi>Base</mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over</mi>
<mo>&gt;</mo>
<mi>Base</mi>
</mrow></td>
</tr>
<tr>
<th>
align="left"
</th>
<td align="center">
<math>
<mover align="left" accent="true">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<mover align="left" accent="true">
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<munder align="left" accentunder="true">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</munder>
</math>
</td>
<td align="center">
<math>
<munder align="left" accentunder="true">
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munder>
</math>
</td>
</tr>
<tr>
<th>
align="right"
</th>
<td align="center">
<math>
<mover align="right" accent="true">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<mover align="right" accent="true">
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<munder align="right" accentunder="true">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</munder>
</math>
</td>
<td align="center">
<math>
<munder align="right" accentunder="true">
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munder>
</math>
</td>
</tr>
<tr>
<th>
align="center"
</th>
<td align="center">
<math>
<mover align="center" accent="true">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<mover align="center" accent="true">
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<munder align="center" accentunder="true">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</munder>
</math>
</td>
<td align="center">
<math>
<munder align="center" accentunder="true">
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munder>
</math>
</td>
</tr>
</table>
<table>
<tr>
<th>
<h5>Under & Over</h5>
<math>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
</math>
</th>
<th>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>
<th>
<h5>Base</h5>
<math>
<mrow>
<mspace height="15px" width="25px" mathbackground="blue"/>
</mrow>
</math>
</th>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,274 @@
<html>
<head><title></title></head>
<body>
<h2> Test with accent="false" </h2>
<table border="1">
<tr>
<td align="center"></td>
<th colspan="6">munderover</th>
</tr>
<tr>
<td align="center"></td>
<td align="center"><mrow>
<mi>Over</mi>
<mo>&lt;</mo>
<mi>Base</mi>
<mo>&lt;</mo>
<mi>Under<mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over</mi>
<mo>&gt;</mo>
<mi>Base</mi>
<mo>&gt;</mo>
<mi>Under</mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over = Under</mi>
<mo>&lt;</mo>
<mi>Base</mi>
</mrow>
</td>
<td align="center"><mrow>
<mi>Over = Under</mi>
<mo>&gt;</mo>
<mi>Base</mi>
</mrow></td>
</tr>
<tr>
<th>
align="left"
</th>
<td align="center">
<math>
<munderover accent="false" accentunder="false">
<mrow>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
</mrow>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover accent="false" accentunder="false">
<mrow>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
</mrow>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover accent="false" accentunder="false">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
</mrow>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
</mrow>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover accent="false" accentunder="false">
<mrow>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
</tr>
<tr>
<th>
align="right"
</th>
<td align="center">
<math>
<munderover accent="false" accentunder="false">
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover accent="false" accentunder="false">
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
</mrow>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover accent="false" accentunder="false">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover accent="false" accentunder="false">
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
</tr>
<tr>
<th>
align="center"
</th>
<td align="center">
<math>
<munderover accent="false" accentunder="false">
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="50px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
</mrow>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover accent="false" accentunder="false">
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="50px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
</mrow>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover accent="false" accentunder="false">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
</mrow>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
</mrow>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover accent="false" accentunder="false">
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
</tr>
</table>
<table>
<tr>
<th>
<h5>Under & Over</h5>
<math>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
</math>
</th>
<th>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>
<th>
<h5>Base</h5>
<math>
<mrow>
<mspace height="15px" width="25px" mathbackground="blue"/>
</mrow>
</math>
</th>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,190 @@
<html>
<head><title></title></head>
<body>
<h2> Test with accent="false" </h2>
<table border="1">
<tr>
<td align="center"></td>
<th colspan="4">munderover</th>
</tr>
<tr>
<td align="center"></td>
<td align="center"><mrow>
<mi>Over</mi>
<mo>&lt;</mo>
<mi>Base</mi>
<mo>&lt;</mo>
<mi>Under<mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over</mi>
<mo>&gt;</mo>
<mi>Base</mi>
<mo>&gt;</mo>
<mi>Under</mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over = Under</mi>
<mo>&lt;</mo>
<mi>Base</mi>
</mrow>
</td>
<td align="center"><mrow>
<mi>Over = Under</mi>
<mo>&gt;</mo>
<mi>Base</mi>
</mrow></td>
</tr>
<tr>
<th>
align="left"
</th>
<td align="center">
<math>
<munderover align="left">
<mspace height="15px" width="50px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<munderover align="left">
<mspace height="15px" width="50px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover align="left">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover align="left">
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
</tr>
<tr>
<th>
align="right"
</th>
<td align="center">
<math>
<munderover align="right">
<mspace height="15px" width="50px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover align="right">
<mspace height="15px" width="50px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover align="right">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover align="right">
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
</tr>
<tr>
<th>
align="center"
</th>
<td align="center">
<math>
<munderover align="center">
<mspace height="15px" width="50px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover align="center">
<mspace height="15px" width="50px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover align="center">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover align="center">
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
</tr>
</table>
<table>
<tr>
<th>
<h5>Under & Over</h5>
<math>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
</math>
</th>
<th>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>
<th>
<h5>Base</h5>
<math>
<mrow>
<mspace height="15px" width="25px" mathbackground="blue"/>
</mrow>
</math>
</th>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,274 @@
<html>
<head><title></title></head>
<body>
<h2> Test with accent="true" </h2>
<table border="1">
<tr>
<td align="center"></td>
<th colspan="6">munderover</th>
</tr>
<tr>
<td align="center"></td>
<td align="center"><mrow>
<mi>Over</mi>
<mo>&lt;</mo>
<mi>Base</mi>
<mo>&lt;</mo>
<mi>Under<mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over</mi>
<mo>&gt;</mo>
<mi>Base</mi>
<mo>&gt;</mo>
<mi>Under</mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over = Under</mi>
<mo>&lt;</mo>
<mi>Base</mi>
</mrow>
</td>
<td align="center"><mrow>
<mi>Over = Under</mi>
<mo>&gt;</mo>
<mi>Base</mi>
</mrow></td>
</tr>
<tr>
<th>
align="left"
</th>
<td align="center">
<math>
<munderover accent="true" accentunder="true">
<mrow>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
</mrow>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover accent="true" accentunder="true">
<mrow>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
</mrow>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover accent="true" accentunder="true">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
</mrow>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
</mrow>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover accent="true" accentunder="true">
<mrow>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
</tr>
<tr>
<th>
align="right"
</th>
<td align="center">
<math>
<munderover accent="true" accentunder="true">
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover accent="true" accentunder="true">
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
</mrow>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover accent="true" accentunder="true">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover accent="true" accentunder="true">
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
</tr>
<tr>
<th>
align="center"
</th>
<td align="center">
<math>
<munderover accent="true" accentunder="true">
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="50px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
</mrow>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover accent="true" accentunder="true">
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="50px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
</mrow>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover accent="true" accentunder="true">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
</mrow>
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px"/>
</mrow>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover accent="true" accentunder="true">
<mrow>
<mspace height="15px" width="25px"/>
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="25px"/>
</mrow>
<mspace height="15px" width="75px" mathbackground="red"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
</tr>
</table>
<table>
<tr>
<th>
<h5>Under & Over</h5>
<math>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
</math>
</th>
<th>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>
<th>
<h5>Base</h5>
<math>
<mrow>
<mspace height="15px" width="25px" mathbackground="blue"/>
</mrow>
</math>
</th>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,190 @@
<html>
<head><title></title></head>
<body>
<h2> Test with accent="true" </h2>
<table border="1">
<tr>
<td align="center"></td>
<th colspan="4">munderover</th>
</tr>
<tr>
<td align="center"></td>
<td align="center"><mrow>
<mi>Over</mi>
<mo>&lt;</mo>
<mi>Base</mi>
<mo>&lt;</mo>
<mi>Under<mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over</mi>
<mo>&gt;</mo>
<mi>Base</mi>
<mo>&gt;</mo>
<mi>Under</mi>
</mrow>
</td>
<td align="center">
<mrow>
<mi>Over = Under</mi>
<mo>&lt;</mo>
<mi>Base</mi>
</mrow>
</td>
<td align="center"><mrow>
<mi>Over = Under</mi>
<mo>&gt;</mo>
<mi>Base</mi>
</mrow></td>
</tr>
<tr>
<th>
align="left"
</th>
<td align="center">
<math>
<munderover align="left" accent="true" accentunder="true">
<mspace height="15px" width="50px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</mover>
</math>
</td>
<td align="center">
<math>
<munderover align="left" accent="true" accentunder="true">
<mspace height="15px" width="50px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover align="left" accent="true" accentunder="true">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover align="left" accent="true" accentunder="true">
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
</tr>
<tr>
<th>
align="right"
</th>
<td align="center">
<math>
<munderover align="right" accent="true" accentunder="true">
<mspace height="15px" width="50px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover align="right" accent="true" accentunder="true">
<mspace height="15px" width="50px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover align="right" accent="true" accentunder="true">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover align="right" accent="true" accentunder="true">
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
</tr>
<tr>
<th>
align="center"
</th>
<td align="center">
<math>
<munderover align="center" accent="true" accentunder="true">
<mspace height="15px" width="50px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover align="center" accent="true" accentunder="true">
<mspace height="15px" width="50px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover align="center" accent="true" accentunder="true">
<mspace height="15px" width="75px" mathbackground="blue"/>
<mspace height="15px" width="25px" mathbackground="red"/>
<mspace height="15px" width="25px" mathbackground="red"/>
</munderover>
</math>
</td>
<td align="center">
<math>
<munderover align="center" accent="true" accentunder="true">
<mspace height="15px" width="25px" mathbackground="blue"/>
<mspace height="15px" width="75px" mathbackground="red"/>
<mspace height="15px" width="75px" mathbackground="red"/>
</munderover>
</math>
</td>
</tr>
</table>
<table>
<tr>
<th>
<h5>Under & Over</h5>
<math>
<mrow>
<mspace height="15px" width="25px" mathbackground="red"/>
</mrow>
</math>
</th>
<th>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>
<th>
<h5>Base</h5>
<math>
<mrow>
<mspace height="15px" width="25px" mathbackground="blue"/>
</mrow>
</math>
</th>
</tr>
</table>
</body>
</html>

View File

@ -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

View File

@ -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

View File

@ -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<SourceSurface> 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

View File

@ -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);
}
}
}

View File

@ -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)

View File

@ -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;

View File

@ -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";
}

View File

@ -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
},

View File

@ -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)

View File

@ -1706,6 +1706,13 @@ nsFtpState::Init(nsFtpChannel *channel)
nsresult rv;
nsCAutoString path;
nsCOMPtr<nsIURL> 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 {

View File

@ -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<PRUint32>(mMaxMessageSize)) {
LOG(("WebSocketChannel:: Error: message too big\n"));
return NS_ERROR_FILE_TOO_BIG;
}

View File

@ -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<mozIStorageStatement> 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

View File

@ -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();

View File

@ -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";

View File

@ -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();
}

View File

@ -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]

View File

@ -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;
}

View File

@ -50,7 +50,7 @@
<binding id="settings">
<content orient="vertical">
<xul:label class="settings-title" xbl:inherits="value=label" crop="end" flex="1"/>
<xul:label class="settings-title" xbl:inherits="xbl:text=label" flex="1"/>
<children />
</content>
</binding>
@ -170,8 +170,8 @@
<binding id="setting-bool" extends="chrome://mozapps/content/extensions/setting.xml#setting-base">
<content>
<xul:vbox class="setting-label">
<xul:label class="preferences-title" xbl:inherits="value=title" crop="end" flex="1"/>
<xul:label class="preferences-description" xbl:inherits="value=desc" crop="end" flex="1">
<xul:label class="preferences-title" xbl:inherits="xbl:text=title" flex="1"/>
<xul:label class="preferences-description" xbl:inherits="xbl:text=desc" flex="1">
<children/>
</xul:label>
</xul:vbox>
@ -207,8 +207,8 @@
<binding id="setting-boolint" extends="chrome://mozapps/content/extensions/setting.xml#setting-base">
<content>
<xul:vbox class="setting-label">
<xul:label class="preferences-title" xbl:inherits="value=title" crop="end" flex="1"/>
<xul:label class="preferences-description" xbl:inherits="value=desc" crop="end" flex="1">
<xul:label class="preferences-title" xbl:inherits="xbl:text=title" flex="1"/>
<xul:label class="preferences-description" xbl:inherits="xbl:text=desc" flex="1">
<children/>
</xul:label>
</xul:vbox>
@ -270,8 +270,8 @@
<binding id="setting-integer" extends="chrome://mozapps/content/extensions/setting.xml#setting-base">
<content>
<xul:vbox class="setting-label">
<xul:label class="preferences-title" xbl:inherits="value=title" crop="end" flex="1"/>
<xul:label class="preferences-description" xbl:inherits="value=desc" crop="end" flex="1">
<xul:label class="preferences-title" xbl:inherits="xbl:text=title" flex="1"/>
<xul:label class="preferences-description" xbl:inherits="xbl:text=desc" flex="1">
<children/>
</xul:label>
</xul:vbox>
@ -306,8 +306,8 @@
<binding id="setting-control" extends="chrome://mozapps/content/extensions/setting.xml#setting-base">
<content>
<xul:vbox class="setting-label">
<xul:label class="preferences-title" xbl:inherits="value=title" crop="end" flex="1"/>
<xul:label class="preferences-description" xbl:inherits="value=desc" crop="end" flex="1">
<xul:label class="preferences-title" xbl:inherits="xbl:text=title" flex="1"/>
<xul:label class="preferences-description" xbl:inherits="xbl:text=desc" flex="1">
<children/>
</xul:label>
</xul:vbox>
@ -320,8 +320,8 @@
<binding id="setting-string" extends="chrome://mozapps/content/extensions/setting.xml#setting-base">
<content>
<xul:vbox class="setting-label">
<xul:label class="preferences-title" xbl:inherits="value=title" crop="end" flex="1"/>
<xul:label class="preferences-description" xbl:inherits="value=desc" crop="end" flex="1">
<xul:label class="preferences-title" xbl:inherits="xbl:text=title" flex="1"/>
<xul:label class="preferences-description" xbl:inherits="xbl:text=desc" flex="1">
<children/>
</xul:label>
</xul:vbox>
@ -358,8 +358,8 @@
<binding id="setting-color" extends="chrome://mozapps/content/extensions/setting.xml#setting-base">
<content>
<xul:vbox class="setting-label">
<xul:label class="preferences-title" xbl:inherits="value=title" crop="end" flex="1"/>
<xul:label class="preferences-description" xbl:inherits="value=desc" crop="end" flex="1">
<xul:label class="preferences-title" xbl:inherits="xbl:text=title" flex="1"/>
<xul:label class="preferences-description" xbl:inherits="xbl:text=desc" flex="1">
<children/>
</xul:label>
</xul:vbox>
@ -395,8 +395,8 @@
<binding id="setting-path" extends="chrome://mozapps/content/extensions/setting.xml#setting-base">
<content>
<xul:vbox class="setting-label">
<xul:label class="preferences-title" xbl:inherits="value=title" crop="end" flex="1"/>
<xul:label class="preferences-description" xbl:inherits="value=desc" crop="end" flex="1">
<xul:label class="preferences-title" xbl:inherits="xbl:text=title" flex="1"/>
<xul:label class="preferences-description" xbl:inherits="xbl:text=desc" flex="1">
<children/>
</xul:label>
</xul:vbox>
@ -476,8 +476,8 @@
<binding id="setting-multi" extends="chrome://mozapps/content/extensions/setting.xml#setting-base">
<content>
<xul:vbox class="setting-label">
<xul:label class="preferences-title" xbl:inherits="value=title" crop="end" flex="1"/>
<xul:label class="preferences-description" xbl:inherits="value=desc" crop="end" flex="1">
<xul:label class="preferences-title" xbl:inherits="xbl:text=title" flex="1"/>
<xul:label class="preferences-description" xbl:inherits="xbl:text=desc" flex="1">
<children/>
</xul:label>
</xul:vbox>

View File

@ -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 \

View File

@ -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();
});
});
});
});

View File

@ -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 <gconf/gconf-client.h>
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;
}

View File

@ -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);

View File

@ -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<char**>(&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()
{

View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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");
}

View File

@ -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);

View File

@ -42,8 +42,6 @@
using namespace mozilla;
NS_IMPL_ISUPPORTS2(nsScreenAndroid, nsIScreen, nsIScreen_MOZILLA_2_0_BRANCH)
nsScreenAndroid::nsScreenAndroid(void *nativeScreen)
{
}

View File

@ -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 :

View File

@ -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);
}

View File

@ -41,17 +41,18 @@
#import <Cocoa/Cocoa.h>
#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; }

View File

@ -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;

View File

@ -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)
{

View File

@ -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

View File

@ -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)
{

View File

@ -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

View File

@ -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;
};

View File

@ -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)
{

View File

@ -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:

View File

@ -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)

Some files were not shown because too many files have changed in this diff Show More