mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 20:05:49 +00:00
b=492724; pull out canvas utility functions into CanvasUtils/LayoutUtils; r+sr=roc
This commit is contained in:
parent
3398165d33
commit
670216332d
94
content/canvas/src/CanvasUtils.cpp
Normal file
94
content/canvas/src/CanvasUtils.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Vladimir Vukicevic <vladimir@pobox.com>
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "prmem.h"
|
||||
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMCanvasRenderingContext2D.h"
|
||||
#include "nsICanvasRenderingContextInternal.h"
|
||||
#include "nsICanvasElement.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsINode.h"
|
||||
|
||||
#include "nsGfxCIID.h"
|
||||
|
||||
#include "nsTArray.h"
|
||||
|
||||
#include "CanvasUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
void
|
||||
CanvasUtils::DoDrawImageSecurityCheck(nsICanvasElement *aCanvasElement,
|
||||
nsIPrincipal *aPrincipal,
|
||||
PRBool forceWriteOnly)
|
||||
{
|
||||
// Callers should ensure that mCanvasElement is non-null before calling this
|
||||
if (!aCanvasElement) {
|
||||
NS_WARNING("DoDrawImageSecurityCheck called without canvas element!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (aCanvasElement->IsWriteOnly())
|
||||
return;
|
||||
|
||||
// If we explicitly set WriteOnly just do it and get out
|
||||
if (forceWriteOnly) {
|
||||
aCanvasElement->SetWriteOnly();
|
||||
return;
|
||||
}
|
||||
|
||||
if (aPrincipal == nsnull)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsINode> elem = do_QueryInterface(aCanvasElement);
|
||||
if (elem) { // XXXbz How could this actually be null?
|
||||
PRBool subsumes;
|
||||
nsresult rv =
|
||||
elem->NodePrincipal()->Subsumes(aPrincipal, &subsumes);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && subsumes) {
|
||||
// This canvas has access to that image anyway
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
aCanvasElement->SetWriteOnly();
|
||||
}
|
76
content/canvas/src/CanvasUtils.h
Normal file
76
content/canvas/src/CanvasUtils.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Vladimir Vukicevic <vladimir@pobox.com>
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _CANVASUTILS_H_
|
||||
#define _CANVASUTILS_H_
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsICanvasElement.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsRect.h"
|
||||
|
||||
#include "gfxASurface.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class CanvasUtils {
|
||||
public:
|
||||
// Check that the rectangle [x,y,w,h] is a subrectangle of [0,0,realWidth,realHeight]
|
||||
|
||||
static PRBool CheckSaneSubrectSize(PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h,
|
||||
PRInt32 realWidth, PRInt32 realHeight)
|
||||
{
|
||||
return nsIntRect(0, 0, realWidth, realHeight).Contains(nsIntRect(x, y, w, h));
|
||||
}
|
||||
|
||||
// Flag aCanvasElement as write-only if drawing an image with aPrincipal
|
||||
// onto it would make it such.
|
||||
|
||||
static void DoDrawImageSecurityCheck(nsICanvasElement *aCanvasElement,
|
||||
nsIPrincipal *aPrincipal,
|
||||
PRBool forceWriteOnly);
|
||||
|
||||
private:
|
||||
// this can't be instantiated
|
||||
CanvasUtils() { }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* _CANVASUTILS_H_ */
|
@ -68,17 +68,11 @@ REQUIRES = \
|
||||
qcms \
|
||||
$(NULL)
|
||||
|
||||
# XXX some platforms can't handle building
|
||||
# an empty .a/lib. Remove this dummy.cpp
|
||||
# whenever w have a rendering context
|
||||
# that doesn't depend on any non-default
|
||||
# libraries.
|
||||
CPPSRCS = dummy.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_ENABLE_CANVAS
|
||||
CPPSRCS += nsCanvasRenderingContext2D.cpp
|
||||
endif
|
||||
CPPSRCS = \
|
||||
CanvasUtils.cpp \
|
||||
nsCanvasRenderingContext2D.cpp \
|
||||
$(NULL)
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a static lib.
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
@ -1,9 +0,0 @@
|
||||
/*
|
||||
* This file only exists because some platforms can't handle building an empty .a
|
||||
* file, or .lib, or whatever (e.g. OS X, possibly Win32).
|
||||
*
|
||||
* Need at least one external symbol for some linkers to create a proper
|
||||
* archive file: https://bugzilla.mozilla.org/show_bug.cgi?id=311143
|
||||
*/
|
||||
void concvsdummy(void) {}
|
||||
|
@ -55,15 +55,9 @@
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIVariant.h"
|
||||
|
||||
#include "imgIRequest.h"
|
||||
#include "imgIContainer.h"
|
||||
#include "gfxIImageFrame.h"
|
||||
#include "nsIDOMHTMLCanvasElement.h"
|
||||
#include "nsICanvasElement.h"
|
||||
#include "nsIDOMHTMLImageElement.h"
|
||||
#include "nsIImageLoadingContent.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsIImage.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsDOMError.h"
|
||||
#include "nsIScriptError.h"
|
||||
@ -110,17 +104,15 @@
|
||||
|
||||
#include "nsBidiPresUtils.h"
|
||||
|
||||
#ifdef MOZ_MEDIA
|
||||
#include "nsHTMLVideoElement.h"
|
||||
#endif
|
||||
#include "CanvasUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#define M_PI_2 1.57079632679489661923
|
||||
#endif
|
||||
|
||||
static PRBool CheckSaneSubrectSize (PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h, PRInt32 realWidth, PRInt32 realHeight);
|
||||
|
||||
/* Float validation stuff */
|
||||
|
||||
#define VALIDATE(_f) if (!JSDOUBLE_IS_FINITE(_f)) return PR_FALSE
|
||||
@ -360,14 +352,6 @@ protected:
|
||||
*/
|
||||
void ApplyStyle(Style aWhichStyle, PRBool aUseGlobalAlpha = PR_TRUE);
|
||||
|
||||
// If aPrincipal is not subsumed by this canvas element, then
|
||||
// we make the canvas write-only so bad guys can't extract the pixel
|
||||
// data. If forceWriteOnly is set, we force write only to be set
|
||||
// and ignore aPrincipal. (This is used for when the original data came
|
||||
// from a <canvas> that had write-only set.)
|
||||
void DoDrawImageSecurityCheck(nsIPrincipal* aPrincipal,
|
||||
PRBool forceWriteOnly);
|
||||
|
||||
// Member vars
|
||||
PRInt32 mWidth, mHeight;
|
||||
PRPackedBool mValid;
|
||||
@ -614,14 +598,6 @@ protected:
|
||||
static PRBool ConvertJSValToDouble(double* aProp, JSContext* aContext,
|
||||
jsval aValue);
|
||||
|
||||
// thebes helpers
|
||||
nsresult ThebesSurfaceFromElement(nsIDOMElement *imgElt,
|
||||
PRBool forceCopy,
|
||||
gfxASurface **aSurface,
|
||||
PRInt32 *widthOut, PRInt32 *heightOut,
|
||||
nsIPrincipal **prinOut,
|
||||
PRBool *forceWriteOnlyOut);
|
||||
|
||||
// other helpers
|
||||
void GetAppUnitsValues(PRUint32 *perDevPixel, PRUint32 *perCSSPixel) {
|
||||
// If we don't have a canvas element, we just return something generic.
|
||||
@ -791,43 +767,6 @@ nsCanvasRenderingContext2D::DirtyAllStyles()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsCanvasRenderingContext2D::DoDrawImageSecurityCheck(nsIPrincipal* aPrincipal,
|
||||
PRBool forceWriteOnly)
|
||||
{
|
||||
// Callers should ensure that mCanvasElement is non-null before calling this
|
||||
if (!mCanvasElement) {
|
||||
NS_WARNING("DoDrawImageSecurityCheck called without canvas element!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mCanvasElement->IsWriteOnly())
|
||||
return;
|
||||
|
||||
// If we explicitly set WriteOnly just do it and get out
|
||||
if (forceWriteOnly) {
|
||||
mCanvasElement->SetWriteOnly();
|
||||
return;
|
||||
}
|
||||
|
||||
if (aPrincipal == nsnull)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsINode> elem = do_QueryInterface(mCanvasElement);
|
||||
if (elem) { // XXXbz How could this actually be null?
|
||||
PRBool subsumes;
|
||||
nsresult rv =
|
||||
elem->NodePrincipal()->Subsumes(aPrincipal, &subsumes);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && subsumes) {
|
||||
// This canvas has access to that image anyway
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mCanvasElement->SetWriteOnly();
|
||||
}
|
||||
|
||||
void
|
||||
nsCanvasRenderingContext2D::ApplyStyle(Style aWhichStyle,
|
||||
PRBool aUseGlobalAlpha)
|
||||
@ -850,8 +789,9 @@ nsCanvasRenderingContext2D::ApplyStyle(Style aWhichStyle,
|
||||
if (!mCanvasElement)
|
||||
return;
|
||||
|
||||
DoDrawImageSecurityCheck(pattern->Principal(),
|
||||
pattern->GetForceWriteOnly());
|
||||
CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement,
|
||||
pattern->Principal(),
|
||||
pattern->GetForceWriteOnly());
|
||||
|
||||
gfxPattern* gpat = pattern->GetPattern();
|
||||
|
||||
@ -1333,7 +1273,6 @@ nsCanvasRenderingContext2D::CreatePattern(nsIDOMHTMLElement *image,
|
||||
const nsAString& repeat,
|
||||
nsIDOMCanvasPattern **_retval)
|
||||
{
|
||||
nsresult rv;
|
||||
gfxPattern::GraphicsExtend extend;
|
||||
|
||||
if (repeat.IsEmpty() || repeat.EqualsLiteral("repeat")) {
|
||||
@ -1351,22 +1290,17 @@ nsCanvasRenderingContext2D::CreatePattern(nsIDOMHTMLElement *image,
|
||||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
}
|
||||
|
||||
PRInt32 imgWidth, imgHeight;
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
PRBool forceWriteOnly = PR_FALSE;
|
||||
nsRefPtr<gfxASurface> imgsurf;
|
||||
rv = ThebesSurfaceFromElement(image, PR_TRUE,
|
||||
getter_AddRefs(imgsurf), &imgWidth, &imgHeight,
|
||||
getter_AddRefs(principal), &forceWriteOnly);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
nsLayoutUtils::SurfaceFromElementResult res =
|
||||
nsLayoutUtils::SurfaceFromElement(image, nsLayoutUtils::SFE_WANT_NEW_SURFACE);
|
||||
if (!res.mSurface)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
nsRefPtr<gfxPattern> thebespat = new gfxPattern(imgsurf);
|
||||
nsRefPtr<gfxPattern> thebespat = new gfxPattern(res.mSurface);
|
||||
|
||||
thebespat->SetExtend(extend);
|
||||
|
||||
nsRefPtr<nsCanvasPattern> pat = new nsCanvasPattern(thebespat, principal,
|
||||
forceWriteOnly);
|
||||
nsRefPtr<nsCanvasPattern> pat = new nsCanvasPattern(thebespat, res.mPrincipal,
|
||||
res.mIsWriteOnly);
|
||||
if (!pat)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
@ -2959,22 +2893,33 @@ nsCanvasRenderingContext2D::DrawImage()
|
||||
ctx, argv[0]))
|
||||
return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
|
||||
|
||||
PRInt32 imgWidth, imgHeight;
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
PRBool forceWriteOnly = PR_FALSE;
|
||||
gfxMatrix matrix;
|
||||
nsRefPtr<gfxPattern> pattern;
|
||||
nsRefPtr<gfxPath> path;
|
||||
nsRefPtr<gfxASurface> imgsurf;
|
||||
#ifdef WINCE
|
||||
nsRefPtr<gfxASurface> currentSurface;
|
||||
#endif
|
||||
rv = ThebesSurfaceFromElement(imgElt, PR_FALSE,
|
||||
getter_AddRefs(imgsurf), &imgWidth, &imgHeight,
|
||||
getter_AddRefs(principal), &forceWriteOnly);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
DoDrawImageSecurityCheck(principal, forceWriteOnly);
|
||||
nsLayoutUtils::SurfaceFromElementResult res =
|
||||
nsLayoutUtils::SurfaceFromElement(imgElt);
|
||||
if (!res.mSurface)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
#ifndef WINCE
|
||||
// On non-CE, force a copy if we're using drawImage with our destination
|
||||
// as a source to work around some Cairo self-copy semantics issues.
|
||||
if (res.mSurface == mSurface) {
|
||||
res = nsLayoutUtils::SurfaceFromElement(imgElt, nsLayoutUtils::SFE_WANT_NEW_SURFACE);
|
||||
if (!res.mSurface)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsRefPtr<gfxASurface> imgsurf = res.mSurface;
|
||||
nsCOMPtr<nsIPrincipal> principal = res.mPrincipal;
|
||||
gfxIntSize imgSize = res.mSize;
|
||||
PRBool forceWriteOnly = res.mIsWriteOnly;
|
||||
|
||||
CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement, principal, forceWriteOnly);
|
||||
|
||||
gfxContextPathAutoSaveRestore pathSR(mThebes, PR_FALSE);
|
||||
|
||||
@ -2987,16 +2932,16 @@ nsCanvasRenderingContext2D::DrawImage()
|
||||
GET_ARG(&dx, argv[1]);
|
||||
GET_ARG(&dy, argv[2]);
|
||||
sx = sy = 0.0;
|
||||
dw = sw = (double) imgWidth;
|
||||
dh = sh = (double) imgHeight;
|
||||
dw = sw = (double) imgSize.width;
|
||||
dh = sh = (double) imgSize.height;
|
||||
} else if (argc == 5) {
|
||||
GET_ARG(&dx, argv[1]);
|
||||
GET_ARG(&dy, argv[2]);
|
||||
GET_ARG(&dw, argv[3]);
|
||||
GET_ARG(&dh, argv[4]);
|
||||
sx = sy = 0.0;
|
||||
sw = (double) imgWidth;
|
||||
sh = (double) imgHeight;
|
||||
sw = (double) imgSize.width;
|
||||
sh = (double) imgSize.height;
|
||||
} else if (argc == 9) {
|
||||
GET_ARG(&sx, argv[1]);
|
||||
GET_ARG(&sy, argv[2]);
|
||||
@ -3027,8 +2972,8 @@ nsCanvasRenderingContext2D::DrawImage()
|
||||
|
||||
// check args
|
||||
if (sx < 0.0 || sy < 0.0 ||
|
||||
sw < 0.0 || sw > (double) imgWidth ||
|
||||
sh < 0.0 || sh > (double) imgHeight ||
|
||||
sw < 0.0 || sw > (double) imgSize.width ||
|
||||
sh < 0.0 || sh > (double) imgSize.height ||
|
||||
dw < 0.0 || dh < 0.0)
|
||||
{
|
||||
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
|
||||
@ -3258,192 +3203,6 @@ nsCanvasRenderingContext2D::ConvertJSValToXPCObject(nsISupports** aSupports, REF
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* thebes ARGB32 surfaces are ARGB stored as a packed 32-bit integer; on little-endian
|
||||
* platforms, they appear as BGRA bytes in the surface data. The color values are also
|
||||
* stored with premultiplied alpha.
|
||||
*
|
||||
* If forceCopy is FALSE, a surface may be returned that's only valid during the current
|
||||
* operation. If it's TRUE, a copy will always be made that can safely be retained.
|
||||
*/
|
||||
|
||||
nsresult
|
||||
nsCanvasRenderingContext2D::ThebesSurfaceFromElement(nsIDOMElement *imgElt,
|
||||
PRBool forceCopy,
|
||||
gfxASurface **aSurface,
|
||||
PRInt32 *widthOut,
|
||||
PRInt32 *heightOut,
|
||||
nsIPrincipal **prinOut,
|
||||
PRBool *forceWriteOnlyOut)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(imgElt);
|
||||
|
||||
/* If it's a Canvas, grab its internal surface as necessary */
|
||||
nsCOMPtr<nsICanvasElement> canvas = do_QueryInterface(imgElt);
|
||||
if (node && canvas) {
|
||||
PRUint32 w, h;
|
||||
rv = canvas->GetSize(&w, &h);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<gfxASurface> sourceSurface;
|
||||
|
||||
if (!forceCopy && canvas->CountContexts() == 1) {
|
||||
nsICanvasRenderingContextInternal *srcCanvas = canvas->GetContextAtIndex(0);
|
||||
rv = srcCanvas->GetThebesSurface(getter_AddRefs(sourceSurface));
|
||||
#ifndef WINCE
|
||||
// force a copy if we couldn't get the surface, or if it's
|
||||
// the same as what we have
|
||||
if (sourceSurface == mSurface || NS_FAILED(rv))
|
||||
#else
|
||||
// force a copy if we couldn't get the surface
|
||||
if (NS_FAILED(rv))
|
||||
#endif
|
||||
sourceSurface = nsnull;
|
||||
}
|
||||
|
||||
if (sourceSurface == nsnull) {
|
||||
nsRefPtr<gfxASurface> surf =
|
||||
gfxPlatform::GetPlatform()->CreateOffscreenSurface
|
||||
(gfxIntSize(w, h), gfxASurface::ImageFormatARGB32);
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
|
||||
rv = canvas->RenderContexts(ctx, gfxPattern::FILTER_NEAREST);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
sourceSurface = surf;
|
||||
}
|
||||
|
||||
*aSurface = sourceSurface.forget().get();
|
||||
*widthOut = w;
|
||||
*heightOut = h;
|
||||
|
||||
NS_ADDREF(*prinOut = node->NodePrincipal());
|
||||
*forceWriteOnlyOut = canvas->IsWriteOnly();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef MOZ_MEDIA
|
||||
/* Maybe it's <video>? */
|
||||
nsCOMPtr<nsIDOMHTMLVideoElement> ve = do_QueryInterface(imgElt);
|
||||
if (node && ve) {
|
||||
nsHTMLVideoElement *video = static_cast<nsHTMLVideoElement*>(ve.get());
|
||||
|
||||
/* If it doesn't have a principal, just bail */
|
||||
nsCOMPtr<nsIPrincipal> principal = video->GetCurrentPrincipal();
|
||||
if (!principal)
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
|
||||
PRUint32 videoWidth, videoHeight;
|
||||
rv = video->GetVideoWidth(&videoWidth);
|
||||
rv |= video->GetVideoHeight(&videoHeight);
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
nsRefPtr<gfxASurface> surf =
|
||||
gfxPlatform::GetPlatform()->CreateOffscreenSurface
|
||||
(gfxIntSize(videoWidth, videoHeight), gfxASurface::ImageFormatARGB32);
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
|
||||
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
|
||||
video->Paint(ctx, gfxPattern::FILTER_NEAREST, gfxRect(0, 0, videoWidth, videoHeight));
|
||||
|
||||
*aSurface = surf.forget().get();
|
||||
*widthOut = videoWidth;
|
||||
*heightOut = videoHeight;
|
||||
|
||||
*prinOut = principal.forget().get();
|
||||
*forceWriteOnlyOut = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Finally, check if it's a normal image */
|
||||
nsCOMPtr<imgIContainer> imgContainer;
|
||||
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(imgElt);
|
||||
|
||||
if (!imageLoader)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
nsCOMPtr<imgIRequest> imgRequest;
|
||||
rv = imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
|
||||
getter_AddRefs(imgRequest));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!imgRequest)
|
||||
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
PRUint32 status;
|
||||
imgRequest->GetImageStatus(&status);
|
||||
if ((status & imgIRequest::STATUS_LOAD_COMPLETE) == 0)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
// In case of data: URIs, we want to ignore principals;
|
||||
// they should have the originating content's principal,
|
||||
// but that's broken at the moment in imgLib.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = imgRequest->GetURI(getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_SECURITY_ERR);
|
||||
|
||||
PRBool isDataURI = PR_FALSE;
|
||||
rv = uri->SchemeIs("data", &isDataURI);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_SECURITY_ERR);
|
||||
|
||||
// Data URIs are always OK; set the principal
|
||||
// to null to indicate that.
|
||||
if (isDataURI) {
|
||||
*prinOut = nsnull;
|
||||
} else {
|
||||
rv = imgRequest->GetImagePrincipal(prinOut);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(*prinOut, NS_ERROR_DOM_SECURITY_ERR);
|
||||
}
|
||||
|
||||
*forceWriteOnlyOut = PR_FALSE;
|
||||
|
||||
rv = imgRequest->GetImage(getter_AddRefs(imgContainer));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!imgContainer)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
nsCOMPtr<gfxIImageFrame> frame;
|
||||
rv = imgContainer->GetCurrentFrame(getter_AddRefs(frame));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIImage> img(do_GetInterface(frame));
|
||||
|
||||
PRInt32 imgWidth, imgHeight;
|
||||
rv = frame->GetWidth(&imgWidth);
|
||||
rv |= frame->GetHeight(&imgHeight);
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (widthOut)
|
||||
*widthOut = imgWidth;
|
||||
if (heightOut)
|
||||
*heightOut = imgHeight;
|
||||
|
||||
nsRefPtr<gfxPattern> gfxpattern;
|
||||
img->GetPattern(getter_AddRefs(gfxpattern));
|
||||
nsRefPtr<gfxASurface> gfxsurf = gfxpattern->GetSurface();
|
||||
|
||||
if (!gfxsurf) {
|
||||
gfxsurf = new gfxImageSurface (gfxIntSize(imgWidth, imgHeight), gfxASurface::ImageFormatARGB32);
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(gfxsurf);
|
||||
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->SetPattern(gfxpattern);
|
||||
ctx->Paint();
|
||||
}
|
||||
|
||||
*aSurface = gfxsurf.forget().get();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* Check that the rect [x,y,w,h] is a valid subrect of [0,0,realWidth,realHeight]
|
||||
* without overflowing any integers and the like.
|
||||
*/
|
||||
@ -3614,7 +3373,7 @@ nsCanvasRenderingContext2D::GetImageData()
|
||||
if (!JS_ConvertArguments (ctx, argc, argv, "jjjj", &x, &y, &w, &h))
|
||||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
|
||||
if (!CheckSaneSubrectSize (x, y, w, h, mWidth, mHeight))
|
||||
if (!CanvasUtils::CheckSaneSubrectSize (x, y, w, h, mWidth, mHeight))
|
||||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
|
||||
nsAutoArrayPtr<PRUint8> surfaceData (new (std::nothrow) PRUint8[w * h * 4]);
|
||||
@ -3802,7 +3561,7 @@ nsCanvasRenderingContext2D::PutImageData()
|
||||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
dataArray = JSVAL_TO_OBJECT(v);
|
||||
|
||||
if (!CheckSaneSubrectSize (x, y, w, h, mWidth, mHeight))
|
||||
if (!CanvasUtils::CheckSaneSubrectSize (x, y, w, h, mWidth, mHeight))
|
||||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
|
||||
jsuint arrayLen;
|
||||
@ -3972,7 +3731,7 @@ nsCanvasRenderingContext2D::CreateImageData()
|
||||
|
||||
// check for overflow when calculating len
|
||||
PRUint32 len0 = w * h;
|
||||
if (len0 / w != h)
|
||||
if (len0 / w != (PRUint32) h)
|
||||
return NS_ERROR_DOM_INDEX_SIZE_ERR;
|
||||
PRUint32 len = len0 * 4;
|
||||
if (len / 4 != len0)
|
||||
|
@ -46,6 +46,8 @@ typedef struct _cairo_user_data_key cairo_user_data_key_t;
|
||||
|
||||
typedef void (*thebes_destroy_func_t) (void *data);
|
||||
|
||||
class gfxImageSurface;
|
||||
|
||||
/**
|
||||
* A surface is something you can draw on. Instantiate a subclass of this
|
||||
* abstract class, and use gfxContext to draw on this surface.
|
||||
|
@ -81,6 +81,13 @@
|
||||
#include "gfxUserFontSet.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsTextFragment.h"
|
||||
#include "nsICanvasElement.h"
|
||||
#include "nsICanvasRenderingContextInternal.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "nsHTMLVideoElement.h"
|
||||
#include "imgIRequest.h"
|
||||
#include "imgIContainer.h"
|
||||
#include "nsIImageLoadingContent.h"
|
||||
|
||||
#ifdef MOZ_SVG
|
||||
#include "nsSVGUtils.h"
|
||||
@ -3290,6 +3297,190 @@ nsLayoutUtils::GetTextFragmentForPrinting(const nsIFrame* aFrame)
|
||||
return frag;
|
||||
}
|
||||
|
||||
nsLayoutUtils::SurfaceFromElementResult
|
||||
nsLayoutUtils::SurfaceFromElement(nsIDOMElement *aElement,
|
||||
PRUint32 aSurfaceFlags)
|
||||
{
|
||||
SurfaceFromElementResult result;
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(aElement);
|
||||
|
||||
PRBool forceCopy = (aSurfaceFlags & SFE_WANT_NEW_SURFACE) != 0;
|
||||
PRBool wantImageSurface = (aSurfaceFlags & SFE_WANT_IMAGE_SURFACE) != 0;
|
||||
|
||||
// If it's a <canvas>, we may be able to just grab its internal surface
|
||||
nsCOMPtr<nsICanvasElement> canvas = do_QueryInterface(aElement);
|
||||
if (node && canvas) {
|
||||
PRUint32 w, h;
|
||||
rv = canvas->GetSize(&w, &h);
|
||||
if (NS_FAILED(rv))
|
||||
return result;
|
||||
|
||||
nsRefPtr<gfxASurface> surf;
|
||||
|
||||
if (!forceCopy && canvas->CountContexts() == 1) {
|
||||
nsICanvasRenderingContextInternal *srcCanvas = canvas->GetContextAtIndex(0);
|
||||
rv = srcCanvas->GetThebesSurface(getter_AddRefs(surf));
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
surf = nsnull;
|
||||
}
|
||||
|
||||
if (surf && wantImageSurface && surf->GetType() != gfxASurface::SurfaceTypeImage)
|
||||
surf = nsnull;
|
||||
|
||||
if (!surf) {
|
||||
if (wantImageSurface) {
|
||||
surf = new gfxImageSurface(gfxIntSize(w, h), gfxASurface::ImageFormatARGB32);
|
||||
} else {
|
||||
surf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(w, h), gfxASurface::ImageFormatARGB32);
|
||||
}
|
||||
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
|
||||
rv = canvas->RenderContexts(ctx, gfxPattern::FILTER_NEAREST);
|
||||
if (NS_FAILED(rv))
|
||||
return result;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = node->NodePrincipal();
|
||||
|
||||
result.mSurface = surf;
|
||||
result.mSize = gfxIntSize(w, h);
|
||||
result.mPrincipal = node->NodePrincipal();
|
||||
result.mIsWriteOnly = canvas->IsWriteOnly();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef MOZ_MEDIA
|
||||
// Maybe it's <video>?
|
||||
nsCOMPtr<nsIDOMHTMLVideoElement> ve = do_QueryInterface(aElement);
|
||||
if (node && ve) {
|
||||
nsHTMLVideoElement *video = static_cast<nsHTMLVideoElement*>(ve.get());
|
||||
|
||||
// If it doesn't have a principal, just bail
|
||||
nsCOMPtr<nsIPrincipal> principal = video->GetCurrentPrincipal();
|
||||
if (!principal)
|
||||
return result;
|
||||
|
||||
PRUint32 w, h;
|
||||
rv = video->GetVideoWidth(&w);
|
||||
rv |= video->GetVideoHeight(&h);
|
||||
if (NS_FAILED(rv))
|
||||
return result;
|
||||
|
||||
nsRefPtr<gfxASurface> surf;
|
||||
if (wantImageSurface) {
|
||||
surf = new gfxImageSurface(gfxIntSize(w, h), gfxASurface::ImageFormatARGB32);
|
||||
} else {
|
||||
surf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(w, h), gfxASurface::ImageFormatARGB32);
|
||||
}
|
||||
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
|
||||
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
video->Paint(ctx, gfxPattern::FILTER_NEAREST, gfxRect(0, 0, w, h));
|
||||
|
||||
result.mSurface = surf;
|
||||
result.mSize = gfxIntSize(w, h);
|
||||
result.mPrincipal = principal;
|
||||
result.mIsWriteOnly = PR_FALSE;
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Finally, check if it's a normal image
|
||||
nsCOMPtr<imgIContainer> imgContainer;
|
||||
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(aElement);
|
||||
|
||||
if (!imageLoader)
|
||||
return result;
|
||||
|
||||
nsCOMPtr<imgIRequest> imgRequest;
|
||||
rv = imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
|
||||
getter_AddRefs(imgRequest));
|
||||
if (NS_FAILED(rv) || !imgRequest)
|
||||
return result;
|
||||
|
||||
PRUint32 status;
|
||||
imgRequest->GetImageStatus(&status);
|
||||
if ((status & imgIRequest::STATUS_LOAD_COMPLETE) == 0)
|
||||
return result;
|
||||
|
||||
// In case of data: URIs, we want to ignore principals;
|
||||
// they should have the originating content's principal,
|
||||
// but that's broken at the moment in imgLib.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = imgRequest->GetURI(getter_AddRefs(uri));
|
||||
if (NS_FAILED(rv))
|
||||
return result;
|
||||
|
||||
PRBool isDataURI = PR_FALSE;
|
||||
rv = uri->SchemeIs("data", &isDataURI);
|
||||
if (NS_FAILED(rv))
|
||||
return result;
|
||||
|
||||
// Data URIs are always OK; set the principal
|
||||
// to null to indicate that.
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
if (!isDataURI) {
|
||||
rv = imgRequest->GetImagePrincipal(getter_AddRefs(principal));
|
||||
if (NS_FAILED(rv) || !principal)
|
||||
return result;
|
||||
}
|
||||
|
||||
rv = imgRequest->GetImage(getter_AddRefs(imgContainer));
|
||||
if (NS_FAILED(rv) || !imgContainer)
|
||||
return result;
|
||||
|
||||
nsCOMPtr<gfxIImageFrame> frame;
|
||||
rv = imgContainer->GetCurrentFrame(getter_AddRefs(frame));
|
||||
if (NS_FAILED(rv))
|
||||
return result;
|
||||
|
||||
nsCOMPtr<nsIImage> img(do_GetInterface(frame));
|
||||
if (!img)
|
||||
return result;
|
||||
|
||||
PRInt32 imgWidth, imgHeight;
|
||||
rv = frame->GetWidth(&imgWidth);
|
||||
rv |= frame->GetHeight(&imgHeight);
|
||||
if (NS_FAILED(rv))
|
||||
return result;
|
||||
|
||||
nsRefPtr<gfxPattern> gfxpattern;
|
||||
img->GetPattern(getter_AddRefs(gfxpattern));
|
||||
nsRefPtr<gfxASurface> gfxsurf = gfxpattern->GetSurface();
|
||||
|
||||
if (wantImageSurface && gfxsurf->GetType() != gfxASurface::SurfaceTypeImage) {
|
||||
forceCopy = PR_TRUE;
|
||||
}
|
||||
|
||||
if (forceCopy || !gfxsurf) {
|
||||
if (wantImageSurface) {
|
||||
gfxsurf = new gfxImageSurface (gfxIntSize(imgWidth, imgHeight), gfxASurface::ImageFormatARGB32);
|
||||
} else {
|
||||
gfxsurf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(imgWidth, imgHeight),
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
}
|
||||
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(gfxsurf);
|
||||
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->SetPattern(gfxpattern);
|
||||
ctx->Paint();
|
||||
}
|
||||
|
||||
result.mSurface = gfxsurf;
|
||||
result.mSize = gfxIntSize(imgWidth, imgHeight);
|
||||
result.mPrincipal = principal;
|
||||
result.mIsWriteOnly = PR_FALSE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsSetAttrRunnable::nsSetAttrRunnable(nsIContent* aContent, nsIAtom* aAttrName,
|
||||
const nsAString& aValue)
|
||||
: mContent(aContent),
|
||||
|
@ -1033,6 +1033,45 @@ public:
|
||||
!aFrame->GetFirstContinuation()->
|
||||
GetProperty(nsGkAtoms::IBSplitSpecialSibling);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a gfxASurface from the given DOM element, if possible.
|
||||
* This obtains the most natural surface from the element; that
|
||||
* is, the one that can be obtained with the fewest conversions.
|
||||
*
|
||||
* The flags below can modify the behaviour of this function. The
|
||||
* result is returned as a SurfaceFromElementResult struct, also
|
||||
* defined below.
|
||||
*
|
||||
* Currently, this will do:
|
||||
* - HTML Canvas elements: will return the underlying canvas surface
|
||||
* - HTML Video elements: will return the current video frame
|
||||
* - Image elements: will return the image
|
||||
*
|
||||
* The above results are modified by the below flags (copying,
|
||||
* forcing image surface, etc.).
|
||||
*/
|
||||
|
||||
enum {
|
||||
/* Always create a new surface for the result */
|
||||
SFE_WANT_NEW_SURFACE = 1 << 0,
|
||||
/* When creating a new surface, create an image surface */
|
||||
SFE_WANT_IMAGE_SURFACE = 1 << 1
|
||||
};
|
||||
|
||||
struct SurfaceFromElementResult {
|
||||
/* mSurface will contain the resulting surface, or will be NULL on error */
|
||||
nsRefPtr<gfxASurface> mSurface;
|
||||
/* The size of the surface */
|
||||
gfxIntSize mSize;
|
||||
/* The principal associated with the element whose surface was returned */
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
/* Whether the element was "write only", that is, the bits should not be exposed to content */
|
||||
PRBool mIsWriteOnly;
|
||||
};
|
||||
|
||||
static SurfaceFromElementResult SurfaceFromElement(nsIDOMElement *aElement,
|
||||
PRUint32 aSurfaceFlags = 0);
|
||||
};
|
||||
|
||||
class nsAutoDisableGetUsedXAssertions
|
||||
|
Loading…
Reference in New Issue
Block a user