mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-02 01:48:05 +00:00
Bug 502715 - Enable the canvas 2d context to function without an actual canvas element r=vladimir
This commit is contained in:
parent
5fdabd8af3
commit
1c601ecdaa
@ -62,6 +62,8 @@ public:
|
||||
// whenever the size of the element changes.
|
||||
NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height) = 0;
|
||||
|
||||
NS_IMETHOD InitializeWithSurface(nsIDocShell *docShell, gfxASurface *surface, PRInt32 width, PRInt32 height) = 0;
|
||||
|
||||
// Render the canvas at the origin of the given gfxContext
|
||||
NS_IMETHOD Render(gfxContext *ctx, gfxPattern::GraphicsFilter aFilter) = 0;
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Rob Arnold <tellrob@gmail.com>
|
||||
* Eric Butler <zantifon@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
@ -316,6 +317,7 @@ public:
|
||||
// nsICanvasRenderingContextInternal
|
||||
NS_IMETHOD SetCanvasElement(nsICanvasElement* aParentCanvas);
|
||||
NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height);
|
||||
NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height);
|
||||
NS_IMETHOD Render(gfxContext *ctx, gfxPattern::GraphicsFilter aFilter);
|
||||
NS_IMETHOD GetInputStream(const char* aMimeType,
|
||||
const PRUnichar* aEncoderOptions,
|
||||
@ -361,6 +363,9 @@ protected:
|
||||
// so these are not nsCOMPtrs
|
||||
nsICanvasElement* mCanvasElement;
|
||||
|
||||
// If mCanvasElement is not provided, then a docshell is
|
||||
nsCOMPtr<nsIDocShell> mDocShell;
|
||||
|
||||
// our CSS parser, for colors and whatnot
|
||||
nsCOMPtr<nsICSSParser> mCSSParser;
|
||||
|
||||
@ -479,6 +484,20 @@ protected:
|
||||
*/
|
||||
nsresult DrawRect(const gfxRect& rect, Style style);
|
||||
|
||||
/**
|
||||
* Gets the pres shell from either the canvas element or the doc shell
|
||||
*/
|
||||
nsIPresShell *GetPresShell() {
|
||||
nsIPresShell *presShell = nsnull;
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mCanvasElement);
|
||||
if (content) {
|
||||
presShell = content->GetOwnerDoc()->GetPrimaryShell();
|
||||
} else if (mDocShell) {
|
||||
mDocShell->GetPresShell(&presShell);
|
||||
}
|
||||
return presShell;
|
||||
}
|
||||
|
||||
// text
|
||||
enum TextAlign {
|
||||
TEXT_ALIGN_START,
|
||||
@ -613,17 +632,14 @@ protected:
|
||||
PRUint32 devPixel = 60;
|
||||
PRUint32 cssPixel = 60;
|
||||
|
||||
nsCOMPtr<nsINode> elem = do_QueryInterface(mCanvasElement);
|
||||
if (elem) {
|
||||
nsIDocument *doc = elem->GetOwnerDoc();
|
||||
if (!doc) goto FINISH;
|
||||
nsIPresShell *ps = doc->GetPrimaryShell();
|
||||
if (!ps) goto FINISH;
|
||||
nsPresContext *pc = ps->GetPresContext();
|
||||
if (!pc) goto FINISH;
|
||||
devPixel = pc->AppUnitsPerDevPixel();
|
||||
cssPixel = pc->AppUnitsPerCSSPixel();
|
||||
}
|
||||
nsIPresShell *ps = GetPresShell();
|
||||
nsPresContext *pc;
|
||||
|
||||
if (!ps) goto FINISH;
|
||||
pc = ps->GetPresContext();
|
||||
if (!pc) goto FINISH;
|
||||
devPixel = pc->AppUnitsPerDevPixel();
|
||||
cssPixel = pc->AppUnitsPerCSSPixel();
|
||||
|
||||
FINISH:
|
||||
if (perDevPixel)
|
||||
@ -795,12 +811,10 @@ nsCanvasRenderingContext2D::ApplyStyle(Style aWhichStyle,
|
||||
|
||||
nsCanvasPattern* pattern = CurrentState().patternStyles[aWhichStyle];
|
||||
if (pattern) {
|
||||
if (!mCanvasElement)
|
||||
return;
|
||||
|
||||
CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement,
|
||||
pattern->Principal(),
|
||||
pattern->GetForceWriteOnly());
|
||||
if (mCanvasElement)
|
||||
CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement,
|
||||
pattern->Principal(),
|
||||
pattern->GetForceWriteOnly());
|
||||
|
||||
gfxPattern* gpat = pattern->GetPattern();
|
||||
|
||||
@ -859,8 +873,7 @@ nsCanvasRenderingContext2D::SetDimensions(PRInt32 width, PRInt32 height)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
nsRefPtr<gfxASurface> surface;
|
||||
|
||||
// Check that the dimensions are sane
|
||||
if (gfxASurface::CheckSurfaceSize(gfxIntSize(width, height), 0xffff)) {
|
||||
@ -868,13 +881,28 @@ nsCanvasRenderingContext2D::SetDimensions(PRInt32 width, PRInt32 height)
|
||||
if (mOpaque)
|
||||
format = gfxASurface::ImageFormatRGB24;
|
||||
|
||||
mSurface = gfxPlatform::GetPlatform()->CreateOffscreenSurface
|
||||
surface = gfxPlatform::GetPlatform()->CreateOffscreenSurface
|
||||
(gfxIntSize(width, height), format);
|
||||
|
||||
if (mSurface->CairoStatus() == 0) {
|
||||
mThebes = new gfxContext(mSurface);
|
||||
if (surface->CairoStatus() != 0) {
|
||||
surface = NULL;
|
||||
}
|
||||
}
|
||||
return InitializeWithSurface(NULL, surface, width, height);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::InitializeWithSurface(nsIDocShell *docShell, gfxASurface *surface, PRInt32 width, PRInt32 height) {
|
||||
Destroy();
|
||||
|
||||
NS_ASSERTION(!docShell ^ !mCanvasElement, "Cannot set both docshell and canvas element");
|
||||
mDocShell = docShell;
|
||||
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
||||
mSurface = surface;
|
||||
mThebes = new gfxContext(mSurface);
|
||||
|
||||
/* Create dummy surfaces here */
|
||||
if (mSurface == nsnull || mSurface->CairoStatus() != 0 ||
|
||||
@ -886,6 +914,11 @@ nsCanvasRenderingContext2D::SetDimensions(PRInt32 width, PRInt32 height)
|
||||
mValid = PR_TRUE;
|
||||
}
|
||||
|
||||
// set up our css parser, if necessary
|
||||
if (!mCSSParser) {
|
||||
mCSSParser = do_CreateInstance("@mozilla.org/content/css-parser;1");
|
||||
}
|
||||
|
||||
// set up the initial canvas defaults
|
||||
mStyleStack.Clear();
|
||||
mSaveCount = 0;
|
||||
@ -1032,11 +1065,6 @@ nsCanvasRenderingContext2D::SetCanvasElement(nsICanvasElement* aCanvasElement)
|
||||
// don't hold a ref to this!
|
||||
mCanvasElement = aCanvasElement;
|
||||
|
||||
// set up our css parser, if necessary
|
||||
if (!mCSSParser) {
|
||||
mCSSParser = do_CreateInstance("@mozilla.org/content/css-parser;1");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1870,16 +1898,15 @@ nsCanvasRenderingContext2D::SetFont(const nsAString& font)
|
||||
*/
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mCanvasElement);
|
||||
if (!content) {
|
||||
NS_WARNING("Canvas element must be an nsIContent and non-null");
|
||||
if (!content && !mDocShell) {
|
||||
NS_WARNING("Canvas element must be an nsIContent and non-null or a docshell must be provided");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsIDocument* document = content->GetOwnerDoc();
|
||||
|
||||
nsIPresShell* presShell = document->GetPrimaryShell();
|
||||
nsIPresShell* presShell = GetPresShell();
|
||||
if (!presShell)
|
||||
return NS_ERROR_FAILURE;
|
||||
return NS_ERROR_FAILURE;
|
||||
nsIDocument* document = presShell->GetDocument();
|
||||
|
||||
nsCString langGroup;
|
||||
presShell->GetPresContext()->GetLangGroup()->ToUTF8String(langGroup);
|
||||
@ -1887,7 +1914,7 @@ nsCanvasRenderingContext2D::SetFont(const nsAString& font)
|
||||
nsCOMArray<nsIStyleRule> rules;
|
||||
|
||||
nsCOMPtr<nsICSSStyleRule> rule;
|
||||
rv = CreateFontStyleRule(font, mCSSParser.get(), content.get(), getter_AddRefs(rule));
|
||||
rv = CreateFontStyleRule(font, mCSSParser.get(), document, getter_AddRefs(rule));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
@ -1899,7 +1926,7 @@ nsCanvasRenderingContext2D::SetFont(const nsAString& font)
|
||||
// values (2em, bolder, etc.)
|
||||
nsRefPtr<nsStyleContext> parentContext;
|
||||
|
||||
if (content->IsInDoc()) {
|
||||
if (content && content->IsInDoc()) {
|
||||
// inherit from the canvas element
|
||||
parentContext = nsInspectorCSSUtils::GetStyleContextForContent(
|
||||
content,
|
||||
@ -1910,7 +1937,7 @@ nsCanvasRenderingContext2D::SetFont(const nsAString& font)
|
||||
nsCOMPtr<nsICSSStyleRule> parentRule;
|
||||
rv = CreateFontStyleRule(NS_LITERAL_STRING("10px sans-serif"),
|
||||
mCSSParser.get(),
|
||||
content.get(),
|
||||
document,
|
||||
getter_AddRefs(parentRule));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
@ -2219,17 +2246,17 @@ nsCanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText,
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mCanvasElement);
|
||||
if (!content) {
|
||||
NS_WARNING("Canvas element must be an nsIContent and non-null");
|
||||
if (!content && !mDocShell) {
|
||||
NS_WARNING("Canvas element must be an nsIContent and non-null or a docshell must be provided");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsIDocument* document = content->GetOwnerDoc();
|
||||
|
||||
nsIPresShell* presShell = document->GetPrimaryShell();
|
||||
nsIPresShell* presShell = GetPresShell();
|
||||
if (!presShell)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIDocument* document = presShell->GetDocument();
|
||||
|
||||
nsBidiPresUtils* bidiUtils = presShell->GetPresContext()->GetBidiUtils();
|
||||
if (!bidiUtils)
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -2241,7 +2268,7 @@ nsCanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText,
|
||||
// for now, default to ltr if not in doc
|
||||
PRBool isRTL = PR_FALSE;
|
||||
|
||||
if (content->IsInDoc()) {
|
||||
if (content && content->IsInDoc()) {
|
||||
// try to find the closest context
|
||||
nsRefPtr<nsStyleContext> canvasStyle =
|
||||
nsInspectorCSSUtils::GetStyleContextForContent(content,
|
||||
@ -2251,6 +2278,8 @@ nsCanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText,
|
||||
return NS_ERROR_FAILURE;
|
||||
isRTL = canvasStyle->GetStyleVisibility()->mDirection ==
|
||||
NS_STYLE_DIRECTION_RTL;
|
||||
} else {
|
||||
isRTL = GET_BIDI_OPTION_DIRECTION(document->GetBidiOptions()) == IBMBIDI_TEXTDIRECTION_RTL;
|
||||
}
|
||||
|
||||
// don't need to take care of these with stroke since Stroke() does that
|
||||
@ -2896,11 +2925,6 @@ nsCanvasRenderingContext2D::DrawImage()
|
||||
nsresult rv;
|
||||
gfxRect dirty;
|
||||
|
||||
// we can't do a security check without a canvas element, so
|
||||
// just skip this entirely
|
||||
if (!mCanvasElement)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsAXPCNativeCallContext *ncc = nsnull;
|
||||
rv = nsContentUtils::XPConnect()->
|
||||
GetCurrentNativeCallContext(&ncc);
|
||||
@ -2959,7 +2983,8 @@ nsCanvasRenderingContext2D::DrawImage()
|
||||
gfxIntSize imgSize = res.mSize;
|
||||
PRBool forceWriteOnly = res.mIsWriteOnly;
|
||||
|
||||
CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement, principal, forceWriteOnly);
|
||||
if (mCanvasElement)
|
||||
CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement, principal, forceWriteOnly);
|
||||
|
||||
gfxContextPathAutoSaveRestore pathSR(mThebes, PR_FALSE);
|
||||
|
||||
@ -3369,10 +3394,10 @@ nsCanvasRenderingContext2D::DrawWindow(nsIDOMWindow* aWindow, float aX, float aY
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::GetImageData()
|
||||
{
|
||||
if (!mValid || !mCanvasElement)
|
||||
if (!mValid)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mCanvasElement->IsWriteOnly() && !nsContentUtils::IsCallerTrustedForRead()) {
|
||||
if (mCanvasElement && mCanvasElement->IsWriteOnly() && !nsContentUtils::IsCallerTrustedForRead()) {
|
||||
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
@ -3727,7 +3752,7 @@ nsCanvasRenderingContext2D::GetThebesSurface(gfxASurface **surface)
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::CreateImageData()
|
||||
{
|
||||
if (!mValid || !mCanvasElement)
|
||||
if (!mValid)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsAXPCNativeCallContext *ncc = nsnull;
|
||||
|
Loading…
Reference in New Issue
Block a user