зеркало из 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:
|
||||
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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче