Bug 351798 - path mouseover fires outside svg. r+sr=roc

This commit is contained in:
tor%cs.brown.edu 2006-09-19 16:35:29 +00:00
Родитель f5598ad68d
Коммит 5542384be0
4 изменённых файлов: 117 добавлений и 16 удалений

Просмотреть файл

@ -91,6 +91,7 @@ public:
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, nsRect *aDirtyRect);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
// nsSVGGeometryFrame overload:
// Lie about our fill/stroke so hit detection works
@ -120,6 +121,8 @@ public:
#endif
private:
already_AddRefed<nsIDOMSVGMatrix> GetImageTransform();
nsCOMPtr<nsIDOMSVGPreserveAspectRatio> mPreserveAspectRatio;
nsCOMPtr<imgIDecoderObserver> mListener;
@ -215,6 +218,37 @@ nsSVGImageFrame::AttributeChanged(PRInt32 aNameSpaceID,
aAttribute, aModType);
}
already_AddRefed<nsIDOMSVGMatrix>
nsSVGImageFrame::GetImageTransform()
{
nsCOMPtr<nsIDOMSVGMatrix> ctm;
GetCanvasTM(getter_AddRefs(ctm));
float x, y, width, height;
nsSVGElement *element = NS_STATIC_CAST(nsSVGElement*, mContent);
element->GetAnimatedLengthValues(&x, &y, &width, &height, nsnull);
PRUint32 nativeWidth, nativeHeight;
nativeWidth = cairo_image_surface_get_width(mSurface);
nativeHeight = cairo_image_surface_get_height(mSurface);
nsCOMPtr<nsIDOMSVGImageElement> image = do_QueryInterface(mContent);
nsCOMPtr<nsIDOMSVGAnimatedPreserveAspectRatio> ratio;
image->GetPreserveAspectRatio(getter_AddRefs(ratio));
nsCOMPtr<nsIDOMSVGMatrix> trans, ctmXY, fini;
trans = nsSVGUtils::GetViewBoxTransform(width, height,
0, 0,
nativeWidth, nativeHeight,
ratio);
ctm->Translate(x, y, getter_AddRefs(ctmXY));
ctmXY->Multiply(trans, getter_AddRefs(fini));
nsIDOMSVGMatrix *retval = nsnull;
fini.swap(retval);
return retval;
}
//----------------------------------------------------------------------
// nsISVGChildFrame methods:
NS_IMETHODIMP
@ -254,21 +288,7 @@ nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas, nsRect *aDirtyRect)
nsSVGElement *element = NS_STATIC_CAST(nsSVGElement*, mContent);
element->GetAnimatedLengthValues(&x, &y, &width, &height, nsnull);
PRUint32 nativeWidth, nativeHeight;
nativeWidth = cairo_image_surface_get_width(mSurface);
nativeHeight = cairo_image_surface_get_height(mSurface);
nsCOMPtr<nsIDOMSVGImageElement> image = do_QueryInterface(mContent);
nsCOMPtr<nsIDOMSVGAnimatedPreserveAspectRatio> ratio;
image->GetPreserveAspectRatio(getter_AddRefs(ratio));
nsCOMPtr<nsIDOMSVGMatrix> trans, ctmXY, fini;
trans = nsSVGUtils::GetViewBoxTransform(width, height,
0, 0,
nativeWidth, nativeHeight,
ratio);
ctm->Translate(x, y, getter_AddRefs(ctmXY));
ctmXY->Multiply(trans, getter_AddRefs(fini));
nsCOMPtr<nsIDOMSVGMatrix> fini = GetImageTransform();
if (GetStyleDisplay()->IsScrollableOverflow()) {
canvas->PushClip();
@ -293,6 +313,27 @@ nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas, nsRect *aDirtyRect)
return NS_OK;
}
NS_IMETHODIMP
nsSVGImageFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
{
if (GetStyleDisplay()->IsScrollableOverflow() && mSurface) {
PRUint32 nativeWidth, nativeHeight;
nativeWidth = cairo_image_surface_get_width(mSurface);
nativeHeight = cairo_image_surface_get_height(mSurface);
nsCOMPtr<nsIDOMSVGMatrix> fini = GetImageTransform();
if (!nsSVGUtils::HitTestRect(fini,
0, 0, nativeWidth, nativeHeight,
x, y)) {
*hit = nsnull;
return NS_OK;
}
}
return nsSVGPathGeometryFrame::GetFrameForPointSVG(x, y, hit);
}
nsIAtom *
nsSVGImageFrame::GetType() const
{

Просмотреть файл

@ -92,7 +92,8 @@ public:
NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation);
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
// nsSVGContainerFrame methods:
virtual already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();
@ -235,6 +236,31 @@ nsSVGInnerSVGFrame::SetOverrideCTM(nsIDOMSVGMatrix *aCTM)
return NS_OK;
}
NS_IMETHODIMP
nsSVGInnerSVGFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
{
if (GetStyleDisplay()->IsScrollableOverflow()) {
float clipX, clipY, clipWidth, clipHeight;
nsCOMPtr<nsIDOMSVGMatrix> clipTransform;
nsSVGElement *svg = NS_STATIC_CAST(nsSVGElement*, mContent);
svg->GetAnimatedLengthValues(&clipX, &clipY, &clipWidth, &clipHeight, nsnull);
nsSVGContainerFrame *parent = NS_STATIC_CAST(nsSVGContainerFrame*,
mParent);
clipTransform = parent->GetCanvasTM();
if (!nsSVGUtils::HitTestRect(clipTransform,
clipX, clipY, clipWidth, clipHeight,
x, y)) {
*hit = nsnull;
return NS_OK;
}
}
return nsSVGInnerSVGFrameBase::GetFrameForPointSVG(x, y, hit);
}
//----------------------------------------------------------------------
// nsISVGSVGFrame methods:

Просмотреть файл

@ -965,3 +965,29 @@ nsSVGUtils::ConvertSVGMatrixToCairo(nsIDOMSVGMatrix *aMatrix)
cairo_matrix_t m = { A, B, C, D, E, F };
return m;
}
PRBool
nsSVGUtils::HitTestRect(nsIDOMSVGMatrix *aMatrix,
float aRX, float aRY, float aRWidth, float aRHeight,
float aX, float aY)
{
PRBool result = PR_TRUE;
if (aMatrix) {
cairo_matrix_t matrix = ConvertSVGMatrixToCairo(aMatrix);
cairo_t *ctx = cairo_create(GetCairoComputationalSurface());
cairo_set_tolerance(ctx, 1.0);
cairo_set_matrix(ctx, &matrix);
cairo_new_path(ctx);
cairo_rectangle(ctx, aRX, aRY, aRWidth, aRHeight);
cairo_identity_matrix(ctx);
if (!cairo_in_fill(ctx, aX, aY))
result = PR_FALSE;
cairo_destroy(ctx);
}
return result;
}

Просмотреть файл

@ -260,6 +260,14 @@ public:
static cairo_matrix_t
ConvertSVGMatrixToCairo(nsIDOMSVGMatrix *aMatrix);
/*
* Hit test a given rectangle/matrix.
*/
static PRBool
HitTestRect(nsIDOMSVGMatrix *aMatrix,
float aRX, float aRY, float aRWidth, float aRHeight,
float aX, float aY);
private:
/* Cairo computational (nil) surface */
static cairo_surface_t *mCairoComputationalSurface;