Bug 687830 - Simplify marker implementation by calculating viewbox on paint rather than attempting to cache it. r=roc

This commit is contained in:
Robert Longson 2011-09-21 08:53:09 +01:00
Родитель 9d3a1beaf9
Коммит 1b60b340a7
3 изменённых файлов: 31 добавлений и 79 удалений

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

@ -288,12 +288,7 @@ nsSVGMarkerElement::UnsetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
PRBool aNotify)
{
if (aNamespaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::viewBox && mCoordCtx) {
mViewBox.SetBaseValue(0, 0, mLengthAttributes[MARKERWIDTH].GetAnimValue(mCoordCtx),
mLengthAttributes[MARKERHEIGHT].GetAnimValue(mCoordCtx),
this, PR_FALSE);
return nsGenericElement::UnsetAttr(aNamespaceID, aName, aNotify);
} else if (aName == nsGkAtoms::orient) {
if (aName == nsGkAtoms::orient) {
mOrientType.SetBaseValue(SVG_MARKER_ORIENT_ANGLE);
}
}
@ -304,48 +299,11 @@ nsSVGMarkerElement::UnsetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
//----------------------------------------------------------------------
// nsSVGElement methods
void
nsSVGMarkerElement::DidChangeLength(PRUint8 aAttrEnum, PRBool aDoSetAttr)
{
nsSVGMarkerElementBase::DidChangeLength(aAttrEnum, aDoSetAttr);
mViewBoxToViewportTransform = nsnull;
if (mCoordCtx && !HasAttr(kNameSpaceID_None, nsGkAtoms::viewBox) &&
(aAttrEnum == MARKERWIDTH || aAttrEnum == MARKERHEIGHT)) {
mViewBox.SetBaseValue(0, 0, mLengthAttributes[MARKERWIDTH].GetAnimValue(mCoordCtx),
mLengthAttributes[MARKERHEIGHT].GetAnimValue(mCoordCtx),
this, PR_FALSE);
}
}
void
nsSVGMarkerElement::DidChangeViewBox(PRBool aDoSetAttr)
{
nsSVGMarkerElementBase::DidChangeViewBox(aDoSetAttr);
mViewBoxToViewportTransform = nsnull;
}
void
nsSVGMarkerElement::DidChangePreserveAspectRatio(PRBool aDoSetAttr)
{
nsSVGMarkerElementBase::DidChangePreserveAspectRatio(aDoSetAttr);
mViewBoxToViewportTransform = nsnull;
}
void
nsSVGMarkerElement::SetParentCoordCtxProvider(nsSVGSVGElement *aContext)
{
mCoordCtx = aContext;
mViewBoxToViewportTransform = nsnull;
if (mCoordCtx && !HasAttr(kNameSpaceID_None, nsGkAtoms::viewBox)) {
mViewBox.SetBaseValue(0, 0, mLengthAttributes[MARKERWIDTH].GetAnimValue(mCoordCtx),
mLengthAttributes[MARKERHEIGHT].GetAnimValue(mCoordCtx),
this, PR_FALSE);
}
}
nsSVGElement::LengthAttributesInfo
@ -388,20 +346,30 @@ gfxMatrix
nsSVGMarkerElement::GetMarkerTransform(float aStrokeWidth,
float aX, float aY, float aAutoAngle)
{
float scale = 1.0;
if (mEnumAttributes[MARKERUNITS].GetAnimValue() ==
SVG_MARKERUNITS_STROKEWIDTH)
scale = aStrokeWidth;
gfxFloat scale = mEnumAttributes[MARKERUNITS].GetAnimValue() ==
SVG_MARKERUNITS_STROKEWIDTH ? aStrokeWidth : 1.0;
float angle = mOrientType.GetAnimValue() == SVG_MARKER_ORIENT_AUTO ?
aAutoAngle :
mAngleAttributes[ORIENT].GetAnimValue() * M_PI / 180.0;
gfxFloat angle = mOrientType.GetAnimValue() == SVG_MARKER_ORIENT_AUTO ?
aAutoAngle :
mAngleAttributes[ORIENT].GetAnimValue() * M_PI / 180.0;
return gfxMatrix(cos(angle) * scale, sin(angle) * scale,
-sin(angle) * scale, cos(angle) * scale,
aX, aY);
}
nsSVGViewBoxRect
nsSVGMarkerElement::GetViewBoxRect()
{
if (mViewBox.IsValid()) {
return mViewBox.GetAnimValue();
}
return nsSVGViewBoxRect(
0, 0,
mLengthAttributes[MARKERWIDTH].GetAnimValue(mCoordCtx),
mLengthAttributes[MARKERHEIGHT].GetAnimValue(mCoordCtx));
}
gfxMatrix
nsSVGMarkerElement::GetViewBoxTransform()
{
@ -411,14 +379,10 @@ nsSVGMarkerElement::GetViewBoxTransform()
float viewportHeight =
mLengthAttributes[MARKERHEIGHT].GetAnimValue(mCoordCtx);
const nsSVGViewBoxRect& viewbox = mViewBox.GetAnimValue();
nsSVGViewBoxRect viewbox = GetViewBoxRect();
if (viewbox.width <= 0.0f || viewbox.height <= 0.0f) {
return gfxMatrix(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); // invalid - don't paint element
}
float refX = mLengthAttributes[REFX].GetAnimValue(mCoordCtx);
float refY = mLengthAttributes[REFY].GetAnimValue(mCoordCtx);
NS_ABORT_IF_FALSE(viewbox.width > 0.0f && viewbox.height > 0.0f,
"Rendering should be disabled");
gfxMatrix viewBoxTM =
nsSVGUtils::GetViewBoxTransform(this,
@ -427,6 +391,9 @@ nsSVGMarkerElement::GetViewBoxTransform()
viewbox.width, viewbox.height,
mPreserveAspectRatio);
float refX = mLengthAttributes[REFX].GetAnimValue(mCoordCtx);
float refY = mLengthAttributes[REFY].GetAnimValue(mCoordCtx);
gfxPoint ref = viewBoxTM.Transform(gfxPoint(refX, refY));
gfxMatrix TM = viewBoxTM * gfxMatrix().Translate(gfxPoint(-ref.x, -ref.y));

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

@ -132,14 +132,10 @@ public:
virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRBool aNotify);
// nsSVGElement specializations:
virtual void DidChangeLength(PRUint8 aAttrEnum, PRBool aDoSetAttr);
virtual void DidChangeViewBox(PRBool aDoSetAttr);
virtual void DidChangePreserveAspectRatio(PRBool aDoSetAttr);
// public helpers
gfxMatrix GetMarkerTransform(float aStrokeWidth,
float aX, float aY, float aAutoAngle);
nsSVGViewBoxRect GetViewBoxRect();
gfxMatrix GetViewBoxTransform();
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;

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

@ -132,29 +132,17 @@ nsSVGMarkerFrame::PaintMark(nsSVGRenderState *aContext,
if (mInUse)
return NS_OK;
AutoMarkerReferencer markerRef(this, aMarkedFrame);
nsSVGMarkerElement *marker = static_cast<nsSVGMarkerElement*>(mContent);
nsCOMPtr<nsIDOMSVGAnimatedRect> arect;
nsresult rv = marker->GetViewBox(getter_AddRefs(arect));
NS_ENSURE_SUCCESS(rv, rv);
const nsSVGViewBoxRect viewBox = marker->GetViewBoxRect();
nsCOMPtr<nsIDOMSVGRect> rect;
rv = arect->GetAnimVal(getter_AddRefs(rect));
NS_ENSURE_SUCCESS(rv, rv);
float x, y, width, height;
rect->GetX(&x);
rect->GetY(&y);
rect->GetWidth(&width);
rect->GetHeight(&height);
if (width <= 0.0f || height <= 0.0f) {
if (viewBox.width <= 0.0f || viewBox.height <= 0.0f) {
// We must disable rendering if the viewBox width or height are zero.
return NS_OK;
}
AutoMarkerReferencer markerRef(this, aMarkedFrame);
mStrokeWidth = aStrokeWidth;
mX = aMark->x;
mY = aMark->y;
@ -165,7 +153,8 @@ nsSVGMarkerFrame::PaintMark(nsSVGRenderState *aContext,
if (GetStyleDisplay()->IsScrollableOverflow()) {
gfx->Save();
gfxRect clipRect =
nsSVGUtils::GetClipRectForFrame(this, x, y, width, height);
nsSVGUtils::GetClipRectForFrame(this, viewBox.x, viewBox.y,
viewBox.width, viewBox.height);
nsSVGUtils::SetClipRect(gfx, GetCanvasTM(), clipRect);
}