diff --git a/layout/style/nsStyleContext.cpp b/layout/style/nsStyleContext.cpp index 5306f963e44e..212d029da759 100644 --- a/layout/style/nsStyleContext.cpp +++ b/layout/style/nsStyleContext.cpp @@ -730,13 +730,20 @@ nsStyleContext::GetVisitedDependentColor(nsCSSProperty aProperty) 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 // possible on whether this->RelevantLinkVisited() is true. const ColorIndexSet &set = - gVisitedIndices[this->RelevantLinkVisited() ? 1 : 0]; + gVisitedIndices[aLinkIsVisited ? 1 : 0]; - nscolor colorColor = colors[set.colorIndex]; - nscolor alphaColor = colors[set.alphaIndex]; + nscolor colorColor = aColors[set.colorIndex]; + nscolor alphaColor = aColors[set.alphaIndex]; return NS_RGBA(NS_GET_R(colorColor), NS_GET_G(colorColor), NS_GET_B(colorColor), NS_GET_A(alphaColor)); } diff --git a/layout/style/nsStyleContext.h b/layout/style/nsStyleContext.h index 469472ff5ddb..cb14ead22b81 100644 --- a/layout/style/nsStyleContext.h +++ b/layout/style/nsStyleContext.h @@ -261,6 +261,16 @@ public: */ 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 NS_HIDDEN_(void) List(FILE* out, PRInt32 aIndent); #endif diff --git a/layout/svg/base/src/nsSVGGeometryFrame.cpp b/layout/svg/base/src/nsSVGGeometryFrame.cpp index a1968063253e..faed7435099b 100644 --- a/layout/svg/base/src/nsSVGGeometryFrame.cpp +++ b/layout/svg/base/src/nsSVGGeometryFrame.cpp @@ -191,6 +191,37 @@ SetupCairoColor(gfxContext *aContext, nscolor aRGB, float 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 nsSVGGeometryFrame::MaybeOptimizeOpacity(float aFillOrStrokeOpacity) { @@ -223,14 +254,8 @@ nsSVGGeometryFrame::SetupCairoFill(gfxContext *aContext) // On failure, use the fallback colour in case we have an // objectBoundingBox where the width or height of the object is zero. // See http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox - if (style->mFill.mType == eStyleSVGPaintType_Server) { - SetupCairoColor(aContext, - GetStyleSVG()->mFill.mFallbackColor, - opacity); - } else - SetupCairoColor(aContext, - GetStyleSVG()->mFill.mPaint.mColor, - opacity); + SetupFallbackOrPaintColor(aContext, GetStyleContext(), + &nsStyleSVG::mFill, opacity); return PR_TRUE; } @@ -314,14 +339,8 @@ nsSVGGeometryFrame::SetupCairoStroke(gfxContext *aContext) // On failure, use the fallback colour in case we have an // objectBoundingBox where the width or height of the object is zero. // See http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox - if (style->mStroke.mType == eStyleSVGPaintType_Server) { - SetupCairoColor(aContext, - GetStyleSVG()->mStroke.mFallbackColor, - opacity); - } else - SetupCairoColor(aContext, - GetStyleSVG()->mStroke.mPaint.mColor, - opacity); + SetupFallbackOrPaintColor(aContext, GetStyleContext(), + &nsStyleSVG::mStroke, opacity); return PR_TRUE; }