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.
This commit is contained in:
Ms2ger 2012-06-06 09:36:38 +02:00
parent 30a9860b7d
commit 19f060907a
10 changed files with 213 additions and 167 deletions

View File

@ -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<gfxContext> ctx = new gfxContext(surf);
ctx->SetMatrix(transform);
presShell->RenderDocument(documentRect, renderFlags, bgColor, ctx);
presContext->PresShell()->
RenderDocument(documentRect, renderFlags, bgColor, ctx);
return true;
}

View File

@ -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<nsStyleContext> 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));

View File

@ -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<nsStyleContext> 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<gfxASurface> 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

View File

@ -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);
}

View File

@ -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

View File

@ -1247,6 +1247,8 @@ protected:
eDefaultFont_COUNT
};
nscolor MakeColorPref(const nsString& aColor);
#ifdef DEBUG
private:
friend struct nsAutoLayoutPhase;

View File

@ -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<CSSParserImpl*>(mImpl)->
ParseColorString(aBuffer, aURI, aLineNumber, aColor);
ParseColorString(aBuffer, aURI, aLineNumber, aValue);
}
nsresult

View File

@ -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

View File

@ -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;
}

View File

@ -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