Bug 704088 - Pass dom::Element to nsLayoutUtils::SurfaceFromElement; r=bz

This commit is contained in:
Ms2ger 2011-12-03 22:50:16 +01:00
parent 79d261bf95
commit cdc32f1c63
9 changed files with 67 additions and 53 deletions

View File

@ -3993,7 +3993,10 @@ nsresult
WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas,
gfxImageSurface **imageOut, int *format)
{
gfxImageSurface *surf = nsnull;
nsCOMPtr<nsIContent> content = do_QueryInterface(imageOrCanvas);
if (!content) {
return NS_ERROR_FAILURE;
}
PRUint32 flags =
nsLayoutUtils::SFE_WANT_NEW_SURFACE |
@ -4005,7 +4008,7 @@ WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas,
flags |= nsLayoutUtils::SFE_NO_PREMULTIPLY_ALPHA;
nsLayoutUtils::SurfaceFromElementResult res =
nsLayoutUtils::SurfaceFromElement(imageOrCanvas, flags);
nsLayoutUtils::SurfaceFromElement(content->AsElement(), flags);
if (!res.mSurface)
return NS_ERROR_FAILURE;
if (res.mSurface->GetType() != gfxASurface::SurfaceTypeImage) {
@ -4034,11 +4037,10 @@ WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas,
}
}
// part 2: if the DOM element is a canvas, check that it's not write-only. That would indicate a tainted canvas,
// i.e. a canvas that could contain cross-domain image data.
nsCOMPtr<nsIContent> maybeDOMCanvas = do_QueryInterface(imageOrCanvas);
if (maybeDOMCanvas && maybeDOMCanvas->IsHTML(nsGkAtoms::canvas)) {
nsHTMLCanvasElement *canvas = static_cast<nsHTMLCanvasElement*>(maybeDOMCanvas.get());
// part 2: if the DOM element is a canvas, check that it's not write-only.
// That would indicate a tainted canvas, i.e. a canvas that could contain
// cross-domain image data.
if (nsHTMLCanvasElement* canvas = nsHTMLCanvasElement::FromContent(content)) {
if (canvas->IsWriteOnly()) {
LogMessageIfVerbose("The canvas used as source for texImage2D here is tainted (write-only). It is forbidden "
"to load a WebGL texture from a tainted canvas. A Canvas becomes tainted for example "
@ -4052,7 +4054,7 @@ WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas,
// Notice that there is never a need to mark the WebGL canvas as write-only, since we reject write-only/cross-domain
// texture sources in the first place.
surf = static_cast<gfxImageSurface*>(res.mSurface.get());
gfxImageSurface* surf = static_cast<gfxImageSurface*>(res.mSurface.get());
res.mSurface.forget();
*imageOut = surf;

View File

@ -1813,11 +1813,12 @@ nsCanvasRenderingContext2D::CreatePattern(nsIDOMHTMLElement *image,
const nsAString& repeat,
nsIDOMCanvasPattern **_retval)
{
if (!image) {
nsCOMPtr<nsIContent> content = do_QueryInterface(image);
if (!content) {
return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
}
gfxPattern::GraphicsExtend extend;
gfxPattern::GraphicsExtend extend;
if (repeat.IsEmpty() || repeat.EqualsLiteral("repeat")) {
extend = gfxPattern::EXTEND_REPEAT;
} else if (repeat.EqualsLiteral("repeat-x")) {
@ -1833,7 +1834,6 @@ nsCanvasRenderingContext2D::CreatePattern(nsIDOMHTMLElement *image,
return NS_ERROR_DOM_SYNTAX_ERR;
}
nsCOMPtr<nsIContent> content = do_QueryInterface(image);
nsHTMLCanvasElement* canvas = nsHTMLCanvasElement::FromContent(content);
if (canvas) {
nsIntSize size = canvas->GetSize();
@ -1845,8 +1845,8 @@ nsCanvasRenderingContext2D::CreatePattern(nsIDOMHTMLElement *image,
// The canvas spec says that createPattern should use the first frame
// of animated images
nsLayoutUtils::SurfaceFromElementResult res =
nsLayoutUtils::SurfaceFromElement(image, nsLayoutUtils::SFE_WANT_FIRST_FRAME |
nsLayoutUtils::SFE_WANT_NEW_SURFACE);
nsLayoutUtils::SurfaceFromElement(content->AsElement(),
nsLayoutUtils::SFE_WANT_FIRST_FRAME | nsLayoutUtils::SFE_WANT_NEW_SURFACE);
if (!res.mSurface)
return NS_ERROR_NOT_AVAILABLE;
@ -3399,11 +3399,11 @@ nsCanvasRenderingContext2D::DrawImage(nsIDOMElement *imgElt, float a1,
if (!EnsureSurface())
return NS_ERROR_FAILURE;
if (!imgElt) {
nsCOMPtr<nsIContent> content = do_QueryInterface(imgElt);
if (!content) {
return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
}
nsCOMPtr<nsIContent> content = do_QueryInterface(imgElt);
nsHTMLCanvasElement* canvas = nsHTMLCanvasElement::FromContent(content);
if (canvas) {
nsIntSize size = canvas->GetSize();
@ -3423,7 +3423,7 @@ nsCanvasRenderingContext2D::DrawImage(nsIDOMElement *imgElt, float a1,
// of animated images
PRUint32 sfeFlags = nsLayoutUtils::SFE_WANT_FIRST_FRAME;
nsLayoutUtils::SurfaceFromElementResult res =
nsLayoutUtils::SurfaceFromElement(imgElt, sfeFlags);
nsLayoutUtils::SurfaceFromElement(content->AsElement(), sfeFlags);
if (!res.mSurface) {
// Spec says to silently do nothing if the element is still loading.
return res.mIsStillLoading ? NS_OK : NS_ERROR_NOT_AVAILABLE;
@ -3433,7 +3433,8 @@ nsCanvasRenderingContext2D::DrawImage(nsIDOMElement *imgElt, float a1,
// as a source to work around some Cairo self-copy semantics issues.
if (res.mSurface == mSurface) {
sfeFlags |= nsLayoutUtils::SFE_WANT_NEW_SURFACE;
res = nsLayoutUtils::SurfaceFromElement(imgElt, sfeFlags);
res = nsLayoutUtils::SurfaceFromElement(content->AsElement(),
sfeFlags);
if (!res.mSurface)
return NS_ERROR_NOT_AVAILABLE;
}

View File

@ -1889,7 +1889,8 @@ nsCanvasRenderingContext2DAzure::CreatePattern(nsIDOMHTMLElement *image,
const nsAString& repeat,
nsIDOMCanvasPattern **_retval)
{
if (!image) {
nsCOMPtr<nsIContent> content = do_QueryInterface(image);
if (!content) {
return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
}
@ -1908,9 +1909,7 @@ nsCanvasRenderingContext2DAzure::CreatePattern(nsIDOMHTMLElement *image,
return NS_ERROR_DOM_SYNTAX_ERR;
}
nsCOMPtr<nsIContent> content = do_QueryInterface(image);
nsHTMLCanvasElement* canvas = nsHTMLCanvasElement::FromContent(content);
if (canvas) {
nsIntSize size = canvas->GetSize();
if (size.width == 0 || size.height == 0) {
@ -1939,8 +1938,8 @@ nsCanvasRenderingContext2DAzure::CreatePattern(nsIDOMHTMLElement *image,
// The canvas spec says that createPattern should use the first frame
// of animated images
nsLayoutUtils::SurfaceFromElementResult res =
nsLayoutUtils::SurfaceFromElement(image, nsLayoutUtils::SFE_WANT_FIRST_FRAME |
nsLayoutUtils::SFE_WANT_NEW_SURFACE);
nsLayoutUtils::SurfaceFromElement(content->AsElement(),
nsLayoutUtils::SFE_WANT_FIRST_FRAME | nsLayoutUtils::SFE_WANT_NEW_SURFACE);
if (!res.mSurface) {
return NS_ERROR_NOT_AVAILABLE;
@ -3570,7 +3569,8 @@ nsCanvasRenderingContext2DAzure::DrawImage(nsIDOMElement *imgElt, float a1,
float a6, float a7, float a8,
PRUint8 optional_argc)
{
if (!imgElt) {
nsCOMPtr<nsIContent> content = do_QueryInterface(imgElt);
if (!content) {
return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
}
@ -3591,7 +3591,6 @@ nsCanvasRenderingContext2DAzure::DrawImage(nsIDOMElement *imgElt, float a1,
double sx,sy,sw,sh;
double dx,dy,dw,dh;
nsCOMPtr<nsIContent> content = do_QueryInterface(imgElt);
nsHTMLCanvasElement* canvas = nsHTMLCanvasElement::FromContent(content);
if (canvas) {
nsIntSize size = canvas->GetSize();
@ -3643,7 +3642,7 @@ nsCanvasRenderingContext2DAzure::DrawImage(nsIDOMElement *imgElt, float a1,
// of animated images
PRUint32 sfeFlags = nsLayoutUtils::SFE_WANT_FIRST_FRAME;
nsLayoutUtils::SurfaceFromElementResult res =
nsLayoutUtils::SurfaceFromElement(imgElt, sfeFlags);
nsLayoutUtils::SurfaceFromElement(content->AsElement(), sfeFlags);
if (!res.mSurface) {
// Spec says to silently do nothing if the element is still loading.

View File

@ -48,6 +48,14 @@ public:
nsHTMLVideoElement(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~nsHTMLVideoElement();
static nsHTMLVideoElement* FromContent(nsIContent* aPossibleVideo)
{
if (!aPossibleVideo || !aPossibleVideo->IsHTML(nsGkAtoms::video)) {
return NULL;
}
return static_cast<nsHTMLVideoElement*>(aPossibleVideo);
}
// nsISupports
NS_DECL_ISUPPORTS_INHERITED

View File

@ -2687,18 +2687,17 @@ nsHTMLMediaElement::CopyInnerTo(nsGenericElement* aDest) const
dest->mMediaSize = mMediaSize;
} else {
nsIFrame* frame = GetPrimaryFrame();
nsCOMPtr<nsIDOMElement> elem;
Element* element;
if (frame && frame->GetType() == nsGkAtoms::HTMLVideoFrame &&
static_cast<nsVideoFrame*>(frame)->ShouldDisplayPoster()) {
elem = do_QueryInterface(static_cast<nsVideoFrame*>(frame)->
GetPosterImage());
nsIContent* content = static_cast<nsVideoFrame*>(frame)->GetPosterImage();
element = content ? content->AsElement() : NULL;
} else {
elem = do_QueryInterface(
static_cast<nsGenericElement*>(const_cast<nsHTMLMediaElement*>(this)));
element = const_cast<nsHTMLMediaElement*>(this);
}
nsLayoutUtils::SurfaceFromElementResult res =
nsLayoutUtils::SurfaceFromElement(elem,
nsLayoutUtils::SurfaceFromElement(element,
nsLayoutUtils::SFE_WANT_NEW_SURFACE);
dest->mPrintSurface = res.mSurface;
dest->mMediaSize = nsIntSize(res.mSize.width, res.mSize.height);

View File

@ -869,10 +869,18 @@ nsDOMWindowUtils::NodesFromRect(float aX, float aY,
}
static already_AddRefed<gfxImageSurface>
CanvasToImageSurface(nsIDOMHTMLCanvasElement *canvas)
CanvasToImageSurface(nsIDOMHTMLCanvasElement* aCanvas)
{
nsCOMPtr<nsINode> node = do_QueryInterface(aCanvas);
if (!node) {
return nsnull;
}
NS_ABORT_IF_FALSE(node->IsElement(),
"An nsINode that implements nsIDOMHTMLCanvasElement should "
"be an element.");
nsLayoutUtils::SurfaceFromElementResult result =
nsLayoutUtils::SurfaceFromElement(canvas,
nsLayoutUtils::SurfaceFromElement(node->AsElement(),
nsLayoutUtils::SFE_WANT_IMAGE_SURFACE);
return static_cast<gfxImageSurface*>(result.mSurface.forget().get());
}

View File

@ -3836,9 +3836,8 @@ ImageRenderer::PrepareImage()
// If the referenced element doesn't have a frame we might still be able
// to paint it if it's an <img>, <canvas>, or <video> element.
if (!mPaintServerFrame) {
nsCOMPtr<nsIDOMElement> imageElement =
do_QueryInterface(property->GetReferencedElement());
mImageElementSurface = nsLayoutUtils::SurfaceFromElement(imageElement);
mImageElementSurface =
nsLayoutUtils::SurfaceFromElement(property->GetReferencedElement());
if (!mImageElementSurface.mSurface)
return false;
}

View File

@ -3917,14 +3917,12 @@ nsLayoutUtils::IsReallyFixedPos(nsIFrame* aFrame)
}
nsLayoutUtils::SurfaceFromElementResult
nsLayoutUtils::SurfaceFromElement(nsIDOMElement *aElement,
nsLayoutUtils::SurfaceFromElement(dom::Element* aElement,
PRUint32 aSurfaceFlags)
{
SurfaceFromElementResult result;
nsresult rv;
nsCOMPtr<nsINode> node = do_QueryInterface(aElement);
bool forceCopy = (aSurfaceFlags & SFE_WANT_NEW_SURFACE) != 0;
bool wantImageSurface = (aSurfaceFlags & SFE_WANT_IMAGE_SURFACE) != 0;
@ -3934,11 +3932,8 @@ nsLayoutUtils::SurfaceFromElement(nsIDOMElement *aElement,
}
// If it's a <canvas>, we may be able to just grab its internal surface
nsCOMPtr<nsIDOMHTMLCanvasElement> domCanvas = do_QueryInterface(aElement);
if (node && domCanvas) {
nsHTMLCanvasElement *canvas = static_cast<nsHTMLCanvasElement*>(domCanvas.get());
nsIntSize nssize = canvas->GetSize();
gfxIntSize size(nssize.width, nssize.height);
if (nsHTMLCanvasElement* canvas = nsHTMLCanvasElement::FromContent(aElement)) {
gfxIntSize size = canvas->GetSize();
nsRefPtr<gfxASurface> surf;
@ -3962,7 +3957,7 @@ nsLayoutUtils::SurfaceFromElement(nsIDOMElement *aElement,
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
// XXX shouldn't use the external interface, but maybe we can layerify this
rv = (static_cast<nsICanvasElementExternal*>(canvas))->RenderContextsExternal(ctx, gfxPattern::FILTER_NEAREST);
rv = canvas->RenderContextsExternal(ctx, gfxPattern::FILTER_NEAREST);
if (NS_FAILED(rv))
return result;
}
@ -3979,7 +3974,7 @@ nsLayoutUtils::SurfaceFromElement(nsIDOMElement *aElement,
result.mSurface = surf;
result.mSize = size;
result.mPrincipal = node->NodePrincipal();
result.mPrincipal = aElement->NodePrincipal();
result.mIsWriteOnly = canvas->IsWriteOnly();
return result;
@ -3987,12 +3982,9 @@ nsLayoutUtils::SurfaceFromElement(nsIDOMElement *aElement,
#ifdef MOZ_MEDIA
// Maybe it's <video>?
nsCOMPtr<nsIDOMHTMLVideoElement> ve = do_QueryInterface(aElement);
if (node && ve) {
nsHTMLVideoElement *video = static_cast<nsHTMLVideoElement*>(ve.get());
unsigned short readyState;
if (NS_SUCCEEDED(ve->GetReadyState(&readyState)) &&
if (nsHTMLVideoElement* video = nsHTMLVideoElement::FromContent(aElement)) {
PRUint16 readyState;
if (NS_SUCCEEDED(video->GetReadyState(&readyState)) &&
(readyState == nsIDOMHTMLMediaElement::HAVE_NOTHING ||
readyState == nsIDOMHTMLMediaElement::HAVE_METADATA)) {
result.mIsStillLoading = true;

View File

@ -73,6 +73,12 @@ class nsFontFaceList;
class nsBlockFrame;
class gfxDrawable;
namespace mozilla {
namespace dom {
class Element;
} // namespace dom
} // namespace mozilla
/**
* nsLayoutUtils is a namespace class used for various helper
* functions that are useful in multiple places in layout. The goal
@ -1381,7 +1387,7 @@ public:
bool mCORSUsed;
};
static SurfaceFromElementResult SurfaceFromElement(nsIDOMElement *aElement,
static SurfaceFromElementResult SurfaceFromElement(mozilla::dom::Element *aElement,
PRUint32 aSurfaceFlags = 0);
/**