b=430906; add moz-opaque attribute to <canvas>; r+sr=roc

This commit is contained in:
Vladimir Vukicevic 2008-06-03 17:00:32 -07:00
Родитель 355e9c0144
Коммит 0db050fa2f
5 изменённых файлов: 57 добавлений и 4 удалений

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

@ -514,6 +514,7 @@ GK_ATOM(mouseout, "mouseout")
GK_ATOM(mouseover, "mouseover") GK_ATOM(mouseover, "mouseover")
GK_ATOM(mousethrough, "mousethrough") GK_ATOM(mousethrough, "mousethrough")
GK_ATOM(mouseup, "mouseup") GK_ATOM(mouseup, "mouseup")
GK_ATOM(moz_opaque, "moz-opaque")
GK_ATOM(msthemecompatible, "msthemecompatible") GK_ATOM(msthemecompatible, "msthemecompatible")
GK_ATOM(multicol, "multicol") GK_ATOM(multicol, "multicol")
GK_ATOM(multiple, "multiple") GK_ATOM(multiple, "multiple")

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

@ -77,6 +77,12 @@ public:
// If this canvas context can be represented with a simple Thebes surface, // If this canvas context can be represented with a simple Thebes surface,
// return the surface. Otherwise returns an error. // return the surface. Otherwise returns an error.
NS_IMETHOD GetThebesSurface(gfxASurface **surface) = 0; NS_IMETHOD GetThebesSurface(gfxASurface **surface) = 0;
// If this context is opaque, the backing store of the canvas should
// be created as opaque; all compositing operators should assume the
// dst alpha is always 1.0. If this is never called, the context
// defaults to false (not opaque).
NS_IMETHOD SetIsOpaque(PRBool isOpaque) = 0;
}; };
NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasRenderingContextInternal, NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasRenderingContextInternal,

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

@ -296,6 +296,7 @@ public:
const PRUnichar* aEncoderOptions, const PRUnichar* aEncoderOptions,
nsIInputStream **aStream); nsIInputStream **aStream);
NS_IMETHOD GetThebesSurface(gfxASurface **surface); NS_IMETHOD GetThebesSurface(gfxASurface **surface);
NS_IMETHOD SetIsOpaque(PRBool isOpaque);
// nsISupports interface // nsISupports interface
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
@ -334,7 +335,8 @@ protected:
// Member vars // Member vars
PRInt32 mWidth, mHeight; PRInt32 mWidth, mHeight;
PRBool mValid; PRPackedBool mValid;
PRPackedBool mOpaque;
// the canvas element informs us when it's going away, // the canvas element informs us when it's going away,
// so these are not nsCOMPtrs // so these are not nsCOMPtrs
@ -470,7 +472,7 @@ NS_NewCanvasRenderingContext2D(nsIDOMCanvasRenderingContext2D** aResult)
} }
nsCanvasRenderingContext2D::nsCanvasRenderingContext2D() nsCanvasRenderingContext2D::nsCanvasRenderingContext2D()
: mValid(PR_FALSE), mCanvasElement(nsnull), : mValid(PR_FALSE), mOpaque(PR_FALSE), mCanvasElement(nsnull),
mSaveCount(0), mCairo(nsnull), mSurface(nsnull), mStyleStack(20) mSaveCount(0), mCairo(nsnull), mSurface(nsnull), mStyleStack(20)
{ {
} }
@ -685,7 +687,12 @@ nsCanvasRenderingContext2D::SetDimensions(PRInt32 width, PRInt32 height)
// Check that the dimensions are sane // Check that the dimensions are sane
if (gfxASurface::CheckSurfaceSize(gfxIntSize(width, height), 0xffff)) { if (gfxASurface::CheckSurfaceSize(gfxIntSize(width, height), 0xffff)) {
mThebesSurface = gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(width, height), gfxASurface::ImageFormatARGB32); gfxASurface::gfxImageFormat format = gfxASurface::ImageFormatARGB32;
if (mOpaque)
format = gfxASurface::ImageFormatRGB24;
mThebesSurface = gfxPlatform::GetPlatform()->CreateOffscreenSurface
(gfxIntSize(width, height), format);
if (mThebesSurface->CairoStatus() == 0) { if (mThebesSurface->CairoStatus() == 0) {
mThebesContext = new gfxContext(mThebesSurface); mThebesContext = new gfxContext(mThebesSurface);
@ -733,6 +740,24 @@ nsCanvasRenderingContext2D::SetDimensions(PRInt32 width, PRInt32 height)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetIsOpaque(PRBool isOpaque)
{
if (isOpaque == mOpaque)
return NS_OK;
mOpaque = isOpaque;
if (mValid) {
/* If we've already been created, let SetDimensions take care of
* recreating our surface
*/
return SetDimensions(mWidth, mHeight);
}
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
nsCanvasRenderingContext2D::Render(gfxContext *ctx) nsCanvasRenderingContext2D::Render(gfxContext *ctx)
{ {
@ -748,12 +773,19 @@ nsCanvasRenderingContext2D::Render(gfxContext *ctx)
nsRefPtr<gfxPattern> pat = new gfxPattern(mThebesSurface); nsRefPtr<gfxPattern> pat = new gfxPattern(mThebesSurface);
gfxContext::GraphicsOperator op = ctx->CurrentOperator();
if (mOpaque)
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
// XXX I don't want to use PixelSnapped here, but layout doesn't guarantee // XXX I don't want to use PixelSnapped here, but layout doesn't guarantee
// pixel alignment for this stuff! // pixel alignment for this stuff!
ctx->NewPath(); ctx->NewPath();
ctx->PixelSnappedRectangleAndSetPattern(gfxRect(0, 0, mWidth, mHeight), pat); ctx->PixelSnappedRectangleAndSetPattern(gfxRect(0, 0, mWidth, mHeight), pat);
ctx->Fill(); ctx->Fill();
if (mOpaque)
ctx->SetOperator(op);
return rv; return rv;
} }

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

@ -118,6 +118,8 @@ public:
protected: protected:
nsIntSize GetWidthHeight(); nsIntSize GetWidthHeight();
PRBool GetIsOpaque();
nsresult UpdateContext(); nsresult UpdateContext();
nsresult ToDataURLImpl(const nsAString& aMimeType, nsresult ToDataURLImpl(const nsAString& aMimeType,
const nsAString& aEncoderOptions, const nsAString& aEncoderOptions,
@ -191,8 +193,15 @@ nsHTMLCanvasElement::GetWidthHeight()
return size; return size;
} }
PRBool
nsHTMLCanvasElement::GetIsOpaque()
{
return HasAttr(kNameSpaceID_None, nsGkAtoms::moz_opaque);
}
NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLCanvasElement, Width, width, DEFAULT_CANVAS_WIDTH) NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLCanvasElement, Width, width, DEFAULT_CANVAS_WIDTH)
NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLCanvasElement, Height, height, DEFAULT_CANVAS_HEIGHT) NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLCanvasElement, Height, height, DEFAULT_CANVAS_HEIGHT)
NS_IMPL_BOOL_ATTR(nsHTMLCanvasElement, MozOpaque, moz_opaque)
nsresult nsresult
nsHTMLCanvasElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, nsHTMLCanvasElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
@ -202,7 +211,7 @@ nsHTMLCanvasElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue, nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue,
aNotify); aNotify);
if (NS_SUCCEEDED(rv) && mCurrentContext && if (NS_SUCCEEDED(rv) && mCurrentContext &&
(aName == nsGkAtoms::width || aName == nsGkAtoms::height)) (aName == nsGkAtoms::width || aName == nsGkAtoms::height || aName == nsGkAtoms::moz_opaque))
{ {
rv = UpdateContext(); rv = UpdateContext();
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -221,6 +230,9 @@ nsHTMLCanvasElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
aAttribute == nsGkAtoms::height) aAttribute == nsGkAtoms::height)
{ {
NS_UpdateHint(retval, NS_STYLE_HINT_REFLOW); NS_UpdateHint(retval, NS_STYLE_HINT_REFLOW);
} else if (aAttribute == nsGkAtoms::moz_opaque)
{
NS_UpdateHint(retval, NS_STYLE_HINT_VISUAL);
} }
return retval; return retval;
} }
@ -488,6 +500,7 @@ nsHTMLCanvasElement::UpdateContext()
nsresult rv = NS_OK; nsresult rv = NS_OK;
if (mCurrentContext) { if (mCurrentContext) {
nsIntSize sz = GetWidthHeight(); nsIntSize sz = GetWidthHeight();
rv = mCurrentContext->SetIsOpaque(GetIsOpaque());
rv = mCurrentContext->SetDimensions(sz.width, sz.height); rv = mCurrentContext->SetDimensions(sz.width, sz.height);
} }

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

@ -52,6 +52,7 @@ interface nsIDOMHTMLCanvasElement : nsIDOMHTMLElement
{ {
attribute long width; attribute long width;
attribute long height; attribute long height;
attribute boolean mozOpaque;
nsISupports getContext(in DOMString contextId); nsISupports getContext(in DOMString contextId);