Bug 379616 - Switch SVG's frame mRect to app units, r+sr=tor

This commit is contained in:
Jeremy Lea 2008-08-19 10:14:01 -04:00
parent 2395826de0
commit 9957840a6a
26 changed files with 183 additions and 225 deletions

View File

@ -1260,9 +1260,6 @@ AddRectsForFrame(nsIFrame* aFrame, nsIFrame* aRelativeTo,
nsRect r;
nsIFrame* outer = nsSVGUtils::GetOuterSVGFrameAndCoveredRegion(aFrame, &r);
if (outer) {
// r is in pixels relative to 'outer', get it into appunits
// relative to aRelativeTo
r.ScaleRoundOut(1.0/aFrame->PresContext()->AppUnitsPerDevPixel());
aCallback->AddRect(r + outer->GetOffsetTo(aRelativeTo));
} else
#endif

View File

@ -42,17 +42,17 @@
#include "nsISupports.h"
#include "nsCOMPtr.h"
#include "nsRect.h"
class gfxContext;
class nsPresContext;
class nsIDOMSVGRect;
class nsIDOMSVGMatrix;
class nsSVGRenderState;
struct nsRect;
#define NS_ISVGCHILDFRAME_IID \
{ 0x667e8781, 0x72bd, 0x4344, \
{ 0x95, 0x8c, 0x69, 0xa5, 0x70, 0xc4, 0xcc, 0xb3 } }
{ 0xe4ecddbf, 0xde7c, 0x4cd9, \
{ 0x92, 0x4a, 0xfa, 0x81, 0xba, 0x83, 0x26, 0x69 } }
class nsISVGChildFrame : public nsISupports {
public:
@ -61,20 +61,15 @@ public:
// Paint this frame - aDirtyRect is the area being redrawn, in frame
// offset pixel coordinates
NS_IMETHOD PaintSVG(nsSVGRenderState* aContext, nsRect *aDirtyRect)=0;
NS_IMETHOD PaintSVG(nsSVGRenderState* aContext, nsIntRect *aDirtyRect)=0;
// Check if this frame or children contain the given point,
// specified in device pixels relative to the origin of the outer
// specified in app units relative to the origin of the outer
// svg frame (origin ill-defined in the case of borders - bug
// 290770). Return value unspecified (usually NS_OK for hit, error
// no hit, but not always [ex: nsSVGPathGeometryFrame.cpp]) and no
// code trusts the return value - this should be fixed (bug 290765).
// *hit set to topmost frame in the children (or 'this' if leaf
// frame) which is accepting pointer events, null if no frame hit.
// See bug 290852 for foreignObject complications.
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit)=0;
// 290770). See bug 290852 for foreignObject complications.
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint)=0;
// Get bounds in our gfxContext's coordinates space (in device pixels)
// Get bounds in our gfxContext's coordinates space (in app units)
NS_IMETHOD_(nsRect) GetCoveredRegion()=0;
NS_IMETHOD UpdateCoveredRegion()=0;

View File

@ -105,7 +105,7 @@ nsSVGClipPathFrame::ClipPaint(nsSVGRenderState* aContext,
PRBool
nsSVGClipPathFrame::ClipHitTest(nsISVGChildFrame* aParent,
nsIDOMSVGMatrix *aMatrix,
float aX, float aY)
const nsPoint &aPoint)
{
// If the flag is set when we get here, it means this clipPath frame
// has already been used in hit testing against the current clip,
@ -116,7 +116,6 @@ nsSVGClipPathFrame::ClipHitTest(nsISVGChildFrame* aParent,
}
AutoClipPathReferencer clipRef(this);
nsRect dirty;
mClipParent = aParent,
mClipParentMatrix = aMatrix;
@ -130,9 +129,7 @@ nsSVGClipPathFrame::ClipHitTest(nsISVGChildFrame* aParent,
// (used to shortcut hit testing).
SVGFrame->NotifySVGChanged(nsISVGChildFrame::TRANSFORM_CHANGED);
nsIFrame *temp = nsnull;
nsresult rv = SVGFrame->GetFrameForPointSVG(aX, aY, &temp);
if (NS_SUCCEEDED(rv) && temp)
if (SVGFrame->GetFrameForPoint(aPoint))
return PR_TRUE;
}
}

View File

@ -59,7 +59,7 @@ public:
PRBool ClipHitTest(nsISVGChildFrame* aParent,
nsIDOMSVGMatrix *aMatrix,
float aX, float aY);
const nsPoint &aPoint);
// Check if this clipPath is made up of more than one geometry object.
// If so, the clipping API in cairo isn't enough and we need to use

View File

@ -165,7 +165,7 @@ nsSVGDisplayContainerFrame::RemoveFrame(nsIAtom* aListName,
NS_IMETHODIMP
nsSVGDisplayContainerFrame::PaintSVG(nsSVGRenderState* aContext,
nsRect *aDirtyRect)
nsIntRect *aDirtyRect)
{
const nsStyleDisplay *display = mStyleContext->GetStyleDisplay();
if (display->mOpacity == 0.0)
@ -179,12 +179,10 @@ nsSVGDisplayContainerFrame::PaintSVG(nsSVGRenderState* aContext,
return NS_OK;
}
NS_IMETHODIMP
nsSVGDisplayContainerFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
NS_IMETHODIMP_(nsIFrame*)
nsSVGDisplayContainerFrame::GetFrameForPoint(const nsPoint &aPoint)
{
nsSVGUtils::HitTestChildren(this, x, y, hit);
return NS_OK;
return nsSVGUtils::HitTestChildren(this, aPoint);
}
NS_IMETHODIMP_(nsRect)

View File

@ -101,8 +101,8 @@ public:
nsIFrame* aPrevInFlow);
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsSVGRenderState* aContext, nsRect *aDirtyRect);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
NS_IMETHOD PaintSVG(nsSVGRenderState* aContext, nsIntRect *aDirtyRect);
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint);
NS_IMETHOD_(nsRect) GetCoveredRegion();
NS_IMETHOD UpdateCoveredRegion();
NS_IMETHOD InitialUpdate();

View File

@ -138,9 +138,9 @@ nsSVGFilterProperty::DoUpdate()
{
nsSVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(mFrame);
if (outerSVGFrame) {
outerSVGFrame->InvalidateRect(mFilterRect);
outerSVGFrame->Invalidate(mFilterRect);
UpdateRect();
outerSVGFrame->InvalidateRect(mFilterRect);
outerSVGFrame->Invalidate(mFilterRect);
}
}

View File

@ -63,7 +63,7 @@ NS_NewSVGFilterFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleCont
static nsIntRect
MapDeviceRectToFilterSpace(const gfxMatrix& aMatrix,
const gfxIntSize& aFilterSize,
const nsRect* aDeviceRect)
const nsIntRect* aDeviceRect)
{
nsIntRect rect(0, 0, aFilterSize.width, aFilterSize.height);
if (aDeviceRect) {
@ -80,8 +80,8 @@ MapDeviceRectToFilterSpace(const gfxMatrix& aMatrix,
nsresult
nsSVGFilterFrame::CreateInstance(nsISVGChildFrame *aTarget,
const nsRect *aDirtyOutputRect,
const nsRect *aDirtyInputRect,
const nsIntRect *aDirtyOutputRect,
const nsIntRect *aDirtyInputRect,
nsSVGFilterInstance **aInstance)
{
*aInstance = nsnull;
@ -203,7 +203,7 @@ RestoreTargetState(nsISVGChildFrame *aTarget)
nsresult
nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext,
nsISVGChildFrame *aTarget,
const nsRect *aDirtyRect)
const nsIntRect *aDirtyRect)
{
nsAutoPtr<nsSVGFilterInstance> instance;
nsresult rv = CreateInstance(aTarget, aDirtyRect, nsnull, getter_Transfers(instance));
@ -238,10 +238,13 @@ nsSVGFilterFrame::GetInvalidationRegion(nsIFrame *aTarget, const nsRect& aRect)
nsISVGChildFrame *svg;
CallQueryInterface(aTarget, &svg);
nscoord p2a = aTarget->PresContext()->AppUnitsPerDevPixel();
nsRect result = aRect;
nsIntRect rect = aRect;
rect.ScaleRoundOut(1.0/p2a);
nsAutoPtr<nsSVGFilterInstance> instance;
nsresult rv = CreateInstance(svg, nsnull, &aRect, getter_Transfers(instance));
nsresult rv = CreateInstance(svg, nsnull, &rect, getter_Transfers(instance));
if (NS_SUCCEEDED(rv)) {
if (!instance) {
// The filter draws nothing, so nothing is dirty.
@ -262,6 +265,7 @@ nsSVGFilterFrame::GetInvalidationRegion(nsIFrame *aTarget, const nsRect& aRect)
nsIntRect deviceRect;
rv = nsSVGUtils::GfxRectToIntRect(r, &deviceRect);
if (NS_SUCCEEDED(rv)) {
deviceRect.ScaleRoundOut(p2a);
result = deviceRect;
}
}

View File

@ -53,13 +53,13 @@ protected:
public:
nsresult FilterPaint(nsSVGRenderState *aContext,
nsISVGChildFrame *aTarget,
const nsRect* aDirtyRect);
const nsIntRect* aDirtyRect);
// Returns invalidation region for filter (can be bigger than the
// referencing geometry to filter region sizing) in device pixels
// referencing geometry to filter region sizing) in app units
// relative to the origin of the outer svg.
// aRect is the area of device pixels that would be invalidated. Normally
// you'd just pass aTarget->GetRect() here.
// aRect is the area that would be invalidated. Normally you'd just pass
// aTarget->GetRect() here.
nsRect GetInvalidationRegion(nsIFrame *aTarget, const nsRect& aRect);
/**
@ -72,8 +72,8 @@ public:
private:
// implementation helpers
nsresult CreateInstance(nsISVGChildFrame *aTarget,
const nsRect *aDirtyOutputRect,
const nsRect *aDirtyInputRect,
const nsIntRect *aDirtyOutputRect,
const nsIntRect *aDirtyInputRect,
nsSVGFilterInstance **aInstance);
};

View File

@ -185,13 +185,13 @@ nsSVGForeignObjectFrame::InvalidateInternal(const nsRect& aDamageRect,
// nsISVGChildFrame methods
/**
* Gets the rectangular region in rounded out CSS pixels that encloses the
* rectangle after it has been transformed by aMatrix. Useful in
* UpdateCoveredRegion/FlushDirtyRegion.
* Gets the rectangular region in app units (rounded out device pixels)
* that encloses the rectangle after it has been transformed by aMatrix.
* Useful in UpdateCoveredRegion/FlushDirtyRegion.
*/
static nsRect
GetTransformedRegion(float aX, float aY, float aWidth, float aHeight,
nsIDOMSVGMatrix* aMatrix)
nsIDOMSVGMatrix* aMatrix, nsPresContext *aPresContext)
{
float x[4], y[4];
x[0] = aX;
@ -221,12 +221,12 @@ GetTransformedRegion(float aX, float aY, float aWidth, float aHeight,
ymax = y[i];
}
return nsSVGUtils::ToBoundingPixelRect(xmin, ymin, xmax, ymax);
return nsSVGUtils::ToAppPixelRect(aPresContext, xmin, ymin, xmax, ymax);
}
NS_IMETHODIMP
nsSVGForeignObjectFrame::PaintSVG(nsSVGRenderState *aContext,
nsRect *aDirtyRect)
nsIntRect *aDirtyRect)
{
if (IsDisabled())
return NS_OK;
@ -285,7 +285,8 @@ nsSVGForeignObjectFrame::PaintSVG(nsSVGRenderState *aContext,
}
nsresult
nsSVGForeignObjectFrame::TransformPointFromOuterPx(float aX, float aY, nsPoint* aOut)
nsSVGForeignObjectFrame::TransformPointFromOuterPx(const nsPoint &aIn,
nsPoint* aOut)
{
if (mParent->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)
return NS_ERROR_FAILURE;
@ -296,41 +297,35 @@ nsSVGForeignObjectFrame::TransformPointFromOuterPx(float aX, float aY, nsPoint*
if (NS_FAILED(rv))
return rv;
nsSVGUtils::TransformPoint(inverse, &aX, &aY);
PRInt32 appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel();
*aOut = nsPoint(NSToCoordRound(aX * appUnitsPerDevPixel),
NSToCoordRound(aY * appUnitsPerDevPixel));
float x = PresContext()->AppUnitsToDevPixels(aIn.x);
float y = PresContext()->AppUnitsToDevPixels(aIn.y);
nsSVGUtils::TransformPoint(inverse, &x, &y);
*aOut = nsPoint(PresContext()->DevPixelsToAppUnits(NSToIntRound(x)),
PresContext()->DevPixelsToAppUnits(NSToIntRound(y)));
return NS_OK;
}
NS_IMETHODIMP
nsSVGForeignObjectFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
NS_IMETHODIMP_(nsIFrame*)
nsSVGForeignObjectFrame::GetFrameForPoint(const nsPoint &aPoint)
{
*hit = nsnull;
if (IsDisabled())
return NS_OK;
nsIFrame* kid = GetFirstChild(nsnull);
if (!kid) {
return NS_OK;
return nsnull;
}
nsPoint pt;
nsresult rv = TransformPointFromOuterPx(x, y, &pt);
if (NS_FAILED(rv))
return rv;
*hit = nsLayoutUtils::GetFrameForPoint(kid, pt);
return NS_OK;
if (NS_FAILED(TransformPointFromOuterPx(aPoint, &pt)))
return nsnull;
return nsLayoutUtils::GetFrameForPoint(kid, pt);
}
nsPoint
nsSVGForeignObjectFrame::TransformPointFromOuter(nsPoint aPt)
{
nsPoint pt(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
float appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel();
TransformPointFromOuterPx(aPt.x / appUnitsPerDevPixel,
aPt.y / appUnitsPerDevPixel,
&pt);
TransformPointFromOuterPx(aPt, &pt);
return pt;
}
@ -360,7 +355,7 @@ nsSVGForeignObjectFrame::UpdateCoveredRegion()
// XXXjwatt: _this_ is where we should reflow _if_ mRect.width has changed!
// we should not unconditionally reflow in AttributeChanged
mRect = GetTransformedRegion(x, y, w, h, ctm);
mRect = GetTransformedRegion(x, y, w, h, ctm, PresContext());
nsSVGUtils::UpdateFilterRegion(this);
@ -684,18 +679,17 @@ nsSVGForeignObjectFrame::FlushDirtyRegion()
return;
nsCOMPtr<nsIDOMSVGMatrix> tm = GetTMIncludingOffset();
nsRect r = mDirtyRegion.GetBounds();
nsIntRect r = mDirtyRegion.GetBounds();
r.ScaleRoundOut(1.0f / PresContext()->AppUnitsPerDevPixel());
float x = r.x, y = r.y, w = r.width, h = r.height;
r = GetTransformedRegion(x, y, w, h, tm);
nsRect rect = GetTransformedRegion(x, y, w, h, tm, PresContext());
// XXX invalidate the entire covered region
// See bug 418063
r.UnionRect(r, mRect);
rect.UnionRect(rect, mRect);
r = nsSVGUtils::FindFilterInvalidation(this, r);
outerSVGFrame->InvalidateRect(r);
rect = nsSVGUtils::FindFilterInvalidation(this, rect);
outerSVGFrame->Invalidate(rect);
mDirtyRegion.SetEmpty();
}

View File

@ -105,8 +105,8 @@ public:
#endif
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsSVGRenderState *aContext, nsRect *aDirtyRect);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
NS_IMETHOD PaintSVG(nsSVGRenderState *aContext, nsIntRect *aDirtyRect);
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint);
NS_IMETHOD_(nsRect) GetCoveredRegion();
NS_IMETHOD UpdateCoveredRegion();
NS_IMETHOD InitialUpdate();
@ -122,8 +122,8 @@ public:
// foreignobject public methods
/**
* @param aPt a point in the twips coordinate system of the SVG outer frame
* Transforms the point to a point in this frame's twips coordinate system
* @param aPt a point in the app unit coordinate system of the SVG outer frame
* Transforms the point to a point in this frame's app unit coordinate system
*/
nsPoint TransformPointFromOuter(nsPoint aPt);
@ -138,7 +138,7 @@ protected:
void RequestReflow(nsIPresShell::IntrinsicDirty aType);
void UpdateGraphic();
already_AddRefed<nsIDOMSVGMatrix> GetTMIncludingOffset();
nsresult TransformPointFromOuterPx(float aX, float aY, nsPoint* aOut);
nsresult TransformPointFromOuterPx(const nsPoint &aIn, nsPoint* aOut);
void FlushDirtyRegion();
// If width or height is less than or equal to zero we must disable rendering

View File

@ -297,7 +297,7 @@ nsSVGGlyphFrame::GetType() const
// nsISVGChildFrame methods
NS_IMETHODIMP
nsSVGGlyphFrame::PaintSVG(nsSVGRenderState *aContext, nsRect *aDirtyRect)
nsSVGGlyphFrame::PaintSVG(nsSVGRenderState *aContext, nsIntRect *aDirtyRect)
{
if (!GetStyleVisibility()->IsVisible())
return NS_OK;
@ -362,17 +362,15 @@ nsSVGGlyphFrame::PaintSVG(nsSVGRenderState *aContext, nsRect *aDirtyRect)
return NS_OK;
}
NS_IMETHODIMP
nsSVGGlyphFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
NS_IMETHODIMP_(nsIFrame*)
nsSVGGlyphFrame::GetFrameForPoint(const nsPoint &aPoint)
{
#ifdef DEBUG
//printf("nsSVGGlyphFrame(%p)::GetFrameForPoint\n", this);
#endif
// test for hit:
*hit = nsnull;
if (!mRect.Contains(nscoord(x), nscoord(y)))
return NS_OK;
if (!mRect.Contains(aPoint))
return nsnull;
PRBool events = PR_FALSE;
switch (GetStyleSVG()->mPointerEvents) {
@ -405,14 +403,10 @@ nsSVGGlyphFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
break;
}
if (!events)
return NS_OK;
if (events && ContainsPoint(aPoint))
return this;
PRBool isHit = ContainsPoint(x, y);
if (isHit)
*hit = this;
return NS_OK;
return nsnull;
}
NS_IMETHODIMP_(nsRect)
@ -448,7 +442,7 @@ nsSVGGlyphFrame::UpdateCoveredRegion()
extent = gfxRect(0, 0, 0, 0);
}
mRect = nsSVGUtils::ToBoundingPixelRect(extent);
mRect = nsSVGUtils::ToAppPixelRect(PresContext(), extent);
return NS_OK;
}
@ -1149,7 +1143,7 @@ nsSVGGlyphFrame::NotifyGlyphMetricsChange()
}
PRBool
nsSVGGlyphFrame::ContainsPoint(float x, float y)
nsSVGGlyphFrame::ContainsPoint(const nsPoint &aPoint)
{
nsRefPtr<gfxContext> tmpCtx = MakeTmpCtx();
SetupGlobalTransform(tmpCtx);
@ -1165,7 +1159,8 @@ nsSVGGlyphFrame::ContainsPoint(float x, float y)
}
tmpCtx->IdentityMatrix();
return tmpCtx->PointInFill(gfxPoint(x, y));
return tmpCtx->PointInFill(gfxPoint(PresContext()->AppUnitsToGfxUnits(aPoint.x),
PresContext()->AppUnitsToGfxUnits(aPoint.y)));
}
PRBool

View File

@ -114,8 +114,8 @@ public:
// nsISVGChildFrame interface:
// These four always use the global transform, even if NS_STATE_NONDISPLAY_CHILD
NS_IMETHOD PaintSVG(nsSVGRenderState *aContext, nsRect *aDirtyRect);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
NS_IMETHOD PaintSVG(nsSVGRenderState *aContext, nsIntRect *aDirtyRect);
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint);
NS_IMETHOD UpdateCoveredRegion();
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);
@ -207,7 +207,7 @@ protected:
gfxContext *aContext);
void NotifyGlyphMetricsChange();
PRBool ContainsPoint(float x, float y);
PRBool ContainsPoint(const nsPoint &aPoint);
PRBool GetGlobalTransform(gfxMatrix *aMatrix);
void SetupGlobalTransform(gfxContext *aContext);
nsresult GetHighlight(PRUint32 *charnum, PRUint32 *nchars,

View File

@ -85,8 +85,8 @@ protected:
public:
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsSVGRenderState *aContext, nsRect *aDirtyRect);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
NS_IMETHOD PaintSVG(nsSVGRenderState *aContext, nsIntRect *aDirtyRect);
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint);
// nsSVGPathGeometryFrame methods:
virtual PRUint16 GetHittestMask();
@ -224,7 +224,7 @@ nsSVGImageFrame::GetImageTransform()
//----------------------------------------------------------------------
// nsISVGChildFrame methods:
NS_IMETHODIMP
nsSVGImageFrame::PaintSVG(nsSVGRenderState *aContext, nsRect *aDirtyRect)
nsSVGImageFrame::PaintSVG(nsSVGRenderState *aContext, nsIntRect *aDirtyRect)
{
nsresult rv = NS_OK;
@ -296,8 +296,8 @@ nsSVGImageFrame::PaintSVG(nsSVGRenderState *aContext, nsRect *aDirtyRect)
return rv;
}
NS_IMETHODIMP
nsSVGImageFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
NS_IMETHODIMP_(nsIFrame*)
nsSVGImageFrame::GetFrameForPoint(const nsPoint &aPoint)
{
if (GetStyleDisplay()->IsScrollableOverflow() && mImageContainer) {
PRInt32 nativeWidth, nativeHeight;
@ -308,13 +308,13 @@ nsSVGImageFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
if (!nsSVGUtils::HitTestRect(fini,
0, 0, nativeWidth, nativeHeight,
x, y)) {
*hit = nsnull;
return NS_OK;
PresContext()->AppUnitsToDevPixels(aPoint.x),
PresContext()->AppUnitsToDevPixels(aPoint.y))) {
return nsnull;
}
}
return nsSVGPathGeometryFrame::GetFrameForPointSVG(x, y, hit);
return nsSVGPathGeometryFrame::GetFrameForPoint(aPoint);
}
nsIAtom *

View File

@ -83,12 +83,12 @@ public:
#endif
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsSVGRenderState *aContext, nsRect *aDirtyRect);
NS_IMETHOD PaintSVG(nsSVGRenderState *aContext, nsIntRect *aDirtyRect);
virtual void NotifySVGChanged(PRUint32 aFlags);
NS_IMETHOD SetMatrixPropagation(PRBool aPropagate);
NS_IMETHOD SetOverrideCTM(nsIDOMSVGMatrix *aCTM);
virtual already_AddRefed<nsIDOMSVGMatrix> GetOverrideCTM();
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint);
// nsSVGContainerFrame methods:
virtual already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();
@ -153,7 +153,7 @@ nsSVGInnerSVGFrame::GetType() const
// nsISVGChildFrame methods
NS_IMETHODIMP
nsSVGInnerSVGFrame::PaintSVG(nsSVGRenderState *aContext, nsRect *aDirtyRect)
nsSVGInnerSVGFrame::PaintSVG(nsSVGRenderState *aContext, nsIntRect *aDirtyRect)
{
gfxContextAutoSaveRestore autoSR;
@ -250,8 +250,8 @@ nsSVGInnerSVGFrame::GetOverrideCTM()
return matrix;
}
NS_IMETHODIMP
nsSVGInnerSVGFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
NS_IMETHODIMP_(nsIFrame*)
nsSVGInnerSVGFrame::GetFrameForPoint(const nsPoint &aPoint)
{
if (GetStyleDisplay()->IsScrollableOverflow()) {
float clipX, clipY, clipWidth, clipHeight;
@ -266,13 +266,13 @@ nsSVGInnerSVGFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
if (!nsSVGUtils::HitTestRect(clipTransform,
clipX, clipY, clipWidth, clipHeight,
x, y)) {
*hit = nsnull;
return NS_OK;
PresContext()->AppUnitsToDevPixels(aPoint.x),
PresContext()->AppUnitsToDevPixels(aPoint.y))) {
return nsnull;
}
}
return nsSVGInnerSVGFrameBase::GetFrameForPointSVG(x, y, hit);
return nsSVGInnerSVGFrameBase::GetFrameForPoint(aPoint);
}
//----------------------------------------------------------------------

View File

@ -205,7 +205,7 @@ nsSVGMarkerFrame::RegionMark(nsSVGPathGeometryFrame *aMarkedFrame,
// has already been used in calculating the current mark region, and
// the document has a marker reference loop.
if (mInUse)
return nsRect();
return nsRect(0,0,0,0);
AutoMarkerReferencer markerRef(this, aMarkedFrame);

View File

@ -196,7 +196,7 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsSVGRenderState *aContext,
PRUint8 *data = image->Data();
PRInt32 stride = image->Stride();
nsRect rect(0, 0, surfaceSize.width, surfaceSize.height);
nsIntRect rect(0, 0, surfaceSize.width, surfaceSize.height);
nsSVGUtils::UnPremultiplyImageDataAlpha(data, stride, rect);
nsSVGUtils::ConvertImageDataToLinearRGB(data, stride, rect);

View File

@ -511,22 +511,12 @@ nsSVGOuterSVGFrame::AttributeChanged(PRInt32 aNameSpaceID,
nsIFrame*
nsSVGOuterSVGFrame::GetFrameForPoint(const nsPoint& aPoint)
{
// XXX This algorithm is really bad. Because we only have a
// singly-linked list we have to test each and every SVG element for
// a hit. What we really want is a double-linked list.
float x = PresContext()->AppUnitsToDevPixels(aPoint.x);
float y = PresContext()->AppUnitsToDevPixels(aPoint.y);
nsRect thisRect(nsPoint(0,0), GetSize());
if (!thisRect.Contains(aPoint)) {
return nsnull;
}
nsIFrame* hit;
nsSVGUtils::HitTestChildren(this, x, y, &hit);
return hit;
return nsSVGUtils::HitTestChildren(this, aPoint);
}
//----------------------------------------------------------------------
@ -644,7 +634,7 @@ nsSVGOuterSVGFrame::InvalidateCoveredRegion(nsIFrame *aFrame)
return;
nsRect rect = nsSVGUtils::FindFilterInvalidation(aFrame, svgFrame->GetCoveredRegion());
InvalidateRect(rect);
Invalidate(rect);
}
PRBool
@ -656,25 +646,16 @@ nsSVGOuterSVGFrame::UpdateAndInvalidateCoveredRegion(nsIFrame *aFrame)
return PR_FALSE;
nsRect oldRegion = svgFrame->GetCoveredRegion();
InvalidateRect(nsSVGUtils::FindFilterInvalidation(aFrame, oldRegion));
Invalidate(nsSVGUtils::FindFilterInvalidation(aFrame, oldRegion));
svgFrame->UpdateCoveredRegion();
nsRect newRegion = svgFrame->GetCoveredRegion();
if (oldRegion == newRegion)
return PR_FALSE;
InvalidateRect(nsSVGUtils::FindFilterInvalidation(aFrame, newRegion));
Invalidate(nsSVGUtils::FindFilterInvalidation(aFrame, newRegion));
return PR_TRUE;
}
void
nsSVGOuterSVGFrame::InvalidateRect(nsRect aRect)
{
if (!aRect.IsEmpty()) {
aRect.ScaleRoundOut(PresContext()->AppUnitsPerDevPixel());
Invalidate(aRect);
}
}
PRBool
nsSVGOuterSVGFrame::IsRedrawSuspended()
{

View File

@ -95,7 +95,7 @@ public:
const nsHTMLReflowState* aReflowState,
nsDidReflowStatus aStatus);
nsIFrame* GetFrameForPoint(const nsPoint& aPoint);
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint& aPoint);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
@ -137,8 +137,6 @@ public:
// InvalidateCoveredRegion.
PRBool UpdateAndInvalidateCoveredRegion(nsIFrame *aFrame);
/* InvalidateRect takes a nsRect in screen pixel coordinates */
void InvalidateRect(nsRect aRect);
PRBool IsRedrawSuspended();
// nsISVGSVGFrame interface:

View File

@ -288,7 +288,7 @@ nsSVGPathGeometryFrame::GetType() const
NS_IMETHODIMP
nsSVGPathGeometryFrame::PaintSVG(nsSVGRenderState *aContext,
nsRect *aDirtyRect)
nsIntRect *aDirtyRect)
{
if (!GetStyleVisibility()->IsVisible())
return NS_OK;
@ -329,11 +329,9 @@ nsSVGPathGeometryFrame::PaintSVG(nsSVGRenderState *aContext,
return NS_OK;
}
NS_IMETHODIMP
nsSVGPathGeometryFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
NS_IMETHODIMP_(nsIFrame*)
nsSVGPathGeometryFrame::GetFrameForPoint(const nsPoint &aPoint)
{
*hit = nsnull;
PRUint16 fillRule, mask;
// check if we're a clipPath - cheaper than IsClipChild(), and we shouldn't
// get in here for other nondisplay children
@ -344,8 +342,8 @@ nsSVGPathGeometryFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
} else {
mask = GetHittestMask();
if (!mask || (!(mask & HITTEST_MASK_FORCE_TEST) &&
!mRect.Contains(nscoord(x), nscoord(y))))
return NS_OK;
!mRect.Contains(aPoint)))
return nsnull;
fillRule = GetStyleSVG()->mFillRule;
}
@ -354,7 +352,9 @@ nsSVGPathGeometryFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
gfxContext context(nsSVGUtils::GetThebesComputationalSurface());
GeneratePath(&context);
gfxPoint devicePoint = context.DeviceToUser(gfxPoint(x, y));
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);
@ -362,16 +362,16 @@ nsSVGPathGeometryFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
context.SetFillRule(gfxContext::FILL_RULE_WINDING);
if (mask & HITTEST_MASK_FILL)
isHit = context.PointInFill(devicePoint);
isHit = context.PointInFill(userSpacePoint);
if (!isHit && (mask & HITTEST_MASK_STROKE)) {
SetupCairoStrokeHitGeometry(&context);
isHit = context.PointInStroke(devicePoint);
isHit = context.PointInStroke(userSpacePoint);
}
if (isHit && nsSVGUtils::HitTestClip(this, x, y))
*hit = this;
if (isHit && nsSVGUtils::HitTestClip(this, aPoint))
return this;
return NS_OK;
return nsnull;
}
NS_IMETHODIMP_(nsRect)
@ -436,13 +436,13 @@ nsSVGPathGeometryFrame::UpdateCoveredRegion()
extent = context.GetUserStrokeExtent();
if (!IsDegeneratePath(extent)) {
extent = context.UserToDevice(extent);
mRect = nsSVGUtils::ToBoundingPixelRect(extent);
mRect = nsSVGUtils::ToAppPixelRect(PresContext(),extent);
}
} else {
context.IdentityMatrix();
extent = context.GetUserPathExtent();
if (!IsDegeneratePath(extent)) {
mRect = nsSVGUtils::ToBoundingPixelRect(extent);
mRect = nsSVGUtils::ToAppPixelRect(PresContext(),extent);
}
}

View File

@ -103,8 +103,8 @@ public:
protected:
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsSVGRenderState *aContext, nsRect *aDirtyRect);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
NS_IMETHOD PaintSVG(nsSVGRenderState *aContext, nsIntRect *aDirtyRect);
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint);
NS_IMETHOD_(nsRect) GetCoveredRegion();
NS_IMETHOD UpdateCoveredRegion();
NS_IMETHOD InitialUpdate();

View File

@ -66,8 +66,8 @@ public:
#endif
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsSVGRenderState* aContext, nsRect *aDirtyRect);
NS_IMETHOD GetFrameForPointSVG(float aX, float aY, nsIFrame** aResult);
NS_IMETHOD PaintSVG(nsSVGRenderState* aContext, nsIntRect *aDirtyRect);
NS_IMETHODIMP_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint);
NS_IMETHODIMP_(nsRect) GetCoveredRegion();
NS_IMETHOD UpdateCoveredRegion();
NS_IMETHOD InitialUpdate();
@ -100,7 +100,7 @@ nsSVGSwitchFrame::GetType() const
}
NS_IMETHODIMP
nsSVGSwitchFrame::PaintSVG(nsSVGRenderState* aContext, nsRect *aDirtyRect)
nsSVGSwitchFrame::PaintSVG(nsSVGRenderState* aContext, nsIntRect *aDirtyRect)
{
const nsStyleDisplay *display = mStyleContext->GetStyleDisplay();
if (display->mOpacity == 0.0)
@ -114,21 +114,19 @@ nsSVGSwitchFrame::PaintSVG(nsSVGRenderState* aContext, nsRect *aDirtyRect)
}
NS_IMETHODIMP
nsSVGSwitchFrame::GetFrameForPointSVG(float aX, float aY, nsIFrame** aResult)
NS_IMETHODIMP_(nsIFrame*)
nsSVGSwitchFrame::GetFrameForPoint(const nsPoint &aPoint)
{
*aResult = nsnull;
nsIFrame *kid = GetActiveChildFrame();
if (kid) {
nsISVGChildFrame* svgFrame;
CallQueryInterface(kid, &svgFrame);
if (svgFrame) {
svgFrame->GetFrameForPointSVG(aX, aY, aResult);
return svgFrame->GetFrameForPoint(aPoint);
}
}
return NS_OK;
return nsnull;
}
NS_IMETHODIMP_(nsRect)

View File

@ -235,19 +235,19 @@ nsSVGTextFrame::GetOverrideCTM()
}
NS_IMETHODIMP
nsSVGTextFrame::PaintSVG(nsSVGRenderState* aContext, nsRect *aDirtyRect)
nsSVGTextFrame::PaintSVG(nsSVGRenderState* aContext, nsIntRect *aDirtyRect)
{
UpdateGlyphPositioning(PR_TRUE);
return nsSVGTextFrameBase::PaintSVG(aContext, aDirtyRect);
}
NS_IMETHODIMP
nsSVGTextFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
NS_IMETHODIMP_(nsIFrame*)
nsSVGTextFrame::GetFrameForPoint(const nsPoint &aPoint)
{
UpdateGlyphPositioning(PR_TRUE);
return nsSVGTextFrameBase::GetFrameForPointSVG(x, y, hit);
return nsSVGTextFrameBase::GetFrameForPoint(aPoint);
}
NS_IMETHODIMP

View File

@ -83,8 +83,8 @@ public:
NS_IMETHOD NotifyRedrawUnsuspended();
// Override these four to ensure that UpdateGlyphPositioning is called
// to bring glyph positions up to date
NS_IMETHOD PaintSVG(nsSVGRenderState* aContext, nsRect *aDirtyRect);
NS_IMETHOD GetFrameForPointSVG(float x, float y, nsIFrame** hit);
NS_IMETHOD PaintSVG(nsSVGRenderState* aContext, nsIntRect *aDirtyRect);
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint & aPoint);
NS_IMETHOD UpdateCoveredRegion();
NS_IMETHOD InitialUpdate();
NS_IMETHOD GetBBox(nsIDOMSVGRect **_retval);

View File

@ -247,7 +247,7 @@ nsSVGUtils::GetFontXHeight(nsIContent *aContent)
void
nsSVGUtils::UnPremultiplyImageDataAlpha(PRUint8 *data,
PRInt32 stride,
const nsRect &rect)
const nsIntRect &rect)
{
for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
@ -273,7 +273,7 @@ nsSVGUtils::UnPremultiplyImageDataAlpha(PRUint8 *data,
void
nsSVGUtils::PremultiplyImageDataAlpha(PRUint8 *data,
PRInt32 stride,
const nsRect &rect)
const nsIntRect &rect)
{
for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
@ -296,7 +296,7 @@ nsSVGUtils::PremultiplyImageDataAlpha(PRUint8 *data,
void
nsSVGUtils::ConvertImageDataToLinearRGB(PRUint8 *data,
PRInt32 stride,
const nsRect &rect)
const nsIntRect &rect)
{
for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
@ -315,7 +315,7 @@ nsSVGUtils::ConvertImageDataToLinearRGB(PRUint8 *data,
void
nsSVGUtils::ConvertImageDataFromLinearRGB(PRUint8 *data,
PRInt32 stride,
const nsRect &rect)
const nsIntRect &rect)
{
for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
@ -919,7 +919,7 @@ nsSVGUtils::RemoveObserver(nsISupports *aObserver, nsISupports *aTarget)
void
nsSVGUtils::PaintChildWithEffects(nsSVGRenderState *aContext,
nsRect *aDirtyRect,
nsIntRect *aDirtyRect,
nsIFrame *aFrame)
{
nsISVGChildFrame *svgChildFrame;
@ -940,11 +940,13 @@ nsSVGUtils::PaintChildWithEffects(nsSVGRenderState *aContext,
/* Check if we need to draw anything */
if (aDirtyRect && svgChildFrame->HasValidCoveredRect()) {
nsRect rect = *aDirtyRect;
rect.ScaleRoundOut(aFrame->PresContext()->AppUnitsPerDevPixel());
if (effectProperties.mFilter) {
if (!aDirtyRect->Intersects(FindFilterInvalidation(aFrame, aFrame->GetRect())))
if (!rect.Intersects(FindFilterInvalidation(aFrame, aFrame->GetRect())))
return;
} else {
if (!aDirtyRect->Intersects(aFrame->GetRect()))
if (!rect.Intersects(aFrame->GetRect()))
return;
}
}
@ -1061,7 +1063,7 @@ nsSVGUtils::UpdateEffects(nsIFrame *aFrame)
}
PRBool
nsSVGUtils::HitTestClip(nsIFrame *aFrame, float x, float y)
nsSVGUtils::HitTestClip(nsIFrame *aFrame, const nsPoint &aPoint)
{
nsSVGEffects::EffectProperties props =
nsSVGEffects::GetEffectProperties(aFrame);
@ -1079,12 +1081,11 @@ nsSVGUtils::HitTestClip(nsIFrame *aFrame, float x, float y)
CallQueryInterface(aFrame, &SVGFrame);
nsCOMPtr<nsIDOMSVGMatrix> matrix = GetCanvasTM(aFrame);
return clipPathFrame->ClipHitTest(SVGFrame, matrix, x, y);
return clipPathFrame->ClipHitTest(SVGFrame, matrix, aPoint);
}
void
nsSVGUtils::HitTestChildren(nsIFrame *aFrame, float x, float y,
nsIFrame **aResult)
nsIFrame *
nsSVGUtils::HitTestChildren(nsIFrame *aFrame, const nsPoint &aPoint)
{
// XXX: The frame's children are linked in a singly-linked list in document
// order. If we were to hit test the children in this order we would need to
@ -1098,11 +1099,11 @@ nsSVGUtils::HitTestChildren(nsIFrame *aFrame, float x, float y,
// Note: While the child list pointers are reversed, any method which walks
// the list would only encounter a single child!
*aResult = nsnull;
nsIFrame* current = nsnull;
nsIFrame* next = aFrame->GetFirstChild(nsnull);
nsIFrame* result = nsnull;
// reverse sibling pointers
while (next) {
nsIFrame* temp = next->GetNextSibling();
@ -1116,9 +1117,9 @@ nsSVGUtils::HitTestChildren(nsIFrame *aFrame, float x, float y,
nsISVGChildFrame* SVGFrame;
CallQueryInterface(current, &SVGFrame);
if (SVGFrame) {
if (NS_SUCCEEDED(SVGFrame->GetFrameForPointSVG(x, y, aResult)) &&
*aResult)
break;
result = SVGFrame->GetFrameForPoint(aPoint);
if (result)
break;
}
// restore current frame's sibling pointer
nsIFrame* temp = current->GetNextSibling();
@ -1135,8 +1136,10 @@ nsSVGUtils::HitTestChildren(nsIFrame *aFrame, float x, float y,
current = temp;
}
if (*aResult && !HitTestClip(aFrame, x, y))
*aResult = nsnull;
if (result && !HitTestClip(aFrame, aPoint))
result = nsnull;
return result;
}
nsRect
@ -1159,22 +1162,21 @@ nsSVGUtils::GetCoveredRegion(const nsFrameList &aFrames)
}
nsRect
nsSVGUtils::ToBoundingPixelRect(double xmin, double ymin,
double xmax, double ymax)
nsSVGUtils::ToAppPixelRect(nsPresContext *aPresContext,
double xmin, double ymin,
double xmax, double ymax)
{
return nsRect(nscoord(floor(xmin)),
nscoord(floor(ymin)),
nscoord(ceil(xmax) - floor(xmin)),
nscoord(ceil(ymax) - floor(ymin)));
return ToAppPixelRect(aPresContext,
gfxRect(xmin, ymin, xmax - xmin, ymax - ymin));
}
nsRect
nsSVGUtils::ToBoundingPixelRect(const gfxRect& rect)
nsSVGUtils::ToAppPixelRect(nsPresContext *aPresContext, const gfxRect& rect)
{
return nsRect(nscoord(floor(rect.X())),
nscoord(floor(rect.Y())),
nscoord(ceil(rect.XMost()) - floor(rect.X())),
nscoord(ceil(rect.YMost()) - floor(rect.Y())));
return nsRect(aPresContext->DevPixelsToAppUnits(NSToIntFloor(rect.X())),
aPresContext->DevPixelsToAppUnits(NSToIntFloor(rect.Y())),
aPresContext->DevPixelsToAppUnits(NSToIntCeil(rect.XMost()) - NSToIntFloor(rect.X())),
aPresContext->DevPixelsToAppUnits(NSToIntCeil(rect.YMost()) - NSToIntFloor(rect.Y())));
}
gfxIntSize

View File

@ -203,25 +203,25 @@ public:
*/
static void UnPremultiplyImageDataAlpha(PRUint8 *data,
PRInt32 stride,
const nsRect &rect);
const nsIntRect &rect);
/*
* Converts image data from unpremultipled to premultiplied alpha
*/
static void PremultiplyImageDataAlpha(PRUint8 *data,
PRInt32 stride,
const nsRect &rect);
const nsIntRect &rect);
/*
* Converts image data from premultiplied sRGB to Linear RGB
*/
static void ConvertImageDataToLinearRGB(PRUint8 *data,
PRInt32 stride,
const nsRect &rect);
const nsIntRect &rect);
/*
* Converts image data from LinearRGB to premultiplied sRGB
*/
static void ConvertImageDataFromLinearRGB(PRUint8 *data,
PRInt32 stride,
const nsRect &rect);
const nsIntRect &rect);
/*
* Report a localized error message to the error console.
@ -322,7 +322,7 @@ public:
/**
* Get the covered region for a frame. Return null if it's not an SVG frame.
* @param aRect gets a rectangle in *pixels*
* @param aRect gets a rectangle in app units
* @return the outer SVG frame which aRect is relative to
*/
static nsIFrame*
@ -341,7 +341,7 @@ public:
* redrawn, in frame offset pixel coordinates */
static void
PaintChildWithEffects(nsSVGRenderState *aContext,
nsRect *aDirtyRect,
nsIntRect *aDirtyRect,
nsIFrame *aFrame);
/**
@ -352,16 +352,14 @@ public:
UpdateEffects(nsIFrame *aFrame);
/* Hit testing - check if point hits the clipPath of indicated
* frame. (x,y) are specified in device pixels relative to the
* origin of the outer svg frame. Returns true if no clipPath
* set. */
* frame. Returns true if no clipPath set. */
static PRBool
HitTestClip(nsIFrame *aFrame, float x, float y);
/* Hit testing - check if point hits any children of frame. */
HitTestClip(nsIFrame *aFrame, const nsPoint &aPoint);
static void
HitTestChildren(nsIFrame *aFrame, float x, float y, nsIFrame **aResult);
/* Hit testing - check if point hits any children of frame. */
static nsIFrame *
HitTestChildren(nsIFrame *aFrame, const nsPoint &aPoint);
/* Add observation of an nsISVGValue to an nsISVGValueObserver */
static void
@ -390,12 +388,13 @@ public:
GetCoveredRegion(const nsFrameList &aFrames);
/*
* Inflate a floating-point rect to a nsRect
* Convert a rect from device pixel units to app pixel units by inflation.
*/
static nsRect
ToBoundingPixelRect(double xmin, double ymin, double xmax, double ymax);
ToAppPixelRect(nsPresContext *aPresContext,
double xmin, double ymin, double xmax, double ymax);
static nsRect
ToBoundingPixelRect(const gfxRect& rect);
ToAppPixelRect(nsPresContext *aPresContext, const gfxRect& rect);
/*
* Convert a surface size to an integer for use by thebes