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

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

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

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

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

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

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

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

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

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

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

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

@ -155,20 +155,11 @@ nsSVGFilterInstance::BuildSources()
mSourceAlpha.mImage.mFilterPrimitiveSubregion = filterRegion; mSourceAlpha.mImage.mFilterPrimitiveSubregion = filterRegion;
nsIntRect sourceBoundsInt; nsIntRect sourceBoundsInt;
if (mTargetBBox) { gfxRect sourceBounds = UserSpaceToFilterSpace(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(); sourceBounds.RoundOut();
// Detect possible float->int overflow // Detect possible float->int overflow
if (NS_FAILED(nsSVGUtils::GfxRectToIntRect(sourceBounds, &sourceBoundsInt))) if (NS_FAILED(nsSVGUtils::GfxRectToIntRect(sourceBounds, &sourceBoundsInt)))
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
}
mSourceColorAlpha.mResultBoundingBox = sourceBoundsInt; mSourceColorAlpha.mResultBoundingBox = sourceBoundsInt;
mSourceAlpha.mResultBoundingBox = sourceBoundsInt; mSourceAlpha.mResultBoundingBox = sourceBoundsInt;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -73,7 +73,6 @@ class gfxContext;
class gfxASurface; class gfxASurface;
class gfxPattern; class gfxPattern;
class gfxImageSurface; class gfxImageSurface;
struct gfxRect;
struct gfxMatrix; struct gfxMatrix;
struct gfxSize; struct gfxSize;
struct gfxIntSize; struct gfxIntSize;
@ -308,7 +307,7 @@ public:
Input: rect - bounding box Input: rect - bounding box
length - length to be converted 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. /* Computes the input length in terms of user space coordinates.
Input: content - object to be used for determining user space Input: content - object to be used for determining user space
@ -466,7 +465,14 @@ public:
static float static float
MaxExpansion(nsIDOMSVGMatrix *aMatrix); 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> static already_AddRefed<nsIDOMSVGMatrix>
AdjustMatrixForUnits(nsIDOMSVGMatrix *aMatrix, AdjustMatrixForUnits(nsIDOMSVGMatrix *aMatrix,
nsSVGEnum *aUnits, nsSVGEnum *aUnits,
@ -476,8 +482,7 @@ public:
* Get bounding-box for aFrame. Matrix propagation is disabled so the * Get bounding-box for aFrame. Matrix propagation is disabled so the
* bounding box is computed in terms of aFrame's own user space. * bounding box is computed in terms of aFrame's own user space.
*/ */
static already_AddRefed<nsIDOMSVGRect> static gfxRect GetBBox(nsIFrame *aFrame);
GetBBox(nsIFrame *aFrame);
/** /**
* Compute a rectangle in userSpaceOnUse or objectBoundingBoxUnits. * Compute a rectangle in userSpaceOnUse or objectBoundingBoxUnits.
* @param aXYWH pointer to 4 consecutive nsSVGLength2 objects containing * @param aXYWH pointer to 4 consecutive nsSVGLength2 objects containing
@ -488,8 +493,8 @@ public:
* may be null if aUnits is SVG_UNIT_TYPE_OBJECTBOUNDINGBOX * may be null if aUnits is SVG_UNIT_TYPE_OBJECTBOUNDINGBOX
*/ */
static gfxRect static gfxRect
GetRelativeRect(PRUint16 aUnits, const nsSVGLength2 *aXYWH, nsIDOMSVGRect *aBBox, GetRelativeRect(PRUint16 aUnits, const nsSVGLength2 *aXYWH,
nsIFrame *aFrame); const gfxRect &aBBox, nsIFrame *aFrame);
/** /**
* Find the first frame, starting with aStartFrame and going up its * Find the first frame, starting with aStartFrame and going up its