diff --git a/layout/svg/base/src/nsSVGGlyphFrame.cpp b/layout/svg/base/src/nsSVGGlyphFrame.cpp index f822c05a35e8..c8900938d98e 100644 --- a/layout/svg/base/src/nsSVGGlyphFrame.cpp +++ b/layout/svg/base/src/nsSVGGlyphFrame.cpp @@ -442,10 +442,22 @@ nsSVGGlyphFrame::UpdateBounds() mRect.SetEmpty(); - gfxRect extent = GetBBoxContribution(gfxMatrix(), - nsSVGUtils::eBBoxIncludeFill | nsSVGUtils::eBBoxIgnoreFillIfNone | - nsSVGUtils::eBBoxIncludeStroke | nsSVGUtils::eBBoxIgnoreStrokeIfNone | - nsSVGUtils::eBBoxIncludeMarkers); + PRUint32 flags = nsSVGUtils::eBBoxIncludeFill | + nsSVGUtils::eBBoxIncludeStroke | + nsSVGUtils::eBBoxIncludeMarkers; + // Our "visual" overflow rect needs to be valid for building display lists + // for hit testing, which means that for certain values of 'pointer-events' + // it needs to include the geometry of the fill or stroke even when the fill/ + // stroke don't actually render (e.g. when stroke="none" or + // stroke-opacity="0"). GetHitTestFlags() accounts for 'pointer-events'. + PRUint16 hitTestFlags = GetHitTestFlags(); + if ((hitTestFlags & SVG_HIT_TEST_FILL)) { + flags |= nsSVGUtils::eBBoxIncludeFillGeometry; + } + if ((hitTestFlags & SVG_HIT_TEST_STROKE)) { + flags |= nsSVGUtils::eBBoxIncludeStrokeGeometry; + } + gfxRect extent = GetBBoxContribution(gfxMatrix(), flags); if (!extent.IsEmpty()) { mRect = nsLayoutUtils::RoundGfxRectToAppRect(extent, @@ -590,15 +602,15 @@ nsSVGGlyphFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace, gfxRect pathExtents = tmpCtx->GetUserPathExtent(); // Account for fill: - if ((aFlags & nsSVGUtils::eBBoxIncludeFill) != 0 && - ((aFlags & nsSVGUtils::eBBoxIgnoreFillIfNone) == 0 || + if ((aFlags & nsSVGUtils::eBBoxIncludeFillGeometry) || + ((aFlags & nsSVGUtils::eBBoxIncludeFill) && GetStyleSVG()->mFill.mType != eStyleSVGPaintType_None)) { bbox = pathExtents; } // Account for stroke: - if ((aFlags & nsSVGUtils::eBBoxIncludeStroke) != 0 && - ((aFlags & nsSVGUtils::eBBoxIgnoreStrokeIfNone) == 0 || HasStroke())) { + if ((aFlags & nsSVGUtils::eBBoxIncludeStrokeGeometry) || + ((aFlags & nsSVGUtils::eBBoxIncludeStroke) && HasStroke())) { bbox = bbox.Union(nsSVGUtils::PathExtentsToMaxStrokeExtents(pathExtents, this, diff --git a/layout/svg/base/src/nsSVGPathGeometryFrame.cpp b/layout/svg/base/src/nsSVGPathGeometryFrame.cpp index 41df5ac7a0ed..1a1af9acea63 100644 --- a/layout/svg/base/src/nsSVGPathGeometryFrame.cpp +++ b/layout/svg/base/src/nsSVGPathGeometryFrame.cpp @@ -225,17 +225,17 @@ nsSVGPathGeometryFrame::UpdateBounds() PRUint32 flags = nsSVGUtils::eBBoxIncludeFill | nsSVGUtils::eBBoxIncludeStroke | nsSVGUtils::eBBoxIncludeMarkers; - PRUint32 pointerEvents = GetStyleVisibility()->mPointerEvents; - if (pointerEvents == NS_STYLE_POINTER_EVENTS_AUTO || - pointerEvents == NS_STYLE_POINTER_EVENTS_VISIBLEPAINTED || - pointerEvents == NS_STYLE_POINTER_EVENTS_PAINTED || - pointerEvents == NS_STYLE_POINTER_EVENTS_NONE) { - // We can only ignore 'none' stroke if the value of the pointer-events - // property doesn't require us to include it in our "visual" overflow rect - // so that our visual overflow rect is valid for building display lists for - // hit-testing. - flags |= nsSVGUtils::eBBoxIgnoreStrokeIfNone | - nsSVGUtils::eBBoxIgnoreFillIfNone; + // Our "visual" overflow rect needs to be valid for building display lists + // for hit testing, which means that for certain values of 'pointer-events' + // it needs to include the geometry of the fill or stroke even when the fill/ + // stroke don't actually render (e.g. when stroke="none" or + // stroke-opacity="0"). GetHitTestFlags() accounts for 'pointer-events'. + PRUint16 hitTestFlags = GetHitTestFlags(); + if ((hitTestFlags & SVG_HIT_TEST_FILL)) { + flags |= nsSVGUtils::eBBoxIncludeFillGeometry; + } + if ((hitTestFlags & SVG_HIT_TEST_STROKE)) { + flags |= nsSVGUtils::eBBoxIncludeStrokeGeometry; } gfxRect extent = GetBBoxContribution(gfxMatrix(), flags); mRect = nsLayoutUtils::RoundGfxRectToAppRect(extent, @@ -324,15 +324,15 @@ nsSVGPathGeometryFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace, gfxRect pathExtents = tmpCtx->GetUserPathExtent(); // Account for fill: - if ((aFlags & nsSVGUtils::eBBoxIncludeFill) != 0 && - ((aFlags & nsSVGUtils::eBBoxIgnoreFillIfNone) == 0 || + if ((aFlags & nsSVGUtils::eBBoxIncludeFillGeometry) || + ((aFlags & nsSVGUtils::eBBoxIncludeFill) && GetStyleSVG()->mFill.mType != eStyleSVGPaintType_None)) { bbox = pathExtents; } // Account for stroke: - if ((aFlags & nsSVGUtils::eBBoxIncludeStroke) != 0 && - ((aFlags & nsSVGUtils::eBBoxIgnoreStrokeIfNone) == 0 || HasStroke())) { + if ((aFlags & nsSVGUtils::eBBoxIncludeStrokeGeometry) || + ((aFlags & nsSVGUtils::eBBoxIncludeStroke) && HasStroke())) { // We can't use tmpCtx->GetUserStrokeExtent() since it doesn't work for // device space extents. Instead we approximate the stroke extents from // pathExtents using PathExtentsToMaxStrokeExtents. diff --git a/layout/svg/base/src/nsSVGUtils.h b/layout/svg/base/src/nsSVGUtils.h index 73d94f95c376..e5a0c1bf09b8 100644 --- a/layout/svg/base/src/nsSVGUtils.h +++ b/layout/svg/base/src/nsSVGUtils.h @@ -591,17 +591,18 @@ public: nsIFrame *aFrame); enum BBoxFlags { - eBBoxIncludeFill = 1 << 0, - eBBoxIgnoreFillIfNone = 1 << 1, - eBBoxIncludeStroke = 1 << 2, - eBBoxIgnoreStrokeIfNone = 1 << 3, - eBBoxIncludeMarkers = 1 << 4 + eBBoxIncludeFill = 1 << 0, + eBBoxIncludeFillGeometry = 1 << 1, + eBBoxIncludeStroke = 1 << 2, + eBBoxIncludeStrokeGeometry = 1 << 3, + eBBoxIncludeMarkers = 1 << 4 }; /** * Get the SVG bbox (the SVG spec's simplified idea of bounds) of aFrame in * aFrame's userspace. */ - static gfxRect GetBBox(nsIFrame *aFrame, PRUint32 aFlags = eBBoxIncludeFill); + static gfxRect GetBBox(nsIFrame *aFrame, + PRUint32 aFlags = eBBoxIncludeFillGeometry); /** * Convert a userSpaceOnUse/objectBoundingBoxUnits rectangle that's specified