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
Родитель a38e49028b
Коммит 35bb6388f9
5 изменённых файлов: 57 добавлений и 4 удалений

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

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

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

@ -77,6 +77,12 @@ public:
// If this canvas context can be represented with a simple Thebes surface,
// return the surface. Otherwise returns an error.
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,

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

@ -296,6 +296,7 @@ public:
const PRUnichar* aEncoderOptions,
nsIInputStream **aStream);
NS_IMETHOD GetThebesSurface(gfxASurface **surface);
NS_IMETHOD SetIsOpaque(PRBool isOpaque);
// nsISupports interface
NS_DECL_ISUPPORTS
@ -334,7 +335,8 @@ protected:
// Member vars
PRInt32 mWidth, mHeight;
PRBool mValid;
PRPackedBool mValid;
PRPackedBool mOpaque;
// the canvas element informs us when it's going away,
// so these are not nsCOMPtrs
@ -470,7 +472,7 @@ NS_NewCanvasRenderingContext2D(nsIDOMCanvasRenderingContext2D** aResult)
}
nsCanvasRenderingContext2D::nsCanvasRenderingContext2D()
: mValid(PR_FALSE), mCanvasElement(nsnull),
: mValid(PR_FALSE), mOpaque(PR_FALSE), mCanvasElement(nsnull),
mSaveCount(0), mCairo(nsnull), mSurface(nsnull), mStyleStack(20)
{
}
@ -685,7 +687,12 @@ nsCanvasRenderingContext2D::SetDimensions(PRInt32 width, PRInt32 height)
// Check that the dimensions are sane
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) {
mThebesContext = new gfxContext(mThebesSurface);
@ -733,6 +740,24 @@ nsCanvasRenderingContext2D::SetDimensions(PRInt32 width, PRInt32 height)
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
nsCanvasRenderingContext2D::Render(gfxContext *ctx)
{
@ -748,12 +773,19 @@ nsCanvasRenderingContext2D::Render(gfxContext *ctx)
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
// pixel alignment for this stuff!
ctx->NewPath();
ctx->PixelSnappedRectangleAndSetPattern(gfxRect(0, 0, mWidth, mHeight), pat);
ctx->Fill();
if (mOpaque)
ctx->SetOperator(op);
return rv;
}

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

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

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

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