This commit is contained in:
Josh Matthews 2011-06-29 23:44:47 -04:00
Родитель 5d3b32a652 effbfd3c5a
Коммит af1ab03319
70 изменённых файлов: 2155 добавлений и 381 удалений

Просмотреть файл

@ -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++;
@ -4239,10 +4328,21 @@ nsCanvasRenderingContext2DAzure::GetThebesSurface(gfxASurface **surface)
return NS_OK;
}
nsRefPtr<gfxASurface> newSurf =
gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mTarget);
if (!mThebesSurface) {
mThebesSurface =
gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mTarget);
*surface = newSurf.forget().get();
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);

Просмотреть файл

@ -4935,7 +4935,8 @@ nsHTMLEditRules::CheckForEmptyBlock(nsIDOMNode *aStartNode,
}
}
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 \

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

После

Ширина:  |  Высота:  |  Размер: 406 B

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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|&#x2026;</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>&#x2026;&nbsp;&nbsp;&nbsp;&nbsp;</div>
<div id="t2" contenteditable="true" spellcheck="true" class="test ltr hidden" ><span class="rlo" endNode="2" start="1" end="1">&#x2026;<i>z</i>d word</span></div>
<div contenteditable="true" spellcheck="true" class="test ltr hidden"><span class="rlo">&#x2026;<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>&nbsp;&#x2026;s</span><span>pe|</span>&#x2026;<span></span></div>
<!-- RTL overflow:hidden -->
<div contenteditable="true" spellcheck="true" class="test rtl hidden" endNode="2" start="8" end="6">Misp&nbsp;&nbsp;&nbsp;&#x2026;<i>z</i>d word</div>
<div contenteditable="true" spellcheck="true" class="test rtl hidden" end="2"><span class="lro">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#x2026;<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">&#x2026;<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&#x2026;&nbsp;&nbsp;&nbsp; word</div>
<div contenteditable="true" spellcheck="true" class="test rtl hidden"><span class="rlo">Mis</span><span class="rlo">pel&#x2026;&nbsp;&nbsp;&nbsp; word</div>
<div contenteditable="true" spellcheck="true" class="test rtl hidden"><span class="rlo" style="margin-right:-0.2em">&nbsp;&#x2026;s</span><span class="rlo">pel&#x2026;&nbsp;&nbsp;&nbsp;</span><span class="rlo"> word</span></div>
</body></html>

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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