Use the appropriate color based on visitedness for the color or fallback color parts of 'fill' and 'stroke'. (Bug 147777) r=jwatt

This commit is contained in:
L. David Baron 2010-04-02 18:58:26 -07:00
parent e4ae9159cc
commit b33a804541
3 changed files with 55 additions and 19 deletions

View file

@ -730,13 +730,20 @@ nsStyleContext::GetVisitedDependentColor(nsCSSProperty aProperty)
colors[1] = ExtractColor(aProperty, visitedStyle); colors[1] = ExtractColor(aProperty, visitedStyle);
return nsStyleContext::CombineVisitedColors(colors,
this->RelevantLinkVisited());
}
/* static */ nscolor
nsStyleContext::CombineVisitedColors(nscolor *aColors, PRBool aLinkIsVisited)
{
// NOTE: We want this code to have as little timing dependence as // NOTE: We want this code to have as little timing dependence as
// possible on whether this->RelevantLinkVisited() is true. // possible on whether this->RelevantLinkVisited() is true.
const ColorIndexSet &set = const ColorIndexSet &set =
gVisitedIndices[this->RelevantLinkVisited() ? 1 : 0]; gVisitedIndices[aLinkIsVisited ? 1 : 0];
nscolor colorColor = colors[set.colorIndex]; nscolor colorColor = aColors[set.colorIndex];
nscolor alphaColor = colors[set.alphaIndex]; nscolor alphaColor = aColors[set.alphaIndex];
return NS_RGBA(NS_GET_R(colorColor), NS_GET_G(colorColor), return NS_RGBA(NS_GET_R(colorColor), NS_GET_G(colorColor),
NS_GET_B(colorColor), NS_GET_A(alphaColor)); NS_GET_B(colorColor), NS_GET_A(alphaColor));
} }

View file

@ -261,6 +261,16 @@ public:
*/ */
NS_HIDDEN_(nscolor) GetVisitedDependentColor(nsCSSProperty aProperty); NS_HIDDEN_(nscolor) GetVisitedDependentColor(nsCSSProperty aProperty);
/**
* aColors should be a two element array of nscolor in which the first
* color is the unvisited color and the second is the visited color.
*
* Combine the R, G, and B components of whichever of aColors should
* be used based on aLinkIsVisited with the A component of aColors[0].
*/
static nscolor CombineVisitedColors(nscolor *aColors,
PRBool aLinkIsVisited);
#ifdef DEBUG #ifdef DEBUG
NS_HIDDEN_(void) List(FILE* out, PRInt32 aIndent); NS_HIDDEN_(void) List(FILE* out, PRInt32 aIndent);
#endif #endif

View file

@ -191,6 +191,37 @@ SetupCairoColor(gfxContext *aContext, nscolor aRGB, float aOpacity)
NS_GET_A(aRGB)/255.0 * aOpacity)); NS_GET_A(aRGB)/255.0 * aOpacity));
} }
static void
SetupFallbackOrPaintColor(gfxContext *aContext, nsStyleContext *aStyleContext,
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
float aOpacity)
{
const nsStyleSVGPaint &paint = aStyleContext->GetStyleSVG()->*aFillOrStroke;
nsStyleContext *styleIfVisited = aStyleContext->GetStyleIfVisited();
PRBool isServer = paint.mType == eStyleSVGPaintType_Server;
nscolor color = isServer ? paint.mFallbackColor : paint.mPaint.mColor;
if (styleIfVisited) {
const nsStyleSVGPaint &paintIfVisited =
styleIfVisited->GetStyleSVG()->*aFillOrStroke;
// To prevent Web content from detecting if a user has visited a URL
// (via URL loading triggered by paint servers or performance
// differences between paint servers or between a paint server and a
// color), we do not allow whether links are visited to change which
// paint server is used or switch between paint servers and simple
// colors. A :visited style may only override a simple color with
// another simple color.
if (paintIfVisited.mType == eStyleSVGPaintType_Color &&
paint.mType == eStyleSVGPaintType_Color) {
nscolor colorIfVisited = paintIfVisited.mPaint.mColor;
nscolor colors[2] = { color, colorIfVisited };
color = nsStyleContext::CombineVisitedColors(colors,
aStyleContext->RelevantLinkVisited());
}
}
SetupCairoColor(aContext, color, aOpacity);
}
float float
nsSVGGeometryFrame::MaybeOptimizeOpacity(float aFillOrStrokeOpacity) nsSVGGeometryFrame::MaybeOptimizeOpacity(float aFillOrStrokeOpacity)
{ {
@ -223,14 +254,8 @@ nsSVGGeometryFrame::SetupCairoFill(gfxContext *aContext)
// On failure, use the fallback colour in case we have an // On failure, use the fallback colour in case we have an
// objectBoundingBox where the width or height of the object is zero. // objectBoundingBox where the width or height of the object is zero.
// See http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox // See http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox
if (style->mFill.mType == eStyleSVGPaintType_Server) { SetupFallbackOrPaintColor(aContext, GetStyleContext(),
SetupCairoColor(aContext, &nsStyleSVG::mFill, opacity);
GetStyleSVG()->mFill.mFallbackColor,
opacity);
} else
SetupCairoColor(aContext,
GetStyleSVG()->mFill.mPaint.mColor,
opacity);
return PR_TRUE; return PR_TRUE;
} }
@ -314,14 +339,8 @@ nsSVGGeometryFrame::SetupCairoStroke(gfxContext *aContext)
// On failure, use the fallback colour in case we have an // On failure, use the fallback colour in case we have an
// objectBoundingBox where the width or height of the object is zero. // objectBoundingBox where the width or height of the object is zero.
// See http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox // See http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox
if (style->mStroke.mType == eStyleSVGPaintType_Server) { SetupFallbackOrPaintColor(aContext, GetStyleContext(),
SetupCairoColor(aContext, &nsStyleSVG::mStroke, opacity);
GetStyleSVG()->mStroke.mFallbackColor,
opacity);
} else
SetupCairoColor(aContext,
GetStyleSVG()->mStroke.mPaint.mColor,
opacity);
return PR_TRUE; return PR_TRUE;
} }