зеркало из https://github.com/mozilla/gecko-dev.git
Bug 351798 - path mouseover fires outside svg. r+sr=roc
This commit is contained in:
Родитель
f5598ad68d
Коммит
5542384be0
|
@ -91,6 +91,7 @@ public:
|
||||||
|
|
||||||
// nsISVGChildFrame interface:
|
// nsISVGChildFrame interface:
|
||||||
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, nsRect *aDirtyRect);
|
NS_IMETHOD PaintSVG(nsISVGRendererCanvas* canvas, nsRect *aDirtyRect);
|
||||||
|
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
|
||||||
|
|
||||||
// nsSVGGeometryFrame overload:
|
// nsSVGGeometryFrame overload:
|
||||||
// Lie about our fill/stroke so hit detection works
|
// Lie about our fill/stroke so hit detection works
|
||||||
|
@ -120,6 +121,8 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
already_AddRefed<nsIDOMSVGMatrix> GetImageTransform();
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMSVGPreserveAspectRatio> mPreserveAspectRatio;
|
nsCOMPtr<nsIDOMSVGPreserveAspectRatio> mPreserveAspectRatio;
|
||||||
|
|
||||||
nsCOMPtr<imgIDecoderObserver> mListener;
|
nsCOMPtr<imgIDecoderObserver> mListener;
|
||||||
|
@ -215,6 +218,37 @@ nsSVGImageFrame::AttributeChanged(PRInt32 aNameSpaceID,
|
||||||
aAttribute, aModType);
|
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:
|
// nsISVGChildFrame methods:
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -254,21 +288,7 @@ nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas, nsRect *aDirtyRect)
|
||||||
nsSVGElement *element = NS_STATIC_CAST(nsSVGElement*, mContent);
|
nsSVGElement *element = NS_STATIC_CAST(nsSVGElement*, mContent);
|
||||||
element->GetAnimatedLengthValues(&x, &y, &width, &height, nsnull);
|
element->GetAnimatedLengthValues(&x, &y, &width, &height, nsnull);
|
||||||
|
|
||||||
PRUint32 nativeWidth, nativeHeight;
|
nsCOMPtr<nsIDOMSVGMatrix> fini = GetImageTransform();
|
||||||
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));
|
|
||||||
|
|
||||||
if (GetStyleDisplay()->IsScrollableOverflow()) {
|
if (GetStyleDisplay()->IsScrollableOverflow()) {
|
||||||
canvas->PushClip();
|
canvas->PushClip();
|
||||||
|
@ -293,6 +313,27 @@ nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas, nsRect *aDirtyRect)
|
||||||
return NS_OK;
|
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 *
|
nsIAtom *
|
||||||
nsSVGImageFrame::GetType() const
|
nsSVGImageFrame::GetType() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -92,7 +92,8 @@ public:
|
||||||
NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation);
|
NS_IMETHOD NotifyCanvasTMChanged(PRBool suppressInvalidation);
|
||||||
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
|
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
|
||||||
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM);
|
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM);
|
||||||
|
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
|
||||||
|
|
||||||
// nsSVGContainerFrame methods:
|
// nsSVGContainerFrame methods:
|
||||||
virtual already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();
|
virtual already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();
|
||||||
|
|
||||||
|
@ -235,6 +236,31 @@ nsSVGInnerSVGFrame::SetOverrideCTM(nsIDOMSVGMatrix *aCTM)
|
||||||
return NS_OK;
|
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:
|
// nsISVGSVGFrame methods:
|
||||||
|
|
||||||
|
|
|
@ -965,3 +965,29 @@ nsSVGUtils::ConvertSVGMatrixToCairo(nsIDOMSVGMatrix *aMatrix)
|
||||||
cairo_matrix_t m = { A, B, C, D, E, F };
|
cairo_matrix_t m = { A, B, C, D, E, F };
|
||||||
return m;
|
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
|
static cairo_matrix_t
|
||||||
ConvertSVGMatrixToCairo(nsIDOMSVGMatrix *aMatrix);
|
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:
|
private:
|
||||||
/* Cairo computational (nil) surface */
|
/* Cairo computational (nil) surface */
|
||||||
static cairo_surface_t *mCairoComputationalSurface;
|
static cairo_surface_t *mCairoComputationalSurface;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче