mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-16 13:56:29 +00:00
Merge backout.
This commit is contained in:
commit
af1ab03319
@ -57,13 +57,15 @@
|
||||
#include "nsTArray.h"
|
||||
|
||||
#include "CanvasUtils.h"
|
||||
#include "mozilla/gfx/Matrix.h"
|
||||
|
||||
using namespace mozilla;
|
||||
namespace mozilla {
|
||||
namespace CanvasUtils {
|
||||
|
||||
void
|
||||
CanvasUtils::DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
|
||||
nsIPrincipal *aPrincipal,
|
||||
PRBool forceWriteOnly)
|
||||
DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
|
||||
nsIPrincipal *aPrincipal,
|
||||
PRBool forceWriteOnly)
|
||||
{
|
||||
// Callers should ensure that mCanvasElement is non-null before calling this
|
||||
if (!aCanvasElement) {
|
||||
@ -96,7 +98,7 @@ CanvasUtils::DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
|
||||
}
|
||||
|
||||
void
|
||||
CanvasUtils::LogMessage (const nsCString& errorString)
|
||||
LogMessage (const nsCString& errorString)
|
||||
{
|
||||
nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
|
||||
if (!console)
|
||||
@ -107,7 +109,7 @@ CanvasUtils::LogMessage (const nsCString& errorString)
|
||||
}
|
||||
|
||||
void
|
||||
CanvasUtils::LogMessagef (const char *fmt, ...)
|
||||
LogMessagef (const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
@ -122,3 +124,116 @@ CanvasUtils::LogMessagef (const char *fmt, ...)
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
bool
|
||||
CoerceDouble(jsval v, double* d)
|
||||
{
|
||||
if (JSVAL_IS_DOUBLE(v)) {
|
||||
*d = JSVAL_TO_DOUBLE(v);
|
||||
} else if (JSVAL_IS_INT(v)) {
|
||||
*d = double(JSVAL_TO_INT(v));
|
||||
} else if (JSVAL_IS_VOID(v)) {
|
||||
*d = 0.0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<size_t N>
|
||||
static bool
|
||||
JSValToMatrixElts(JSContext* cx, const jsval& val,
|
||||
double* (&elts)[N], nsresult* rv)
|
||||
{
|
||||
JSObject* obj;
|
||||
jsuint length;
|
||||
|
||||
if (JSVAL_IS_PRIMITIVE(val) ||
|
||||
!(obj = JSVAL_TO_OBJECT(val)) ||
|
||||
!JS_GetArrayLength(cx, obj, &length) ||
|
||||
N != length) {
|
||||
// Not an array-like thing or wrong size
|
||||
*rv = NS_ERROR_INVALID_ARG;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0; i < N; ++i) {
|
||||
jsval elt;
|
||||
double d;
|
||||
if (!JS_GetElement(cx, obj, i, &elt)) {
|
||||
*rv = NS_ERROR_FAILURE;
|
||||
return false;
|
||||
}
|
||||
if (!CoerceDouble(elt, &d)) {
|
||||
*rv = NS_ERROR_INVALID_ARG;
|
||||
return false;
|
||||
}
|
||||
if (!FloatValidate(d)) {
|
||||
// This is weird, but it's the behavior of SetTransform()
|
||||
*rv = NS_OK;
|
||||
return false;
|
||||
}
|
||||
*elts[i] = d;
|
||||
}
|
||||
|
||||
*rv = NS_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSValToMatrix(JSContext* cx, const jsval& val, gfxMatrix* matrix, nsresult* rv)
|
||||
{
|
||||
double* elts[] = { &matrix->xx, &matrix->yx, &matrix->xy, &matrix->yy,
|
||||
&matrix->x0, &matrix->y0 };
|
||||
return JSValToMatrixElts(cx, val, elts, rv);
|
||||
}
|
||||
|
||||
bool
|
||||
JSValToMatrix(JSContext* cx, const jsval& val, Matrix* matrix, nsresult* rv)
|
||||
{
|
||||
gfxMatrix m;
|
||||
if (!JSValToMatrix(cx, val, &m, rv))
|
||||
return false;
|
||||
*matrix = Matrix(Float(m.xx), Float(m.yx), Float(m.xy), Float(m.yy),
|
||||
Float(m.x0), Float(m.y0));
|
||||
return true;
|
||||
}
|
||||
|
||||
template<size_t N>
|
||||
static nsresult
|
||||
MatrixEltsToJSVal(/*const*/ jsval (&elts)[N], JSContext* cx, jsval* val)
|
||||
{
|
||||
JSObject* obj = JS_NewArrayObject(cx, N, elts);
|
||||
if (!obj) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
*val = OBJECT_TO_JSVAL(obj);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MatrixToJSVal(const gfxMatrix& matrix, JSContext* cx, jsval* val)
|
||||
{
|
||||
jsval elts[] = {
|
||||
DOUBLE_TO_JSVAL(matrix.xx), DOUBLE_TO_JSVAL(matrix.yx),
|
||||
DOUBLE_TO_JSVAL(matrix.xy), DOUBLE_TO_JSVAL(matrix.yy),
|
||||
DOUBLE_TO_JSVAL(matrix.x0), DOUBLE_TO_JSVAL(matrix.y0)
|
||||
};
|
||||
return MatrixEltsToJSVal(elts, cx, val);
|
||||
}
|
||||
|
||||
nsresult
|
||||
MatrixToJSVal(const Matrix& matrix, JSContext* cx, jsval* val)
|
||||
{
|
||||
jsval elts[] = {
|
||||
DOUBLE_TO_JSVAL(matrix._11), DOUBLE_TO_JSVAL(matrix._12),
|
||||
DOUBLE_TO_JSVAL(matrix._21), DOUBLE_TO_JSVAL(matrix._22),
|
||||
DOUBLE_TO_JSVAL(matrix._31), DOUBLE_TO_JSVAL(matrix._32)
|
||||
};
|
||||
return MatrixEltsToJSVal(elts, cx, val);
|
||||
}
|
||||
|
||||
} // namespace CanvasUtils
|
||||
} // namespace mozilla
|
||||
|
@ -47,37 +47,178 @@ class nsIPrincipal;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class CanvasUtils {
|
||||
public:
|
||||
// Check that the rectangle [x,y,w,h] is a subrectangle of [0,0,realWidth,realHeight]
|
||||
namespace gfx {
|
||||
class Matrix;
|
||||
}
|
||||
|
||||
static PRBool CheckSaneSubrectSize(PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h,
|
||||
PRInt32 realWidth, PRInt32 realHeight) {
|
||||
CheckedInt32 checked_x_plus_w = CheckedInt32(x) + w;
|
||||
CheckedInt32 checked_y_plus_h = CheckedInt32(y) + h;
|
||||
namespace CanvasUtils {
|
||||
|
||||
return w >= 0 && h >= 0 && x >= 0 && y >= 0 &&
|
||||
checked_x_plus_w.valid() &&
|
||||
checked_x_plus_w.value() <= realWidth &&
|
||||
checked_y_plus_h.valid() &&
|
||||
checked_y_plus_h.value() <= realHeight;
|
||||
using namespace gfx;
|
||||
|
||||
// Check that the rectangle [x,y,w,h] is a subrectangle of [0,0,realWidth,realHeight]
|
||||
|
||||
inline PRBool CheckSaneSubrectSize(PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h,
|
||||
PRInt32 realWidth, PRInt32 realHeight) {
|
||||
CheckedInt32 checked_xmost = CheckedInt32(x) + w;
|
||||
CheckedInt32 checked_ymost = CheckedInt32(y) + h;
|
||||
|
||||
return w >= 0 && h >= 0 && x >= 0 && y >= 0 &&
|
||||
checked_xmost.valid() &&
|
||||
checked_xmost.value() <= realWidth &&
|
||||
checked_ymost.valid() &&
|
||||
checked_ymost.value() <= realHeight;
|
||||
}
|
||||
|
||||
// Flag aCanvasElement as write-only if drawing an image with aPrincipal
|
||||
// onto it would make it such.
|
||||
|
||||
void DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
|
||||
nsIPrincipal *aPrincipal,
|
||||
PRBool forceWriteOnly);
|
||||
|
||||
void LogMessage (const nsCString& errorString);
|
||||
void LogMessagef (const char *fmt, ...);
|
||||
|
||||
// Make a double out of |v|, treating undefined values as 0.0 (for
|
||||
// the sake of sparse arrays). Return true iff coercion
|
||||
// succeeded.
|
||||
bool CoerceDouble(jsval v, double* d);
|
||||
|
||||
// Return true iff the conversion succeeded, false otherwise. *rv is
|
||||
// the value to return to script if this returns false.
|
||||
bool JSValToMatrix(JSContext* cx, const jsval& val,
|
||||
gfxMatrix* matrix, nsresult* rv);
|
||||
bool JSValToMatrix(JSContext* cx, const jsval& val,
|
||||
Matrix* matrix, nsresult* rv);
|
||||
|
||||
nsresult MatrixToJSVal(const gfxMatrix& matrix,
|
||||
JSContext* cx, jsval* val);
|
||||
nsresult MatrixToJSVal(const Matrix& matrix,
|
||||
JSContext* cx, jsval* val);
|
||||
|
||||
/* Float validation stuff */
|
||||
#define VALIDATE(_f) if (!NS_finite(_f)) return PR_FALSE
|
||||
|
||||
inline PRBool FloatValidate (double f1) {
|
||||
VALIDATE(f1);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
inline PRBool FloatValidate (double f1, double f2) {
|
||||
VALIDATE(f1); VALIDATE(f2);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
inline PRBool FloatValidate (double f1, double f2, double f3) {
|
||||
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
inline PRBool FloatValidate (double f1, double f2, double f3, double f4) {
|
||||
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
inline PRBool FloatValidate (double f1, double f2, double f3, double f4, double f5) {
|
||||
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4); VALIDATE(f5);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
inline PRBool FloatValidate (double f1, double f2, double f3, double f4, double f5, double f6) {
|
||||
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4); VALIDATE(f5); VALIDATE(f6);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
#undef VALIDATE
|
||||
|
||||
template<typename T>
|
||||
nsresult
|
||||
JSValToDashArray(JSContext* cx, const jsval& val,
|
||||
FallibleTArray<T>& dashArray);
|
||||
|
||||
template<typename T>
|
||||
nsresult
|
||||
DashArrayToJSVal(FallibleTArray<T>& dashArray,
|
||||
JSContext* cx, jsval* val);
|
||||
|
||||
template<typename T>
|
||||
nsresult
|
||||
JSValToDashArray(JSContext* cx, const jsval& patternArray,
|
||||
FallibleTArray<T>& dashes)
|
||||
{
|
||||
// The cap is pretty arbitrary. 16k should be enough for
|
||||
// anybody...
|
||||
static const jsuint MAX_NUM_DASHES = 1 << 14;
|
||||
|
||||
if (!JSVAL_IS_PRIMITIVE(patternArray)) {
|
||||
JSObject* obj = JSVAL_TO_OBJECT(patternArray);
|
||||
jsuint length;
|
||||
if (!JS_GetArrayLength(cx, obj, &length)) {
|
||||
// Not an array-like thing
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
} else if (length > MAX_NUM_DASHES) {
|
||||
// Too many dashes in the pattern
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
bool haveNonzeroElement = false;
|
||||
for (jsint i = 0; i < jsint(length); ++i) {
|
||||
jsval elt;
|
||||
double d;
|
||||
if (!JS_GetElement(cx, obj, i, &elt)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (!(CoerceDouble(elt, &d) &&
|
||||
FloatValidate(d) &&
|
||||
d >= 0.0)) {
|
||||
// Pattern elements must be finite "numbers" >= 0.
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
} else if (d > 0.0) {
|
||||
haveNonzeroElement = true;
|
||||
}
|
||||
if (!dashes.AppendElement(d)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (dashes.Length() > 0 && !haveNonzeroElement) {
|
||||
// An all-zero pattern makes no sense.
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
} else if (!(JSVAL_IS_VOID(patternArray) || JSVAL_IS_NULL(patternArray))) {
|
||||
// undefined and null mean "reset to no dash". Any other
|
||||
// random garbage is a type error.
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// Flag aCanvasElement as write-only if drawing an image with aPrincipal
|
||||
// onto it would make it such.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
|
||||
nsIPrincipal *aPrincipal,
|
||||
PRBool forceWriteOnly);
|
||||
|
||||
static void LogMessage (const nsCString& errorString);
|
||||
static void LogMessagef (const char *fmt, ...);
|
||||
|
||||
private:
|
||||
// this can't be instantiated
|
||||
CanvasUtils() { }
|
||||
};
|
||||
template<typename T>
|
||||
nsresult
|
||||
DashArrayToJSVal(FallibleTArray<T>& dashes,
|
||||
JSContext* cx, jsval* val)
|
||||
{
|
||||
if (dashes.IsEmpty()) {
|
||||
*val = JSVAL_NULL;
|
||||
} else {
|
||||
JSObject* obj = JS_NewArrayObject(cx, dashes.Length(), nsnull);
|
||||
if (!obj) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
for (PRUint32 i = 0; i < dashes.Length(); ++i) {
|
||||
double d = dashes[i];
|
||||
jsval elt = DOUBLE_TO_JSVAL(d);
|
||||
if (!JS_SetElement(cx, obj, i, &elt)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
*val = OBJECT_TO_JSVAL(obj);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _CANVASUTILS_H_ */
|
||||
|
@ -119,51 +119,16 @@
|
||||
// windows.h (included by chromium code) defines this, in its infinite wisdom
|
||||
#undef DrawText
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::CanvasUtils;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::ipc;
|
||||
using namespace mozilla::layers;
|
||||
|
||||
static float kDefaultFontSize = 10.0;
|
||||
static NS_NAMED_LITERAL_STRING(kDefaultFontName, "sans-serif");
|
||||
static NS_NAMED_LITERAL_STRING(kDefaultFontStyle, "10px sans-serif");
|
||||
|
||||
/* Float validation stuff */
|
||||
#define VALIDATE(_f) if (!NS_finite(_f)) return PR_FALSE
|
||||
|
||||
static PRBool FloatValidate (double f1) {
|
||||
VALIDATE(f1);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRBool FloatValidate (double f1, double f2) {
|
||||
VALIDATE(f1); VALIDATE(f2);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRBool FloatValidate (double f1, double f2, double f3) {
|
||||
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRBool FloatValidate (double f1, double f2, double f3, double f4) {
|
||||
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRBool FloatValidate (double f1, double f2, double f3, double f4, double f5) {
|
||||
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4); VALIDATE(f5);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRBool FloatValidate (double f1, double f2, double f3, double f4, double f5, double f6) {
|
||||
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4); VALIDATE(f5); VALIDATE(f6);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
#undef VALIDATE
|
||||
|
||||
/* Memory reporter stuff */
|
||||
static nsIMemoryReporter *gCanvasMemoryReporter = nsnull;
|
||||
static PRInt64 gCanvasMemoryUsed = 0;
|
||||
@ -202,6 +167,12 @@ CopyContext(gfxContext* dest, gfxContext* src)
|
||||
dest->SetFillRule(src->CurrentFillRule());
|
||||
|
||||
dest->SetAntialiasMode(src->CurrentAntialiasMode());
|
||||
|
||||
AutoFallibleTArray<gfxFloat, 10> dashes;
|
||||
double dashOffset;
|
||||
if (src->CurrentDash(dashes, &dashOffset)) {
|
||||
dest->SetDash(dashes.Elements(), dashes.Length(), dashOffset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1436,6 +1407,64 @@ nsCanvasRenderingContext2D::SetTransform(float m11, float m12, float m21, float
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetMozCurrentTransform(JSContext* cx,
|
||||
const jsval& matrix)
|
||||
{
|
||||
nsresult rv;
|
||||
gfxMatrix newCTM;
|
||||
|
||||
if (!JSValToMatrix(cx, matrix, &newCTM, &rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mThebes->SetMatrix(newCTM);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetMozCurrentTransform(JSContext* cx,
|
||||
jsval* matrix)
|
||||
{
|
||||
return MatrixToJSVal(mThebes->CurrentMatrix(), cx, matrix);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetMozCurrentTransformInverse(JSContext* cx,
|
||||
const jsval& matrix)
|
||||
{
|
||||
nsresult rv;
|
||||
gfxMatrix newCTMInverse;
|
||||
|
||||
if (!JSValToMatrix(cx, matrix, &newCTMInverse, &rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
|
||||
if (!newCTMInverse.IsSingular()) {
|
||||
mThebes->SetMatrix(newCTMInverse.Invert());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetMozCurrentTransformInverse(JSContext* cx,
|
||||
jsval* matrix)
|
||||
{
|
||||
gfxMatrix ctm = mThebes->CurrentMatrix();
|
||||
|
||||
if (!mThebes->CurrentMatrix().IsSingular()) {
|
||||
ctm.Invert();
|
||||
} else {
|
||||
double NaN = JSVAL_TO_DOUBLE(JS_GetNaNValue(cx));
|
||||
ctm = gfxMatrix(NaN, NaN, NaN, NaN, NaN, NaN);
|
||||
}
|
||||
|
||||
return MatrixToJSVal(ctm, cx, matrix);
|
||||
}
|
||||
|
||||
//
|
||||
// colors
|
||||
//
|
||||
@ -3264,6 +3293,59 @@ nsCanvasRenderingContext2D::GetMiterLimit(float *miter)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetMozDash(JSContext *cx, const jsval& patternArray)
|
||||
{
|
||||
AutoFallibleTArray<gfxFloat, 10> dashes;
|
||||
nsresult rv = JSValToDashArray(cx, patternArray, dashes);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mThebes->SetDash(dashes.Elements(), dashes.Length(),
|
||||
mThebes->CurrentDashOffset());
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetMozDash(JSContext* cx, jsval* dashArray)
|
||||
{
|
||||
AutoFallibleTArray<gfxFloat, 10> dashes;
|
||||
if (!mThebes->CurrentDash(dashes, nsnull)) {
|
||||
dashes.SetLength(0);
|
||||
}
|
||||
return DashArrayToJSVal(dashes, cx, dashArray);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::SetMozDashOffset(float offset)
|
||||
{
|
||||
if (!FloatValidate(offset)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
AutoFallibleTArray<gfxFloat, 10> dashes;
|
||||
if (!mThebes->CurrentDash(dashes, nsnull)) {
|
||||
// Either no dash is set or the cairo call failed. Either
|
||||
// way, eat the error.
|
||||
|
||||
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
|
||||
return NS_OK;
|
||||
}
|
||||
NS_ABORT_IF_FALSE(dashes.Length() > 0,
|
||||
"CurrentDash() should have returned false");
|
||||
|
||||
mThebes->SetDash(dashes.Elements(), dashes.Length(),
|
||||
gfxFloat(offset));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetMozDashOffset(float* offset)
|
||||
{
|
||||
*offset = float(mThebes->CurrentDashOffset());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::IsPointInPath(float x, float y, PRBool *retVal)
|
||||
{
|
||||
|
@ -127,11 +127,12 @@
|
||||
#undef DrawText
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::CanvasUtils;
|
||||
using namespace mozilla::css;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::ipc;
|
||||
using namespace mozilla::css;
|
||||
using namespace mozilla::layers;
|
||||
|
||||
namespace mgfx = mozilla::gfx;
|
||||
|
||||
@ -139,41 +140,6 @@ static float kDefaultFontSize = 10.0;
|
||||
static NS_NAMED_LITERAL_STRING(kDefaultFontName, "sans-serif");
|
||||
static NS_NAMED_LITERAL_STRING(kDefaultFontStyle, "10px sans-serif");
|
||||
|
||||
/* Float validation stuff */
|
||||
#define VALIDATE(_f) if (!NS_finite(_f)) return PR_FALSE
|
||||
|
||||
static PRBool FloatValidate (double f1) {
|
||||
VALIDATE(f1);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRBool FloatValidate (double f1, double f2) {
|
||||
VALIDATE(f1); VALIDATE(f2);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRBool FloatValidate (double f1, double f2, double f3) {
|
||||
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRBool FloatValidate (double f1, double f2, double f3, double f4) {
|
||||
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRBool FloatValidate (double f1, double f2, double f3, double f4, double f5) {
|
||||
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4); VALIDATE(f5);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRBool FloatValidate (double f1, double f2, double f3, double f4, double f5, double f6) {
|
||||
VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4); VALIDATE(f5); VALIDATE(f6);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
#undef VALIDATE
|
||||
|
||||
/* Memory reporter stuff */
|
||||
static nsIMemoryReporter *gCanvasAzureMemoryReporter = nsnull;
|
||||
static PRInt64 gCanvasAzureMemoryUsed = 0;
|
||||
@ -605,6 +571,10 @@ protected:
|
||||
*/
|
||||
PRPackedBool mPredictManyRedrawCalls;
|
||||
|
||||
// This is stored after GetThebesSurface has been called once to avoid
|
||||
// excessive ThebesSurface initialization overhead.
|
||||
nsRefPtr<gfxASurface> mThebesSurface;
|
||||
|
||||
/**
|
||||
* We also have a device space pathbuilder. The reason for this is as
|
||||
* follows, when a path is being built, but the transform changes, we
|
||||
@ -718,6 +688,7 @@ protected:
|
||||
miterLimit(10.0f),
|
||||
globalAlpha(1.0f),
|
||||
shadowBlur(0.0),
|
||||
dashOffset(0.0f),
|
||||
op(OP_OVER),
|
||||
fillRule(FILL_WINDING),
|
||||
lineCap(CAP_BUTT),
|
||||
@ -737,6 +708,8 @@ protected:
|
||||
miterLimit(other.miterLimit),
|
||||
globalAlpha(other.globalAlpha),
|
||||
shadowBlur(other.shadowBlur),
|
||||
dash(other.dash),
|
||||
dashOffset(other.dashOffset),
|
||||
op(other.op),
|
||||
fillRule(FILL_WINDING),
|
||||
lineCap(other.lineCap),
|
||||
@ -795,6 +768,8 @@ protected:
|
||||
Float miterLimit;
|
||||
Float globalAlpha;
|
||||
Float shadowBlur;
|
||||
FallibleTArray<Float> dash;
|
||||
Float dashOffset;
|
||||
|
||||
CompositionOp op;
|
||||
FillRule fillRule;
|
||||
@ -1090,9 +1065,14 @@ nsCanvasRenderingContext2DAzure::Reset()
|
||||
}
|
||||
|
||||
mTarget = nsnull;
|
||||
|
||||
// Since the target changes the backing texture will change, and this will
|
||||
// no longer be valid.
|
||||
mThebesSurface = nsnull;
|
||||
mValid = PR_FALSE;
|
||||
mIsEntireFrameInvalid = PR_FALSE;
|
||||
mPredictManyRedrawCalls = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1625,6 +1605,62 @@ nsCanvasRenderingContext2DAzure::SetTransform(float m11, float m12, float m21, f
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2DAzure::SetMozCurrentTransform(JSContext* cx,
|
||||
const jsval& matrix)
|
||||
{
|
||||
nsresult rv;
|
||||
Matrix newCTM;
|
||||
|
||||
if (!JSValToMatrix(cx, matrix, &newCTM, &rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mTarget->SetTransform(newCTM);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2DAzure::GetMozCurrentTransform(JSContext* cx,
|
||||
jsval* matrix)
|
||||
{
|
||||
return MatrixToJSVal(mTarget->GetTransform(), cx, matrix);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2DAzure::SetMozCurrentTransformInverse(JSContext* cx,
|
||||
const jsval& matrix)
|
||||
{
|
||||
nsresult rv;
|
||||
Matrix newCTMInverse;
|
||||
|
||||
if (!JSValToMatrix(cx, matrix, &newCTMInverse, &rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
|
||||
if (newCTMInverse.Invert()) {
|
||||
mTarget->SetTransform(newCTMInverse);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2DAzure::GetMozCurrentTransformInverse(JSContext* cx,
|
||||
jsval* matrix)
|
||||
{
|
||||
Matrix ctm = mTarget->GetTransform();
|
||||
|
||||
if (!ctm.Invert()) {
|
||||
double NaN = JSVAL_TO_DOUBLE(JS_GetNaNValue(cx));
|
||||
ctm = Matrix(NaN, NaN, NaN, NaN, NaN, NaN);
|
||||
}
|
||||
|
||||
return MatrixToJSVal(ctm, cx, matrix);
|
||||
}
|
||||
|
||||
//
|
||||
// colors
|
||||
//
|
||||
@ -2050,8 +2086,6 @@ nsCanvasRenderingContext2DAzure::FillRect(float x, float y, float w, float h)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool doDrawShadow = NeedToDrawShadow();
|
||||
|
||||
const ContextState &state = CurrentState();
|
||||
|
||||
if (state.patternStyles[STYLE_FILL]) {
|
||||
@ -2127,7 +2161,10 @@ nsCanvasRenderingContext2DAzure::StrokeRect(float x, float y, float w, float h)
|
||||
StrokeLine(Point(x, y), Point(x + w, y),
|
||||
GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
|
||||
StrokeOptions(state.lineWidth, state.lineJoin,
|
||||
cap, state.miterLimit),
|
||||
cap, state.miterLimit,
|
||||
state.dash.Length(),
|
||||
state.dash.Elements(),
|
||||
state.dashOffset),
|
||||
DrawOptions(state.globalAlpha, state.op));
|
||||
return NS_OK;
|
||||
} else if (!w) {
|
||||
@ -2139,7 +2176,10 @@ nsCanvasRenderingContext2DAzure::StrokeRect(float x, float y, float w, float h)
|
||||
StrokeLine(Point(x, y), Point(x, y + h),
|
||||
GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
|
||||
StrokeOptions(state.lineWidth, state.lineJoin,
|
||||
cap, state.miterLimit),
|
||||
cap, state.miterLimit,
|
||||
state.dash.Length(),
|
||||
state.dash.Elements(),
|
||||
state.dashOffset),
|
||||
DrawOptions(state.globalAlpha, state.op));
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2148,7 +2188,10 @@ nsCanvasRenderingContext2DAzure::StrokeRect(float x, float y, float w, float h)
|
||||
StrokeRect(mgfx::Rect(x, y, w, h),
|
||||
GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
|
||||
StrokeOptions(state.lineWidth, state.lineJoin,
|
||||
state.lineCap, state.miterLimit),
|
||||
state.lineCap, state.miterLimit,
|
||||
state.dash.Length(),
|
||||
state.dash.Elements(),
|
||||
state.dashOffset),
|
||||
DrawOptions(state.globalAlpha, state.op));
|
||||
|
||||
return Redraw();
|
||||
@ -2212,7 +2255,10 @@ nsCanvasRenderingContext2DAzure::Stroke()
|
||||
AdjustedTarget(this)->
|
||||
Stroke(mPath, GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
|
||||
StrokeOptions(state.lineWidth, state.lineJoin,
|
||||
state.lineCap, state.miterLimit),
|
||||
state.lineCap, state.miterLimit,
|
||||
state.dash.Length(),
|
||||
state.dash.Elements(),
|
||||
state.dashOffset),
|
||||
DrawOptions(state.globalAlpha, state.op));
|
||||
|
||||
return Redraw();
|
||||
@ -2434,8 +2480,6 @@ nsCanvasRenderingContext2DAzure::Arc(float x, float y,
|
||||
|
||||
// Calculate the total arc we're going to sweep.
|
||||
Float arcSweepLeft = abs(endAngle - startAngle);
|
||||
// Calculate the amount of curves needed, 1 per quarter circle.
|
||||
Float curves = ceil(arcSweepLeft / (M_PI / 2.0f));
|
||||
|
||||
Float sweepDirection = ccw ? -1.0f : 1.0f;
|
||||
|
||||
@ -2953,6 +2997,8 @@ nsCanvasRenderingContext2DAzure::MeasureText(const nsAString& rawText,
|
||||
*/
|
||||
struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiProcessor
|
||||
{
|
||||
typedef nsCanvasRenderingContext2DAzure::ContextState ContextState;
|
||||
|
||||
virtual void SetText(const PRUnichar* text, PRInt32 length, nsBidiDirection direction)
|
||||
{
|
||||
mTextRun = gfxTextRunCache::MakeTextRun(text,
|
||||
@ -3017,7 +3063,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP
|
||||
Point baselineOrigin =
|
||||
Point(point.x * devUnitsPerAppUnit, point.y * devUnitsPerAppUnit);
|
||||
|
||||
for (int c = 0; c < numRuns; c++) {
|
||||
for (PRUint32 c = 0; c < numRuns; c++) {
|
||||
gfxFont *font = runs[c].mFont;
|
||||
PRUint32 endRun = 0;
|
||||
if (c + 1 < numRuns) {
|
||||
@ -3037,7 +3083,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP
|
||||
|
||||
float advanceSum = 0;
|
||||
|
||||
for (int i = runs[c].mCharacterOffset; i < endRun; i++) {
|
||||
for (PRUint32 i = runs[c].mCharacterOffset; i < endRun; i++) {
|
||||
Glyph newGlyph;
|
||||
if (glyphs[i].IsSimpleGlyph()) {
|
||||
newGlyph.mIndex = glyphs[i].GetSimpleGlyph();
|
||||
@ -3060,7 +3106,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP
|
||||
gfxTextRun::DetailedGlyph *detailedGlyphs =
|
||||
mTextRun->GetDetailedGlyphs(i);
|
||||
|
||||
for (int c = 0; c < glyphs[i].GetGlyphCount(); c++) {
|
||||
for (PRUint32 c = 0; c < glyphs[i].GetGlyphCount(); c++) {
|
||||
newGlyph.mIndex = detailedGlyphs[c].mGlyphID;
|
||||
if (mTextRun->IsRightToLeft()) {
|
||||
newGlyph.mPosition.x = baselineOrigin.x + detailedGlyphs[c].mXOffset * devUnitsPerAppUnit -
|
||||
@ -3093,12 +3139,16 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP
|
||||
|
||||
Matrix oldTransform = mCtx->mTarget->GetTransform();
|
||||
|
||||
const ContextState& state = *mState;
|
||||
nsCanvasRenderingContext2DAzure::AdjustedTarget(mCtx)->
|
||||
Stroke(path, nsCanvasRenderingContext2DAzure::GeneralPattern().
|
||||
ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_STROKE, mCtx->mTarget),
|
||||
StrokeOptions(mCtx->CurrentState().lineWidth, mCtx->CurrentState().lineJoin,
|
||||
mCtx->CurrentState().lineCap, mCtx->CurrentState().miterLimit),
|
||||
DrawOptions(mState->globalAlpha, mState->op));
|
||||
StrokeOptions(state.lineWidth, state.lineJoin,
|
||||
state.lineCap, state.miterLimit,
|
||||
state.dash.Length(),
|
||||
state.dash.Elements(),
|
||||
state.dashOffset),
|
||||
DrawOptions(state.globalAlpha, state.op));
|
||||
|
||||
}
|
||||
}
|
||||
@ -3126,7 +3176,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP
|
||||
nsCanvasRenderingContext2DAzure::TextDrawOperation mOp;
|
||||
|
||||
// context state
|
||||
nsCanvasRenderingContext2DAzure::ContextState *mState;
|
||||
ContextState *mState;
|
||||
|
||||
// union of bounding boxes of all runs, needed for shadows
|
||||
gfxRect mBoundingBox;
|
||||
@ -3524,6 +3574,47 @@ nsCanvasRenderingContext2DAzure::GetMiterLimit(float *miter)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2DAzure::SetMozDash(JSContext *cx, const jsval& patternArray)
|
||||
{
|
||||
FallibleTArray<Float> dash;
|
||||
nsresult rv = JSValToDashArray(cx, patternArray, dash);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
ContextState& state = CurrentState();
|
||||
state.dash = dash;
|
||||
if (state.dash.IsEmpty()) {
|
||||
state.dashOffset = 0;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2DAzure::GetMozDash(JSContext* cx, jsval* dashArray)
|
||||
{
|
||||
return DashArrayToJSVal(CurrentState().dash, cx, dashArray);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2DAzure::SetMozDashOffset(float offset)
|
||||
{
|
||||
if (!FloatValidate(offset)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
ContextState& state = CurrentState();
|
||||
if (!state.dash.IsEmpty()) {
|
||||
state.dashOffset = offset;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2DAzure::GetMozDashOffset(float* offset)
|
||||
{
|
||||
*offset = CurrentState().dashOffset;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2DAzure::IsPointInPath(float x, float y, PRBool *retVal)
|
||||
{
|
||||
@ -4030,8 +4121,6 @@ nsCanvasRenderingContext2DAzure::GetImageData_explicit(PRInt32 x, PRInt32 y, PRU
|
||||
memset(aData, 0, aDataLen);
|
||||
}
|
||||
|
||||
bool finishedPainting = false;
|
||||
|
||||
IntRect srcReadRect = srcRect.Intersect(destRect);
|
||||
IntRect dstWriteRect = srcReadRect;
|
||||
dstWriteRect.MoveBy(-x, -y);
|
||||
@ -4055,8 +4144,8 @@ nsCanvasRenderingContext2DAzure::GetImageData_explicit(PRInt32 x, PRInt32 y, PRU
|
||||
// from src and advancing that ptr before writing to dst.
|
||||
PRUint8 *dst = aData + dstWriteRect.y * (w * 4) + dstWriteRect.x * 4;
|
||||
|
||||
for (PRUint32 j = 0; j < dstWriteRect.height; j++) {
|
||||
for (PRUint32 i = 0; i < dstWriteRect.width; i++) {
|
||||
for (int j = 0; j < dstWriteRect.height; j++) {
|
||||
for (int i = 0; i < dstWriteRect.width; i++) {
|
||||
// XXX Is there some useful swizzle MMX we can use here?
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
PRUint8 b = *src++;
|
||||
@ -4238,11 +4327,22 @@ nsCanvasRenderingContext2DAzure::GetThebesSurface(gfxASurface **surface)
|
||||
*surface = tmpSurf.forget().get();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxASurface> newSurf =
|
||||
gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mTarget);
|
||||
|
||||
*surface = newSurf.forget().get();
|
||||
if (!mThebesSurface) {
|
||||
mThebesSurface =
|
||||
gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mTarget);
|
||||
|
||||
if (!mThebesSurface) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} else {
|
||||
// Normally GetThebesSurfaceForDrawTarget will handle the flush, when
|
||||
// we're returning a cached ThebesSurface we need to flush here.
|
||||
mTarget->Flush();
|
||||
}
|
||||
|
||||
mThebesSurface->AddRef();
|
||||
*surface = mThebesSurface;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ NS_IMPL_ELEMENT_CLONE(nsHTMLLIElement)
|
||||
NS_IMPL_STRING_ATTR(nsHTMLLIElement, Type, type)
|
||||
NS_IMPL_INT_ATTR(nsHTMLLIElement, Value, value)
|
||||
|
||||
|
||||
// values that are handled case-insensitively
|
||||
static const nsAttrValue::EnumTable kUnorderedListItemTypeTable[] = {
|
||||
{ "disc", NS_STYLE_LIST_STYLE_DISC },
|
||||
{ "circle", NS_STYLE_LIST_STYLE_CIRCLE },
|
||||
@ -117,11 +117,12 @@ static const nsAttrValue::EnumTable kUnorderedListItemTypeTable[] = {
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
// values that are handled case-sensitively
|
||||
static const nsAttrValue::EnumTable kOrderedListItemTypeTable[] = {
|
||||
{ "A", NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA },
|
||||
{ "a", NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA },
|
||||
{ "I", NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN },
|
||||
{ "i", NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN },
|
||||
{ "A", NS_STYLE_LIST_STYLE_UPPER_ALPHA },
|
||||
{ "a", NS_STYLE_LIST_STYLE_LOWER_ALPHA },
|
||||
{ "I", NS_STYLE_LIST_STYLE_UPPER_ROMAN },
|
||||
{ "i", NS_STYLE_LIST_STYLE_LOWER_ROMAN },
|
||||
{ "1", NS_STYLE_LIST_STYLE_DECIMAL },
|
||||
{ 0 }
|
||||
};
|
||||
|
@ -148,7 +148,7 @@ NS_IMPL_BOOL_ATTR(nsHTMLSharedListElement, Compact, compact)
|
||||
NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLSharedListElement, Start, start, 1)
|
||||
NS_IMPL_STRING_ATTR(nsHTMLSharedListElement, Type, type)
|
||||
|
||||
|
||||
// Shared with nsHTMLSharedElement.cpp
|
||||
nsAttrValue::EnumTable kListTypeTable[] = {
|
||||
{ "none", NS_STYLE_LIST_STYLE_NONE },
|
||||
{ "disc", NS_STYLE_LIST_STYLE_DISC },
|
||||
@ -163,12 +163,12 @@ nsAttrValue::EnumTable kListTypeTable[] = {
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
nsAttrValue::EnumTable kOldListTypeTable[] = {
|
||||
{ "1", NS_STYLE_LIST_STYLE_OLD_DECIMAL },
|
||||
{ "A", NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA },
|
||||
{ "a", NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA },
|
||||
{ "I", NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN },
|
||||
{ "i", NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN },
|
||||
static const nsAttrValue::EnumTable kOldListTypeTable[] = {
|
||||
{ "1", NS_STYLE_LIST_STYLE_DECIMAL },
|
||||
{ "A", NS_STYLE_LIST_STYLE_UPPER_ALPHA },
|
||||
{ "a", NS_STYLE_LIST_STYLE_LOWER_ALPHA },
|
||||
{ "I", NS_STYLE_LIST_STYLE_UPPER_ROMAN },
|
||||
{ "i", NS_STYLE_LIST_STYLE_LOWER_ROMAN },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
<handler event="keypress" key=" " modifiers="shift" command="cmd_scrollPageUp" />
|
||||
<handler event="keypress" key=" " command="cmd_scrollPageDown" />
|
||||
|
||||
<handler event="keypress" keycode="VK_LEFT" command="cmd_charPrevious"/>
|
||||
<handler event="keypress" keycode="VK_RIGHT" command="cmd_charNext"/>
|
||||
<handler event="keypress" keycode="VK_LEFT" command="cmd_selectCharPrevious" modifiers="shift"/>
|
||||
|
@ -31,6 +31,7 @@
|
||||
* Ryan Jones <sciguyryan@gmail.com>
|
||||
* Jeff Walden <jwalden+code@mit.edu>
|
||||
* Ben Bucksch <ben.bucksch beonex.com>
|
||||
* Emanuele Costa <emanuele.costa@gmail.com>
|
||||
*
|
||||
* 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"),
|
||||
@ -7483,6 +7484,15 @@ nsGlobalWindow::SetActive(PRBool aActive)
|
||||
NotifyDocumentTree(mDoc, nsnull);
|
||||
}
|
||||
|
||||
void nsGlobalWindow::SetIsBackground(PRBool aIsBackground)
|
||||
{
|
||||
PRBool resetTimers = (!aIsBackground && IsBackground());
|
||||
nsPIDOMWindow::SetIsBackground(aIsBackground);
|
||||
if (resetTimers) {
|
||||
ResetTimersForNonBackgroundWindow();
|
||||
}
|
||||
}
|
||||
|
||||
void nsGlobalWindow::MaybeUpdateTouchState()
|
||||
{
|
||||
FORWARD_TO_INNER_VOID(MaybeUpdateTouchState, ());
|
||||
@ -8848,10 +8858,8 @@ nsGlobalWindow::SetTimeoutOrInterval(nsIScriptTimeoutHandler *aHandler,
|
||||
}
|
||||
|
||||
nsRefPtr<nsTimeout> timeout = new nsTimeout();
|
||||
|
||||
if (aIsInterval) {
|
||||
timeout->mInterval = interval;
|
||||
}
|
||||
timeout->mIsInterval = aIsInterval;
|
||||
timeout->mInterval = interval;
|
||||
timeout->mScriptHandler = aHandler;
|
||||
|
||||
// Now clamp the actual interval we will use for the timer based on
|
||||
@ -9152,7 +9160,7 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout)
|
||||
++gRunningTimeoutDepth;
|
||||
++mTimeoutFiringDepth;
|
||||
|
||||
PRBool trackNestingLevel = !timeout->mInterval;
|
||||
PRBool trackNestingLevel = !timeout->mIsInterval;
|
||||
PRUint32 nestingLevel;
|
||||
if (trackNestingLevel) {
|
||||
nestingLevel = sNestingLevel;
|
||||
@ -9238,7 +9246,7 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout)
|
||||
|
||||
// If we have a regular interval timer, we re-schedule the
|
||||
// timeout, accounting for clock drift.
|
||||
if (timeout->mInterval) {
|
||||
if (timeout->mIsInterval) {
|
||||
// Compute time to next timeout for interval timer.
|
||||
// Make sure nextInterval is at least DOMMinTimeoutValue().
|
||||
TimeDuration nextInterval =
|
||||
@ -9309,7 +9317,7 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout)
|
||||
}
|
||||
|
||||
if (timeout->mTimer) {
|
||||
if (timeout->mInterval) {
|
||||
if (timeout->mIsInterval) {
|
||||
isInterval = PR_TRUE;
|
||||
} else {
|
||||
// The timeout still has an OS timer, and it's not an
|
||||
@ -9387,7 +9395,7 @@ nsGlobalWindow::ClearTimeoutOrInterval(PRInt32 aTimerID)
|
||||
/* We're running from inside the timeout. Mark this
|
||||
timeout for deferred deletion by the code in
|
||||
RunTimeout() */
|
||||
timeout->mInterval = 0;
|
||||
timeout->mIsInterval = PR_FALSE;
|
||||
}
|
||||
else {
|
||||
/* Delete the timeout from the pending timeout list */
|
||||
@ -9407,6 +9415,94 @@ nsGlobalWindow::ClearTimeoutOrInterval(PRInt32 aTimerID)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsGlobalWindow::ResetTimersForNonBackgroundWindow()
|
||||
{
|
||||
FORWARD_TO_INNER(ResetTimersForNonBackgroundWindow, (),
|
||||
NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
if (IsFrozen() || mTimeoutsSuspendDepth) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
|
||||
for (nsTimeout *timeout = FirstTimeout(); IsTimeout(timeout); ) {
|
||||
// It's important that this check be <= so that we guarantee that
|
||||
// taking NS_MAX with |now| won't make a quantity equal to
|
||||
// timeout->mWhen below.
|
||||
if (timeout->mWhen <= now) {
|
||||
timeout = timeout->Next();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (timeout->mWhen - now >
|
||||
TimeDuration::FromMilliseconds(gMinBackgroundTimeoutValue)) {
|
||||
// No need to loop further. Timeouts are sorted in mWhen order
|
||||
// and the ones after this point were all set up for at least
|
||||
// gMinBackgroundTimeoutValue ms and hence were not clamped.
|
||||
break;
|
||||
}
|
||||
|
||||
/* We switched from background. Re-init the timer appropriately */
|
||||
// Compute the interval the timer should have had if it had not been set in a
|
||||
// background window
|
||||
TimeDuration interval =
|
||||
TimeDuration::FromMilliseconds(NS_MAX(timeout->mInterval,
|
||||
PRUint32(DOMMinTimeoutValue())));
|
||||
PRUint32 oldIntervalMillisecs = 0;
|
||||
timeout->mTimer->GetDelay(&oldIntervalMillisecs);
|
||||
TimeDuration oldInterval = TimeDuration::FromMilliseconds(oldIntervalMillisecs);
|
||||
if (oldInterval > interval) {
|
||||
// unclamp
|
||||
TimeStamp firingTime =
|
||||
NS_MAX(timeout->mWhen - oldInterval + interval, now);
|
||||
|
||||
NS_ASSERTION(firingTime < timeout->mWhen,
|
||||
"Our firing time should strictly decrease!");
|
||||
|
||||
TimeDuration delay = firingTime - now;
|
||||
timeout->mWhen = firingTime;
|
||||
|
||||
// Since we reset mWhen we need to move |timeout| to the right
|
||||
// place in the list so that it remains sorted by mWhen.
|
||||
|
||||
// Get the pointer to the next timeout now, before we move the
|
||||
// current timeout in the list.
|
||||
nsTimeout* nextTimeout = timeout->Next();
|
||||
|
||||
// It is safe to remove and re-insert because mWhen is now
|
||||
// strictly smaller than it used to be, so we know we'll insert
|
||||
// |timeout| before nextTimeout.
|
||||
NS_ASSERTION(!IsTimeout(nextTimeout) ||
|
||||
timeout->mWhen < nextTimeout->mWhen, "How did that happen?");
|
||||
PR_REMOVE_LINK(timeout);
|
||||
// InsertTimeoutIntoList will addref |timeout| and reset
|
||||
// mFiringDepth. Make sure to undo that after calling it.
|
||||
PRUint32 firingDepth = timeout->mFiringDepth;
|
||||
InsertTimeoutIntoList(timeout);
|
||||
timeout->mFiringDepth = firingDepth;
|
||||
timeout->Release();
|
||||
|
||||
nsresult rv =
|
||||
timeout->mTimer->InitWithFuncCallback(TimerCallback,
|
||||
timeout,
|
||||
delay.ToMilliseconds(),
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Error resetting non background timer for DOM timeout!");
|
||||
return rv;
|
||||
}
|
||||
|
||||
timeout = nextTimeout;
|
||||
} else {
|
||||
timeout = timeout->Next();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// A JavaScript specific version.
|
||||
nsresult
|
||||
nsGlobalWindow::ClearTimeoutOrInterval()
|
||||
|
@ -195,10 +195,13 @@ struct nsTimeout : PRCList
|
||||
// True if this is one of the timeouts that are currently running
|
||||
PRPackedBool mRunning;
|
||||
|
||||
// True if this is a repeating/interval timer
|
||||
PRPackedBool mIsInterval;
|
||||
|
||||
// Returned as value of setTimeout()
|
||||
PRUint32 mPublicId;
|
||||
|
||||
// Non-zero interval in milliseconds if repetitive timeout
|
||||
// Interval in milliseconds
|
||||
PRUint32 mInterval;
|
||||
|
||||
// mWhen and mTimeRemaining can't be in a union, sadly, because they
|
||||
@ -342,6 +345,7 @@ public:
|
||||
virtual NS_HIDDEN_(nsPIDOMWindow*) GetPrivateRoot();
|
||||
virtual NS_HIDDEN_(void) ActivateOrDeactivate(PRBool aActivate);
|
||||
virtual NS_HIDDEN_(void) SetActive(PRBool aActive);
|
||||
virtual NS_HIDDEN_(void) SetIsBackground(PRBool aIsBackground);
|
||||
virtual NS_HIDDEN_(void) SetChromeEventHandler(nsIDOMEventTarget* aChromeEventHandler);
|
||||
|
||||
virtual NS_HIDDEN_(void) SetOpenerScriptPrincipal(nsIPrincipal* aPrincipal);
|
||||
@ -664,6 +668,7 @@ protected:
|
||||
// JS specific timeout functions (JS args grabbed from context).
|
||||
nsresult SetTimeoutOrInterval(PRBool aIsInterval, PRInt32* aReturn);
|
||||
nsresult ClearTimeoutOrInterval();
|
||||
nsresult ResetTimersForNonBackgroundWindow();
|
||||
|
||||
// The timeout implementation functions.
|
||||
void RunTimeout(nsTimeout *aTimeout);
|
||||
|
@ -105,7 +105,7 @@ public:
|
||||
return mIsActive;
|
||||
}
|
||||
|
||||
void SetIsBackground(PRBool aIsBackground)
|
||||
virtual void SetIsBackground(PRBool aIsBackground)
|
||||
{
|
||||
mIsBackground = aIsBackground;
|
||||
}
|
||||
|
@ -79,6 +79,10 @@ interface nsIDOMCanvasRenderingContext2D : nsISupports
|
||||
void translate(in float x, in float y);
|
||||
void transform(in float m11, in float m12, in float m21, in float m22, in float dx, in float dy);
|
||||
void setTransform(in float m11, in float m12, in float m21, in float m22, in float dx, in float dy);
|
||||
[implicit_jscontext]
|
||||
attribute jsval mozCurrentTransform; // [ m11, m12, m21, m22, dx, dy ], i.e. row major
|
||||
[implicit_jscontext]
|
||||
attribute jsval mozCurrentTransformInverse;
|
||||
|
||||
// compositing
|
||||
attribute float globalAlpha; /* default 1.0 -- opaque */
|
||||
@ -117,6 +121,10 @@ enum CanvasMultiGetterType {
|
||||
attribute DOMString lineJoin; /* "round", "bevel", "miter" (default) */
|
||||
attribute float miterLimit; /* default 10 */
|
||||
|
||||
[implicit_jscontext]
|
||||
attribute jsval mozDash; /* default |null| */
|
||||
attribute float mozDashOffset; /* default 0.0 */
|
||||
|
||||
// shadows
|
||||
attribute float shadowOffsetX;
|
||||
attribute float shadowOffsetY;
|
||||
|
@ -298,42 +298,92 @@ ContentChild::AllocPMemoryReportRequest()
|
||||
return new MemoryReportRequestChild();
|
||||
}
|
||||
|
||||
// This is just a wrapper for InfallibleTArray<MemoryReport> that implements
|
||||
// nsISupports, so it can be passed to nsIMemoryMultiReporter::CollectReports.
|
||||
class MemoryReportsWrapper : public nsISupports {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
MemoryReportsWrapper(InfallibleTArray<MemoryReport> *r) : mReports(r) { }
|
||||
InfallibleTArray<MemoryReport> *mReports;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS0(MemoryReportsWrapper)
|
||||
|
||||
class MemoryReportCallback : public nsIMemoryMultiReporterCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
MemoryReportCallback(const nsACString &aProcess)
|
||||
: mProcess(aProcess)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Callback(const nsACString &aProcess, const nsACString &aPath,
|
||||
PRInt32 aKind, PRInt32 aUnits, PRInt64 aAmount,
|
||||
const nsACString &aDescription,
|
||||
nsISupports *aiWrappedReports)
|
||||
{
|
||||
MemoryReportsWrapper *wrappedReports =
|
||||
static_cast<MemoryReportsWrapper *>(aiWrappedReports);
|
||||
|
||||
MemoryReport memreport(mProcess, nsCString(aPath), aKind, aUnits,
|
||||
aAmount, nsCString(aDescription));
|
||||
wrappedReports->mReports->AppendElement(memreport);
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
const nsCString mProcess;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
MemoryReportCallback
|
||||
, nsIMemoryMultiReporterCallback
|
||||
)
|
||||
|
||||
bool
|
||||
ContentChild::RecvPMemoryReportRequestConstructor(PMemoryReportRequestChild* child)
|
||||
{
|
||||
InfallibleTArray<MemoryReport> reports;
|
||||
|
||||
nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
|
||||
nsCOMPtr<nsISimpleEnumerator> r;
|
||||
mgr->EnumerateReporters(getter_AddRefs(r));
|
||||
|
||||
InfallibleTArray<MemoryReport> reports;
|
||||
|
||||
static const int maxLength = 31; // big enough; pid is only a few chars
|
||||
nsPrintfCString process(maxLength, "Content (%d)", getpid());
|
||||
|
||||
// First do the vanilla memory reporters.
|
||||
nsCOMPtr<nsISimpleEnumerator> e;
|
||||
mgr->EnumerateReporters(getter_AddRefs(e));
|
||||
PRBool more;
|
||||
while (NS_SUCCEEDED(r->HasMoreElements(&more)) && more) {
|
||||
nsCOMPtr<nsIMemoryReporter> report;
|
||||
r->GetNext(getter_AddRefs(report));
|
||||
while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) {
|
||||
nsCOMPtr<nsIMemoryReporter> r;
|
||||
e->GetNext(getter_AddRefs(r));
|
||||
|
||||
nsCString path;
|
||||
PRInt32 kind;
|
||||
PRInt32 units;
|
||||
nsCString desc;
|
||||
PRInt64 amount;
|
||||
report->GetPath(getter_Copies(path));
|
||||
report->GetKind(&kind);
|
||||
report->GetUnits(&units);
|
||||
report->GetAmount(&amount);
|
||||
report->GetDescription(getter_Copies(desc));
|
||||
|
||||
static const int maxLength = 31; // big enough; pid is only a few chars
|
||||
MemoryReport memreport(nsPrintfCString(maxLength, "Content (%d)",
|
||||
getpid()),
|
||||
path,
|
||||
kind,
|
||||
units,
|
||||
amount,
|
||||
desc);
|
||||
nsCString desc;
|
||||
r->GetPath(getter_Copies(path));
|
||||
r->GetKind(&kind);
|
||||
r->GetUnits(&units);
|
||||
r->GetAmount(&amount);
|
||||
r->GetDescription(getter_Copies(desc));
|
||||
|
||||
MemoryReport memreport(process, path, kind, units, amount, desc);
|
||||
reports.AppendElement(memreport);
|
||||
}
|
||||
|
||||
// Then do the memory multi-reporters, by calling CollectReports on each
|
||||
// one, whereupon the callback will turn each measurement into a
|
||||
// MemoryReport.
|
||||
mgr->EnumerateMultiReporters(getter_AddRefs(e));
|
||||
MemoryReportsWrapper wrappedReports(&reports);
|
||||
MemoryReportCallback cb(process);
|
||||
while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) {
|
||||
nsCOMPtr<nsIMemoryMultiReporter> r;
|
||||
e->GetNext(getter_AddRefs(r));
|
||||
|
||||
r->CollectReports(&cb, &wrappedReports);
|
||||
}
|
||||
|
||||
child->Send__delete__(child, reports);
|
||||
|
@ -514,8 +514,10 @@ bool
|
||||
TabParent::RecvGetIMEEnabled(PRUint32* aValue)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
if (!widget)
|
||||
if (!widget) {
|
||||
*aValue = nsIWidget::IME_STATUS_DISABLED;
|
||||
return true;
|
||||
}
|
||||
|
||||
IMEContext context;
|
||||
widget->GetInputMode(context);
|
||||
|
@ -4934,8 +4934,9 @@ nsHTMLEditRules::CheckForEmptyBlock(nsIDOMNode *aStartNode,
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
}
|
||||
}
|
||||
|
||||
if (emptyBlock)
|
||||
|
||||
nsCOMPtr<nsIContent> emptyContent = do_QueryInterface(emptyBlock);
|
||||
if (emptyBlock && emptyContent->IsEditable())
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> blockParent;
|
||||
PRInt32 offset;
|
||||
|
@ -52,6 +52,7 @@ _TEST_FILES = \
|
||||
test_bug372345.html \
|
||||
test_bug410986.html \
|
||||
test_bug432225.html \
|
||||
test_bug439808.html \
|
||||
test_bug455992.html \
|
||||
test_bug456244.html \
|
||||
test_bug478725.html \
|
||||
@ -61,6 +62,8 @@ _TEST_FILES = \
|
||||
test_bug520189.html \
|
||||
test_bug525389.html \
|
||||
test_bug537046.html \
|
||||
test_bug549262.html \
|
||||
file_bug549262.html \
|
||||
test_bug550434.html \
|
||||
test_bug551704.html \
|
||||
test_bug592592.html \
|
||||
|
8
editor/libeditor/html/tests/file_bug549262.html
Normal file
8
editor/libeditor/html/tests/file_bug549262.html
Normal file
@ -0,0 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<a href="">test</a>
|
||||
<div id="editor" contenteditable="true">abc</div>
|
||||
<div style="height: 20000px;"></div>
|
||||
</body>
|
||||
</html>
|
38
editor/libeditor/html/tests/test_bug439808.html
Normal file
38
editor/libeditor/html/tests/test_bug439808.html
Normal file
@ -0,0 +1,38 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=439808
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 439808</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=439808">Mozilla Bug 439808</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<span><span contenteditable id="e">twest</span></span>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 439808 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
var e = document.getElementById("e");
|
||||
e.focus();
|
||||
getSelection().collapse(e.firstChild, 1);
|
||||
synthesizeKey("VK_DELETE", {});
|
||||
is(e.textContent, "test", "Delete key worked");
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
is(e.textContent, "est", "Backspace key worked");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
74
editor/libeditor/html/tests/test_bug549262.html
Normal file
74
editor/libeditor/html/tests/test_bug549262.html
Normal file
@ -0,0 +1,74 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=549262
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 549262</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=549262">Mozilla Bug 549262</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 549262 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var win = window.open("file_bug549262.html", "_blank",
|
||||
"width=600,height=600");
|
||||
SimpleTest.waitForFocus(function() {
|
||||
// Make sure that pressing Space when a contenteditable element is not focused
|
||||
// will scroll the page.
|
||||
var ed = win.document.getElementById("editor");
|
||||
var sc = win.document.querySelector("a");
|
||||
sc.focus();
|
||||
is(win.scrollY, 0, "Sanity check");
|
||||
synthesizeKey(" ", {}, win);
|
||||
setTimeout(function() {
|
||||
isnot(win.scrollY, 0, "Page is scrolled down");
|
||||
is(ed.textContent, "abc", "The content of the editable element has not changed");
|
||||
synthesizeKey(" ", {shiftKey: true}, win);
|
||||
setTimeout(function() {
|
||||
is(win.scrollY, 0, "Page is scrolled up");
|
||||
is(ed.textContent, "abc", "The content of the editable element has not changed");
|
||||
|
||||
// Make sure that pressing Space when a contenteditable element is focused
|
||||
// will not scroll the page, and will edit the element.
|
||||
ed.focus();
|
||||
win.getSelection().collapse(ed.firstChild, 1);
|
||||
synthesizeKey(" ", {}, win);
|
||||
setTimeout(function() {
|
||||
is(win.scrollY, 0, "Page is not scrolled down");
|
||||
is(ed.textContent, "a bc", "The content of the editable element has changed");
|
||||
sc.focus();
|
||||
synthesizeKey(" ", {}, win);
|
||||
setTimeout(function() {
|
||||
isnot(win.scrollY, 0, "Page is scrolled down");
|
||||
is(ed.textContent, "a bc", "The content of the editable element has not changed");
|
||||
ed.focus();
|
||||
win.getSelection().collapse(ed.firstChild, 3);
|
||||
synthesizeKey(" ", {shiftKey: true}, win);
|
||||
setTimeout(function() {
|
||||
isnot(win.scrollY, 0, "Page is not scrolled up");
|
||||
is(ed.textContent, "a b c", "The content of the editable element has changed");
|
||||
|
||||
win.close();
|
||||
SimpleTest.finish();
|
||||
}, 0);
|
||||
}, 0);
|
||||
}, 0);
|
||||
}, 0);
|
||||
}, 0);
|
||||
}, win);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
22
gfx/2d/2D.h
22
gfx/2d/2D.h
@ -107,20 +107,38 @@ struct DrawOptions {
|
||||
* mLineJoin - Join style used for joining lines.
|
||||
* mLineCap - Cap style used for capping lines.
|
||||
* mMiterLimit - Miter limit in units of linewidth
|
||||
* mDashPattern - Series of on/off userspace lengths defining dash.
|
||||
* Owned by the caller; must live at least as long as
|
||||
* this StrokeOptions.
|
||||
* mDashPattern != null <=> mDashLength > 0.
|
||||
* mDashLength - Number of on/off lengths in mDashPattern.
|
||||
* mDashOffset - Userspace offset within mDashPattern at which stroking
|
||||
* begins.
|
||||
*/
|
||||
struct StrokeOptions {
|
||||
StrokeOptions(Float aLineWidth = 1.0f,
|
||||
JoinStyle aLineJoin = JOIN_MITER_OR_BEVEL,
|
||||
CapStyle aLineCap = CAP_BUTT,
|
||||
Float aMiterLimit = 10.0f)
|
||||
Float aMiterLimit = 10.0f,
|
||||
size_t aDashLength = 0,
|
||||
const Float* aDashPattern = 0,
|
||||
Float aDashOffset = 0.f)
|
||||
: mLineWidth(aLineWidth)
|
||||
, mMiterLimit(aMiterLimit)
|
||||
, mDashPattern(aDashLength > 0 ? aDashPattern : 0)
|
||||
, mDashLength(aDashLength)
|
||||
, mDashOffset(aDashOffset)
|
||||
, mLineJoin(aLineJoin)
|
||||
, mLineCap(aLineCap)
|
||||
{}
|
||||
{
|
||||
MOZ_ASSERT(aDashLength == 0 || aDashPattern);
|
||||
}
|
||||
|
||||
Float mLineWidth;
|
||||
Float mMiterLimit;
|
||||
const Float* mDashPattern;
|
||||
size_t mDashLength;
|
||||
Float mDashOffset;
|
||||
JoinStyle mLineJoin : 4;
|
||||
CapStyle mLineCap : 3;
|
||||
};
|
||||
|
@ -65,6 +65,8 @@ typedef HRESULT (WINAPI*D3D10CreateEffectFromMemoryFunc)(
|
||||
__out ID3D10Effect **ppEffect
|
||||
);
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
@ -665,8 +667,10 @@ DrawTargetD2D::CopySurface(SourceSurface *aSurface,
|
||||
const IntRect &aSourceRect,
|
||||
const IntPoint &aDestination)
|
||||
{
|
||||
Rect srcRect(aSourceRect.x, aSourceRect.y, aSourceRect.width, aSourceRect.height);
|
||||
Rect dstRect(aDestination.x, aDestination.y, aSourceRect.width, aSourceRect.height);
|
||||
Rect srcRect(Float(aSourceRect.x), Float(aSourceRect.y),
|
||||
Float(aSourceRect.width), Float(aSourceRect.height));
|
||||
Rect dstRect(Float(aDestination.x), Float(aDestination.y),
|
||||
Float(aSourceRect.width), Float(aSourceRect.height));
|
||||
|
||||
mRT->SetTransform(D2D1::IdentityMatrix());
|
||||
mRT->PushAxisAlignedClip(D2DRect(dstRect), D2D1_ANTIALIAS_MODE_ALIASED);
|
||||
@ -1632,10 +1636,36 @@ DrawTargetD2D::CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions)
|
||||
}
|
||||
|
||||
|
||||
HRESULT hr = factory()->CreateStrokeStyle(D2D1::StrokeStyleProperties(capStyle, capStyle,
|
||||
capStyle, joinStyle,
|
||||
aStrokeOptions.mMiterLimit),
|
||||
NULL, 0, byRef(style));
|
||||
HRESULT hr;
|
||||
if (aStrokeOptions.mDashPattern) {
|
||||
typedef vector<Float> FloatVector;
|
||||
// D2D "helpfully" multiplies the dash pattern by the line width.
|
||||
// That's not what cairo does, or is what <canvas>'s dash wants.
|
||||
// So fix the multiplication in advance.
|
||||
Float lineWidth = aStrokeOptions.mLineWidth;
|
||||
FloatVector dash(aStrokeOptions.mDashPattern,
|
||||
aStrokeOptions.mDashPattern + aStrokeOptions.mDashLength);
|
||||
for (FloatVector::iterator it = dash.begin(); it != dash.end(); ++it) {
|
||||
*it /= lineWidth;
|
||||
}
|
||||
|
||||
hr = factory()->CreateStrokeStyle(
|
||||
D2D1::StrokeStyleProperties(capStyle, capStyle,
|
||||
capStyle, joinStyle,
|
||||
aStrokeOptions.mMiterLimit,
|
||||
D2D1_DASH_STYLE_CUSTOM,
|
||||
aStrokeOptions.mDashOffset),
|
||||
&dash[0], // data() is not C++98, although it's in recent gcc
|
||||
// and VC10's STL
|
||||
dash.size(),
|
||||
byRef(style));
|
||||
} else {
|
||||
hr = factory()->CreateStrokeStyle(
|
||||
D2D1::StrokeStyleProperties(capStyle, capStyle,
|
||||
capStyle, joinStyle,
|
||||
aStrokeOptions.mMiterLimit),
|
||||
NULL, 0, byRef(style));
|
||||
}
|
||||
|
||||
if (FAILED(hr)) {
|
||||
gfxWarning() << "Failed to create Direct2D stroke style.";
|
||||
|
@ -545,7 +545,28 @@ gfxContext::SetDash(gfxFloat *dashes, int ndash, gfxFloat offset)
|
||||
{
|
||||
cairo_set_dash(mCairo, dashes, ndash, offset);
|
||||
}
|
||||
//void getDash() const;
|
||||
|
||||
bool
|
||||
gfxContext::CurrentDash(FallibleTArray<gfxFloat>& dashes, gfxFloat* offset) const
|
||||
{
|
||||
int count = cairo_get_dash_count(mCairo);
|
||||
if (count <= 0 || !dashes.SetLength(count)) {
|
||||
return false;
|
||||
}
|
||||
cairo_get_dash(mCairo, dashes.Elements(), offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
gfxFloat
|
||||
gfxContext::CurrentDashOffset() const
|
||||
{
|
||||
if (cairo_get_dash_count(mCairo) <= 0) {
|
||||
return 0.0;
|
||||
}
|
||||
gfxFloat offset;
|
||||
cairo_get_dash(mCairo, NULL, &offset);
|
||||
return offset;
|
||||
}
|
||||
|
||||
void
|
||||
gfxContext::SetLineWidth(gfxFloat width)
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
typedef struct _cairo cairo_t;
|
||||
template <typename T> class FallibleTArray;
|
||||
|
||||
/**
|
||||
* This is the main class for doing actual drawing. It is initialized using
|
||||
@ -465,7 +466,12 @@ public:
|
||||
|
||||
void SetDash(gfxLineType ltype);
|
||||
void SetDash(gfxFloat *dashes, int ndash, gfxFloat offset);
|
||||
//void getDash() const;
|
||||
// Return true if dashing is set, false if it's not enabled or the
|
||||
// context is in an error state. |offset| can be NULL to mean
|
||||
// "don't care".
|
||||
bool CurrentDash(FallibleTArray<gfxFloat>& dashes, gfxFloat* offset) const;
|
||||
// Returns 0.0 if dashing isn't enabled.
|
||||
gfxFloat CurrentDashOffset() const;
|
||||
|
||||
/**
|
||||
* Sets the line width that's used for line drawing.
|
||||
|
@ -557,11 +557,6 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) {
|
||||
#define NS_STYLE_LIST_STYLE_KATAKANA 16
|
||||
#define NS_STYLE_LIST_STYLE_HIRAGANA_IROHA 17
|
||||
#define NS_STYLE_LIST_STYLE_KATAKANA_IROHA 18
|
||||
#define NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN 19
|
||||
#define NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN 20
|
||||
#define NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA 21
|
||||
#define NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA 22
|
||||
#define NS_STYLE_LIST_STYLE_OLD_DECIMAL 23
|
||||
#define NS_STYLE_LIST_STYLE_MOZ_CJK_HEAVENLY_STEM 24
|
||||
#define NS_STYLE_LIST_STYLE_MOZ_CJK_EARTHLY_BRANCH 25
|
||||
#define NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_INFORMAL 26
|
||||
|
@ -48,6 +48,11 @@ function exitprintpreview() {
|
||||
.getInterface(Components.interfaces.nsIWebBrowserPrint).exitPrintPreview();
|
||||
}
|
||||
|
||||
function finish() {
|
||||
SimpleTest.finish();
|
||||
window.close();
|
||||
}
|
||||
|
||||
function run()
|
||||
{
|
||||
/** Test for Bug 396024 **/
|
||||
@ -59,7 +64,7 @@ function run()
|
||||
.getService(Components.interfaces.nsIPrinterEnumerator);
|
||||
} catch(e) {
|
||||
todo(false, "Test skipped on MacOSX, as the print preview code doesn't work there");
|
||||
SimpleTest.finish();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -72,7 +77,7 @@ function run()
|
||||
setTimeout(run2, 0)
|
||||
} else {
|
||||
todo(false, "No printer seems installed on this machine, that is necessary for this test");
|
||||
SimpleTest.finish();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,8 +117,7 @@ function run5() {
|
||||
//XXX this shouldn't be necessary, see bug 405555
|
||||
printpreview();
|
||||
exitprintpreview();
|
||||
SimpleTest.finish(); //should not have crashed after all of this
|
||||
window.close();
|
||||
finish(); //should not have crashed after all of this
|
||||
}
|
||||
]]></script>
|
||||
</window>
|
||||
|
@ -48,6 +48,11 @@ function exitprintpreview() {
|
||||
.getInterface(Components.interfaces.nsIWebBrowserPrint).exitPrintPreview();
|
||||
}
|
||||
|
||||
function finish() {
|
||||
SimpleTest.finish();
|
||||
window.close();
|
||||
}
|
||||
|
||||
function run1()
|
||||
{
|
||||
/** Test for Bug 482976 **/
|
||||
@ -59,7 +64,7 @@ function run1()
|
||||
.getService(Components.interfaces.nsIPrinterEnumerator);
|
||||
} catch(e) {
|
||||
todo(false, "Test skipped on MacOSX, as the print preview code doesn't work there");
|
||||
SimpleTest.finish();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -68,12 +73,10 @@ function run1()
|
||||
ok(gWbp.doingPrintPreview, "Should be doing print preview");
|
||||
exitprintpreview();
|
||||
ok(!gWbp.doingPrintPreview, "Should not be doing print preview anymore");
|
||||
SimpleTest.finish();
|
||||
} else {
|
||||
todo(false, "No printer seems installed on this machine, that is necessary for this test");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
window.close();
|
||||
finish();
|
||||
}
|
||||
]]></script>
|
||||
</window>
|
||||
|
@ -65,6 +65,11 @@ function exitprintpreview() {
|
||||
.getInterface(Components.interfaces.nsIWebBrowserPrint).exitPrintPreview();
|
||||
}
|
||||
|
||||
function finish() {
|
||||
SimpleTest.finish();
|
||||
window.close();
|
||||
}
|
||||
|
||||
function runTests()
|
||||
{
|
||||
var printService = Components.classes["@mozilla.org/gfx/printsettings-service;1"]
|
||||
@ -75,7 +80,7 @@ function runTests()
|
||||
.getService(Components.interfaces.nsIPrinterEnumerator);
|
||||
} catch(e) {
|
||||
todo(false, "Test skipped on MacOSX, as the print preview code doesn't work there");
|
||||
SimpleTest.finish();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -83,7 +88,7 @@ function runTests()
|
||||
startTest1();
|
||||
} else {
|
||||
todo(false, "No printer seems installed on this machine, that is necessary for this test");
|
||||
SimpleTest.finish();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,8 +244,7 @@ function runTest5() {
|
||||
'<input contenteditable="true" style="display: table; page-break-before: left; width: 10000px;">';
|
||||
printpreview();
|
||||
exitprintpreview();
|
||||
SimpleTest.finish();
|
||||
window.close();
|
||||
finish();
|
||||
}
|
||||
|
||||
]]></script>
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
<input id="i3" onkeydown="gKeyDown3++; frames[0].document.getElementById('i4').focus();"
|
||||
onkeypress="gKeyPress3++;" onkeyup="gKeyUp3++;"/>
|
||||
<iframe id="iframe" src="http://example.org/chrome/layout/base/tests/chrome/bug551434_childframe.html"></iframe>
|
||||
<iframe id="iframe" src="http://example.org/chrome/layout/base/test/chrome/bug551434_childframe.html"></iframe>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
|
@ -91,6 +91,10 @@
|
||||
#define NS_CANVASRENDERINGCONTEXT2D_CID \
|
||||
{ 0xa35d1cd4, 0xc505, 0x4d2d, { 0xa0, 0xf9, 0xae, 0xf0, 0x0b, 0x7c, 0xe5, 0xa5 } }
|
||||
|
||||
// {BCD923C0-9788-4350-AC48-365F473161EB}
|
||||
#define NS_CANVASRENDERINGCONTEXT2DTHEBES_CID \
|
||||
{ 0xbcd923c0, 0x9788, 0x4350, { 0xac, 0x48, 0x36, 0x5f, 0x47, 0x31, 0x61, 0xeb } }
|
||||
|
||||
// {9052bb12-79b0-4bdd-8e60-7bf078026b6d}
|
||||
#define NS_CANVASRENDERINGCONTEXT2DAZURE_CID \
|
||||
{0x9052bb12, 0x79b0, 0x4bdd, {0x8e, 0x60, 0x7b, 0xf0, 0x78, 0x02, 0x6b, 0x6d}}
|
||||
|
@ -440,6 +440,7 @@ nsresult NS_NewTreeBoxObject(nsIBoxObject** aResult);
|
||||
#endif
|
||||
|
||||
nsresult NS_NewCanvasRenderingContext2D(nsIDOMCanvasRenderingContext2D** aResult);
|
||||
nsresult NS_NewCanvasRenderingContext2DThebes(nsIDOMCanvasRenderingContext2D** aResult);
|
||||
nsresult NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult);
|
||||
|
||||
nsresult NS_CreateFrameTraversal(nsIFrameTraversal** aResult);
|
||||
@ -568,6 +569,7 @@ MAKE_CTOR(CreateVideoDocument, nsIDocument, NS_NewVid
|
||||
MAKE_CTOR(CreateFocusManager, nsIFocusManager, NS_NewFocusManager)
|
||||
|
||||
MAKE_CTOR(CreateCanvasRenderingContext2D, nsIDOMCanvasRenderingContext2D, NS_NewCanvasRenderingContext2D)
|
||||
MAKE_CTOR(CreateCanvasRenderingContext2DThebes, nsIDOMCanvasRenderingContext2D, NS_NewCanvasRenderingContext2DThebes)
|
||||
MAKE_CTOR(CreateCanvasRenderingContextWebGL, nsIDOMWebGLRenderingContext, NS_NewCanvasRenderingContextWebGL)
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStyleSheetService, Init)
|
||||
@ -771,6 +773,7 @@ NS_DEFINE_NAMED_CID(NS_HTMLOPTIONELEMENT_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_HTMLAUDIOELEMENT_CID);
|
||||
#endif
|
||||
NS_DEFINE_NAMED_CID(NS_CANVASRENDERINGCONTEXT2D_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_CANVASRENDERINGCONTEXT2DTHEBES_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_CANVASRENDERINGCONTEXT2DAZURE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_CANVASRENDERINGCONTEXTWEBGL_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_TEXT_ENCODER_CID);
|
||||
@ -914,6 +917,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
|
||||
#ifdef MOZ_MEDIA
|
||||
{ &kNS_HTMLAUDIOELEMENT_CID, false, NULL, CreateHTMLAudioElement },
|
||||
#endif
|
||||
{ &kNS_CANVASRENDERINGCONTEXT2DTHEBES_CID, false, NULL, CreateCanvasRenderingContext2DThebes },
|
||||
{ &kNS_CANVASRENDERINGCONTEXT2D_CID, false, NULL, CreateCanvasRenderingContext2D },
|
||||
{ &kNS_CANVASRENDERINGCONTEXTWEBGL_CID, false, NULL, CreateCanvasRenderingContextWebGL },
|
||||
{ &kNS_TEXT_ENCODER_CID, false, NULL, CreateTextEncoder },
|
||||
@ -1049,6 +1053,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
|
||||
{ NS_HTMLAUDIOELEMENT_CONTRACTID, &kNS_HTMLAUDIOELEMENT_CID },
|
||||
#endif
|
||||
{ "@mozilla.org/content/canvas-rendering-context;1?id=2d", &kNS_CANVASRENDERINGCONTEXT2D_CID },
|
||||
{ "@mozilla.org/content/canvas-rendering-context;1?id=2dthebes", &kNS_CANVASRENDERINGCONTEXT2DTHEBES_CID },
|
||||
{ "@mozilla.org/content/canvas-rendering-context;1?id=moz-webgl", &kNS_CANVASRENDERINGCONTEXTWEBGL_CID },
|
||||
{ "@mozilla.org/content/canvas-rendering-context;1?id=experimental-webgl", &kNS_CANVASRENDERINGCONTEXTWEBGL_CID },
|
||||
{ NS_DOC_ENCODER_CONTRACTID_BASE "text/xml", &kNS_TEXT_ENCODER_CID },
|
||||
|
@ -335,16 +335,11 @@ nsBulletFrame::PaintBullet(nsRenderingContext& aRenderingContext, nsPoint aPt,
|
||||
break;
|
||||
|
||||
case NS_STYLE_LIST_STYLE_DECIMAL:
|
||||
case NS_STYLE_LIST_STYLE_OLD_DECIMAL:
|
||||
case NS_STYLE_LIST_STYLE_DECIMAL_LEADING_ZERO:
|
||||
case NS_STYLE_LIST_STYLE_LOWER_ROMAN:
|
||||
case NS_STYLE_LIST_STYLE_UPPER_ROMAN:
|
||||
case NS_STYLE_LIST_STYLE_LOWER_ALPHA:
|
||||
case NS_STYLE_LIST_STYLE_UPPER_ALPHA:
|
||||
case NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN:
|
||||
case NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN:
|
||||
case NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA:
|
||||
case NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA:
|
||||
case NS_STYLE_LIST_STYLE_LOWER_GREEK:
|
||||
case NS_STYLE_LIST_STYLE_HEBREW:
|
||||
case NS_STYLE_LIST_STYLE_ARMENIAN:
|
||||
@ -1062,7 +1057,6 @@ nsBulletFrame::AppendCounterText(PRInt32 aListStyleType,
|
||||
break;
|
||||
|
||||
case NS_STYLE_LIST_STYLE_DECIMAL:
|
||||
case NS_STYLE_LIST_STYLE_OLD_DECIMAL:
|
||||
default: // CSS2 say "A users agent that does not recognize a numbering system
|
||||
// should use 'decimal'
|
||||
success = DecimalToText(aOrdinal, result);
|
||||
@ -1073,23 +1067,19 @@ nsBulletFrame::AppendCounterText(PRInt32 aListStyleType,
|
||||
break;
|
||||
|
||||
case NS_STYLE_LIST_STYLE_LOWER_ROMAN:
|
||||
case NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN:
|
||||
success = RomanToText(aOrdinal, result,
|
||||
gLowerRomanCharsA, gLowerRomanCharsB);
|
||||
break;
|
||||
case NS_STYLE_LIST_STYLE_UPPER_ROMAN:
|
||||
case NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN:
|
||||
success = RomanToText(aOrdinal, result,
|
||||
gUpperRomanCharsA, gUpperRomanCharsB);
|
||||
break;
|
||||
|
||||
case NS_STYLE_LIST_STYLE_LOWER_ALPHA:
|
||||
case NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA:
|
||||
success = CharListToText(aOrdinal, result, gLowerAlphaChars, ALPHA_SIZE);
|
||||
break;
|
||||
|
||||
case NS_STYLE_LIST_STYLE_UPPER_ALPHA:
|
||||
case NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA:
|
||||
success = CharListToText(aOrdinal, result, gUpperAlphaChars, ALPHA_SIZE);
|
||||
break;
|
||||
|
||||
@ -1371,15 +1361,10 @@ nsBulletFrame::GetDesiredSize(nsPresContext* aCX,
|
||||
default:
|
||||
case NS_STYLE_LIST_STYLE_DECIMAL_LEADING_ZERO:
|
||||
case NS_STYLE_LIST_STYLE_DECIMAL:
|
||||
case NS_STYLE_LIST_STYLE_OLD_DECIMAL:
|
||||
case NS_STYLE_LIST_STYLE_LOWER_ROMAN:
|
||||
case NS_STYLE_LIST_STYLE_UPPER_ROMAN:
|
||||
case NS_STYLE_LIST_STYLE_LOWER_ALPHA:
|
||||
case NS_STYLE_LIST_STYLE_UPPER_ALPHA:
|
||||
case NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN:
|
||||
case NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN:
|
||||
case NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA:
|
||||
case NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA:
|
||||
case NS_STYLE_LIST_STYLE_KATAKANA:
|
||||
case NS_STYLE_LIST_STYLE_HIRAGANA:
|
||||
case NS_STYLE_LIST_STYLE_KATAKANA_IROHA:
|
||||
|
@ -310,23 +310,29 @@ public:
|
||||
const nsCharClipDisplayItem::ClipEdges& aClipEdges,
|
||||
const nscolor* aOverrideColor = nsnull);
|
||||
// helper: paint text frame when we're impacted by at least one selection.
|
||||
// Return PR_FALSE if the text was not painted and we should continue with
|
||||
// Return false if the text was not painted and we should continue with
|
||||
// the fast path.
|
||||
PRBool PaintTextWithSelection(gfxContext* aCtx,
|
||||
const gfxPoint& aFramePt,
|
||||
const gfxPoint& aTextBaselinePt,
|
||||
const gfxRect& aDirtyRect,
|
||||
PropertyProvider& aProvider,
|
||||
nsTextPaintStyle& aTextPaintStyle,
|
||||
const nsCharClipDisplayItem::ClipEdges& aClipEdges);
|
||||
bool PaintTextWithSelection(gfxContext* aCtx,
|
||||
const gfxPoint& aFramePt,
|
||||
const gfxPoint& aTextBaselinePt,
|
||||
const gfxRect& aDirtyRect,
|
||||
PropertyProvider& aProvider,
|
||||
PRUint32 aContentOffset,
|
||||
PRUint32 aContentLength,
|
||||
nsTextPaintStyle& aTextPaintStyle,
|
||||
const nsCharClipDisplayItem::ClipEdges& aClipEdges);
|
||||
// helper: paint text with foreground and background colors determined
|
||||
// by selection(s). Also computes a mask of all selection types applying to
|
||||
// our text, returned in aAllTypes.
|
||||
void PaintTextWithSelectionColors(gfxContext* aCtx,
|
||||
// Return false if the text was not painted and we should continue with
|
||||
// the fast path.
|
||||
bool PaintTextWithSelectionColors(gfxContext* aCtx,
|
||||
const gfxPoint& aFramePt,
|
||||
const gfxPoint& aTextBaselinePt,
|
||||
const gfxRect& aDirtyRect,
|
||||
PropertyProvider& aProvider,
|
||||
PRUint32 aContentOffset,
|
||||
PRUint32 aContentLength,
|
||||
nsTextPaintStyle& aTextPaintStyle,
|
||||
SelectionDetails* aDetails,
|
||||
SelectionType* aAllTypes);
|
||||
@ -336,6 +342,8 @@ public:
|
||||
const gfxPoint& aTextBaselinePt,
|
||||
const gfxRect& aDirtyRect,
|
||||
PropertyProvider& aProvider,
|
||||
PRUint32 aContentOffset,
|
||||
PRUint32 aContentLength,
|
||||
nsTextPaintStyle& aTextPaintStyle,
|
||||
SelectionDetails* aDetails,
|
||||
SelectionType aSelectionType);
|
||||
|
@ -4661,10 +4661,14 @@ public:
|
||||
/**
|
||||
* aStart and aLength are in the original string. aSelectionDetails is
|
||||
* according to the original string.
|
||||
* @param aXOffset the offset from the origin of the frame to the start
|
||||
* of the text (the left baseline origin for LTR, the right baseline origin
|
||||
* for RTL)
|
||||
*/
|
||||
SelectionIterator(SelectionDetails** aSelectionDetails,
|
||||
PRInt32 aStart, PRInt32 aLength,
|
||||
PropertyProvider& aProvider, gfxTextRun* aTextRun);
|
||||
PropertyProvider& aProvider, gfxTextRun* aTextRun,
|
||||
gfxFloat aXOffset);
|
||||
|
||||
/**
|
||||
* Returns the next segment of uniformly selected (or not) text.
|
||||
@ -4698,11 +4702,11 @@ private:
|
||||
|
||||
SelectionIterator::SelectionIterator(SelectionDetails** aSelectionDetails,
|
||||
PRInt32 aStart, PRInt32 aLength, PropertyProvider& aProvider,
|
||||
gfxTextRun* aTextRun)
|
||||
gfxTextRun* aTextRun, gfxFloat aXOffset)
|
||||
: mSelectionDetails(aSelectionDetails), mProvider(aProvider),
|
||||
mTextRun(aTextRun), mIterator(aProvider.GetStart()),
|
||||
mOriginalStart(aStart), mOriginalEnd(aStart + aLength),
|
||||
mXOffset(mTextRun->IsRightToLeft() ? aProvider.GetFrame()->GetSize().width : 0)
|
||||
mXOffset(aXOffset)
|
||||
{
|
||||
mIterator.SetOriginalOffset(aStart);
|
||||
}
|
||||
@ -4838,33 +4842,32 @@ nsTextFrame::PaintOneShadow(PRUint32 aOffset, PRUint32 aLength,
|
||||
|
||||
// Paints selection backgrounds and text in the correct colors. Also computes
|
||||
// aAllTypes, the union of all selection types that are applying to this text.
|
||||
void
|
||||
bool
|
||||
nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
|
||||
const gfxPoint& aFramePt,
|
||||
const gfxPoint& aTextBaselinePt, const gfxRect& aDirtyRect,
|
||||
PropertyProvider& aProvider, nsTextPaintStyle& aTextPaintStyle,
|
||||
SelectionDetails* aDetails, SelectionType* aAllTypes)
|
||||
PropertyProvider& aProvider,
|
||||
PRUint32 aContentOffset, PRUint32 aContentLength,
|
||||
nsTextPaintStyle& aTextPaintStyle, SelectionDetails* aDetails,
|
||||
SelectionType* aAllTypes)
|
||||
{
|
||||
PRInt32 contentOffset = aProvider.GetStart().GetOriginalOffset();
|
||||
PRInt32 contentLength = aProvider.GetOriginalLength();
|
||||
|
||||
// Figure out which selections control the colors to use for each character.
|
||||
nsAutoTArray<SelectionDetails*,BIG_TEXT_NODE_SIZE> prevailingSelectionsBuffer;
|
||||
if (!prevailingSelectionsBuffer.AppendElements(contentLength))
|
||||
return;
|
||||
if (!prevailingSelectionsBuffer.AppendElements(aContentLength))
|
||||
return false;
|
||||
SelectionDetails** prevailingSelections = prevailingSelectionsBuffer.Elements();
|
||||
|
||||
PRInt32 i;
|
||||
SelectionType allTypes = 0;
|
||||
for (i = 0; i < contentLength; ++i) {
|
||||
for (PRUint32 i = 0; i < aContentLength; ++i) {
|
||||
prevailingSelections[i] = nsnull;
|
||||
}
|
||||
|
||||
SelectionDetails *sdptr = aDetails;
|
||||
PRBool anyBackgrounds = PR_FALSE;
|
||||
while (sdptr) {
|
||||
PRInt32 start = NS_MAX(0, sdptr->mStart - contentOffset);
|
||||
PRInt32 end = NS_MIN(contentLength, sdptr->mEnd - contentOffset);
|
||||
PRInt32 start = NS_MAX(0, sdptr->mStart - PRInt32(aContentOffset));
|
||||
PRInt32 end = NS_MIN(PRInt32(aContentLength),
|
||||
sdptr->mEnd - PRInt32(aContentOffset));
|
||||
SelectionType type = sdptr->mType;
|
||||
if (start < end) {
|
||||
allTypes |= type;
|
||||
@ -4875,7 +4878,7 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
|
||||
if (NS_GET_A(background) > 0) {
|
||||
anyBackgrounds = PR_TRUE;
|
||||
}
|
||||
for (i = start; i < end; ++i) {
|
||||
for (PRInt32 i = start; i < end; ++i) {
|
||||
// Favour normal selection over IME selections
|
||||
if (!prevailingSelections[i] ||
|
||||
type < prevailingSelections[i]->mType) {
|
||||
@ -4888,14 +4891,26 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
|
||||
}
|
||||
*aAllTypes = allTypes;
|
||||
|
||||
if (!allTypes) {
|
||||
// Nothing is selected in the given text range.
|
||||
if (aContentLength == aProvider.GetOriginalLength()) {
|
||||
// It's the full text range so we can remove the FRAME_SELECTED_CONTENT
|
||||
// bit to avoid going through this slow path until something is selected
|
||||
// in this frame again.
|
||||
RemoveStateBits(NS_FRAME_SELECTED_CONTENT);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const gfxFloat startXOffset = aTextBaselinePt.x - aFramePt.x;
|
||||
gfxFloat xOffset, hyphenWidth;
|
||||
PRUint32 offset, length; // in transformed string
|
||||
SelectionType type;
|
||||
nsTextRangeStyle rangeStyle;
|
||||
// Draw background colors
|
||||
if (anyBackgrounds) {
|
||||
SelectionIterator iterator(prevailingSelections, contentOffset, contentLength,
|
||||
aProvider, mTextRun);
|
||||
SelectionIterator iterator(prevailingSelections, aContentOffset, aContentLength,
|
||||
aProvider, mTextRun, startXOffset);
|
||||
while (iterator.GetNextSegment(&xOffset, &offset, &length, &hyphenWidth,
|
||||
&type, &rangeStyle)) {
|
||||
nscolor foreground, background;
|
||||
@ -4915,8 +4930,8 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
|
||||
}
|
||||
|
||||
// Draw text
|
||||
SelectionIterator iterator(prevailingSelections, contentOffset, contentLength,
|
||||
aProvider, mTextRun);
|
||||
SelectionIterator iterator(prevailingSelections, aContentOffset, aContentLength,
|
||||
aProvider, mTextRun, startXOffset);
|
||||
while (iterator.GetNextSegment(&xOffset, &offset, &length, &hyphenWidth,
|
||||
&type, &rangeStyle)) {
|
||||
nscolor foreground, background;
|
||||
@ -4934,38 +4949,38 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
|
||||
}
|
||||
iterator.UpdateWithAdvance(advance);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx,
|
||||
const gfxPoint& aFramePt,
|
||||
const gfxPoint& aTextBaselinePt, const gfxRect& aDirtyRect,
|
||||
PropertyProvider& aProvider, nsTextPaintStyle& aTextPaintStyle,
|
||||
SelectionDetails* aDetails, SelectionType aSelectionType)
|
||||
PropertyProvider& aProvider,
|
||||
PRUint32 aContentOffset, PRUint32 aContentLength,
|
||||
nsTextPaintStyle& aTextPaintStyle, SelectionDetails* aDetails,
|
||||
SelectionType aSelectionType)
|
||||
{
|
||||
// Hide text decorations if we're currently hiding @font-face fallback text
|
||||
if (aProvider.GetFontGroup()->ShouldSkipDrawing())
|
||||
return;
|
||||
|
||||
PRInt32 contentOffset = aProvider.GetStart().GetOriginalOffset();
|
||||
PRInt32 contentLength = aProvider.GetOriginalLength();
|
||||
|
||||
// Figure out which characters will be decorated for this selection.
|
||||
nsAutoTArray<SelectionDetails*, BIG_TEXT_NODE_SIZE> selectedCharsBuffer;
|
||||
if (!selectedCharsBuffer.AppendElements(contentLength))
|
||||
if (!selectedCharsBuffer.AppendElements(aContentLength))
|
||||
return;
|
||||
SelectionDetails** selectedChars = selectedCharsBuffer.Elements();
|
||||
PRInt32 i;
|
||||
for (i = 0; i < contentLength; ++i) {
|
||||
for (PRUint32 i = 0; i < aContentLength; ++i) {
|
||||
selectedChars[i] = nsnull;
|
||||
}
|
||||
|
||||
SelectionDetails *sdptr = aDetails;
|
||||
while (sdptr) {
|
||||
if (sdptr->mType == aSelectionType) {
|
||||
PRInt32 start = NS_MAX(0, sdptr->mStart - contentOffset);
|
||||
PRInt32 end = NS_MIN(contentLength, sdptr->mEnd - contentOffset);
|
||||
for (i = start; i < end; ++i) {
|
||||
PRInt32 start = NS_MAX(0, sdptr->mStart - PRInt32(aContentOffset));
|
||||
PRInt32 end = NS_MIN(PRInt32(aContentLength),
|
||||
sdptr->mEnd - PRInt32(aContentOffset));
|
||||
for (PRInt32 i = start; i < end; ++i) {
|
||||
selectedChars[i] = sdptr;
|
||||
}
|
||||
}
|
||||
@ -4979,8 +4994,9 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx,
|
||||
decorationMetrics.underlineOffset =
|
||||
aProvider.GetFontGroup()->GetUnderlineOffset();
|
||||
|
||||
SelectionIterator iterator(selectedChars, contentOffset, contentLength,
|
||||
aProvider, mTextRun);
|
||||
gfxFloat startXOffset = aTextBaselinePt.x - aFramePt.x;
|
||||
SelectionIterator iterator(selectedChars, aContentOffset, aContentLength,
|
||||
aProvider, mTextRun, startXOffset);
|
||||
gfxFloat xOffset, hyphenWidth;
|
||||
PRUint32 offset, length;
|
||||
PRInt32 app = aTextPaintStyle.PresContext()->AppUnitsPerDevPixel();
|
||||
@ -5004,20 +5020,32 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx,
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
bool
|
||||
nsTextFrame::PaintTextWithSelection(gfxContext* aCtx,
|
||||
const gfxPoint& aFramePt,
|
||||
const gfxPoint& aTextBaselinePt, const gfxRect& aDirtyRect,
|
||||
PropertyProvider& aProvider, nsTextPaintStyle& aTextPaintStyle,
|
||||
PropertyProvider& aProvider, PRUint32 aContentOffset, PRUint32 aContentLength,
|
||||
nsTextPaintStyle& aTextPaintStyle,
|
||||
const nsCharClipDisplayItem::ClipEdges& aClipEdges)
|
||||
{
|
||||
SelectionDetails* details = GetSelectionDetails();
|
||||
if (!details)
|
||||
return PR_FALSE;
|
||||
if (!details) {
|
||||
if (aContentLength == aProvider.GetOriginalLength()) {
|
||||
// It's the full text range so we can remove the FRAME_SELECTED_CONTENT
|
||||
// bit to avoid going through this slow path until something is selected
|
||||
// in this frame again.
|
||||
RemoveStateBits(NS_FRAME_SELECTED_CONTENT);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
SelectionType allTypes;
|
||||
PaintTextWithSelectionColors(aCtx, aFramePt, aTextBaselinePt, aDirtyRect,
|
||||
aProvider, aTextPaintStyle, details, &allTypes);
|
||||
if (!PaintTextWithSelectionColors(aCtx, aFramePt, aTextBaselinePt, aDirtyRect,
|
||||
aProvider, aContentOffset, aContentLength,
|
||||
aTextPaintStyle, details, &allTypes)) {
|
||||
DestroySelectionDetails(details);
|
||||
return false;
|
||||
}
|
||||
PaintTextDecorations(aCtx, aDirtyRect, aFramePt, aTextBaselinePt,
|
||||
aTextPaintStyle, aProvider, aClipEdges);
|
||||
PRInt32 i;
|
||||
@ -5033,12 +5061,13 @@ nsTextFrame::PaintTextWithSelection(gfxContext* aCtx,
|
||||
// (there might not be any for this type but that's OK,
|
||||
// PaintTextSelectionDecorations will exit early).
|
||||
PaintTextSelectionDecorations(aCtx, aFramePt, aTextBaselinePt, aDirtyRect,
|
||||
aProvider, aTextPaintStyle, details, type);
|
||||
aProvider, aContentOffset, aContentLength,
|
||||
aTextPaintStyle, details, type);
|
||||
}
|
||||
}
|
||||
|
||||
DestroySelectionDetails(details);
|
||||
return PR_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
nscolor
|
||||
@ -5260,8 +5289,13 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
|
||||
aDirtyRect.width, aDirtyRect.height);
|
||||
// Fork off to the (slower) paint-with-selection path if necessary.
|
||||
if (nsLayoutUtils::GetNonGeneratedAncestor(this)->GetStateBits() & NS_FRAME_SELECTED_CONTENT) {
|
||||
if (PaintTextWithSelection(ctx, framePt, textBaselinePt,
|
||||
dirtyRect, provider, textPaintStyle, clipEdges))
|
||||
gfxSkipCharsIterator tmp(provider.GetStart());
|
||||
PRInt32 contentOffset = tmp.ConvertSkippedToOriginal(startOffset);
|
||||
PRInt32 contentLength =
|
||||
tmp.ConvertSkippedToOriginal(startOffset + maxLength) - contentOffset;
|
||||
if (PaintTextWithSelection(ctx, framePt, textBaselinePt, dirtyRect,
|
||||
provider, contentOffset, contentLength,
|
||||
textPaintStyle, clipEdges))
|
||||
return;
|
||||
}
|
||||
|
||||
|
18
layout/reftests/canvas/ctm-1-ref.html
Normal file
18
layout/reftests/canvas/ctm-1-ref.html
Normal file
@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("c1").getContext("2d");
|
||||
|
||||
ctx.setTransform(10, 0, 0, 1, 0, 0);
|
||||
ctx.fillRect(1, 1, 10, 10);
|
||||
|
||||
ctx.setTransform(1, 0, 0, 10, 0, 0);
|
||||
ctx.fillRect(150, 1, 10, 10);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body style="padding: 0px; margin: 0px;">
|
||||
<div><canvas id="c1" width="300" height="300"></canvas></div>
|
||||
</body>
|
||||
</html>
|
18
layout/reftests/canvas/ctm-1.html
Normal file
18
layout/reftests/canvas/ctm-1.html
Normal file
@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("c1").getContext("2d");
|
||||
|
||||
ctx.mozCurrentTransform = [ 10, 0, 0, 1, 0, 0 ];
|
||||
ctx.fillRect(1, 1, 10, 10);
|
||||
|
||||
ctx.mozCurrentTransformInverse = [ 1, 0, 0, .1, 0, 0 ];
|
||||
ctx.fillRect(150, 1, 10, 10);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body style="padding: 0px; margin: 0px;">
|
||||
<div><canvas id="c1" width="300" height="300"></canvas></div>
|
||||
</body>
|
||||
</html>
|
83
layout/reftests/canvas/ctm-sanity.html
Normal file
83
layout/reftests/canvas/ctm-sanity.html
Normal file
@ -0,0 +1,83 @@
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
|
||||
function assert(cond, msg) { if (!cond) { throw msg; } }
|
||||
|
||||
function isSameTM(m1, m2) {
|
||||
// XXX this is probably the ugliest possible way to write this function,
|
||||
// but it's intended to be lowest-common-denominator
|
||||
if (!(m1.length === 6 && m1.length === m2.length)) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0; i < m1.length; ++i) {
|
||||
if (m1[i] !== m2[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
var IM = [ 1, 0, 0, 1, 0, 0 ];
|
||||
|
||||
try {
|
||||
var ctx = document.getElementById("c1").getContext("2d");
|
||||
|
||||
assert(isSameTM(IM, ctx.mozCurrentTransform),
|
||||
"currentTransform is identity by default");
|
||||
assert(isSameTM(IM, ctx.mozCurrentTransformInverse),
|
||||
"currentTransformInverse is identity by default");
|
||||
|
||||
var m = [ 1, 2, 3, 4, 5, 6 ];
|
||||
ctx.mozCurrentTransform = m;
|
||||
assert(isSameTM(m, ctx.mozCurrentTransform),
|
||||
"currentTransform sucessfully set");
|
||||
var badVals = [ -1,
|
||||
"string",
|
||||
{ obj: true },
|
||||
[ "array of string" ],
|
||||
[ -1 ],
|
||||
[ "string", 1, 2, 3, 4, 5 ],
|
||||
[ { obj: true }, 1, 2, 3, 4, 5 ],
|
||||
];
|
||||
for (var i = 0; i < badVals.length; ++i) {
|
||||
var error = false;
|
||||
try { ctx.mozCurrentTransform = badVals[i]; }
|
||||
catch(e) { error = true; }
|
||||
assert(error && isSameTM(m, ctx.mozCurrentTransform),
|
||||
"Expected |currentTransform = "+ badVals[i] +"| to throw exception and not change .currentTransform");
|
||||
|
||||
error = false;
|
||||
try { ctx.mozCurrentTransformInverse = badVals[i]; }
|
||||
catch(e) { error = true; }
|
||||
assert(error && isSameTM(m, ctx.mozCurrentTransform),
|
||||
"Expected |currentTransformInverse = "+ badVals[i] +"| to throw exception and not change .currentTransform");
|
||||
}
|
||||
ctx.mozCurrentTransform = IM;
|
||||
|
||||
var noopVals = [ [ Number.NaN, 1, 2, 3, 4, 5 ],
|
||||
[ Infinity, 1, 2, 3, 4, 5 ],
|
||||
];
|
||||
for (var i = 0; i < noopVals.length; ++i) {
|
||||
ctx.mozCurrentTransform = noopVals[i];
|
||||
assert(isSameTM(ctx.mozCurrentTransform, IM),
|
||||
"Illegal float values result in no-ops (sigh)");
|
||||
}
|
||||
ctx.mozCurrentTransform = IM;
|
||||
|
||||
ctx.setTransform(m[0], m[1], m[2], m[3], m[4], m[5]);
|
||||
assert(isSameTM(ctx.mozCurrentTransform, m),
|
||||
"setTransform() updates currentTransform");
|
||||
} catch (e) {
|
||||
document.body.innerHTML = "FAIL: "+ e.toString();
|
||||
return;
|
||||
}
|
||||
document.body.innerHTML = "Pass";
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div><canvas id="c1" width="300" height="300"></canvas></div>
|
||||
</body>
|
||||
</html>
|
53
layout/reftests/canvas/ctm-singular-sanity.html
Normal file
53
layout/reftests/canvas/ctm-singular-sanity.html
Normal file
@ -0,0 +1,53 @@
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
|
||||
function assert(cond, msg) { if (!cond) { throw msg; } }
|
||||
|
||||
function isSameTM(m1, m2) {
|
||||
// XXX this is probably the ugliest possible way to write this function,
|
||||
// but it's intended to be lowest-common-denominator
|
||||
if (!(m1.length === 6 && m1.length === m2.length)) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0; i < m1.length; ++i) {
|
||||
if (m1[i] !== m2[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
var IM = [ 1, 0, 0, 1, 0, 0 ];
|
||||
|
||||
try {
|
||||
var ctx = document.getElementById("c1").getContext("2d");
|
||||
|
||||
var singular = [ 0, 0, 0, 0, 0, 0 ];
|
||||
ctx.mozCurrentTransform = singular;
|
||||
assert(isSameTM(singular, ctx.mozCurrentTransform),
|
||||
"Expected setting CTM to a singular matrix to work");
|
||||
var inv = ctx.mozCurrentTransformInverse;
|
||||
assert(!isSameTM(inv, inv),
|
||||
"Expected to get back matrix of NaN's from currentTransformInverse");
|
||||
ctx.mozCurrentTransform = IM;
|
||||
|
||||
var m = [ 1, 2, 3, 4, 5, 6 ];
|
||||
ctx.mozCurrentTransform = m;
|
||||
ctx.mozCurrentTransformInverse = singular;
|
||||
assert(isSameTM(m, ctx.mozCurrentTransform,
|
||||
"Setting currentTransformInverse to a singular matrix is a no-op");
|
||||
ctx.mozCurrentTransform = IM;
|
||||
} catch (e) {
|
||||
document.body.innerHTML = "FAIL: "+ e.toString();
|
||||
return;
|
||||
}
|
||||
document.body.innerHTML = "Pass";
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div><canvas id="c1" width="300" height="300"></canvas></div>
|
||||
</body>
|
||||
</html>
|
14
layout/reftests/canvas/dash-1-ref.svg
Normal file
14
layout/reftests/canvas/dash-1-ref.svg
Normal file
@ -0,0 +1,14 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
width="300" height="300" viewBox="0 0 300 300" >
|
||||
<style>
|
||||
line { stroke: black; stroke-width: 5px; }
|
||||
</style>
|
||||
|
||||
<line x1="50px" y1="50px" x2="250px" y2="50px"
|
||||
style="stroke-dasharray: 5px, 10px">
|
||||
</line>
|
||||
|
||||
<line x1="50px" y1="100px" x2="250px" y2="100px"
|
||||
style="stroke-dasharray: 5px, 10px; stroke-dashoffset: 5px;">
|
||||
</line>
|
||||
</svg>
|
After Width: | Height: | Size: 406 B |
26
layout/reftests/canvas/dash-1.html
Normal file
26
layout/reftests/canvas/dash-1.html
Normal file
@ -0,0 +1,26 @@
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("c1").getContext("2d");
|
||||
|
||||
ctx.lineWidth = 5;
|
||||
|
||||
ctx.mozDash = [ 5, 10 ]; // 5 on, 10 off
|
||||
ctx.moveTo(50, 50);
|
||||
ctx.lineTo(250, 50);
|
||||
ctx.stroke();
|
||||
ctx.beginPath();
|
||||
|
||||
ctx.mozDashOffset = 5;
|
||||
ctx.moveTo(50, 100);
|
||||
ctx.lineTo(250, 100);
|
||||
ctx.stroke();
|
||||
ctx.beginPath();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body style="padding: 0px; margin: 0px;">
|
||||
<div><canvas id="c1" width="300" height="300"></canvas></div>
|
||||
</body>
|
||||
</html>
|
85
layout/reftests/canvas/dash-sanity.html
Normal file
85
layout/reftests/canvas/dash-sanity.html
Normal file
@ -0,0 +1,85 @@
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
function assert(cond, msg) { if (!cond) { throw msg; } }
|
||||
window.onload = function() {
|
||||
try {
|
||||
var ctx = document.getElementById("c1").getContext("2d");
|
||||
|
||||
assert(null === ctx.mozDash,
|
||||
"Default dash is null (no dash)");
|
||||
assert(0 == ctx.mozDashOffset,
|
||||
"Default dashOffset is 0 (no dash)");
|
||||
|
||||
ctx.mozDash = [ 2 ];
|
||||
assert(1 == ctx.mozDash.length && 2 == ctx.mozDash[0],
|
||||
"dash = [ 2 ] works");
|
||||
ctx.mozDash = null;
|
||||
assert(null === ctx.mozDash,
|
||||
"dash = null resets to null");
|
||||
ctx.mozDash = [ 2 ];
|
||||
ctx.mozDash = undefined;
|
||||
assert(null === ctx.mozDash,
|
||||
"dash = undefined resets to null");
|
||||
ctx.mozDash = [ 2 ];
|
||||
ctx.mozDash = [ ];
|
||||
assert(null === ctx.mozDash,
|
||||
"dash = [] resets to null");
|
||||
|
||||
ctx.mozDash = [ 2 ];
|
||||
assert(0 == ctx.mozDashOffset, "dashOffset is 0");
|
||||
ctx.mozDashOffset = 1;
|
||||
assert(1 == ctx.mozDashOffset, "Setting dashOffset succeeded");
|
||||
ctx.mozDash = null;
|
||||
assert(0 == ctx.mozDashOffset, "Disabling dash resets dashOffset");
|
||||
ctx.mozDash = [ 2 ];
|
||||
assert(0 == ctx.mozDashOffset, "Previous dashOffset isn't remembered");
|
||||
ctx.mozDash = null;
|
||||
|
||||
// NB: might want to add a |.dash = number| special case,
|
||||
// don't test that it fails here. Might also want to add a
|
||||
// |.dash = [0]| special case for resetting, so don't test
|
||||
// that either.
|
||||
var badVals = [ -1,
|
||||
"string",
|
||||
/* According to the WebIDL sequence-ifying
|
||||
* (really they mean array-ifying here)
|
||||
* algorithm, objects without .length
|
||||
* properties convert to a 0-length arrays.
|
||||
* This seems ... odd, since by the book we're
|
||||
* forced to accept |ctx.dash = Function|,
|
||||
* e.g., but there it is.
|
||||
*/
|
||||
// { obj: true },
|
||||
[ "array of string" ],
|
||||
[ -1 ],
|
||||
[ 0, 0, 0 ],
|
||||
[ 2, "string" ],
|
||||
];
|
||||
ctx.mozDash = [ 2 ];
|
||||
for (var i = 0; i < badVals.length; ++i) {
|
||||
var error = false;
|
||||
try { ctx.mozDash = badVals[i]; }
|
||||
catch(e) { error = true; }
|
||||
assert(error && 1 == ctx.mozDash.length && 2 == ctx.mozDash[0],
|
||||
"Expected |dash = "+ badVals[i] +"| to throw exception and not change .dash");
|
||||
}
|
||||
ctx.mozDash = null;
|
||||
|
||||
ctx.save();
|
||||
ctx.mozDash = [ 2 ];
|
||||
ctx.restore();
|
||||
assert(null === ctx.mozDash,
|
||||
"dash was saved then restored");
|
||||
} catch (e) {
|
||||
document.body.innerHTML = "FAIL: "+ e.toString();
|
||||
return;
|
||||
}
|
||||
document.body.innerHTML = "Pass";
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div><canvas id="c1" width="300" height="300"></canvas></div>
|
||||
</body>
|
||||
</html>
|
@ -56,3 +56,10 @@ fails-if(cocoaWidget) == linear-gradient-1b.html linear-gradient-1-ref.html
|
||||
== evenodd-fill-1.html evenodd-fill-ref.html
|
||||
== evenodd-fill-2.html evenodd-fill-ref.html
|
||||
== evenodd-fill-3.html nonzero-fill-2.html
|
||||
|
||||
== dash-sanity.html data:text/html,<body>Pass
|
||||
random-if(Android) == dash-1.html dash-1-ref.svg # Bug 668412 (really is android-specific, not IPC-specific)
|
||||
|
||||
== ctm-sanity.html data:text/html,<body>Pass
|
||||
fails == ctm-singular-sanity.html data:text/html,<body>Pass # Bug 612033
|
||||
== ctm-1.html ctm-1-ref.html
|
||||
|
@ -12,3 +12,4 @@ HTTP(..) == quirks-decorations.html quirks-decorations-ref.html
|
||||
HTTP(..) == quirks-line-height.html quirks-line-height-ref.html
|
||||
HTTP(..) == standards-decorations.html standards-decorations-ref.html
|
||||
HTTP(..) == standards-line-height.html standards-line-height-ref.html
|
||||
HTTP(..) == selection.html selection-ref.html
|
||||
|
113
layout/reftests/text-overflow/selection-ref.html
Normal file
113
layout/reftests/text-overflow/selection-ref.html
Normal file
@ -0,0 +1,113 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/licenses/publicdomain/
|
||||
-->
|
||||
<html class="reftest-wait"><head>
|
||||
<title>text-overflow: Selected text, background, decorations</title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
|
||||
<style type="text/css">
|
||||
@font-face {
|
||||
font-family: DejaVuSansMono;
|
||||
src: url(../fonts/DejaVuSansMono.woff);
|
||||
}
|
||||
@font-face {
|
||||
font-family: TestEllipsisFallback;
|
||||
src: url(TestEllipsisFallback.woff);
|
||||
}
|
||||
html,body {
|
||||
color:black; background-color:white; font-size:16px; padding:0; margin:0; font-family:DejaVuSansMono;
|
||||
}
|
||||
|
||||
.test {
|
||||
overflow:auto;
|
||||
white-space:nowrap;
|
||||
width: 5em;
|
||||
position:relative;
|
||||
margin-top:1em;
|
||||
padding-left: 0.9em;
|
||||
padding-right: 1.3em;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
overflow:hidden;
|
||||
width: 4.4em;
|
||||
}
|
||||
|
||||
.rlo {
|
||||
unicode-bidi: bidi-override; direction: rtl;
|
||||
}
|
||||
.lro {
|
||||
unicode-bidi: bidi-override; direction: ltr;
|
||||
}
|
||||
.rtl {
|
||||
direction:rtl;
|
||||
}
|
||||
i { display:none; }
|
||||
x {font-family:DejaVuSansMono;}
|
||||
</style>
|
||||
<script>
|
||||
function getTextNode(elm) {
|
||||
if (elm.nodeType != 3)
|
||||
return getTextNode(elm.firstChild);
|
||||
return elm;
|
||||
}
|
||||
function addRange(elm) {
|
||||
try {
|
||||
var sel = window.getSelection();
|
||||
var range = document.createRange();
|
||||
var startNode = elm.getAttribute('startNode');
|
||||
if (startNode == null)
|
||||
startNode = getTextNode(elm);
|
||||
else
|
||||
startNode = getTextNode(elm.childNodes[startNode])
|
||||
var start = elm.getAttribute('start');
|
||||
if (start == null) start = 2;
|
||||
var endNode = elm.getAttribute('endNode');
|
||||
if (endNode == null)
|
||||
endNode = startNode;
|
||||
else
|
||||
endNode = getTextNode(elm.childNodes[endNode])
|
||||
var end = elm.getAttribute('end');
|
||||
if (end == null) end = endNode.textContent.length;
|
||||
if (startNode==endNode && start > end) return;
|
||||
if (startNode==null) return;
|
||||
range.setStart(startNode, start);
|
||||
range.setEnd(endNode, end);
|
||||
sel.addRange(range);
|
||||
} catch (e) {
|
||||
alert(e+'\n'+elm.id+'\n'+t)
|
||||
}
|
||||
}
|
||||
function selectText() {
|
||||
var divs = document.getElementsByTagName('div');
|
||||
for (i = 0; i < divs.length; ++i) {
|
||||
addRange(divs[i]);
|
||||
}
|
||||
var t1 = document.getElementById('t1');
|
||||
addRange(t1.firstChild);
|
||||
var t2 = document.getElementById('t2');
|
||||
addRange(t2.firstChild);
|
||||
document.documentElement.removeAttribute('class');
|
||||
}
|
||||
</script>
|
||||
</head><body onload="selectText();">
|
||||
|
||||
<!-- LTR overflow:hidden -->
|
||||
<div contenteditable="true" spellcheck="true" class="test ltr hidden" end=6>Mispe|…</div>
|
||||
<span style="display:block;width:15em"><div contenteditable="true" spellcheck="true" class="test ltr hidden" style="width:auto; float:right; font-family:TestEllipsisFallback; text-align:right; width:9em;" start=0 end=0>...<x><i>z</i>d word</x></div></span><br clear="all">
|
||||
|
||||
<div id="t1" contenteditable="true" spellcheck="true" class="test ltr hidden"><span class="rlo" endNode="1" start="0" end="6"><i>z</i>d word</span>… </div>
|
||||
<div id="t2" contenteditable="true" spellcheck="true" class="test ltr hidden" ><span class="rlo" endNode="2" start="1" end="1">…<i>z</i>d word</span></div>
|
||||
<div contenteditable="true" spellcheck="true" class="test ltr hidden"><span class="rlo">…<i>z</i>d word</div>
|
||||
<div contenteditable="true" spellcheck="true" class="test ltr hidden" endNode="1" start="2" end="3" style="text-indent:-0.2em"><span> …s</span><span>pe|</span>…<span></span></div>
|
||||
|
||||
<!-- RTL overflow:hidden -->
|
||||
<div contenteditable="true" spellcheck="true" class="test rtl hidden" endNode="2" start="8" end="6">Misp …<i>z</i>d word</div>
|
||||
<div contenteditable="true" spellcheck="true" class="test rtl hidden" end="2"><span class="lro"> …<i>z</i>d word</span></div>
|
||||
<div contenteditable="true" spellcheck="true" class="test rtl hidden" endNode="1" end=0 start=1><span class="lro">…<i>z</i>d</span><span class="rlo"> word</span></div>
|
||||
<div contenteditable="true" spellcheck="true" class="test rtl hidden"><span class="rlo">Mis</span><span class="rlo">pel… word</div>
|
||||
<div contenteditable="true" spellcheck="true" class="test rtl hidden"><span class="rlo">Mis</span><span class="rlo">pel… word</div>
|
||||
<div contenteditable="true" spellcheck="true" class="test rtl hidden"><span class="rlo" style="margin-right:-0.2em"> …s</span><span class="rlo">pel… </span><span class="rlo"> word</span></div>
|
||||
|
||||
</body></html>
|
111
layout/reftests/text-overflow/selection.html
Normal file
111
layout/reftests/text-overflow/selection.html
Normal file
@ -0,0 +1,111 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
Test: Selected text, background, decorations
|
||||
-->
|
||||
<html class="reftest-wait"><head>
|
||||
<title>text-overflow: Selected text, background, decorations</title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
|
||||
<style type="text/css">
|
||||
@font-face {
|
||||
font-family: DejaVuSansMono;
|
||||
src: url(../fonts/DejaVuSansMono.woff);
|
||||
}
|
||||
@font-face {
|
||||
font-family: TestEllipsisFallback;
|
||||
src: url(TestEllipsisFallback.woff);
|
||||
}
|
||||
html,body {
|
||||
color:black; background-color:white; font-size:16px; padding:0; margin:0; font-family:DejaVuSansMono;
|
||||
}
|
||||
|
||||
.test {
|
||||
overflow:auto;
|
||||
text-overflow:ellipsis;
|
||||
white-space:nowrap;
|
||||
width: 5em;
|
||||
position:relative;
|
||||
margin-top:1em;
|
||||
padding-left: 0.9em;
|
||||
padding-right: 1.3em;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
overflow:hidden;
|
||||
width: 4.4em;
|
||||
}
|
||||
|
||||
.rlo {
|
||||
unicode-bidi: bidi-override; direction: rtl;
|
||||
}
|
||||
.lro {
|
||||
unicode-bidi: bidi-override; direction: ltr;
|
||||
}
|
||||
.rtl {
|
||||
direction:rtl;
|
||||
}
|
||||
x {font-family:DejaVuSansMono;}
|
||||
</style>
|
||||
<script>
|
||||
function getTextNode(elm) {
|
||||
if (elm.nodeType != 3)
|
||||
return getTextNode(elm.firstChild);
|
||||
return elm;
|
||||
}
|
||||
function addRange(elm) {
|
||||
try {
|
||||
var sel = window.getSelection();
|
||||
var range = document.createRange();
|
||||
var startNode = elm.getAttribute('startNode');
|
||||
if (startNode == null)
|
||||
startNode = getTextNode(elm);
|
||||
else
|
||||
startNode = getTextNode(elm.childNodes[startNode])
|
||||
var start = elm.getAttribute('start');
|
||||
if (start == null) start = 2;
|
||||
var endNode = elm.getAttribute('endNode');
|
||||
if (endNode == null)
|
||||
endNode = startNode;
|
||||
else
|
||||
endNode = getTextNode(elm.childNodes[endNode])
|
||||
var end = elm.getAttribute('end');
|
||||
if (end == null) end = endNode.textContent.length;
|
||||
if (startNode==endNode && start > end) return;
|
||||
if (startNode==null) return;
|
||||
range.setStart(startNode, start);
|
||||
range.setEnd(endNode, end);
|
||||
sel.addRange(range);
|
||||
} catch (e) {
|
||||
alert(e+'\n'+elm.id+'\n'+t)
|
||||
}
|
||||
}
|
||||
function selectText() {
|
||||
var divs = document.getElementsByTagName('div');
|
||||
for (i = 0; i < divs.length; ++i) {
|
||||
addRange(divs[i]);
|
||||
}
|
||||
document.documentElement.removeAttribute('class');
|
||||
}
|
||||
</script>
|
||||
</head><body onload="selectText();">
|
||||
|
||||
|
||||
<!-- LTR overflow:hidden -->
|
||||
<div contenteditable="true" spellcheck="true" class="test ltr hidden">Mispe|led word</div>
|
||||
<span style="display:block;width:15em"><div contenteditable="true" spellcheck="true" class="test ltr hidden" style="width:auto; float:right; font-family:TestEllipsisFallback; text-indent:-1em; " start=0 end=9><x>M ispeled word</x></div></span><br clear="all">
|
||||
<div contenteditable="true" spellcheck="true" class="test ltr hidden"><span class="rlo">Mispelled word</span></div>
|
||||
<div contenteditable="true" spellcheck="true" class="test ltr hidden"><span class="rlo">Mispelled</span><span class="rlo"> word</span></div>
|
||||
<div contenteditable="true" spellcheck="true" class="test ltr hidden"><span class="rlo">Mis</span><span class="rlo">pelled word</div>
|
||||
<div contenteditable="true" spellcheck="true" class="test ltr hidden" endNode="1" style="text-indent:-0.2em"><span>Mis</span><span>pe|led</span><span> word</span></div>
|
||||
|
||||
<!-- RTL overflow:hidden -->
|
||||
<div contenteditable="true" spellcheck="true" class="test rtl hidden">Mispelled word</div>
|
||||
<div contenteditable="true" spellcheck="true" class="test rtl hidden" end="2"><span class="lro">Mispelled word</span></div>
|
||||
<div contenteditable="true" spellcheck="true" class="test rtl hidden"><span class="lro">Mispelled</span><span class="rlo"> word</span></div>
|
||||
<div contenteditable="true" spellcheck="true" class="test rtl hidden"><span class="rlo">Mis</span><span class="rlo">pelled word</div>
|
||||
<div contenteditable="true" spellcheck="true" class="test rtl hidden"><span class="rlo">Mis</span><span class="rlo">pelled word</div>
|
||||
<div contenteditable="true" spellcheck="true" class="test rtl hidden"><span class="rlo" style="margin-right:-0.2em">Mis</span><span class="rlo">pelled</span><span class="rlo"> word</span></div>
|
||||
|
||||
</body></html>
|
9
layout/reftests/xul/menulist-shrinkwrap-1-ref.xul
Normal file
9
layout/reftests/xul/menulist-shrinkwrap-1-ref.xul
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" align="left">
|
||||
<menulist style="color: transparent">
|
||||
<menupopup>
|
||||
<menuitem value="1" label="short" />
|
||||
<menuitem value="2" label="long item" />
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</window>
|
9
layout/reftests/xul/menulist-shrinkwrap-1.xul
Normal file
9
layout/reftests/xul/menulist-shrinkwrap-1.xul
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" align="left">
|
||||
<menulist style="color: transparent">
|
||||
<menupopup>
|
||||
<menuitem value="1" label="long item" />
|
||||
<menuitem value="2" label="short" />
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</window>
|
24
layout/reftests/xul/menulist-shrinkwrap-2-ref.xul
Normal file
24
layout/reftests/xul/menulist-shrinkwrap-2-ref.xul
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<style xmlns="http://www.w3.org/1999/xhtml">
|
||||
<![CDATA[
|
||||
menulist, menuitem, label { font: Menu }
|
||||
#measurelabel { color: transparent }
|
||||
]]>
|
||||
</style>
|
||||
<stack>
|
||||
<vbox>
|
||||
<menulist>
|
||||
<menupopup>
|
||||
<menuitem value="1" label="long item" />
|
||||
<menuitem value="2" label="short" />
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</vbox>
|
||||
<hbox>
|
||||
<label id="measurelabel" value="long item" />
|
||||
<!-- cover up the right edge of the above -->
|
||||
<box flex="1" style="background: white" />
|
||||
</hbox>
|
||||
</stack>
|
||||
</window>
|
24
layout/reftests/xul/menulist-shrinkwrap-2.xul
Normal file
24
layout/reftests/xul/menulist-shrinkwrap-2.xul
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<style xmlns="http://www.w3.org/1999/xhtml">
|
||||
<![CDATA[
|
||||
menulist, menuitem, label { font: Menu }
|
||||
#measurelabel { color: transparent }
|
||||
]]>
|
||||
</style>
|
||||
<stack>
|
||||
<vbox align="left">
|
||||
<menulist>
|
||||
<menupopup>
|
||||
<menuitem value="1" label="long item" />
|
||||
<menuitem value="2" label="short" />
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</vbox>
|
||||
<hbox>
|
||||
<label id="measurelabel" value="long item" />
|
||||
<!-- cover up the right edge of the above -->
|
||||
<box flex="1" style="background: white" />
|
||||
</hbox>
|
||||
</stack>
|
||||
</window>
|
@ -1 +1,3 @@
|
||||
== menuitem-key.xul menuitem-key-ref.xul
|
||||
== menulist-shrinkwrap-1.xul menulist-shrinkwrap-1-ref.xul
|
||||
fails-if(winWidget) == menulist-shrinkwrap-2.xul menulist-shrinkwrap-2-ref.xul
|
||||
|
@ -1422,13 +1422,12 @@ nsStyleAnimation::AddWeighted(nsCSSProperty aProperty,
|
||||
PRInt32 result = NS_floor(aCoeff1 * double(aValue1.GetIntValue()) +
|
||||
aCoeff2 * double(aValue2.GetIntValue()));
|
||||
if (aProperty == eCSSProperty_font_weight) {
|
||||
NS_ASSERTION(result > 0, "unexpected value");
|
||||
result -= result % 100;
|
||||
if (result < 100) {
|
||||
result = 100;
|
||||
} else if (result > 900) {
|
||||
result = 900;
|
||||
}
|
||||
result -= result % 100;
|
||||
} else {
|
||||
result = RestrictValue(aProperty, result);
|
||||
}
|
||||
|
@ -139,6 +139,7 @@ _TEST_FILES = test_acid3_test46.html \
|
||||
test_dont_use_document_colors.html \
|
||||
test_font_face_parser.html \
|
||||
test_garbage_at_end_of_declarations.html \
|
||||
test_html_attribute_computed_values.html \
|
||||
test_ident_escaping.html \
|
||||
test_inherit_computation.html \
|
||||
test_inherit_storage.html \
|
||||
|
85
layout/style/test/test_html_attribute_computed_values.html
Normal file
85
layout/style/test/test_html_attribute_computed_values.html
Normal file
@ -0,0 +1,85 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug </title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug </a>
|
||||
<div id="content"></div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
|
||||
var gValues = [
|
||||
{
|
||||
element: "<li type='i'></li>",
|
||||
property: "list-style-type",
|
||||
value: "lower-roman"
|
||||
},
|
||||
{
|
||||
element: "<li type='I'></li>",
|
||||
property: "list-style-type",
|
||||
value: "upper-roman"
|
||||
},
|
||||
{
|
||||
element: "<li type='a'></li>",
|
||||
property: "list-style-type",
|
||||
value: "lower-alpha"
|
||||
},
|
||||
{
|
||||
element: "<li type='A'></li>",
|
||||
property: "list-style-type",
|
||||
value: "upper-alpha"
|
||||
},
|
||||
{
|
||||
element: "<li type='1'></li>",
|
||||
property: "list-style-type",
|
||||
value: "decimal"
|
||||
},
|
||||
{
|
||||
element: "<ol type='i'></ol>",
|
||||
property: "list-style-type",
|
||||
value: "lower-roman"
|
||||
},
|
||||
{
|
||||
element: "<ol type='I'></ol>",
|
||||
property: "list-style-type",
|
||||
value: "upper-roman"
|
||||
},
|
||||
{
|
||||
element: "<ol type='a'></ol>",
|
||||
property: "list-style-type",
|
||||
value: "lower-alpha"
|
||||
},
|
||||
{
|
||||
element: "<ol type='A'></ol>",
|
||||
property: "list-style-type",
|
||||
value: "upper-alpha"
|
||||
},
|
||||
{
|
||||
element: "<ol type='1'></ol>",
|
||||
property: "list-style-type",
|
||||
value: "decimal"
|
||||
},
|
||||
];
|
||||
|
||||
var content = document.getElementById("content");
|
||||
for (var i = 0; i < gValues.length; ++i) {
|
||||
var v = gValues[i];
|
||||
|
||||
content.innerHTML = v.element;
|
||||
is(getComputedStyle(content.firstChild, "").getPropertyValue(v.property),
|
||||
v.value,
|
||||
v.property + " for " + v.element);
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1384,14 +1384,27 @@ nsMenuFrame::SizeToPopup(nsBoxLayoutState& aState, nsSize& aSize)
|
||||
if (!mPopupFrame)
|
||||
return PR_FALSE;
|
||||
tmpSize = mPopupFrame->GetPrefSize(aState);
|
||||
aSize.width = tmpSize.width;
|
||||
|
||||
// Produce a size such that:
|
||||
// (1) the menu and its popup can be the same width
|
||||
// (2) there's enough room in the menu for the content and its
|
||||
// border-padding
|
||||
// (3) there's enough room in the popup for the content and its
|
||||
// scrollbar
|
||||
nsMargin borderPadding;
|
||||
GetBorderAndPadding(borderPadding);
|
||||
|
||||
// if there is a scroll frame, add the desired width of the scrollbar as well
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(mPopupFrame->GetFirstChild(nsnull));
|
||||
nscoord scrollbarWidth = 0;
|
||||
if (scrollFrame) {
|
||||
aSize.width += scrollFrame->GetDesiredScrollbarSizes(&aState).LeftRight();
|
||||
scrollbarWidth =
|
||||
scrollFrame->GetDesiredScrollbarSizes(&aState).LeftRight();
|
||||
}
|
||||
|
||||
aSize.width =
|
||||
tmpSize.width + NS_MAX(borderPadding.LeftRight(), scrollbarWidth);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ pref("browser.sessionstore.resume_session_once", false);
|
||||
pref("browser.sessionstore.resume_from_crash", true);
|
||||
pref("browser.sessionstore.resume_from_crash_timeout", 60); // minutes
|
||||
pref("browser.sessionstore.interval", 10000); // milliseconds
|
||||
pref("browser.sessionstore.max_tabs_undo", 5);
|
||||
pref("browser.sessionstore.max_tabs_undo", 1);
|
||||
|
||||
/* these should help performance */
|
||||
pref("mozilla.widget.force-24bpp", true);
|
||||
|
@ -1754,13 +1754,13 @@ const ContentTouchHandler = {
|
||||
case "Browser:ContextMenu":
|
||||
// Long tap
|
||||
let contextMenu = { name: aMessage.name, json: json, target: aMessage.target };
|
||||
if (!SelectionHelper.showPopup(contextMenu)) {
|
||||
if (ContextHelper.showPopup(contextMenu)) {
|
||||
// Stop all input sequences
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("CancelTouchSequence", true, false);
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
if (ContextHelper.showPopup(contextMenu)) {
|
||||
// Stop all input sequences
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("CancelTouchSequence", true, false);
|
||||
document.dispatchEvent(event);
|
||||
} else {
|
||||
SelectionHelper.showPopup(contextMenu);
|
||||
}
|
||||
break;
|
||||
case "Browser:CaptureEvents": {
|
||||
@ -2194,6 +2194,10 @@ IdentityHandler.prototype = {
|
||||
* Click handler for the identity-box element in primary chrome.
|
||||
*/
|
||||
handleIdentityButtonEvent: function(aEvent) {
|
||||
let broadcaster = document.getElementById("bcast_uidiscovery");
|
||||
if (broadcaster && broadcaster.getAttribute("mode") == "discovery")
|
||||
return;
|
||||
|
||||
aEvent.stopPropagation();
|
||||
|
||||
if ((aEvent.type == "click" && aEvent.button != 0) ||
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="start();"
|
||||
windowtype="navigator:localepicker"
|
||||
width="480"
|
||||
height="800">
|
||||
<script src="chrome://browser/content/Util.js" type="application/javascript;version=1.8"/>
|
||||
|
@ -188,9 +188,15 @@ BrowserCLH.prototype = {
|
||||
|
||||
// Open the main browser window, if we don't already have one
|
||||
let win;
|
||||
let localePickerWin;
|
||||
try {
|
||||
win = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (!win) {
|
||||
localePickerWin = Services.wm.getMostRecentWindow("navigator:localepicker");
|
||||
if (localePickerWin) {
|
||||
localePickerWin.focus();
|
||||
aCmdLine.preventDefault = true;
|
||||
return;
|
||||
} else if (!win) {
|
||||
// Default to the saved homepage
|
||||
let defaultURL = getHomePage();
|
||||
|
||||
|
@ -74,7 +74,7 @@ SessionStore.prototype = {
|
||||
_lastSaveTime: 0,
|
||||
_lastSessionTime: 0,
|
||||
_interval: 10000,
|
||||
_maxTabsUndo: 5,
|
||||
_maxTabsUndo: 1,
|
||||
_shouldRestore: false,
|
||||
|
||||
init: function ss_init() {
|
||||
@ -441,7 +441,6 @@ SessionStore.prototype = {
|
||||
this._windows[aWindow.__SSID].selected = parseInt(index) + 1; // 1-based
|
||||
|
||||
// Restore the resurrected browser
|
||||
// * currently we only load the last URL into the browser
|
||||
if (aBrowser.__SS_restore) {
|
||||
let data = aBrowser.__SS_data;
|
||||
if (data.entries.length > 0) {
|
||||
@ -634,13 +633,18 @@ SessionStore.prototype = {
|
||||
let closedTab = closedTabs.splice(aIndex, 1).shift();
|
||||
|
||||
// create a new tab and bring to front
|
||||
let tab = aWindow.Browser.addTab(closedTab.entries[0].url, true);
|
||||
let tab = aWindow.Browser.addTab(closedTab.entries[closedTab.index - 1].url, true);
|
||||
|
||||
tab.browser.messageManager.sendAsyncMessage("WebNavigation:LoadURI", {
|
||||
uri: closedTab.entries[closedTab.index - 1].url,
|
||||
flags: null,
|
||||
entries: closedTab.entries,
|
||||
index: closedTab.index
|
||||
});
|
||||
|
||||
// Put back the extra data
|
||||
tab.browser.__SS_extdata = closedTab.extData;
|
||||
|
||||
// TODO: save and restore more data (position, field values, etc)
|
||||
|
||||
return tab.chromeTab;
|
||||
},
|
||||
|
||||
|
@ -167,16 +167,16 @@ function update()
|
||||
// once before most of the memory required to generate this page is
|
||||
// allocated.
|
||||
var reportersByProcess = {};
|
||||
var e = mgr.enumerateReporters();
|
||||
while (e.hasMoreElements()) {
|
||||
var rOrig = e.getNext().QueryInterface(Ci.nsIMemoryReporter);
|
||||
var process = rOrig.process === "" ? "Main" : rOrig.process;
|
||||
|
||||
function addReporter(aProcess, aPath, aKind, aUnits, aAmount, aDescription)
|
||||
{
|
||||
var process = aProcess === "" ? "Main" : aProcess;
|
||||
var r = {
|
||||
_path: rOrig.path,
|
||||
_kind: rOrig.kind,
|
||||
_units: rOrig.units,
|
||||
_amount: rOrig.amount,
|
||||
_description: rOrig.description
|
||||
_path: aPath,
|
||||
_kind: aKind,
|
||||
_units: aUnits,
|
||||
_amount: aAmount,
|
||||
_description: aDescription
|
||||
};
|
||||
if (!reportersByProcess[process]) {
|
||||
reportersByProcess[process] = {};
|
||||
@ -191,6 +191,19 @@ function update()
|
||||
}
|
||||
}
|
||||
|
||||
// Process vanilla reporters first, then multi-reporters.
|
||||
var e = mgr.enumerateReporters();
|
||||
while (e.hasMoreElements()) {
|
||||
var rOrig = e.getNext().QueryInterface(Ci.nsIMemoryReporter);
|
||||
addReporter(rOrig.process, rOrig.path, rOrig.kind, rOrig.units,
|
||||
rOrig.amount, rOrig.description);
|
||||
}
|
||||
var e = mgr.enumerateMultiReporters();
|
||||
while (e.hasMoreElements()) {
|
||||
var r = e.getNext().QueryInterface(Ci.nsIMemoryMultiReporter);
|
||||
r.collectReports(addReporter, null);
|
||||
}
|
||||
|
||||
// Generate output for one process at a time. Always start with the
|
||||
// Main process.
|
||||
var text = genProcessText("Main", reportersByProcess["Main"]);
|
||||
@ -242,7 +255,7 @@ function update()
|
||||
function cmp_amount(a, b)
|
||||
{
|
||||
if (a._units != b._units)
|
||||
return b._units - a._units;
|
||||
return a._units - b._units; // use the enum order from nsIMemoryReporter
|
||||
else
|
||||
return b._amount - a._amount;
|
||||
};
|
||||
|
@ -18,17 +18,29 @@
|
||||
var mgr = Cc["@mozilla.org/memory-reporter-manager;1"].
|
||||
getService(Ci.nsIMemoryReporterManager);
|
||||
|
||||
// Remove all the real reporters; save them to restore at the end.
|
||||
// Remove all the real reporters and multi-reporters; save them to
|
||||
// restore at the end.
|
||||
var e = mgr.enumerateReporters();
|
||||
var realReporters = [];
|
||||
var dummy = 0;
|
||||
while (e.hasMoreElements()) {
|
||||
var mr = e.getNext().QueryInterface(Ci.nsIMemoryReporter);
|
||||
// Get the memoryUsed field, even though we don't use it, just to test
|
||||
var r = e.getNext().QueryInterface(Ci.nsIMemoryReporter);
|
||||
// Get the |amount| field, even though we don't use it, just to test
|
||||
// that the reporter doesn't crash or anything.
|
||||
dummy += mr.memoryUsed;
|
||||
mgr.unregisterReporter(mr);
|
||||
realReporters.push(mr);
|
||||
dummy += r.amount;
|
||||
mgr.unregisterReporter(r);
|
||||
realReporters.push(r);
|
||||
}
|
||||
e = mgr.enumerateMultiReporters();
|
||||
var realMultiReporters = [];
|
||||
var dummy = 0;
|
||||
while (e.hasMoreElements()) {
|
||||
var r = e.getNext().QueryInterface(Ci.nsIMemoryMultiReporter);
|
||||
// Call collectReports, even though we don't use its results, just to
|
||||
// test that the multi-reporter doesn't crash or anything.
|
||||
r.collectReports(function(){}, null);
|
||||
mgr.unregisterMultiReporter(r);
|
||||
realMultiReporters.push(r);
|
||||
}
|
||||
|
||||
// Setup various fake-but-deterministic reporters.
|
||||
@ -224,14 +236,17 @@ Other Measurements\n\
|
||||
|
||||
function finish()
|
||||
{
|
||||
// Unregister fake reporters, re-register the real reporters, just in
|
||||
// case subsequent tests rely on them.
|
||||
// Unregister fake reporters, re-register the real reporters and
|
||||
// multi-reporters, just in case subsequent tests rely on them.
|
||||
for (var i = 0; i < fakeReporters.length; i++) {
|
||||
mgr.unregisterReporter(fakeReporters[i]);
|
||||
}
|
||||
for (var i = 0; i < realReporters.length; i++) {
|
||||
mgr.registerReporter(realReporters[i]);
|
||||
}
|
||||
for (var i = 0; i < realMultiReporters.length; i++) {
|
||||
mgr.registerMultiReporter(realMultiReporters[i]);
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
@ -363,7 +363,7 @@
|
||||
</xul:label>
|
||||
</xul:vbox>
|
||||
<xul:hbox anonid="input-container" class="setting-input">
|
||||
<xul:colorpicker type="button" anonid="input" xbl:inherits="disabled" onchange="inputChanged();"/>
|
||||
<xul:colorpicker type="button" anonid="input" xbl:inherits="disabled" onchange="document.getBindingParent(this).inputChanged();"/>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
|
||||
|
@ -181,78 +181,69 @@ add_test(function() {
|
||||
EventUtils.synthesizeKey("b", {}, gManagerWindow);
|
||||
is(input.value, "2", "Menulist should have updated value");
|
||||
is(gManagerWindow._testValue, "2", "Menulist oncommand handler should've updated the test value");
|
||||
delete gManagerWindow._testValue;
|
||||
|
||||
setTimeout(function () {
|
||||
EventUtils.synthesizeKey("c", {}, gManagerWindow);
|
||||
is(input.value, "3", "Menulist should have updated value");
|
||||
is(gManagerWindow._testValue, "3", "Menulist oncommand handler should've updated the test value");
|
||||
delete gManagerWindow._testValue;
|
||||
Services.prefs.setCharPref("extensions.inlinesettings1.color", "#FF0000");
|
||||
input = gManagerWindow.document.getAnonymousElementByAttribute(settings[5], "anonid", "input");
|
||||
is(input.color, "#FF0000", "Color picker should have initial value");
|
||||
input.focus();
|
||||
EventUtils.synthesizeKey("VK_RIGHT", {}, gManagerWindow);
|
||||
EventUtils.synthesizeKey("VK_RIGHT", {}, gManagerWindow);
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, gManagerWindow);
|
||||
input.hidePopup();
|
||||
is(input.color, "#FF9900", "Color picker should have updated value");
|
||||
is(Services.prefs.getCharPref("extensions.inlinesettings1.color"), "#FF9900", "Color pref should have been updated");
|
||||
|
||||
Services.prefs.setCharPref("extensions.inlinesettings1.color", "#FF0000");
|
||||
setTimeout(function () {
|
||||
input = gManagerWindow.document.getAnonymousElementByAttribute(settings[5], "anonid", "input");
|
||||
is(input.color, "#FF0000", "Color picker should have initial value");
|
||||
input.focus();
|
||||
EventUtils.synthesizeKey("VK_RIGHT", {}, gManagerWindow);
|
||||
EventUtils.synthesizeKey("VK_RIGHT", {}, gManagerWindow);
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, gManagerWindow);
|
||||
is(input.color, "#FF9900", "Color picker should have updated value");
|
||||
is(Services.prefs.getCharPref("extensions.inlinesettings1.color"), "#FF9900", "Color pref should have been updated");
|
||||
try {
|
||||
mockFilePickerFactory.register();
|
||||
|
||||
setTimeout(function () {
|
||||
mockFilePickerFactory.register();
|
||||
var button = gManagerWindow.document.getAnonymousElementByAttribute(settings[6], "anonid", "button");
|
||||
input = gManagerWindow.document.getAnonymousElementByAttribute(settings[6], "anonid", "input");
|
||||
is(input.value, "", "Label value should be empty");
|
||||
|
||||
try {
|
||||
var button = gManagerWindow.document.getAnonymousElementByAttribute(settings[6], "anonid", "button");
|
||||
input = gManagerWindow.document.getAnonymousElementByAttribute(settings[6], "anonid", "input");
|
||||
is(input.value, "", "Label value should be empty");
|
||||
var profD = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||
var curProcD = Services.dirsvc.get("CurProcD", Ci.nsIFile);
|
||||
|
||||
var profD = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||
var curProcD = Services.dirsvc.get("CurProcD", Ci.nsIFile);
|
||||
_returnFile = profD;
|
||||
_returnValue = Ci.nsIFilePicker.returnOK;
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
is(_mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file");
|
||||
is(input.value, profD.path, "Label value should match file chosen");
|
||||
is(Services.prefs.getCharPref("extensions.inlinesettings1.file"), profD.path, "File pref should match file chosen");
|
||||
|
||||
_returnFile = profD;
|
||||
_returnValue = Ci.nsIFilePicker.returnOK;
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
is(_mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file");
|
||||
is(input.value, profD.path, "Label value should match file chosen");
|
||||
is(Services.prefs.getCharPref("extensions.inlinesettings1.file"), profD.path, "File pref should match file chosen");
|
||||
_returnFile = curProcD;
|
||||
_returnValue = Ci.nsIFilePicker.returnCancel;
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
is(_mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file");
|
||||
is(input.value, profD.path, "Label value should not have changed");
|
||||
is(Services.prefs.getCharPref("extensions.inlinesettings1.file"), profD.path, "File pref should not have changed");
|
||||
|
||||
_returnFile = curProcD;
|
||||
_returnValue = Ci.nsIFilePicker.returnCancel;
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
is(_mode, Ci.nsIFilePicker.modeOpen, "File picker mode should be open file");
|
||||
is(input.value, profD.path, "Label value should not have changed");
|
||||
is(Services.prefs.getCharPref("extensions.inlinesettings1.file"), profD.path, "File pref should not have changed");
|
||||
button = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "button");
|
||||
input = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "input");
|
||||
is(input.value, "", "Label value should be empty");
|
||||
|
||||
button = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "button");
|
||||
input = gManagerWindow.document.getAnonymousElementByAttribute(settings[7], "anonid", "input");
|
||||
is(input.value, "", "Label value should be empty");
|
||||
|
||||
_returnFile = profD;
|
||||
_returnValue = Ci.nsIFilePicker.returnOK;
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
is(_mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory");
|
||||
is(input.value, profD.path, "Label value should match file chosen");
|
||||
is(Services.prefs.getCharPref("extensions.inlinesettings1.directory"), profD.path, "Directory pref should match file chosen");
|
||||
_returnFile = profD;
|
||||
_returnValue = Ci.nsIFilePicker.returnOK;
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
is(_mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory");
|
||||
is(input.value, profD.path, "Label value should match file chosen");
|
||||
is(Services.prefs.getCharPref("extensions.inlinesettings1.directory"), profD.path, "Directory pref should match file chosen");
|
||||
|
||||
_returnFile = curProcD;
|
||||
_returnValue = Ci.nsIFilePicker.returnCancel;
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
is(_mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory");
|
||||
is(input.value, profD.path, "Label value should not have changed");
|
||||
is(Services.prefs.getCharPref("extensions.inlinesettings1.directory"), profD.path, "Directory pref should not have changed");
|
||||
_returnFile = curProcD;
|
||||
_returnValue = Ci.nsIFilePicker.returnCancel;
|
||||
EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
|
||||
is(_mode, Ci.nsIFilePicker.modeGetFolder, "File picker mode should be directory");
|
||||
is(input.value, profD.path, "Label value should not have changed");
|
||||
is(Services.prefs.getCharPref("extensions.inlinesettings1.directory"), profD.path, "Directory pref should not have changed");
|
||||
|
||||
} finally {
|
||||
mockFilePickerFactory.unregister();
|
||||
}
|
||||
} finally {
|
||||
mockFilePickerFactory.unregister();
|
||||
|
||||
button = gManagerWindow.document.getElementById("detail-prefs-btn");
|
||||
is_element_hidden(button, "Preferences button should not be visible");
|
||||
button = gManagerWindow.document.getElementById("detail-prefs-btn");
|
||||
is_element_hidden(button, "Preferences button should not be visible");
|
||||
|
||||
gCategoryUtilities.openType("extension", run_next_test);
|
||||
}, 0);
|
||||
}, 0);
|
||||
}, 1200); // Timeout value from toolkit/content/tests/widgets/test_menulist_keynav.xul
|
||||
gCategoryUtilities.openType("extension", run_next_test);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -178,6 +178,10 @@ XPCOMUtils.defineLazyGetter(this, "gABI", function aus_gABI() {
|
||||
|
||||
if (macutils.isUniversalBinary)
|
||||
abi += "-u-" + macutils.architecturesInBinary;
|
||||
#ifdef MOZ_SHARK
|
||||
// Disambiguate optimised and shark nightlies
|
||||
abi += "-shark"
|
||||
#endif
|
||||
#endif
|
||||
return abi;
|
||||
});
|
||||
|
@ -59,6 +59,11 @@ const IS_OS2 = false;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
const IS_MACOSX = true;
|
||||
#ifdef MOZ_SHARK
|
||||
const IS_SHARK = true;
|
||||
#else
|
||||
const IS_SHARK = false;
|
||||
#endif
|
||||
#else
|
||||
const IS_MACOSX = false;
|
||||
#endif
|
||||
|
@ -141,6 +141,11 @@ function check_test_pt4() {
|
||||
|
||||
if (macutils.isUniversalBinary)
|
||||
abi += "-u-" + macutils.architecturesInBinary;
|
||||
if (IS_SHARK) {
|
||||
// Disambiguate optimised and shark nightlies
|
||||
abi += "-shark"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
do_check_eq(getResult(gRequestURL), gAppInfo.OS + "_" + abi);
|
||||
|
@ -96,7 +96,7 @@ GetRenderingContext(nsIDocShell *shell, gfxASurface *surface,
|
||||
|
||||
if (!ctx) {
|
||||
// create the canvas rendering context
|
||||
ctx = do_CreateInstance("@mozilla.org/content/canvas-rendering-context;1?id=2d", &rv);
|
||||
ctx = do_CreateInstance("@mozilla.org/content/canvas-rendering-context;1?id=2dthebes", &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Could not create nsICanvasRenderingContextInternal for tab previews!");
|
||||
return rv;
|
||||
|
@ -97,6 +97,75 @@ int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpDa
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Callback hook which will dynamically allocate a buffer large
|
||||
// enough for the file picker dialog.
|
||||
static unsigned int CALLBACK FilePickerHook(HWND hwnd, UINT msg,
|
||||
WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
// Finds the child drop down of a File Picker dialog and sets the
|
||||
// maximum amount of text it can hold when typed in manually.
|
||||
// A wParam of 0 mean 0x7FFFFFFE characters.
|
||||
HWND comboBox = FindWindowEx(GetParent(hwnd), NULL,
|
||||
L"ComboBoxEx32", NULL );
|
||||
if(comboBox)
|
||||
SendMessage(comboBox, CB_LIMITTEXT, 0, 0);
|
||||
}
|
||||
break;
|
||||
case WM_NOTIFY:
|
||||
{
|
||||
LPOFNOTIFYW lpofn = (LPOFNOTIFYW) lParam;
|
||||
// CDN_SELCHANGE is sent when the selection in the list box of the file
|
||||
// selection dialog changes
|
||||
if (lpofn->hdr.code == CDN_SELCHANGE) {
|
||||
HWND parentHWND = GetParent(hwnd);
|
||||
|
||||
// Get the required size for the selected files buffer
|
||||
UINT newBufLength = 0;
|
||||
int requiredBufLength = CommDlg_OpenSave_GetSpecW(parentHWND,
|
||||
NULL, 0);
|
||||
if(requiredBufLength >= 0)
|
||||
newBufLength += requiredBufLength;
|
||||
else
|
||||
newBufLength += MAX_PATH;
|
||||
|
||||
// If the user selects multiple files, the buffer contains the
|
||||
// current directory followed by the file names of the selected
|
||||
// files. So make room for the directory path. If the user
|
||||
// selects a single file, it is no harm to add extra space.
|
||||
requiredBufLength = CommDlg_OpenSave_GetFolderPathW(parentHWND,
|
||||
NULL, 0);
|
||||
if(requiredBufLength >= 0)
|
||||
newBufLength += requiredBufLength;
|
||||
else
|
||||
newBufLength += MAX_PATH;
|
||||
|
||||
// Check if lpstrFile and nMaxFile are large enough
|
||||
if (newBufLength > lpofn->lpOFN->nMaxFile)
|
||||
{
|
||||
if (lpofn->lpOFN->lpstrFile)
|
||||
delete[] lpofn->lpOFN->lpstrFile;
|
||||
|
||||
// We allocate FILE_BUFFER_SIZE more bytes than is needed so that
|
||||
// if the user selects a file and holds down shift and down to
|
||||
// select additional items, we will not continuously reallocate
|
||||
newBufLength += FILE_BUFFER_SIZE;
|
||||
|
||||
PRUnichar* filesBuffer = new PRUnichar[newBufLength];
|
||||
ZeroMemory(filesBuffer, newBufLength * sizeof(PRUnichar));
|
||||
|
||||
lpofn->lpOFN->lpstrFile = filesBuffer;
|
||||
lpofn->lpOFN->nMaxFile = newBufLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFilePicker::ShowW(PRInt16 *aReturnVal)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aReturnVal);
|
||||
@ -109,7 +178,8 @@ NS_IMETHODIMP nsFilePicker::ShowW(PRInt16 *aReturnVal)
|
||||
}
|
||||
|
||||
PRBool result = PR_FALSE;
|
||||
PRUnichar fileBuffer[FILE_BUFFER_SIZE+1];
|
||||
nsAutoArrayPtr<PRUnichar> fileBuffer(new PRUnichar[FILE_BUFFER_SIZE+1]);
|
||||
|
||||
wcsncpy(fileBuffer, mDefault.get(), FILE_BUFFER_SIZE);
|
||||
fileBuffer[FILE_BUFFER_SIZE] = '\0'; // null terminate in case copy truncated
|
||||
|
||||
@ -229,8 +299,19 @@ NS_IMETHODIMP nsFilePicker::ShowW(PRInt16 *aReturnVal)
|
||||
result = ::GetOpenFileNameW(&ofn);
|
||||
}
|
||||
else if (mMode == modeOpenMultiple) {
|
||||
ofn.Flags |= OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_EXPLORER;
|
||||
ofn.Flags |= OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT |
|
||||
OFN_EXPLORER | OFN_ENABLEHOOK;
|
||||
|
||||
// The hook set here ensures that the buffer returned will always be
|
||||
// long enough to hold all selected files. The hook may modify the
|
||||
// value of ofn.lpstrFile and deallocate the old buffer that it pointed
|
||||
// to (fileBuffer). The hook assumes that the passed in value is heap
|
||||
// allocated and that the returned value should be freed by the caller.
|
||||
// If the hook changes the buffer, it will deallocate the old buffer.
|
||||
ofn.lpfnHook = FilePickerHook;
|
||||
fileBuffer.forget();
|
||||
result = ::GetOpenFileNameW(&ofn);
|
||||
fileBuffer = ofn.lpstrFile;
|
||||
}
|
||||
else if (mMode == modeSave) {
|
||||
ofn.Flags |= OFN_NOREADONLYRETURN;
|
||||
|
@ -515,10 +515,10 @@ nsNativeThemeWin::StandardGetState(nsIFrame* aFrame, PRUint8 aWidgetType,
|
||||
nsEventStates eventState = GetContentState(aFrame, aWidgetType);
|
||||
if (eventState.HasAllStates(NS_EVENT_STATE_HOVER | NS_EVENT_STATE_ACTIVE))
|
||||
return TS_ACTIVE;
|
||||
if (wantFocused && eventState.HasState(NS_EVENT_STATE_FOCUS))
|
||||
return TS_FOCUSED;
|
||||
if (eventState.HasState(NS_EVENT_STATE_HOVER))
|
||||
return TS_HOVER;
|
||||
if (wantFocused && eventState.HasState(NS_EVENT_STATE_FOCUS))
|
||||
return TS_FOCUSED;
|
||||
|
||||
return TS_NORMAL;
|
||||
}
|
||||
|
@ -40,6 +40,16 @@
|
||||
|
||||
interface nsISimpleEnumerator;
|
||||
|
||||
/*
|
||||
* An nsIMemoryReporter reports a single memory measurement as an object.
|
||||
* Use this when it makes sense to gather this measurement without gathering
|
||||
* related measurements at the same time.
|
||||
*
|
||||
* Note that the |amount| field may be implemented as a function, and so
|
||||
* accessing it can trigger significant computation; the other fields can
|
||||
* be accessed without triggering this computation. (Compare and contrast
|
||||
* this with nsIMemoryMultiReporter.)
|
||||
*/
|
||||
[scriptable, uuid(37d18434-9819-4ce1-922f-15d8b63da066)]
|
||||
interface nsIMemoryReporter : nsISupports
|
||||
{
|
||||
@ -133,7 +143,7 @@ interface nsIMemoryReporter : nsISupports
|
||||
/*
|
||||
* The numeric value reported by this memory reporter.
|
||||
*/
|
||||
readonly attribute long long amount;
|
||||
readonly attribute PRInt64 amount;
|
||||
|
||||
/*
|
||||
* A human-readable description of this memory usage report.
|
||||
@ -141,7 +151,34 @@ interface nsIMemoryReporter : nsISupports
|
||||
readonly attribute string description;
|
||||
};
|
||||
|
||||
[scriptable, uuid(7c62de18-1edd-40f8-9da2-a8c622763074)]
|
||||
[scriptable, function, uuid(5b15f3fa-ba15-443c-8337-7770f5f0ce5d)]
|
||||
interface nsIMemoryMultiReporterCallback : nsISupports
|
||||
{
|
||||
void callback(in ACString process, in AUTF8String path, in PRInt32 kind,
|
||||
in PRInt32 units, in PRInt64 amount,
|
||||
in AUTF8String description, in nsISupports closure);
|
||||
};
|
||||
|
||||
/*
|
||||
* An nsIMemoryMultiReporter reports multiple memory measurements via a
|
||||
* callback function which is called once for each measurement. Use this
|
||||
* when you want to gather multiple measurements in a single operation (eg.
|
||||
* a single traversal of a large data structure).
|
||||
*
|
||||
* The arguments to the callback deliberately match the fields in
|
||||
* nsIMemoryReporter, but note that seeing any of these arguments requires
|
||||
* calling collectReports which will trigger all relevant computation.
|
||||
* (Compare and contrast this with nsIMemoryReporter, which allows all
|
||||
* fields except |amount| to be accessed without triggering computation.)
|
||||
*/
|
||||
[scriptable, uuid(eae277ad-b67d-4389-95f4-03fa11c09d06)]
|
||||
interface nsIMemoryMultiReporter : nsISupports
|
||||
{
|
||||
void collectReports(in nsIMemoryMultiReporterCallback callback,
|
||||
in nsISupports closure);
|
||||
};
|
||||
|
||||
[scriptable, uuid(80a93b4c-6fff-4acd-8598-3891074a30ab)]
|
||||
interface nsIMemoryReporterManager : nsISupports
|
||||
{
|
||||
/*
|
||||
@ -150,18 +187,36 @@ interface nsIMemoryReporterManager : nsISupports
|
||||
nsISimpleEnumerator enumerateReporters ();
|
||||
|
||||
/*
|
||||
* Register the given nsIMemoryReporter. It is an error to register
|
||||
* more than one reporter with the same path. After a reporter is
|
||||
* registered, it will be available via enumerateReporters(). The
|
||||
* Manager service will hold a strong reference to the given reporter.
|
||||
* Return an enumerator of nsIMemoryMultiReporters that are currently
|
||||
* registered.
|
||||
*/
|
||||
nsISimpleEnumerator enumerateMultiReporters ();
|
||||
|
||||
/*
|
||||
* Register the given nsIMemoryReporter. After a reporter is registered,
|
||||
* it will be available via enumerateReporters(). The Manager service
|
||||
* will hold a strong reference to the given reporter.
|
||||
*/
|
||||
void registerReporter (in nsIMemoryReporter reporter);
|
||||
|
||||
/*
|
||||
* Register the given nsIMemoryMultiReporter. After a multi-reporter is
|
||||
* registered, it will be available via enumerateMultiReporters(). The
|
||||
* Manager service will hold a strong reference to the given
|
||||
* multi-reporter.
|
||||
*/
|
||||
void registerMultiReporter (in nsIMemoryMultiReporter reporter);
|
||||
|
||||
/*
|
||||
* Unregister the given memory reporter.
|
||||
*/
|
||||
void unregisterReporter (in nsIMemoryReporter reporter);
|
||||
|
||||
/*
|
||||
* Unregister the given memory multi-reporter.
|
||||
*/
|
||||
void unregisterMultiReporter (in nsIMemoryMultiReporter reporter);
|
||||
|
||||
/*
|
||||
* Initialize.
|
||||
*/
|
||||
@ -189,6 +244,9 @@ interface nsIMemoryReporterManager : nsISupports
|
||||
#define NS_MEMORY_REPORTER_NAME(_classname) MemoryReporter_##_classname
|
||||
|
||||
NS_COM nsresult NS_RegisterMemoryReporter (nsIMemoryReporter *reporter);
|
||||
NS_COM nsresult NS_RegisterMemoryMultiReporter (nsIMemoryMultiReporter *reporter);
|
||||
|
||||
NS_COM nsresult NS_UnregisterMemoryReporter (nsIMemoryReporter *reporter);
|
||||
NS_COM nsresult NS_UnregisterMemoryMultiReporter (nsIMemoryMultiReporter *reporter);
|
||||
|
||||
%}
|
||||
|
@ -437,6 +437,15 @@ nsMemoryReporterManager::EnumerateReporters(nsISimpleEnumerator **result)
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemoryReporterManager::EnumerateMultiReporters(nsISimpleEnumerator **result)
|
||||
{
|
||||
nsresult rv;
|
||||
mozilla::MutexAutoLock autoLock(mMutex);
|
||||
rv = NS_NewArrayEnumerator(result, mMultiReporters);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemoryReporterManager::RegisterReporter(nsIMemoryReporter *reporter)
|
||||
{
|
||||
@ -448,6 +457,17 @@ nsMemoryReporterManager::RegisterReporter(nsIMemoryReporter *reporter)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemoryReporterManager::RegisterMultiReporter(nsIMemoryMultiReporter *reporter)
|
||||
{
|
||||
mozilla::MutexAutoLock autoLock(mMutex);
|
||||
if (mMultiReporters.IndexOf(reporter) != -1)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mMultiReporters.AppendObject(reporter);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemoryReporterManager::UnregisterReporter(nsIMemoryReporter *reporter)
|
||||
{
|
||||
@ -458,6 +478,16 @@ nsMemoryReporterManager::UnregisterReporter(nsIMemoryReporter *reporter)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemoryReporterManager::UnregisterMultiReporter(nsIMemoryMultiReporter *reporter)
|
||||
{
|
||||
mozilla::MutexAutoLock autoLock(mMutex);
|
||||
if (!mMultiReporters.RemoveObject(reporter))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsMemoryReporter, nsIMemoryReporter)
|
||||
|
||||
nsMemoryReporter::nsMemoryReporter(nsCString& process,
|
||||
@ -515,7 +545,6 @@ NS_IMETHODIMP nsMemoryReporter::GetDescription(char **aDescription)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_COM nsresult
|
||||
NS_RegisterMemoryReporter (nsIMemoryReporter *reporter)
|
||||
{
|
||||
@ -525,6 +554,15 @@ NS_RegisterMemoryReporter (nsIMemoryReporter *reporter)
|
||||
return mgr->RegisterReporter(reporter);
|
||||
}
|
||||
|
||||
NS_COM nsresult
|
||||
NS_RegisterMemoryMultiReporter (nsIMemoryMultiReporter *reporter)
|
||||
{
|
||||
nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
|
||||
if (mgr == nsnull)
|
||||
return NS_ERROR_FAILURE;
|
||||
return mgr->RegisterMultiReporter(reporter);
|
||||
}
|
||||
|
||||
NS_COM nsresult
|
||||
NS_UnregisterMemoryReporter (nsIMemoryReporter *reporter)
|
||||
{
|
||||
@ -534,3 +572,12 @@ NS_UnregisterMemoryReporter (nsIMemoryReporter *reporter)
|
||||
return mgr->UnregisterReporter(reporter);
|
||||
}
|
||||
|
||||
NS_COM nsresult
|
||||
NS_UnregisterMemoryMultiReporter (nsIMemoryMultiReporter *reporter)
|
||||
{
|
||||
nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
|
||||
if (mgr == nsnull)
|
||||
return NS_ERROR_FAILURE;
|
||||
return mgr->UnregisterMultiReporter(reporter);
|
||||
}
|
||||
|
||||
|
@ -40,8 +40,9 @@ public:
|
||||
virtual ~nsMemoryReporterManager();
|
||||
|
||||
private:
|
||||
nsCOMArray<nsIMemoryReporter> mReporters;
|
||||
Mutex mMutex;
|
||||
nsCOMArray<nsIMemoryReporter> mReporters;
|
||||
nsCOMArray<nsIMemoryMultiReporter> mMultiReporters;
|
||||
Mutex mMutex;
|
||||
};
|
||||
|
||||
#define NS_MEMORY_REPORTER_MANAGER_CID \
|
||||
|
Loading…
x
Reference in New Issue
Block a user