From 4ff76331cab7b0e3f07fa7d2802864201dadb195 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Wed, 6 Jun 2012 09:36:38 +0200 Subject: [PATCH] Bug 629882 - Support currentColor in the 2D canvas context; r=dbaron This changes nsCSSParser::ParseColorString to fill in an nsCSSValue instead of an nscolor, and exposes nsRuleNode::ComputeColor to turn this nsCSSValue into an nscolor. Because gradients can be used with different canvas elements in different documents, these cannot pass useful values for nsRuleNode::ComputeColor's aPresContext and aStyleContext arguments. This patch also changes SetColor to deal with those parameters being null. --- content/canvas/src/DocumentRendererChild.cpp | 16 ++-- .../canvas/src/nsCanvasRenderingContext2D.cpp | 91 ++++++++++-------- .../src/nsCanvasRenderingContext2DAzure.cpp | 93 +++++++++++-------- content/canvas/test/test_canvas.html | 6 +- layout/base/nsPresContext.cpp | 18 ++-- layout/base/nsPresContext.h | 2 + layout/style/nsCSSParser.cpp | 60 +++--------- layout/style/nsCSSParser.h | 20 ++-- layout/style/nsRuleNode.cpp | 56 +++++++++-- layout/style/nsRuleNode.h | 18 ++++ 10 files changed, 213 insertions(+), 167 deletions(-) diff --git a/content/canvas/src/DocumentRendererChild.cpp b/content/canvas/src/DocumentRendererChild.cpp index c9499c00a2b..f742e0ac571 100644 --- a/content/canvas/src/DocumentRendererChild.cpp +++ b/content/canvas/src/DocumentRendererChild.cpp @@ -36,7 +36,7 @@ bool DocumentRendererChild::RenderDocument(nsIDOMWindow *window, const nsRect& documentRect, const gfxMatrix& transform, - const nsString& bgcolor, + const nsString& aBGColor, PRUint32 renderFlags, bool flushLayout, const nsIntSize& renderSize, @@ -56,13 +56,16 @@ DocumentRendererChild::RenderDocument(nsIDOMWindow *window, if (!presContext) return false; - nscolor bgColor; nsCSSParser parser; - nsresult rv = parser.ParseColorString(bgcolor, nsnull, 0, &bgColor); - if (NS_FAILED(rv)) + nsCSSValue bgColorValue; + if (!parser.ParseColorString(aBGColor, nsnull, 0, bgColorValue)) { return false; + } - nsIPresShell* presShell = presContext->PresShell(); + nscolor bgColor; + if (!nsRuleNode::ComputeColor(bgColorValue, presContext, nsnull, bgColor)) { + return false; + } // Draw directly into the output array. data.SetLength(renderSize.width * renderSize.height * 4); @@ -75,7 +78,8 @@ DocumentRendererChild::RenderDocument(nsIDOMWindow *window, nsRefPtr ctx = new gfxContext(surf); ctx->SetMatrix(transform); - presShell->RenderDocument(documentRect, renderFlags, bgColor, ctx); + presContext->PresShell()-> + RenderDocument(documentRect, renderFlags, bgColor, ctx); return true; } diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp index ec44181230a..f4e43de333a 100644 --- a/content/canvas/src/nsCanvasRenderingContext2D.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp @@ -87,6 +87,7 @@ #include "mozilla/dom/PBrowserParent.h" #include "mozilla/ipc/DocumentRendererParent.h" #include "mozilla/ipc/PDocumentRendererParent.h" +#include "mozilla/unused.h" // windows.h (included by chromium code) defines this, in its infinite wisdom #undef DrawText @@ -173,12 +174,16 @@ public: if (!FloatValidate(offset) || offset < 0.0 || offset > 1.0) return NS_ERROR_DOM_INDEX_SIZE_ERR; - nscolor color; + nsCSSValue value; nsCSSParser parser; - nsresult rv = parser.ParseColorString(nsString(colorstr), - nsnull, 0, &color); - if (NS_FAILED(rv)) + if (!parser.ParseColorString(colorstr, nsnull, 0, value)) { return NS_ERROR_DOM_SYNTAX_ERR; + } + + nscolor color; + if (!nsRuleNode::ComputeColor(value, nsnull, nsnull, color)) { + return NS_ERROR_DOM_SYNTAX_ERR; + } mPattern->AddColorStop(offset, gfxRGBA(color)); @@ -403,6 +408,9 @@ protected: nsresult SetStyleFromStringOrInterface(const nsAString& aStr, nsISupports *aInterface, Style aWhichStyle); nsresult GetStyleAsStringOrInterface(nsAString& aStr, nsISupports **aInterface, PRInt32 *aType, Style aWhichStyle); + // Returns whether a color was successfully parsed. + bool ParseColor(const nsAString& aString, nscolor* aColor); + void StyleColorToString(const nscolor& aColor, nsAString& aStr); void DirtyAllStyles(); @@ -819,6 +827,36 @@ nsCanvasRenderingContext2D::~nsCanvasRenderingContext2D() } } +bool +nsCanvasRenderingContext2D::ParseColor(const nsAString& aString, + nscolor* aColor) +{ + nsIDocument* document = HTMLCanvasElement() + ? HTMLCanvasElement()->OwnerDoc() + : nsnull; + + // Pass the CSS Loader object to the parser, to allow parser error + // reports to include the outer window ID. + nsCSSParser parser(document ? document->CSSLoader() : nsnull); + nsCSSValue value; + if (!parser.ParseColorString(aString, nsnull, 0, value)) { + return false; + } + + nsIPresShell* presShell = GetPresShell(); + nsRefPtr parentContext; + if (HTMLCanvasElement() && HTMLCanvasElement()->IsInDoc()) { + // Inherit from the canvas element. + parentContext = nsComputedDOMStyle::GetStyleContextForElement( + HTMLCanvasElement(), nsnull, presShell); + } + + unused << nsRuleNode::ComputeColor( + value, presShell ? presShell->GetPresContext() : nsnull, parentContext, + *aColor); + return true; +} + nsresult nsCanvasRenderingContext2D::Reset() { @@ -844,19 +882,9 @@ nsCanvasRenderingContext2D::SetStyleFromStringOrInterface(const nsAString& aStr, nsISupports *aInterface, Style aWhichStyle) { - nsresult rv; - nscolor color; - if (!aStr.IsVoid()) { - nsIDocument* document = mCanvasElement ? - HTMLCanvasElement()->OwnerDoc() : nsnull; - - // Pass the CSS Loader object to the parser, to allow parser error - // reports to include the outer window ID. - nsCSSParser parser(document ? document->CSSLoader() : nsnull); - rv = parser.ParseColorString(aStr, nsnull, 0, &color); - if (NS_FAILED(rv)) { - // Error reporting happens inside the CSS parser + nscolor color; + if (!ParseColor(aStr, &color)) { return NS_OK; } @@ -1896,18 +1924,10 @@ nsCanvasRenderingContext2D::GetShadowBlur(float *blur) } NS_IMETHODIMP -nsCanvasRenderingContext2D::SetShadowColor(const nsAString& colorstr) +nsCanvasRenderingContext2D::SetShadowColor(const nsAString& aColor) { - nsIDocument* document = mCanvasElement ? - HTMLCanvasElement()->OwnerDoc() : nsnull; - - // Pass the CSS Loader object to the parser, to allow parser error reports - // to include the outer window ID. - nsCSSParser parser(document ? document->CSSLoader() : nsnull); nscolor color; - nsresult rv = parser.ParseColorString(colorstr, nsnull, 0, &color); - if (NS_FAILED(rv)) { - // Error reporting happens inside the CSS parser + if (!ParseColor(aColor, &color)) { return NS_OK; } @@ -3651,19 +3671,9 @@ nsCanvasRenderingContext2D::DrawWindow(nsIDOMWindow* aWindow, float aX, float aY return NS_ERROR_FAILURE; nscolor bgColor; - - nsIDocument* elementDoc = mCanvasElement ? - HTMLCanvasElement()->OwnerDoc() : nsnull; - - // Pass the CSS Loader object to the parser, to allow parser error reports - // to include the outer window ID. - nsCSSParser parser(elementDoc ? elementDoc->CSSLoader() : nsnull); - nsresult rv = parser.ParseColorString(PromiseFlatString(aBGColor), - nsnull, 0, &bgColor); - NS_ENSURE_SUCCESS(rv, rv); - - nsIPresShell* presShell = presContext->PresShell(); - NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE); + if (!ParseColor(aBGColor, &bgColor)) { + return NS_ERROR_FAILURE; + } nsRect r(nsPresContext::CSSPixelsToAppUnits(aX), nsPresContext::CSSPixelsToAppUnits(aY), @@ -3685,7 +3695,8 @@ nsCanvasRenderingContext2D::DrawWindow(nsIDOMWindow* aWindow, float aX, float aY renderDocFlags |= nsIPresShell::RENDER_ASYNC_DECODE_IMAGES; } - rv = presShell->RenderDocument(r, renderDocFlags, bgColor, mThebes); + nsresult rv = presContext->PresShell()-> + RenderDocument(r, renderDocFlags, bgColor, mThebes); // get rid of the pattern surface ref, just in case mThebes->SetColor(gfxRGBA(1,1,1,1)); diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp index 0d10f9c6a33..d8960d2a025 100644 --- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp @@ -88,6 +88,7 @@ #include "mozilla/ipc/DocumentRendererParent.h" #include "mozilla/ipc/PDocumentRendererParent.h" #include "mozilla/Preferences.h" +#include "mozilla/unused.h" #ifdef XP_WIN #include "gfxWindowsPlatform.h" @@ -172,11 +173,14 @@ public: return NS_ERROR_DOM_INDEX_SIZE_ERR; } - nscolor color; + nsCSSValue value; nsCSSParser parser; - nsresult rv = parser.ParseColorString(nsString(colorstr), - nsnull, 0, &color); - if (NS_FAILED(rv)) { + if (!parser.ParseColorString(colorstr, nsnull, 0, value)) { + return NS_ERROR_DOM_SYNTAX_ERR; + } + + nscolor color; + if (!nsRuleNode::ComputeColor(value, nsnull, nsnull, color)) { return NS_ERROR_DOM_SYNTAX_ERR; } @@ -443,6 +447,9 @@ protected: nsresult SetStyleFromStringOrInterface(const nsAString& aStr, nsISupports *aInterface, Style aWhichStyle); nsresult GetStyleAsStringOrInterface(nsAString& aStr, nsISupports **aInterface, PRInt32 *aType, Style aWhichStyle); + // Returns whether a color was successfully parsed. + bool ParseColor(const nsAString& aString, nscolor* aColor); + void StyleColorToString(const nscolor& aColor, nsAString& aStr); /** @@ -1009,6 +1016,36 @@ nsCanvasRenderingContext2DAzure::~nsCanvasRenderingContext2DAzure() } } +bool +nsCanvasRenderingContext2DAzure::ParseColor(const nsAString& aString, + nscolor* aColor) +{ + nsIDocument* document = HTMLCanvasElement() + ? HTMLCanvasElement()->OwnerDoc() + : nsnull; + + // Pass the CSS Loader object to the parser, to allow parser error + // reports to include the outer window ID. + nsCSSParser parser(document ? document->CSSLoader() : nsnull); + nsCSSValue value; + if (!parser.ParseColorString(aString, nsnull, 0, value)) { + return false; + } + + nsIPresShell* presShell = GetPresShell(); + nsRefPtr parentContext; + if (HTMLCanvasElement() && HTMLCanvasElement()->IsInDoc()) { + // Inherit from the canvas element. + parentContext = nsComputedDOMStyle::GetStyleContextForElement( + HTMLCanvasElement(), nsnull, presShell); + } + + unused << nsRuleNode::ComputeColor( + value, presShell ? presShell->GetPresContext() : nsnull, parentContext, + *aColor); + return true; +} + nsresult nsCanvasRenderingContext2DAzure::Reset() { @@ -1039,19 +1076,9 @@ nsCanvasRenderingContext2DAzure::SetStyleFromStringOrInterface(const nsAString& nsISupports *aInterface, Style aWhichStyle) { - nsresult rv; - nscolor color; - if (!aStr.IsVoid()) { - nsIDocument* document = mCanvasElement ? - HTMLCanvasElement()->OwnerDoc() : nsnull; - - // Pass the CSS Loader object to the parser, to allow parser error - // reports to include the outer window ID. - nsCSSParser parser(document ? document->CSSLoader() : nsnull); - rv = parser.ParseColorString(aStr, nsnull, 0, &color); - if (NS_FAILED(rv)) { - // Error reporting happens inside the CSS parser + nscolor color; + if (!ParseColor(aStr, &color)) { return NS_OK; } @@ -2014,20 +2041,13 @@ nsCanvasRenderingContext2DAzure::GetShadowBlur(float *blur) } NS_IMETHODIMP -nsCanvasRenderingContext2DAzure::SetShadowColor(const nsAString& colorstr) +nsCanvasRenderingContext2DAzure::SetShadowColor(const nsAString& aColor) { - nsIDocument* document = mCanvasElement ? - HTMLCanvasElement()->OwnerDoc() : nsnull; - - // Pass the CSS Loader object to the parser, to allow parser error reports - // to include the outer window ID. - nsCSSParser parser(document ? document->CSSLoader() : nsnull); nscolor color; - nsresult rv = parser.ParseColorString(colorstr, nsnull, 0, &color); - if (NS_FAILED(rv)) { - // Error reporting happens inside the CSS parser + if (!ParseColor(aColor, &color)) { return NS_OK; } + CurrentState().shadowColor = color; return NS_OK; @@ -3788,7 +3808,7 @@ nsCanvasRenderingContext2DAzure::DrawWindow(nsIDOMWindow* aWindow, float aX, flo // protect against too-large surfaces that will cause allocation // or overflow issues if (!gfxASurface::CheckSurfaceSize(gfxIntSize(PRInt32(aW), PRInt32(aH)), - 0xffff)) + 0xffff)) return NS_ERROR_FAILURE; nsRefPtr drawSurf; @@ -3828,19 +3848,9 @@ nsCanvasRenderingContext2DAzure::DrawWindow(nsIDOMWindow* aWindow, float aX, flo return NS_ERROR_FAILURE; nscolor bgColor; - - nsIDocument* elementDoc = mCanvasElement ? - HTMLCanvasElement()->OwnerDoc() : nsnull; - - // Pass the CSS Loader object to the parser, to allow parser error reports - // to include the outer window ID. - nsCSSParser parser(elementDoc ? elementDoc->CSSLoader() : nsnull); - nsresult rv = parser.ParseColorString(PromiseFlatString(aBGColor), - nsnull, 0, &bgColor); - NS_ENSURE_SUCCESS(rv, rv); - - nsIPresShell* presShell = presContext->PresShell(); - NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE); + if (!ParseColor(aBGColor, &bgColor)) { + return NS_ERROR_FAILURE; + } nsRect r(nsPresContext::CSSPixelsToAppUnits(aX), nsPresContext::CSSPixelsToAppUnits(aY), @@ -3862,7 +3872,8 @@ nsCanvasRenderingContext2DAzure::DrawWindow(nsIDOMWindow* aWindow, float aX, flo renderDocFlags |= nsIPresShell::RENDER_ASYNC_DECODE_IMAGES; } - rv = presShell->RenderDocument(r, renderDocFlags, bgColor, thebes); + unused << presContext->PresShell()-> + RenderDocument(r, renderDocFlags, bgColor, thebes); // note that aX and aY are coordinates in the document that // we're drawing; aX and aY are drawn to 0,0 in current user diff --git a/content/canvas/test/test_canvas.html b/content/canvas/test/test_canvas.html index 94bd544160c..61212d29324 100644 --- a/content/canvas/test/test_canvas.html +++ b/content/canvas/test/test_canvas.html @@ -4120,7 +4120,7 @@ canvas.setAttribute('style', 'color: #0f0'); ctx.fillStyle = '#f00'; ctx.fillStyle = 'currentColor'; ctx.fillRect(0, 0, 100, 50); -todo_isPixel(ctx, 50,25, 0,255,0,255, 0); +isPixel(ctx, 50,25, 0,255,0,255, 0); } @@ -4145,7 +4145,7 @@ ctx.fillStyle = '#f00'; ctx.fillStyle = 'currentColor'; canvas.setAttribute('style', 'color: #f00'); ctx.fillRect(0, 0, 100, 50); -todo_isPixel(ctx, 50,25, 0,255,0,255, 0); +isPixel(ctx, 50,25, 0,255,0,255, 0); } @@ -4181,7 +4181,7 @@ ctx.drawImage(canvas2, 0, 0); document.body.parentNode.removeAttribute('style'); document.body.removeAttribute('style'); -todo_isPixel(ctx, 50,25, 0,0,0,255, 0); +isPixel(ctx, 50,25, 0,0,0,255, 0); } diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 7b7b1b4ebb5..8784a388b7d 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -109,18 +109,20 @@ private: } // anonymous namespace -static nscolor -MakeColorPref(const nsString& aColor) +nscolor +nsPresContext::MakeColorPref(const nsString& aColor) { - nscolor color; nsCSSParser parser; - nsresult rv = - parser.ParseColorString(aColor, nsnull, 0, &color); - if (NS_FAILED(rv)) { + nsCSSValue value; + if (!parser.ParseColorString(aColor, nsnull, 0, value)) { // Any better choices? - color = NS_RGB(0, 0, 0); + return NS_RGB(0, 0, 0); } - return color; + + nscolor color; + return nsRuleNode::ComputeColor(value, this, nsnull, color) + ? color + : NS_RGB(0, 0, 0); } int diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index 0a4a9d88d45..572f6f2aa39 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -1247,6 +1247,8 @@ protected: eDefaultFont_COUNT }; + nscolor MakeColorPref(const nsString& aColor); + #ifdef DEBUG private: friend struct nsAutoLayoutPhase; diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index ebcd5e6f3d6..a406343678d 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -209,10 +209,10 @@ public: nsMediaList* aMediaList, bool aHTMLMode); - nsresult ParseColorString(const nsSubstring& aBuffer, - nsIURI* aURL, // for error reporting - PRUint32 aLineNumber, // for error reporting - nscolor* aColor); + bool ParseColorString(const nsSubstring& aBuffer, + nsIURI* aURL, // for error reporting + PRUint32 aLineNumber, // for error reporting + nsCSSValue& aValue); nsresult ParseSelectorString(const nsSubstring& aSelectorString, nsIURI* aURL, // for error reporting @@ -1167,58 +1167,20 @@ CSSParserImpl::ParseMediaList(const nsSubstring& aBuffer, return NS_OK; } -nsresult +bool CSSParserImpl::ParseColorString(const nsSubstring& aBuffer, nsIURI* aURI, // for error reporting PRUint32 aLineNumber, // for error reporting - nscolor* aColor) + nsCSSValue& aValue) { AssertInitialState(); InitScanner(aBuffer, aURI, aLineNumber, aURI, nsnull); - nsCSSValue value; // Parse a color, and check that there's nothing else after it. - bool colorParsed = ParseColor(value) && !GetToken(true); + bool colorParsed = ParseColor(aValue) && !GetToken(true); OUTPUT_ERROR(); ReleaseScanner(); - - if (!colorParsed) { - return NS_ERROR_FAILURE; - } - - switch (value.GetUnit()) { - case eCSSUnit_Color: - *aColor = value.GetColorValue(); - return NS_OK; - - case eCSSUnit_Ident: { - nsDependentString id(value.GetStringBufferValue()); - if (!NS_ColorNameToRGB(id, aColor)) { - return NS_ERROR_FAILURE; - } - return NS_OK; - } - - case eCSSUnit_EnumColor: { - PRInt32 val = value.GetIntValue(); - if (val < 0) { - // XXX - negative numbers are NS_COLOR_CURRENTCOLOR, - // NS_COLOR_MOZ_HYPERLINKTEXT, etc. which we don't handle. - // Should remove this limitation at some point. - return NS_ERROR_FAILURE; - } - nscolor rgba; - nsresult rv = LookAndFeel::GetColor(LookAndFeel::ColorID(val), &rgba); - if (NS_FAILED(rv)) { - return rv; - } - *aColor = rgba; - return NS_OK; - } - - default: - return NS_ERROR_FAILURE; - } + return colorParsed; } nsresult @@ -9526,14 +9488,14 @@ nsCSSParser::ParseMediaList(const nsSubstring& aBuffer, ParseMediaList(aBuffer, aURI, aLineNumber, aMediaList, aHTMLMode); } -nsresult +bool nsCSSParser::ParseColorString(const nsSubstring& aBuffer, nsIURI* aURI, PRUint32 aLineNumber, - nscolor* aColor) + nsCSSValue& aValue) { return static_cast(mImpl)-> - ParseColorString(aBuffer, aURI, aLineNumber, aColor); + ParseColorString(aBuffer, aURI, aLineNumber, aValue); } nsresult diff --git a/layout/style/nsCSSParser.h b/layout/style/nsCSSParser.h index e10242aad76..4732366d1e6 100644 --- a/layout/style/nsCSSParser.h +++ b/layout/style/nsCSSParser.h @@ -23,6 +23,7 @@ class nsIURI; struct nsCSSSelectorList; class nsMediaList; class nsCSSKeyframeRule; +class nsCSSValue; namespace mozilla { namespace css { @@ -136,18 +137,15 @@ public: bool aHTMLMode); /** - * Parse aBuffer into a nscolor |aColor|. The alpha component of the - * resulting aColor may vary due to rgba()/hsla(). Will return - * NS_ERROR_FAILURE if aBuffer is not a valid CSS color specification. - * - * Will also currently return NS_ERROR_FAILURE if it is not - * self-contained (i.e. doesn't reference any external style state, - * such as "initial" or "inherit"). + * Parse aBuffer into a nsCSSValue |aValue|. Will return false + * if aBuffer is not a valid CSS color specification. + * One can use nsRuleNode::ComputeColor to compute an nscolor from + * the returned nsCSSValue. */ - nsresult ParseColorString(const nsSubstring& aBuffer, - nsIURI* aURL, - PRUint32 aLineNumber, - nscolor* aColor); + bool ParseColorString(const nsSubstring& aBuffer, + nsIURI* aURL, + PRUint32 aLineNumber, + nsCSSValue& aValue); /** * Parse aBuffer into a selector list. On success, caller must diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 16dce7d8354..7103da5aff5 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -13,7 +13,6 @@ #include "nscore.h" #include "nsIServiceManager.h" #include "nsIWidget.h" -#include "mozilla/LookAndFeel.h" #include "nsIPresShell.h" #include "nsFontMetrics.h" #include "gfxFont.h" @@ -36,9 +35,12 @@ #include "nsCSSProps.h" #include "nsTArray.h" #include "nsContentUtils.h" -#include "mozilla/dom/Element.h" #include "CSSCalc.h" #include "nsPrintfCString.h" + +#include "mozilla/Assertions.h" +#include "mozilla/dom/Element.h" +#include "mozilla/LookAndFeel.h" #include "mozilla/Util.h" #if defined(_MSC_VER) || defined(__MINGW32__) @@ -733,33 +735,52 @@ static bool SetColor(const nsCSSValue& aValue, const nscolor aParentColor, } } else { + aResult = NS_RGB(0, 0, 0); + result = false; switch (intValue) { case NS_COLOR_MOZ_HYPERLINKTEXT: - aResult = aPresContext->DefaultLinkColor(); + if (aPresContext) { + aResult = aPresContext->DefaultLinkColor(); + result = true; + } break; case NS_COLOR_MOZ_VISITEDHYPERLINKTEXT: - aResult = aPresContext->DefaultVisitedLinkColor(); + if (aPresContext) { + aResult = aPresContext->DefaultVisitedLinkColor(); + result = true; + } break; case NS_COLOR_MOZ_ACTIVEHYPERLINKTEXT: - aResult = aPresContext->DefaultActiveLinkColor(); + if (aPresContext) { + aResult = aPresContext->DefaultActiveLinkColor(); + result = true; + } break; case NS_COLOR_CURRENTCOLOR: // The data computed from this can't be shared in the rule tree // because they could be used on a node with a different color aCanStoreInRuleTree = false; - aResult = aContext->GetStyleColor()->mColor; + if (aContext) { + aResult = aContext->GetStyleColor()->mColor; + result = true; + } break; case NS_COLOR_MOZ_DEFAULT_COLOR: - aResult = aPresContext->DefaultColor(); + if (aPresContext) { + aResult = aPresContext->DefaultColor(); + result = true; + } break; case NS_COLOR_MOZ_DEFAULT_BACKGROUND_COLOR: - aResult = aPresContext->DefaultBackgroundColor(); + if (aPresContext) { + aResult = aPresContext->DefaultBackgroundColor(); + result = true; + } break; default: NS_NOTREACHED("Should never have an unknown negative colorID."); break; } - result = true; } } else if (eCSSUnit_Inherit == unit) { @@ -7714,3 +7735,20 @@ nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext* aStyleContext, return false; } + +/* static */ +bool +nsRuleNode::ComputeColor(const nsCSSValue& aValue, nsPresContext* aPresContext, + nsStyleContext* aStyleContext, nscolor& aResult) +{ + MOZ_ASSERT(aValue.GetUnit() != eCSSUnit_Inherit, + "aValue shouldn't have eCSSUnit_Inherit"); + MOZ_ASSERT(aValue.GetUnit() != eCSSUnit_Initial, + "aValue shouldn't have eCSSUnit_Initial"); + + bool canStoreInRuleTree; + bool ok = SetColor(aValue, NS_RGB(0, 0, 0), aPresContext, aStyleContext, + aResult, canStoreInRuleTree); + MOZ_ASSERT(ok || !(aPresContext && aStyleContext)); + return ok; +} diff --git a/layout/style/nsRuleNode.h b/layout/style/nsRuleNode.h index 8ad9d97b3b5..c10bc3f672b 100644 --- a/layout/style/nsRuleNode.h +++ b/layout/style/nsRuleNode.h @@ -734,6 +734,24 @@ public: static nscoord FindNextLargerFontSize(nscoord aFontSize, PRInt32 aBasePointSize, nsPresContext* aPresContext, nsFontSizeType aFontSizeType = eFontSize_HTML); + + /** + * @param aValue The color value, returned from nsCSSParser::ParseColorString + * @param aPresContext Presentation context whose preferences are used + * for certain enumerated colors + * @param aStyleContext Style context whose color is used for 'currentColor' + * + * @note aPresContext and aStyleContext may be null, but in that case, fully + * opaque black will be returned for the values that rely on these + * objects to compute the color. (For example, -moz-hyperlinktext.) + * + * @return false if we fail to extract a color; this will not happen if both + * aPresContext and aStyleContext are non-null + */ + static bool ComputeColor(const nsCSSValue& aValue, + nsPresContext* aPresContext, + nsStyleContext* aStyleContext, + nscolor& aResult); }; #endif