Bug 772017, part 2 - Have the visual overflow rect for SVG frames include non-rendering stroke when 'pointer-events' demands it. r=roc.

This commit is contained in:
Jonathan Watt 2012-07-11 12:25:27 +01:00
parent a5d221fbdb
commit 1a49fcfa1a
3 changed files with 42 additions and 29 deletions

View File

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

View File

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

View File

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