Bug 495938. Stop using nsIDOMSVGRect objects on the stack. r=longsonr

This commit is contained in:
Jonathan Watt 2009-06-11 17:21:03 +02:00
Родитель 2ee7e4670a
Коммит bb7678b0ca
16 изменённых файлов: 108 добавлений и 247 удалений

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

@ -48,7 +48,7 @@
#include "nsIDOMSVGPoint.h"
#include "nsSVGUtils.h"
#include "nsDOMError.h"
#include "nsIDOMSVGRect.h"
#include "nsSVGRect.h"
//----------------------------------------------------------------------
// nsISupports methods
@ -95,10 +95,8 @@ NS_IMETHODIMP nsSVGGraphicElement::GetBBox(nsIDOMSVGRect **_retval)
return NS_ERROR_FAILURE;
nsISVGChildFrame* svgframe = do_QueryFrame(frame);
NS_ASSERTION(svgframe, "wrong frame type");
if (svgframe) {
*_retval = nsSVGUtils::GetBBox(frame).get();
return NS_OK;
return NS_NewSVGRect(_retval, nsSVGUtils::GetBBox(frame));
}
return NS_ERROR_FAILURE;
}

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

@ -39,7 +39,6 @@
#include "nsSVGLength.h"
#include "nsIDOMSVGMatrix.h"
#include "nsIDOMSVGRect.h"
#include "nsGkAtoms.h"
#include "nsSVGValue.h"
#include "nsTextFormatter.h"

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

@ -770,12 +770,9 @@ nsSVGSVGElement::GetBBox(nsIDOMSVGRect **_retval)
nsISVGChildFrame* svgframe = do_QueryFrame(frame);
if (svgframe) {
*_retval = nsSVGUtils::GetBBox(frame).get();
return NS_OK;
} else {
// XXX: outer svg
return NS_ERROR_NOT_IMPLEMENTED;
return NS_NewSVGRect(_retval, nsSVGUtils::GetBBox(frame));
}
return NS_ERROR_NOT_IMPLEMENTED; // XXX: outer svg
}
/* nsIDOMSVGMatrix getCTM (); */

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

@ -48,7 +48,6 @@
class gfxContext;
class nsPresContext;
class nsIDOMSVGRect;
class nsIDOMSVGMatrix;
class nsSVGRenderState;

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

@ -42,7 +42,6 @@
#include "nsSVGUtils.h"
#include "nsSVGClipPathElement.h"
#include "gfxContext.h"
#include "nsIDOMSVGRect.h"
#include "nsSVGMatrix.h"
//----------------------------------------------------------------------

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

@ -111,22 +111,14 @@ nsAutoFilterInstance::nsAutoFilterInstance(nsIFrame *aTarget,
PRUint16 primitiveUnits =
filter->mEnumAttributes[nsSVGFilterElement::PRIMITIVEUNITS].GetAnimValue();
nsCOMPtr<nsIDOMSVGRect> bbox;
gfxRect bbox;
if (aOverrideSourceBBox) {
NS_NewSVGRect(getter_AddRefs(bbox),
aOverrideSourceBBox->x, aOverrideSourceBBox->y,
aOverrideSourceBBox->width, aOverrideSourceBBox->height);
bbox = gfxRect(aOverrideSourceBBox->x, aOverrideSourceBBox->y,
aOverrideSourceBBox->width, aOverrideSourceBBox->height);
} else {
bbox = nsSVGUtils::GetBBox(aTarget);
}
if (!bbox &&
(filterUnits == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX ||
primitiveUnits == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)) {
// XXX dispatch error console warning?
return;
}
// Get the filter region (in the filtered element's user space):
// XXX if filterUnits is set (or has defaulted) to objectBoundingBox, we

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

@ -155,20 +155,11 @@ nsSVGFilterInstance::BuildSources()
mSourceAlpha.mImage.mFilterPrimitiveSubregion = filterRegion;
nsIntRect sourceBoundsInt;
if (mTargetBBox) {
float x, y, w, h;
mTargetBBox->GetX(&x);
mTargetBBox->GetY(&y);
mTargetBBox->GetWidth(&w);
mTargetBBox->GetHeight(&h);
gfxRect sourceBounds = UserSpaceToFilterSpace(gfxRect(x, y, w, h));
sourceBounds.RoundOut();
// Detect possible float->int overflow
if (NS_FAILED(nsSVGUtils::GfxRectToIntRect(sourceBounds, &sourceBoundsInt)))
return NS_ERROR_FAILURE;
}
gfxRect sourceBounds = UserSpaceToFilterSpace(mTargetBBox);
sourceBounds.RoundOut();
// Detect possible float->int overflow
if (NS_FAILED(nsSVGUtils::GfxRectToIntRect(sourceBounds, &sourceBoundsInt)))
return NS_ERROR_FAILURE;
mSourceColorAlpha.mResultBoundingBox = sourceBoundsInt;
mSourceAlpha.mResultBoundingBox = sourceBoundsInt;

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

@ -38,7 +38,6 @@
#define __NS_SVGFILTERINSTANCE_H__
#include "nsIDOMSVGLength.h"
#include "nsIDOMSVGRect.h"
#include "nsIDOMSVGFilters.h"
#include "nsRect.h"
#include "nsIContent.h"
@ -53,6 +52,7 @@ class nsSVGLength2;
class nsSVGElement;
class nsSVGFilterElement;
class nsSVGFilterPaintCallback;
struct gfxRect;
/**
* This class performs all filter processing.
@ -69,7 +69,7 @@ public:
nsSVGFilterInstance(nsIFrame *aTargetFrame,
nsSVGFilterPaintCallback *aPaintCallback,
nsSVGFilterElement *aFilterElement,
nsIDOMSVGRect *aTargetBBox,
const gfxRect &aTargetBBox,
const gfxRect& aFilterRect,
const nsIntSize& aFilterSpaceSize,
nsIDOMSVGMatrix *aFilterSpaceToDeviceSpaceTransform,
@ -184,7 +184,7 @@ private:
nsIFrame* mTargetFrame;
nsSVGFilterPaintCallback* mPaintCallback;
nsSVGFilterElement* mFilterElement;
nsCOMPtr<nsIDOMSVGRect> mTargetBBox;
gfxRect mTargetBBox;
nsCOMPtr<nsIDOMSVGMatrix> mFilterSpaceToDeviceSpaceTransform;
gfxRect mFilterRect;
nsIntSize mFilterSpaceSize;

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

@ -47,7 +47,6 @@
#include "nsSVGGeometryFrame.h"
#include "nsSVGGradientFrame.h"
#include "gfxContext.h"
#include "nsIDOMSVGRect.h"
#include "gfxPattern.h"
//----------------------------------------------------------------------
@ -168,15 +167,8 @@ nsSVGGradientFrame::GetGradientTransform(nsSVGGeometryFrame *aSource)
nsIFrame *frame = (callerType == nsGkAtoms::svgGlyphFrame) ?
aSource->GetParent() : aSource;
nsCOMPtr<nsIDOMSVGRect> rect = nsSVGUtils::GetBBox(frame);
if (rect) {
float x, y, width, height;
rect->GetX(&x);
rect->GetY(&y);
rect->GetWidth(&width);
rect->GetHeight(&height);
bboxMatrix = gfxMatrix(width, 0, 0, height, x, y);
}
gfxRect bbox = nsSVGUtils::GetBBox(frame);
bboxMatrix = gfxMatrix(bbox.Width(), 0, 0, bbox.Height(), bbox.X(), bbox.Y());
}
nsSVGGradientElement *element =

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

@ -103,6 +103,8 @@ private:
PRUint32 GetStopCount();
void GetStopInformation(PRInt32 aIndex,
float *aOffset, nscolor *aColor, float *aStopOpacity);
// Will be singular for gradientUnits="objectBoundingBox" with an empty bbox.
gfxMatrix GetGradientTransform(nsSVGGeometryFrame *aSource);
protected:

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

@ -40,7 +40,6 @@
#include "nsSVGMaskElement.h"
#include "nsIDOMSVGMatrix.h"
#include "gfxContext.h"
#include "nsIDOMSVGRect.h"
#include "gfxImageSurface.h"
//----------------------------------------------------------------------
@ -76,11 +75,9 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsSVGRenderState *aContext,
PRUint16 units =
mask->mEnumAttributes[nsSVGMaskElement::MASKUNITS].GetAnimValue();
nsCOMPtr<nsIDOMSVGRect> bbox;
gfxRect bbox;
if (units == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
bbox = nsSVGUtils::GetBBox(aParent);
if (!bbox)
return nsnull;
}
gfxRect maskArea = nsSVGUtils::GetRelativeRect(units,

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

@ -43,7 +43,6 @@
#include "nsStyleContext.h"
#include "nsINameSpaceManager.h"
#include "nsISVGChildFrame.h"
#include "nsIDOMSVGRect.h"
#include "nsSVGMatrix.h"
#include "nsSVGRect.h"
#include "nsSVGUtils.h"
@ -56,11 +55,6 @@
#include "gfxPlatform.h"
#include "gfxPattern.h"
#ifdef DEBUG_scooter
static void printCTM(char *msg, gfxMatrix aCTM);
static void printCTM(char *msg, nsIDOMSVGMatrix *aCTM);
static void printRect(char *msg, nsIDOMSVGRect *aRect);
#endif
//----------------------------------------------------------------------
// Implementation
@ -202,10 +196,10 @@ nsSVGPatternFrame::PaintPattern(gfxASurface** surface,
// Get all of the information we need from our "caller" -- i.e.
// the geometry that is being rendered with a pattern
nsSVGElement *callerContent;
nsCOMPtr<nsIDOMSVGRect> callerBBox;
gfxRect callerBBox;
nsCOMPtr<nsIDOMSVGMatrix> callerCTM;
if (NS_FAILED(GetCallerGeometry(getter_AddRefs(callerCTM),
getter_AddRefs(callerBBox),
if (NS_FAILED(GetTargetGeometry(getter_AddRefs(callerCTM),
&callerBBox,
&callerContent, aSource)))
return NS_ERROR_FAILURE;
@ -217,28 +211,16 @@ nsSVGPatternFrame::PaintPattern(gfxASurface** surface,
// Get the bounding box of the pattern. This will be used to determine
// the size of the surface, and will also be used to define the bounding
// box for the pattern tile.
nsCOMPtr<nsIDOMSVGRect> bbox;
if (NS_FAILED(GetPatternRect(getter_AddRefs(bbox),
callerBBox, callerCTM,
callerContent)))
return NS_ERROR_FAILURE;
gfxRect bbox = GetPatternRect(callerBBox, callerCTM, callerContent);
// Get the transformation matrix that we will hand to the renderer's pattern
// routine.
*patternMatrix = GetPatternMatrix(bbox, callerBBox, callerCTM);
#ifdef DEBUG_scooter
printRect("Geometry Rect: ", callerBBox);
printRect("Pattern Rect: ", bbox);
printCTM("Pattern TM ", *patternMatrix);
printCTM("Child TM ", mCTM);
#endif
// Now that we have all of the necessary geometries, we can
// create our surface.
float patternWidth, patternHeight;
bbox->GetWidth(&patternWidth);
bbox->GetHeight(&patternHeight);
float patternWidth = bbox.Width();
float patternHeight = bbox.Height();
PRBool resultOverflows;
gfxIntSize surfaceSize =
@ -264,10 +246,6 @@ nsSVGPatternFrame::PaintPattern(gfxASurface** surface,
patternHeight / surfaceSize.height);
}
#ifdef DEBUG_scooter
printf("Creating %dX%d surface\n", int(surfaceSize.width), int(surfaceSize.height));
#endif
nsRefPtr<gfxASurface> tmpSurface =
gfxPlatform::GetPlatform()->CreateOffscreenSurface(surfaceSize,
gfxASurface::ImageFormatARGB32);
@ -494,11 +472,10 @@ nsSVGPatternFrame::GetPatternWithAttr(nsIAtom *aAttrName, nsIContent *aDefault)
// Helper functions
// -------------------------------------------------------------------------
nsresult
nsSVGPatternFrame::GetPatternRect(nsIDOMSVGRect **patternRect,
nsIDOMSVGRect *bbox,
nsIDOMSVGMatrix *callerCTM,
nsSVGElement *content)
gfxRect
nsSVGPatternFrame::GetPatternRect(const gfxRect &aTargetBBox,
nsIDOMSVGMatrix *aTargetCTM,
nsSVGElement *aTarget)
{
// Get our type
PRUint16 type = GetPatternUnits();
@ -514,19 +491,19 @@ nsSVGPatternFrame::GetPatternRect(nsIDOMSVGRect **patternRect,
tmpWidth = GetWidth();
if (type == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
x = nsSVGUtils::ObjectSpace(bbox, tmpX);
y = nsSVGUtils::ObjectSpace(bbox, tmpY);
width = nsSVGUtils::ObjectSpace(bbox, tmpWidth);
height = nsSVGUtils::ObjectSpace(bbox, tmpHeight);
x = nsSVGUtils::ObjectSpace(aTargetBBox, tmpX);
y = nsSVGUtils::ObjectSpace(aTargetBBox, tmpY);
width = nsSVGUtils::ObjectSpace(aTargetBBox, tmpWidth);
height = nsSVGUtils::ObjectSpace(aTargetBBox, tmpHeight);
} else {
float scale = nsSVGUtils::MaxExpansion(callerCTM);
x = nsSVGUtils::UserSpace(content, tmpX) * scale;
y = nsSVGUtils::UserSpace(content, tmpY) * scale;
width = nsSVGUtils::UserSpace(content, tmpWidth) * scale;
height = nsSVGUtils::UserSpace(content, tmpHeight) * scale;
float scale = nsSVGUtils::MaxExpansion(aTargetCTM);
x = nsSVGUtils::UserSpace(aTarget, tmpX) * scale;
y = nsSVGUtils::UserSpace(aTarget, tmpY) * scale;
width = nsSVGUtils::UserSpace(aTarget, tmpWidth) * scale;
height = nsSVGUtils::UserSpace(aTarget, tmpHeight) * scale;
}
return NS_NewSVGRect(patternRect, x, y, width, height);
return gfxRect(x, y, width, height);
}
static float
@ -537,7 +514,7 @@ GetLengthValue(const nsSVGLength2 *aLength)
nsresult
nsSVGPatternFrame::ConstructCTM(nsIDOMSVGMatrix **aCTM,
nsIDOMSVGRect *callerBBox,
const gfxRect &callerBBox,
nsIDOMSVGMatrix *callerCTM)
{
nsCOMPtr<nsIDOMSVGMatrix> tCTM, tempTM;
@ -547,12 +524,8 @@ nsSVGPatternFrame::ConstructCTM(nsIDOMSVGMatrix **aCTM,
PRUint16 type = GetPatternContentUnits();
if (type == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
// Use the bounding box
float width, height;
callerBBox->GetWidth(&width);
callerBBox->GetHeight(&height);
NS_NewSVGMatrix(getter_AddRefs(tCTM), width, 0.0f, 0.0f,
height, 0.0f, 0.0f);
NS_NewSVGMatrix(getter_AddRefs(tCTM), callerBBox.Width(), 0.0f, 0.0f,
callerBBox.Height(), 0.0f, 0.0f);
} else {
float scale = nsSVGUtils::MaxExpansion(callerCTM);
NS_NewSVGMatrix(getter_AddRefs(tCTM), scale, 0, 0, scale, 0, 0);
@ -582,25 +555,21 @@ nsSVGPatternFrame::ConstructCTM(nsIDOMSVGMatrix **aCTM,
}
gfxMatrix
nsSVGPatternFrame::GetPatternMatrix(nsIDOMSVGRect *bbox,
nsIDOMSVGRect *callerBBox,
nsSVGPatternFrame::GetPatternMatrix(const gfxRect &bbox,
const gfxRect &callerBBox,
nsIDOMSVGMatrix *callerCTM)
{
// Get the pattern transform
gfxMatrix patternTransform = GetPatternTransform();
// We really want the pattern matrix to handle translations
float minx, miny;
bbox->GetX(&minx);
bbox->GetY(&miny);
float minx = bbox.X();
float miny = bbox.Y();
PRUint16 type = GetPatternContentUnits();
if (type == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
float x, y;
callerBBox->GetX(&x);
callerBBox->GetY(&y);
minx += x;
miny += y;
minx += callerBBox.X();
miny += callerBBox.Y();
}
float scale = 1.0f / nsSVGUtils::MaxExpansion(callerCTM);
@ -611,71 +580,54 @@ nsSVGPatternFrame::GetPatternMatrix(nsIDOMSVGRect *bbox,
}
nsresult
nsSVGPatternFrame::GetCallerGeometry(nsIDOMSVGMatrix **aCTM,
nsIDOMSVGRect **aBBox,
nsSVGElement **aContent,
nsSVGGeometryFrame *aSource)
nsSVGPatternFrame::GetTargetGeometry(nsIDOMSVGMatrix **aCTM,
gfxRect *aBBox,
nsSVGElement **aTargetContent,
nsSVGGeometryFrame *aTarget)
{
*aCTM = nsnull;
*aBBox = nsnull;
*aContent = nsnull;
*aTargetContent = nsnull;
// Make sure the callerContent is an SVG element. If we are attempting
// to paint a pattern for text, then the content will be the #text, so we
// actually want the parent, which should be the <svg:text> or <svg:tspan>
// element.
nsIAtom *callerType = aSource->GetType();
nsIAtom *callerType = aTarget->GetType();
if (callerType == nsGkAtoms::svgGlyphFrame) {
*aContent = static_cast<nsSVGElement*>
(aSource->GetContent()->GetParent());
*aTargetContent = static_cast<nsSVGElement*>
(aTarget->GetContent()->GetParent());
} else {
*aContent = static_cast<nsSVGElement*>(aSource->GetContent());
*aTargetContent = static_cast<nsSVGElement*>(aTarget->GetContent());
}
NS_ASSERTION(aContent,"Caller does not have any content!");
if (!aContent)
NS_ASSERTION(aTargetContent,"Caller does not have any content!");
if (!aTargetContent)
return NS_ERROR_FAILURE;
if (callerType == nsGkAtoms::svgGlyphFrame) {
*aBBox = nsSVGUtils::GetBBox(aSource->GetParent()).get();
*aBBox = nsSVGUtils::GetBBox(aTarget->GetParent());
} else {
*aBBox = nsSVGUtils::GetBBox(aSource).get();
*aBBox = nsSVGUtils::GetBBox(aTarget);
}
// Sanity check
PRUint16 type = GetPatternUnits();
if (type == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
float width, height;
(*aBBox)->GetWidth(&width);
(*aBBox)->GetHeight(&height);
if (width <= 0 || height <= 0) {
if (aBBox->Width() <= 0 || aBBox->Height() <= 0) {
return NS_ERROR_FAILURE;
}
}
// Get the transformation matrix from our calling geometry
*aCTM = NS_NewSVGMatrix(aSource->GetCanvasTM()).get();
*aCTM = NS_NewSVGMatrix(aTarget->GetCanvasTM()).get();
// OK, now fix up the bounding box to reflect user coordinates
// We handle device unit scaling in pattern matrix
{
float x, y, width, height;
(*aBBox)->GetX(&x);
(*aBBox)->GetY(&y);
(*aBBox)->GetWidth(&width);
(*aBBox)->GetHeight(&height);
float scale = nsSVGUtils::MaxExpansion(*aCTM);
#ifdef DEBUG_scooter
fprintf(stderr, "pattern scale %f\n", scale);
fprintf(stderr, "x,y,width,height: %f %f %f %f\n", x, y, width, height);
#endif
x *= scale;
y *= scale;
width *= scale;
height *= scale;
(*aBBox)->SetX(x);
(*aBBox)->SetY(y);
(*aBBox)->SetWidth(width);
(*aBBox)->SetHeight(height);
if (scale <= 0) {
return NS_ERROR_FAILURE;
}
aBBox->Scale(scale);
}
return NS_OK;
}
@ -736,32 +688,3 @@ nsIFrame* NS_NewSVGPatternFrame(nsIPresShell* aPresShell,
return new (aPresShell) nsSVGPatternFrame(aContext);
}
#ifdef DEBUG_scooter
static void printCTM(char *msg, gfxMatrix aCTM)
{
printf("%s {%f,%f,%f,%f,%f,%f}\n", msg,
aCTM.xx, aCTM.yx, aCTM.xy, aCTM.yy, aCTM.x0, aCTM.y0);
}
static void printCTM(char *msg, nsIDOMSVGMatrix *aCTM)
{
float a,b,c,d,e,f;
aCTM->GetA(&a);
aCTM->GetB(&b);
aCTM->GetC(&c);
aCTM->GetD(&d);
aCTM->GetE(&e);
aCTM->GetF(&f);
printf("%s {%f,%f,%f,%f,%f,%f}\n",msg,a,b,c,d,e,f);
}
static void printRect(char *msg, nsIDOMSVGRect *aRect)
{
float x,y,width,height;
aRect->GetX(&x);
aRect->GetY(&y);
aRect->GetWidth(&width);
aRect->GetHeight(&height);
printf("%s {%f,%f,%f,%f}\n",msg,x,y,width,height);
}
#endif

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

@ -128,20 +128,19 @@ protected:
const nsSVGPreserveAspectRatio &GetPreserveAspectRatio();
NS_IMETHOD GetPatternFirstChild(nsIFrame **kid);
nsresult GetPatternRect(nsIDOMSVGRect **patternRect,
nsIDOMSVGRect *bbox,
gfxRect GetPatternRect(const gfxRect &bbox,
nsIDOMSVGMatrix *callerCTM,
nsSVGElement *content);
gfxMatrix GetPatternMatrix(nsIDOMSVGRect *bbox,
nsIDOMSVGRect *callerBBox,
gfxMatrix GetPatternMatrix(const gfxRect &bbox,
const gfxRect &callerBBox,
nsIDOMSVGMatrix *callerCTM);
nsresult ConstructCTM(nsIDOMSVGMatrix **ctm,
nsIDOMSVGRect *callerBBox,
const gfxRect &callerBBox,
nsIDOMSVGMatrix *callerCTM);
nsresult GetCallerGeometry(nsIDOMSVGMatrix **aCTM,
nsIDOMSVGRect **aBBox,
nsSVGElement **aContent,
nsSVGGeometryFrame *aSource);
nsresult GetTargetGeometry(nsIDOMSVGMatrix **aCTM,
gfxRect *aBBox,
nsSVGElement **aTargetContent,
nsSVGGeometryFrame *aTarget);
private:
// this is a *temporary* reference to the frame of the element currently

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

@ -38,7 +38,6 @@
#include "nsSVGGFrame.h"
#include "nsSVGSwitchElement.h"
#include "nsIDOMSVGRect.h"
#include "gfxRect.h"
#include "gfxMatrix.h"

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

@ -637,24 +637,19 @@ nsSVGUtils::ComputeNormalizedHypotenuse(double aWidth, double aHeight)
}
float
nsSVGUtils::ObjectSpace(nsIDOMSVGRect *aRect, const nsSVGLength2 *aLength)
nsSVGUtils::ObjectSpace(const gfxRect &aRect, const nsSVGLength2 *aLength)
{
float fraction, axis;
switch (aLength->GetCtxType()) {
case X:
aRect->GetWidth(&axis);
axis = aRect.Width();
break;
case Y:
aRect->GetHeight(&axis);
axis = aRect.Height();
break;
case XY:
{
float width, height;
aRect->GetWidth(&width);
aRect->GetHeight(&height);
axis = float(ComputeNormalizedHypotenuse(width, height));
}
axis = float(ComputeNormalizedHypotenuse(aRect.Width(), aRect.Height()));
}
if (aLength->IsPercentage()) {
@ -1300,33 +1295,28 @@ nsSVGUtils::GfxRectToIntRect(const gfxRect& aIn, nsIntRect* aOut)
? NS_OK : NS_ERROR_FAILURE;
}
already_AddRefed<nsIDOMSVGRect>
gfxRect
nsSVGUtils::GetBBox(nsIFrame *aFrame)
{
gfxRect bbox;
nsISVGChildFrame *svg = do_QueryFrame(aFrame);
if (!svg) {
nsIDOMSVGRect *rect = nsnull;
gfxRect r = nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(aFrame);
NS_NewSVGRect(&rect, r);
return rect;
if (svg) {
bbox = svg->GetBBoxContribution(gfxMatrix());
} else {
bbox = nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(aFrame);
}
nsCOMPtr<nsIDOMSVGRect> bbox;
NS_NewSVGRect(getter_AddRefs(bbox), svg->GetBBoxContribution(gfxMatrix()));
return bbox.forget();
NS_ASSERTION(bbox.Width() >= 0.0 && bbox.Height() >= 0.0, "Invalid bbox!");
return bbox;
}
gfxRect
nsSVGUtils::GetRelativeRect(PRUint16 aUnits, const nsSVGLength2 *aXYWH,
nsIDOMSVGRect *aBBox, nsIFrame *aFrame)
const gfxRect &aBBox, nsIFrame *aFrame)
{
float x, y, width, height;
if (aUnits == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
aBBox->GetX(&x);
x += ObjectSpace(aBBox, &aXYWH[0]);
aBBox->GetY(&y);
y += ObjectSpace(aBBox, &aXYWH[1]);
x = aBBox.X() + ObjectSpace(aBBox, &aXYWH[0]);
y = aBBox.Y() + ObjectSpace(aBBox, &aXYWH[1]);
width = ObjectSpace(aBBox, &aXYWH[2]);
height = ObjectSpace(aBBox, &aXYWH[3]);
} else {
@ -1381,32 +1371,10 @@ nsSVGUtils::AdjustMatrixForUnits(nsIDOMSVGMatrix *aMatrix,
if (aFrame &&
aUnits->GetAnimValue() == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
float minx, miny, width, height;
PRBool gotRect = PR_FALSE;
if (aFrame->IsFrameOfType(nsIFrame::eSVG)) {
nsCOMPtr<nsIDOMSVGRect> rect = GetBBox(aFrame);
if (rect) {
gotRect = PR_TRUE;
rect->GetX(&minx);
rect->GetY(&miny);
rect->GetWidth(&width);
rect->GetHeight(&height);
}
} else {
gotRect = PR_TRUE;
gfxRect r = nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(aFrame);
minx = r.X();
miny = r.Y();
width = r.Width();
height = r.Height();
}
if (gotRect) {
nsCOMPtr<nsIDOMSVGMatrix> tmp;
aMatrix->Translate(minx, miny, getter_AddRefs(tmp));
tmp->ScaleNonUniform(width, height, getter_AddRefs(fini));
}
gfxRect bbox = GetBBox(aFrame);
nsCOMPtr<nsIDOMSVGMatrix> tmp;
aMatrix->Translate(bbox.X(), bbox.Y(), getter_AddRefs(tmp));
tmp->ScaleNonUniform(bbox.Width(), bbox.Height(), getter_AddRefs(fini));
}
nsIDOMSVGMatrix* retval = fini.get();
@ -1510,3 +1478,4 @@ nsSVGRenderState::GetRenderingContext(nsIFrame *aFrame)
}
return mRenderingContext;
}

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

@ -73,7 +73,6 @@ class gfxContext;
class gfxASurface;
class gfxPattern;
class gfxImageSurface;
struct gfxRect;
struct gfxMatrix;
struct gfxSize;
struct gfxIntSize;
@ -308,7 +307,7 @@ public:
Input: rect - bounding box
length - length to be converted
*/
static float ObjectSpace(nsIDOMSVGRect *aRect, const nsSVGLength2 *aLength);
static float ObjectSpace(const gfxRect &aRect, const nsSVGLength2 *aLength);
/* Computes the input length in terms of user space coordinates.
Input: content - object to be used for determining user space
@ -466,7 +465,14 @@ public:
static float
MaxExpansion(nsIDOMSVGMatrix *aMatrix);
/* Take a CTM and adjust for object bounding box coordinates, if needed */
/**
* Take the CTM to userspace for an element, and adjust it to a CTM to its
* object bounding box space if aUnits is SVG_UNIT_TYPE_OBJECTBOUNDINGBOX.
* (I.e. so that [0,0] is at the top left of its bbox, and [1,1] is at the
* bottom right of its bbox).
*
* If the bbox is empty, this will return a singular matrix.
*/
static already_AddRefed<nsIDOMSVGMatrix>
AdjustMatrixForUnits(nsIDOMSVGMatrix *aMatrix,
nsSVGEnum *aUnits,
@ -476,8 +482,7 @@ public:
* Get bounding-box for aFrame. Matrix propagation is disabled so the
* bounding box is computed in terms of aFrame's own user space.
*/
static already_AddRefed<nsIDOMSVGRect>
GetBBox(nsIFrame *aFrame);
static gfxRect GetBBox(nsIFrame *aFrame);
/**
* Compute a rectangle in userSpaceOnUse or objectBoundingBoxUnits.
* @param aXYWH pointer to 4 consecutive nsSVGLength2 objects containing
@ -488,8 +493,8 @@ public:
* may be null if aUnits is SVG_UNIT_TYPE_OBJECTBOUNDINGBOX
*/
static gfxRect
GetRelativeRect(PRUint16 aUnits, const nsSVGLength2 *aXYWH, nsIDOMSVGRect *aBBox,
nsIFrame *aFrame);
GetRelativeRect(PRUint16 aUnits, const nsSVGLength2 *aXYWH,
const gfxRect &aBBox, nsIFrame *aFrame);
/**
* Find the first frame, starting with aStartFrame and going up its