nsSVGPathGeometryFrame::GetFrameForPoint(const nsPoint &aPoint) { PRUint16 fillRule, hitTestFlags; if (GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD) { hitTestFlags = SVG_HIT_TEST_FILL; fillRule = GetClipRule(); } else { hitTestFlags = GetHitTestFlags(); // XXX once bug 614732 is fixed, aPoint won't need any conversion in order // to compare it with mRect. gfxMatrix canvasTM = GetCanvasTM(); if (canvasTM.IsSingular()) { return nsnull; } nsPoint point = nsSVGUtils::TransformOuterSVGPointToChildFrame(aPoint, canvasTM, PresContext()); if (!hitTestFlags || ((hitTestFlags & SVG_HIT_TEST_CHECK_MRECT) && !mRect.Contains(point))) return nsnull; fillRule = GetStyleSVG()->mFillRule; } bool isHit = false; nsRefPtr<gfxContext> context = new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface()); GeneratePath(context); gfxPoint userSpacePoint = context->DeviceToUser(gfxPoint(PresContext()->AppUnitsToGfxUnits(aPoint.x), PresContext()->AppUnitsToGfxUnits(aPoint.y))); if (fillRule == NS_STYLE_FILL_RULE_EVENODD) context->SetFillRule(gfxContext::FILL_RULE_EVEN_ODD); else context->SetFillRule(gfxContext::FILL_RULE_WINDING); if (hitTestFlags & SVG_HIT_TEST_FILL) isHit = context->PointInFill(userSpacePoint); if (!isHit && (hitTestFlags & SVG_HIT_TEST_STROKE)) { SetupCairoStrokeHitGeometry(context); isHit = context->PointInStroke(userSpacePoint); } if (isHit && nsSVGUtils::HitTestClip(this, aPoint)) return this; return nsnull; }
nsSVGPathGeometryFrame::GetFrameForPoint(const nsPoint &aPoint) { PRUint16 fillRule, mask; // check if we're a clipPath - cheaper than IsClipChild(), and we shouldn't // get in here for other nondisplay children if (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD) { NS_ASSERTION(IsClipChild(), "should be in clipPath but we're not"); mask = HITTEST_MASK_FILL; fillRule = GetClipRule(); } else { mask = GetHittestMask(); if (!mask || (!(mask & HITTEST_MASK_FORCE_TEST) && !mRect.Contains(aPoint))) return nsnull; fillRule = GetStyleSVG()->mFillRule; } PRBool isHit = PR_FALSE; gfxContext context(nsSVGUtils::GetThebesComputationalSurface()); GeneratePath(&context); gfxPoint userSpacePoint = context.DeviceToUser(gfxPoint(PresContext()->AppUnitsToGfxUnits(aPoint.x), PresContext()->AppUnitsToGfxUnits(aPoint.y))); if (fillRule == NS_STYLE_FILL_RULE_EVENODD) context.SetFillRule(gfxContext::FILL_RULE_EVEN_ODD); else context.SetFillRule(gfxContext::FILL_RULE_WINDING); if (mask & HITTEST_MASK_FILL) isHit = context.PointInFill(userSpacePoint); if (!isHit && (mask & HITTEST_MASK_STROKE)) { SetupCairoStrokeHitGeometry(&context); isHit = context.PointInStroke(userSpacePoint); } if (isHit && nsSVGUtils::HitTestClip(this, aPoint)) return this; return nsnull; }
PRBool nsSVGGeometryFrame::SetupCairoStroke(gfxContext *aContext) { if (!HasStroke()) { return PR_FALSE; } SetupCairoStrokeHitGeometry(aContext); const nsStyleSVG* style = GetStyleSVG(); float opacity = MaybeOptimizeOpacity(style->mStrokeOpacity); nsSVGPaintServerFrame *ps = GetPaintServer(&style->mStroke, nsSVGEffects::StrokeProperty()); if (ps && ps->SetupPaintServer(aContext, this, opacity)) return PR_TRUE; // 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 SetupFallbackOrPaintColor(aContext, GetStyleContext(), &nsStyleSVG::mStroke, opacity); return PR_TRUE; }