Bug 342200 - Remove nsSVGPathGeometryFrame subclasses. r+sr=roc

This commit is contained in:
tor%cs.brown.edu 2006-06-21 15:42:28 +00:00
Родитель aa0670b627
Коммит 3f9980a5fd
26 изменённых файлов: 1031 добавлений и 1751 удалений

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

@ -110,6 +110,7 @@ CPPSRCS = \
nsSVGNumberList.cpp \
nsSVGPathDataParser.cpp \
nsSVGPathElement.cpp \
nsSVGPathGeometryElement.cpp \
nsSVGPathSeg.cpp \
nsSVGPathSegList.cpp \
nsSVGPatternElement.cpp \

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

@ -36,12 +36,13 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsSVGGraphicElement.h"
#include "nsSVGPathGeometryElement.h"
#include "nsIDOMSVGCircleElement.h"
#include "nsSVGLength2.h"
#include "nsGkAtoms.h"
#include "nsSVGUtils.h"
typedef nsSVGGraphicElement nsSVGCircleElementBase;
typedef nsSVGPathGeometryElement nsSVGCircleElementBase;
class nsSVGCircleElement : public nsSVGCircleElementBase,
public nsIDOMSVGCircleElement
@ -61,6 +62,9 @@ public:
NS_FORWARD_NSIDOMELEMENT(nsSVGCircleElementBase::)
NS_FORWARD_NSIDOMSVGELEMENT(nsSVGCircleElementBase::)
// nsSVGPathGeometryElement methods:
virtual void ConstructPath(cairo_t *aCtx);
protected:
virtual LengthAttributesInfo GetLengthInfo();
@ -137,3 +141,15 @@ nsSVGCircleElement::GetLengthInfo()
NS_ARRAY_LENGTH(sLengthInfo));
}
//----------------------------------------------------------------------
// nsSVGPathGeometryElement methods
void
nsSVGCircleElement::ConstructPath(cairo_t *aCtx)
{
float x, y, r;
GetAnimatedLengthValues(&x, &y, &r, nsnull);
cairo_arc(aCtx, x, y, r, 0, 2*M_PI);
}

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

@ -37,12 +37,13 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsSVGGraphicElement.h"
#include "nsSVGPathGeometryElement.h"
#include "nsIDOMSVGEllipseElement.h"
#include "nsSVGLength2.h"
#include "nsGkAtoms.h"
#include "nsSVGUtils.h"
typedef nsSVGGraphicElement nsSVGEllipseElementBase;
typedef nsSVGPathGeometryElement nsSVGEllipseElementBase;
class nsSVGEllipseElement : public nsSVGEllipseElementBase,
public nsIDOMSVGEllipseElement
@ -62,6 +63,9 @@ public:
NS_FORWARD_NSIDOMELEMENT(nsSVGEllipseElementBase::)
NS_FORWARD_NSIDOMSVGELEMENT(nsSVGEllipseElementBase::)
// nsSVGPathGeometryElement methods:
virtual void ConstructPath(cairo_t *aCtx);
protected:
virtual LengthAttributesInfo GetLengthInfo();
@ -144,3 +148,20 @@ nsSVGEllipseElement::GetLengthInfo()
return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
NS_ARRAY_LENGTH(sLengthInfo));
}
//----------------------------------------------------------------------
// nsSVGPathGeometryElement methods
void
nsSVGEllipseElement::ConstructPath(cairo_t *aCtx)
{
float x, y, rx, ry;
GetAnimatedLengthValues(&x, &y, &rx, &ry, nsnull);
cairo_save(aCtx);
cairo_translate(aCtx, x, y);
cairo_scale(aCtx, rx, ry);
cairo_arc(aCtx, 0, 0, 1, 0, 2 * M_PI);
cairo_restore(aCtx);
}

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

@ -48,7 +48,7 @@
#include "nsSVGPreserveAspectRatio.h"
#include "imgIContainer.h"
#include "imgIDecoderObserver.h"
#include "nsSVGGraphicElement.h"
#include "nsSVGPathGeometryElement.h"
#include "nsIDOMSVGImageElement.h"
#include "nsIDOMSVGURIReference.h"
#include "nsImageLoadingContent.h"
@ -57,7 +57,7 @@
class nsIDOMSVGAnimatedString;
class nsIDOMSVGAnimatedPreserveAspectRatio;
typedef nsSVGGraphicElement nsSVGImageElementBase;
typedef nsSVGPathGeometryElement nsSVGImageElementBase;
class nsSVGImageElement : public nsSVGImageElementBase,
public nsIDOMSVGImageElement,
@ -92,6 +92,9 @@ public:
NS_IMETHODIMP_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
// nsSVGPathGeometryElement methods:
virtual void ConstructPath(cairo_t *aCtx);
protected:
virtual LengthAttributesInfo GetLengthInfo();
@ -316,3 +319,21 @@ nsSVGImageElement::IsAttributeMapped(const nsIAtom* name) const
return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||
nsSVGImageElementBase::IsAttributeMapped(name);
}
//----------------------------------------------------------------------
// nsSVGPathGeometryElement methods
/* For the purposes of the update/invalidation logic pretend to
be a rectangle. */
void
nsSVGImageElement::ConstructPath(cairo_t *aCtx)
{
float x, y, width, height;
GetAnimatedLengthValues(&x, &y, &width, &height, nsnull);
if (width == 0 || height == 0)
return;
cairo_rectangle(aCtx, x, y, width, height);
}

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

@ -37,12 +37,12 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsSVGGraphicElement.h"
#include "nsSVGPathGeometryElement.h"
#include "nsIDOMSVGLineElement.h"
#include "nsSVGLength2.h"
#include "nsGkAtoms.h"
typedef nsSVGGraphicElement nsSVGLineElementBase;
typedef nsSVGPathGeometryElement nsSVGLineElementBase;
class nsSVGLineElement : public nsSVGLineElementBase,
public nsIDOMSVGLineElement
@ -65,6 +65,11 @@ public:
// nsIContent interface
NS_IMETHODIMP_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
// nsSVGPathGeometryElement methods:
virtual PRBool IsMarkable() { return PR_TRUE; }
virtual void GetMarkPoints(nsVoidArray *aMarks);
virtual void ConstructPath(cairo_t *aCtx);
protected:
virtual LengthAttributesInfo GetLengthInfo();
@ -161,3 +166,37 @@ nsSVGLineElement::GetLengthInfo()
return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
NS_ARRAY_LENGTH(sLengthInfo));
}
//----------------------------------------------------------------------
// nsSVGPathGeometryElement methods
void
nsSVGLineElement::GetMarkPoints(nsVoidArray *aMarks) {
float x1, y1, x2, y2;
GetAnimatedLengthValues(&x1, &y1, &x2, &y2, nsnull);
nsSVGMark *m1, *m2;
m1 = new nsSVGMark();
m2 = new nsSVGMark();
m1->x = x1;
m1->y = y1;
m2->x = x2;
m2->y = y2;
m1->angle = m2->angle = atan2(y2 - y1, x2 - x1);
aMarks->AppendElement(m1);
aMarks->AppendElement(m2);
}
void
nsSVGLineElement::ConstructPath(cairo_t *aCtx)
{
float x1, y1, x2, y2;
GetAnimatedLengthValues(&x1, &y1, &x2, &y2, nsnull);
cairo_move_to(aCtx, x1, y1);
cairo_line_to(aCtx, x2, y2);
}

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

@ -45,6 +45,7 @@
#include "nsSVGPathDataParser.h"
#include "nsSVGPathElement.h"
#include "nsISVGValueUtils.h"
#include "nsSVGUtils.h"
NS_IMPL_NS_NEW_SVG_ELEMENT(Path)
@ -403,6 +404,478 @@ nsSVGPathElement::GetFlattenedPath()
return retval;
}
//----------------------------------------------------------------------
// nsSVGPathGeometryElement methods
PRBool
nsSVGPathElement::IsDependentAttribute(nsIAtom *aName)
{
if (aName == nsGkAtoms::d)
return PR_TRUE;
return PR_FALSE;
}
PRBool
nsSVGPathElement::IsMarkable()
{
return PR_TRUE;
}
static double
CalcVectorAngle(double ux, double uy, double vx, double vy)
{
double ta = atan2(uy, ux);
double tb = atan2(vy, vx);
if (tb >= ta)
return tb-ta;
return 2 * M_PI - (ta-tb);
}
void
nsSVGPathElement::GetMarkPoints(nsVoidArray *aMarks) {
if (NS_FAILED(CreatePathSegList()))
return;
PRUint32 count;
mSegments->GetNumberOfItems(&count);
nsCOMPtr<nsIDOMSVGPathSeg> segment;
float cx = 0.0f; // current point
float cy = 0.0f;
float cx1 = 0.0f; // last controlpoint (for s,S,t,T)
float cy1 = 0.0f;
PRUint16 lastSegmentType = nsIDOMSVGPathSeg::PATHSEG_UNKNOWN;
float px, py; // subpath initial point
float pathAngle;
PRUint32 pathIndex;
float prevAngle = 0, startAngle, endAngle;
PRBool newSegment = PR_FALSE;
PRUint32 i;
for (i = 0; i < count; ++i) {
nsCOMPtr<nsIDOMSVGPathSeg> segment;
mSegments->GetItem(i, getter_AddRefs(segment));
PRUint16 type = nsIDOMSVGPathSeg::PATHSEG_UNKNOWN;
segment->GetPathSegType(&type);
float x, y;
PRBool absCoords = PR_FALSE;
switch (type) {
case nsIDOMSVGPathSeg::PATHSEG_CLOSEPATH:
{
x = px;
y = py;
startAngle = endAngle = atan2(y - cy, x - cx);
}
break;
case nsIDOMSVGPathSeg::PATHSEG_MOVETO_ABS:
absCoords = PR_TRUE;
case nsIDOMSVGPathSeg::PATHSEG_MOVETO_REL:
{
if (!absCoords) {
nsCOMPtr<nsIDOMSVGPathSegMovetoRel> moveseg = do_QueryInterface(segment);
NS_ASSERTION(moveseg, "interface not implemented");
moveseg->GetX(&x);
moveseg->GetY(&y);
x += cx;
y += cy;
} else {
nsCOMPtr<nsIDOMSVGPathSegMovetoAbs> moveseg = do_QueryInterface(segment);
NS_ASSERTION(moveseg, "interface not implemented");
moveseg->GetX(&x);
moveseg->GetY(&y);
}
px = x;
py = y;
startAngle = endAngle = prevAngle;
newSegment = PR_TRUE;
}
break;
case nsIDOMSVGPathSeg::PATHSEG_LINETO_ABS:
absCoords = PR_TRUE;
case nsIDOMSVGPathSeg::PATHSEG_LINETO_REL:
{
if (!absCoords) {
nsCOMPtr<nsIDOMSVGPathSegLinetoRel> lineseg = do_QueryInterface(segment);
NS_ASSERTION(lineseg, "interface not implemented");
lineseg->GetX(&x);
lineseg->GetY(&y);
x += cx;
y += cy;
} else {
nsCOMPtr<nsIDOMSVGPathSegLinetoAbs> lineseg = do_QueryInterface(segment);
NS_ASSERTION(lineseg, "interface not implemented");
lineseg->GetX(&x);
lineseg->GetY(&y);
}
startAngle = endAngle = atan2(y - cy, x - cx);
}
break;
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS:
absCoords = PR_TRUE;
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_REL:
{
float x1, y1, x2, y2;
if (!absCoords) {
nsCOMPtr<nsIDOMSVGPathSegCurvetoCubicRel> curveseg = do_QueryInterface(segment);
NS_ASSERTION(curveseg, "interface not implemented");
curveseg->GetX(&x);
curveseg->GetY(&y);
curveseg->GetX1(&x1);
curveseg->GetY1(&y1);
curveseg->GetX2(&x2);
curveseg->GetY2(&y2);
x += cx;
y += cy;
x1 += cx;
y1 += cy;
x2 += cx;
y2 += cy;
} else {
nsCOMPtr<nsIDOMSVGPathSegCurvetoCubicAbs> curveseg = do_QueryInterface(segment);
NS_ASSERTION(curveseg, "interface not implemented");
curveseg->GetX(&x);
curveseg->GetY(&y);
curveseg->GetX1(&x1);
curveseg->GetY1(&y1);
curveseg->GetX2(&x2);
curveseg->GetY2(&y2);
}
cx1 = x2;
cy1 = y2;
if (x1 == cx && y1 == cy) {
x1 = x2;
y1 = y2;
}
if (x2 == x && y2 == y) {
x2 = x1;
y2 = y1;
}
startAngle = atan2(y1 - cy, x1 - cx);
endAngle = atan2(y - y2, x - x2);
}
break;
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS:
absCoords = PR_TRUE;
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_REL:
{
float x1, y1;
if (!absCoords) {
nsCOMPtr<nsIDOMSVGPathSegCurvetoQuadraticRel> curveseg = do_QueryInterface(segment);
NS_ASSERTION(curveseg, "interface not implemented");
curveseg->GetX(&x);
curveseg->GetY(&y);
curveseg->GetX1(&x1);
curveseg->GetY1(&y1);
x += cx;
y += cy;
x1 += cx;
y1 += cy;
} else {
nsCOMPtr<nsIDOMSVGPathSegCurvetoQuadraticAbs> curveseg = do_QueryInterface(segment);
NS_ASSERTION(curveseg, "interface not implemented");
curveseg->GetX(&x);
curveseg->GetY(&y);
curveseg->GetX1(&x1);
curveseg->GetY1(&y1);
}
cx1 = x1;
cy1 = y1;
startAngle = atan2(y1 - cy, x1 - cx);
endAngle = atan2(y - y1, x - x1);
}
break;
case nsIDOMSVGPathSeg::PATHSEG_ARC_ABS:
absCoords = PR_TRUE;
case nsIDOMSVGPathSeg::PATHSEG_ARC_REL:
{
float r1, r2, angle;
PRBool largeArcFlag, sweepFlag;
if (!absCoords) {
nsCOMPtr<nsIDOMSVGPathSegArcRel> arcseg = do_QueryInterface(segment);
NS_ASSERTION(arcseg, "interface not implemented");
arcseg->GetX(&x);
arcseg->GetY(&y);
arcseg->GetR1(&r1);
arcseg->GetR2(&r2);
arcseg->GetAngle(&angle);
arcseg->GetLargeArcFlag(&largeArcFlag);
arcseg->GetSweepFlag(&sweepFlag);
x += cx;
y += cy;
} else {
nsCOMPtr<nsIDOMSVGPathSegArcAbs> arcseg = do_QueryInterface(segment);
NS_ASSERTION(arcseg, "interface not implemented");
arcseg->GetX(&x);
arcseg->GetY(&y);
arcseg->GetR1(&r1);
arcseg->GetR2(&r2);
arcseg->GetAngle(&angle);
arcseg->GetLargeArcFlag(&largeArcFlag);
arcseg->GetSweepFlag(&sweepFlag);
}
/* check for degenerate ellipse */
if (r1 == 0.0 || r2 == 0.0) {
startAngle = endAngle = atan2(y - cy, x - cx);
break;
}
r1 = fabs(r1); r2 = fabs(r2);
float xp, yp, cxp, cyp;
/* slope fun&games ... see SVG spec, section F.6 */
angle = angle*M_PI/180.0;
xp = cos(angle)*(cx-x)/2.0 + sin(angle)*(cy-y)/2.0;
yp = -sin(angle)*(cx-x)/2.0 + cos(angle)*(cy-y)/2.0;
/* make sure radii are large enough */
float root, numerator = r1*r1*r2*r2 - r1*r1*yp*yp - r2*r2*xp*xp;
if (numerator < 0.0) {
float s = sqrt(1.0 - numerator/(r1*r1*r2*r2));
r1 *= s;
r2 *= s;
root = 0.0;
} else {
root = sqrt(numerator/(r1*r1*yp*yp + r2*r2*xp*xp));
if (largeArcFlag == sweepFlag)
root = -root;
}
cxp = root*r1*yp/r2;
cyp = -root*r2*xp/r1;
float theta, delta;
theta = CalcVectorAngle(1.0, 0.0, (xp-cxp)/r1, (yp-cyp)/r2);
delta = CalcVectorAngle((xp-cxp)/r1, (yp-cyp)/r2,
(-xp-cxp)/r1, (-yp-cyp)/r2);
if (!sweepFlag && delta > 0)
delta -= 2.0*M_PI;
else if (sweepFlag && delta < 0)
delta += 2.0*M_PI;
float tx1, ty1, tx2, ty2;
tx1 = -cos(angle)*r1*sin(theta) - sin(angle)*r2*cos(theta);
ty1 = -sin(angle)*r1*sin(theta) + cos(angle)*r2*cos(theta);
tx2 = -cos(angle)*r1*sin(theta+delta) - sin(angle)*r2*cos(theta+delta);
ty2 = -sin(angle)*r1*sin(theta+delta) + cos(angle)*r2*cos(theta+delta);
if (delta < 0.0f) {
tx1 = -tx1;
ty1 = -ty1;
tx2 = -tx2;
ty2 = -ty2;
}
startAngle = atan2(ty1, tx1);
endAngle = atan2(ty2, tx2);
}
break;
case nsIDOMSVGPathSeg::PATHSEG_LINETO_HORIZONTAL_ABS:
absCoords = PR_TRUE;
case nsIDOMSVGPathSeg::PATHSEG_LINETO_HORIZONTAL_REL:
{
y = cy;
if (!absCoords) {
nsCOMPtr<nsIDOMSVGPathSegLinetoHorizontalRel> lineseg = do_QueryInterface(segment);
NS_ASSERTION(lineseg, "interface not implemented");
lineseg->GetX(&x);
x += cx;
} else {
nsCOMPtr<nsIDOMSVGPathSegLinetoHorizontalAbs> lineseg = do_QueryInterface(segment);
NS_ASSERTION(lineseg, "interface not implemented");
lineseg->GetX(&x);
}
startAngle = endAngle = atan2(0, x - cx);
}
break;
case nsIDOMSVGPathSeg::PATHSEG_LINETO_VERTICAL_ABS:
absCoords = PR_TRUE;
case nsIDOMSVGPathSeg::PATHSEG_LINETO_VERTICAL_REL:
{
x = cx;
if (!absCoords) {
nsCOMPtr<nsIDOMSVGPathSegLinetoVerticalRel> lineseg = do_QueryInterface(segment);
NS_ASSERTION(lineseg, "interface not implemented");
lineseg->GetY(&y);
y += cy;
} else {
nsCOMPtr<nsIDOMSVGPathSegLinetoVerticalAbs> lineseg = do_QueryInterface(segment);
NS_ASSERTION(lineseg, "interface not implemented");
lineseg->GetY(&y);
}
startAngle = endAngle = atan2(y - cy, 0);
}
break;
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
absCoords = PR_TRUE;
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
{
float x1, y1, x2, y2;
if (lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_REL ||
lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS ||
lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_REL ||
lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS ) {
// the first controlpoint is the reflection of the last one about the current point:
x1 = 2*cx - cx1;
y1 = 2*cy - cy1;
}
else {
// the first controlpoint is equal to the current point:
x1 = cx;
y1 = cy;
}
if (!absCoords) {
nsCOMPtr<nsIDOMSVGPathSegCurvetoCubicSmoothRel> curveseg = do_QueryInterface(segment);
NS_ASSERTION(curveseg, "interface not implemented");
curveseg->GetX(&x);
curveseg->GetY(&y);
curveseg->GetX2(&x2);
curveseg->GetY2(&y2);
x += cx;
y += cy;
x2 += cx;
y2 += cy;
} else {
nsCOMPtr<nsIDOMSVGPathSegCurvetoCubicSmoothAbs> curveseg = do_QueryInterface(segment);
NS_ASSERTION(curveseg, "interface not implemented");
curveseg->GetX(&x);
curveseg->GetY(&y);
curveseg->GetX2(&x2);
curveseg->GetY2(&y2);
}
cx1 = x2;
cy1 = y2;
if (x1 == cx && y1 == cy) {
x1 = x2;
y1 = y2;
}
if (x2 == x && y2 == y) {
x2 = x1;
y2 = y1;
}
startAngle = atan2(y1 - cy, x1 - cx);
endAngle = atan2(y - y2, x - x2);
}
break;
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
absCoords = PR_TRUE;
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
{
float x1, y1;
if (lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_REL ||
lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS ||
lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL ||
lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS ) {
// the first controlpoint is the reflection of the last one about the current point:
x1 = 2*cx - cx1;
y1 = 2*cy - cy1;
}
else {
// the first controlpoint is equal to the current point:
x1 = cx;
y1 = cy;
}
if (!absCoords) {
nsCOMPtr<nsIDOMSVGPathSegCurvetoQuadraticSmoothRel> curveseg = do_QueryInterface(segment);
NS_ASSERTION(curveseg, "interface not implemented");
curveseg->GetX(&x);
curveseg->GetY(&y);
x += cx;
y += cy;
} else {
nsCOMPtr<nsIDOMSVGPathSegCurvetoQuadraticSmoothAbs> curveseg = do_QueryInterface(segment);
NS_ASSERTION(curveseg, "interface not implemented");
curveseg->GetX(&x);
curveseg->GetY(&y);
}
cx1 = x1;
cy1 = y1;
startAngle = atan2(y1 - cy, x1 - cx);
endAngle = atan2(y - y1, x - x1);
}
break;
default:
NS_ASSERTION(1==0, "unknown path segment");
break;
}
lastSegmentType = type;
if (newSegment &&
type != nsIDOMSVGPathSeg::PATHSEG_MOVETO_ABS &&
type != nsIDOMSVGPathSeg::PATHSEG_MOVETO_REL) {
pathIndex = aMarks->Count() - 1;
pathAngle = startAngle;
((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = pathAngle;
newSegment = PR_FALSE;
prevAngle = endAngle;
} else if (type == nsIDOMSVGPathSeg::PATHSEG_MOVETO_ABS ||
type == nsIDOMSVGPathSeg::PATHSEG_MOVETO_REL) {
if (aMarks->Count())
((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = prevAngle;
} else {
((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle =
nsSVGUtils::AngleBisect(prevAngle, startAngle);
prevAngle = endAngle;
}
nsSVGMark *mark = new nsSVGMark;
mark->x = x;
mark->y = y;
aMarks->AppendElement(mark);
if (type == nsIDOMSVGPathSeg::PATHSEG_CLOSEPATH) {
prevAngle = nsSVGUtils::AngleBisect(endAngle, pathAngle);
((nsSVGMark *)aMarks->ElementAt(pathIndex))->angle = prevAngle;
}
cx = x;
cy = y;
}
if (aMarks->Count())
((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = prevAngle;
}
//==================================================================
// nsSVGPathList
@ -537,4 +1010,8 @@ nsSVGFlattenedPath::FindPoint(float aAdvance, float aXOffset, float aYOffset,
}
}
void
nsSVGPathElement::ConstructPath(cairo_t *aCtx)
{
mPathData.Playback(aCtx);
}

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

@ -39,7 +39,7 @@
#ifndef __NS_SVGPATHELEMENT_H__
#define __NS_SVGPATHELEMENT_H__
#include "nsSVGGraphicElement.h"
#include "nsSVGPathGeometryElement.h"
#include "nsIDOMSVGPathElement.h"
#include "nsIDOMSVGAnimatedPathData.h"
@ -80,7 +80,7 @@ public:
float *aX, float *aY, float *aAngle);
};
typedef nsSVGGraphicElement nsSVGPathElementBase;
typedef nsSVGPathGeometryElement nsSVGPathElementBase;
class nsSVGPathElement : public nsSVGPathElementBase,
public nsIDOMSVGPathElement,
@ -113,6 +113,12 @@ public:
NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable,
nsISVGValue::modificationType aModType);
// nsSVGPathGeometryElement methods:
virtual PRBool IsDependentAttribute(nsIAtom *aName);
virtual PRBool IsMarkable();
virtual void GetMarkPoints(nsVoidArray *aMarks);
virtual void ConstructPath(cairo_t *aCtx);
nsSVGFlattenedPath *GetFlattenedPath();
protected:

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

@ -0,0 +1,67 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla SVG project.
*
* The Initial Developer of the Original Code is IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsSVGPathGeometryElement.h"
nsSVGPathGeometryElement::nsSVGPathGeometryElement(nsINodeInfo *aNodeInfo)
: nsSVGPathGeometryElementBase(aNodeInfo)
{
}
PRBool
nsSVGPathGeometryElement::IsDependentAttribute(nsIAtom *aName)
{
// Check for nsSVGLength2 attribute
LengthAttributesInfo info = GetLengthInfo();
for (PRUint32 i = 0; i < info.mLengthCount; i++) {
if (aName == *info.mLengthInfo[i].mName) {
return PR_TRUE;
}
}
return PR_FALSE;
}
PRBool
nsSVGPathGeometryElement::IsMarkable()
{
return PR_FALSE;
}
void
nsSVGPathGeometryElement::GetMarkPoints(nsVoidArray *aMarks)
{
}

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

@ -0,0 +1,60 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla SVG project.
*
* The Initial Developer of the Original Code is IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __NS_SVGPATHGEOMETRYELEMENT_H__
#define __NS_SVGPATHGEOMETRYELEMENT_H__
#include "nsSVGGraphicElement.h"
#include "cairo.h"
struct nsSVGMark {
float x, y, angle;
};
typedef nsSVGGraphicElement nsSVGPathGeometryElementBase;
class nsSVGPathGeometryElement : public nsSVGPathGeometryElementBase
{
public:
nsSVGPathGeometryElement(nsINodeInfo *aNodeInfo);
virtual PRBool IsDependentAttribute(nsIAtom *aName);
virtual PRBool IsMarkable();
virtual void GetMarkPoints(nsVoidArray *aMarks);
virtual void ConstructPath(cairo_t *aCtx) = 0;
};
#endif

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

@ -36,14 +36,16 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsSVGGraphicElement.h"
#include "nsSVGPathGeometryElement.h"
#include "nsSVGAtoms.h"
#include "nsSVGPointList.h"
#include "nsIDOMSVGPolygonElement.h"
#include "nsIDOMSVGAnimatedPoints.h"
#include "nsCOMPtr.h"
#include "nsIDOMSVGPoint.h"
#include "nsSVGUtils.h"
typedef nsSVGGraphicElement nsSVGPolygonElementBase;
typedef nsSVGPathGeometryElement nsSVGPolygonElementBase;
class nsSVGPolygonElement : public nsSVGPolygonElementBase,
public nsIDOMSVGPolygonElement,
@ -69,7 +71,13 @@ public:
// nsIContent interface
NS_IMETHODIMP_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
// nsSVGPathGeometryElement methods:
virtual PRBool IsDependentAttribute(nsIAtom *aName);
virtual PRBool IsMarkable() { return PR_TRUE; }
virtual void GetMarkPoints(nsVoidArray *aMarks);
virtual void ConstructPath(cairo_t *aCtx);
protected:
nsCOMPtr<nsIDOMSVGPointList> mPoints;
};
@ -159,3 +167,95 @@ nsSVGPolygonElement::IsAttributeMapped(const nsIAtom* name) const
return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||
nsSVGPolygonElementBase::IsAttributeMapped(name);
}
//----------------------------------------------------------------------
// nsSVGPathGeometryElement methods
PRBool
nsSVGPolygonElement::IsDependentAttribute(nsIAtom *aName)
{
if (aName == nsGkAtoms::points)
return PR_TRUE;
return PR_FALSE;
}
void
nsSVGPolygonElement::GetMarkPoints(nsVoidArray *aMarks)
{
if (!mPoints)
return;
PRUint32 count;
mPoints->GetNumberOfItems(&count);
if (count == 0)
return;
float px = 0.0, py = 0.0, prevAngle, startAngle;
nsCOMPtr<nsIDOMSVGPoint> point;
for (PRUint32 i = 0; i < count; ++i) {
mPoints->GetItem(i, getter_AddRefs(point));
float x, y;
point->GetX(&x);
point->GetY(&y);
float angle = atan2(y-py, x-px);
if (i == 1)
startAngle = angle;
else if (i > 1)
((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle =
nsSVGUtils::AngleBisect(prevAngle, angle);
nsSVGMark *mark;
mark = new nsSVGMark;
mark->x = x;
mark->y = y;
aMarks->AppendElement(mark);
prevAngle = angle;
px = x;
py = y;
}
float nx, ny, angle;
mPoints->GetItem(0, getter_AddRefs(point));
point->GetX(&nx);
point->GetY(&ny);
angle = atan2(ny - py, nx - px);
((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle =
nsSVGUtils::AngleBisect(prevAngle, angle);
((nsSVGMark *)aMarks->ElementAt(0))->angle =
nsSVGUtils::AngleBisect(angle, startAngle);
}
void
nsSVGPolygonElement::ConstructPath(cairo_t *aCtx)
{
if (!mPoints)
return;
PRUint32 count;
mPoints->GetNumberOfItems(&count);
if (count == 0)
return;
PRUint32 i;
for (i = 0; i < count; ++i) {
nsCOMPtr<nsIDOMSVGPoint> point;
mPoints->GetItem(i, getter_AddRefs(point));
float x, y;
point->GetX(&x);
point->GetY(&y);
if (i == 0)
cairo_move_to(aCtx, x, y);
else
cairo_line_to(aCtx, x, y);
}
// the difference between a polyline and a polygon is that the
// polygon is closed:
cairo_close_path(aCtx);
}

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

@ -36,14 +36,16 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsSVGGraphicElement.h"
#include "nsSVGPathGeometryElement.h"
#include "nsSVGAtoms.h"
#include "nsSVGPointList.h"
#include "nsIDOMSVGPolylineElement.h"
#include "nsIDOMSVGAnimatedPoints.h"
#include "nsCOMPtr.h"
#include "nsIDOMSVGPoint.h"
#include "nsSVGUtils.h"
typedef nsSVGGraphicElement nsSVGPolylineElementBase;
typedef nsSVGPathGeometryElement nsSVGPolylineElementBase;
class nsSVGPolylineElement : public nsSVGPolylineElementBase,
public nsIDOMSVGPolylineElement,
@ -69,7 +71,13 @@ public:
// nsIContent interface
NS_IMETHODIMP_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
// nsSVGPathGeometryElement methods:
virtual PRBool IsDependentAttribute(nsIAtom *aName);
virtual PRBool IsMarkable() { return PR_TRUE; }
virtual void GetMarkPoints(nsVoidArray *aMarks);
virtual void ConstructPath(cairo_t *aCtx);
protected:
nsCOMPtr<nsIDOMSVGPointList> mPoints;
};
@ -159,3 +167,83 @@ nsSVGPolylineElement::IsAttributeMapped(const nsIAtom* name) const
return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||
nsSVGPolylineElementBase::IsAttributeMapped(name);
}
//----------------------------------------------------------------------
// nsSVGPathGeometryElement methods
PRBool
nsSVGPolylineElement::IsDependentAttribute(nsIAtom *aName)
{
if (aName == nsGkAtoms::points)
return PR_TRUE;
return PR_FALSE;
}
void
nsSVGPolylineElement::GetMarkPoints(nsVoidArray *aMarks)
{
if (!mPoints)
return;
PRUint32 count;
mPoints->GetNumberOfItems(&count);
if (count == 0)
return;
float px = 0.0, py = 0.0, prevAngle;
for (PRUint32 i = 0; i < count; ++i) {
nsCOMPtr<nsIDOMSVGPoint> point;
mPoints->GetItem(i, getter_AddRefs(point));
float x, y;
point->GetX(&x);
point->GetY(&y);
float angle = atan2(y-py, x-px);
if (i == 1)
((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = angle;
else if (i > 1)
((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle =
nsSVGUtils::AngleBisect(prevAngle, angle);
nsSVGMark *mark;
mark = new nsSVGMark;
mark->x = x;
mark->y = y;
aMarks->AppendElement(mark);
prevAngle = angle;
px = x;
py = y;
}
((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = prevAngle;
}
void
nsSVGPolylineElement::ConstructPath(cairo_t *aCtx)
{
if (!mPoints)
return;
PRUint32 count;
mPoints->GetNumberOfItems(&count);
if (count == 0)
return;
PRUint32 i;
for (i = 0; i < count; ++i) {
nsCOMPtr<nsIDOMSVGPoint> point;
mPoints->GetItem(i, getter_AddRefs(point));
float x, y;
point->GetX(&x);
point->GetY(&y);
if (i == 0)
cairo_move_to(aCtx, x, y);
else
cairo_line_to(aCtx, x, y);
}
}

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

@ -37,12 +37,12 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsSVGGraphicElement.h"
#include "nsSVGPathGeometryElement.h"
#include "nsIDOMSVGRectElement.h"
#include "nsSVGLength2.h"
#include "nsGkAtoms.h"
typedef nsSVGGraphicElement nsSVGRectElementBase;
typedef nsSVGPathGeometryElement nsSVGRectElementBase;
class nsSVGRectElement : public nsSVGRectElementBase,
public nsIDOMSVGRectElement
@ -62,6 +62,9 @@ public:
NS_FORWARD_NSIDOMELEMENT(nsSVGRectElementBase::)
NS_FORWARD_NSIDOMSVGELEMENT(nsSVGRectElementBase::)
// nsSVGPathGeometryElement methods:
virtual void ConstructPath(cairo_t *aCtx);
protected:
virtual LengthAttributesInfo GetLengthInfo();
@ -158,3 +161,77 @@ nsSVGRectElement::GetLengthInfo()
return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
NS_ARRAY_LENGTH(sLengthInfo));
}
//----------------------------------------------------------------------
// nsSVGPathGeometryElement methods
void
nsSVGRectElement::ConstructPath(cairo_t *aCtx)
{
float x, y, width, height, rx, ry;
GetAnimatedLengthValues(&x, &y, &width, &height, &rx, &ry, nsnull);
/* In a perfect world, this would be handled by the DOM, and
return a DOM exception. */
if (width <= 0 || height <= 0 || ry < 0 || rx < 0)
return;
/* Clamp rx and ry to half the rect's width and height respectively. */
float halfWidth = width/2;
float halfHeight = height/2;
if (rx > halfWidth)
rx = halfWidth;
if (ry > halfHeight)
ry = halfHeight;
/* If either the 'rx' or the 'ry' attribute isn't set in the markup, then we
have to set it to the value of the other. We do this after clamping rx and
ry since omitting one of the attributes implicitly means they should both
be the same. */
PRBool hasRx = HasAttr(kNameSpaceID_None, nsGkAtoms::rx);
PRBool hasRy = HasAttr(kNameSpaceID_None, nsGkAtoms::ry);
if (hasRx && !hasRy)
ry = rx;
else if (hasRy && !hasRx)
rx = ry;
/* However, we may now have made rx > width/2 or else ry > height/2. (If this
is the case, we know we must be giving rx and ry the same value.) */
if (rx > halfWidth)
rx = ry = halfWidth;
else if (ry > halfHeight)
rx = ry = halfHeight;
if (rx == 0 && ry == 0) {
cairo_rectangle(aCtx, x, y, width, height);
} else {
// Conversion factor used for ellipse to bezier conversion.
// Gives radial error of 0.0273% in circular case.
// See comp.graphics.algorithms FAQ 4.04
const float magic = 4*(sqrt(2.)-1)/3;
cairo_move_to(aCtx, x+rx, y);
cairo_line_to(aCtx, x+width-rx, y);
cairo_curve_to(aCtx,
x+width-rx + magic*rx, y,
x+width, y+ry-magic*ry,
x+width, y+ry);
cairo_line_to(aCtx, x+width, y+height-ry);
cairo_curve_to(aCtx,
x+width, y+height-ry + magic*ry,
x+width-rx + magic*rx, y+height,
x+width-rx, y+height);
cairo_line_to(aCtx, x+rx, y+height);
cairo_curve_to(aCtx,
x+rx - magic*rx, y+height,
x, y+height-ry + magic*ry,
x, y+height-ry);
cairo_line_to(aCtx, x, y+ry);
cairo_curve_to(aCtx,
x, y+ry - magic*ry,
x+rx - magic*rx, y,
x+rx, y);
cairo_close_path(aCtx);
}
}

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

@ -181,17 +181,7 @@ NS_NewSVGOuterSVGFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleCo
nsIFrame*
NS_NewSVGInnerSVGFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
nsIFrame*
NS_NewSVGPolylineFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
nsIFrame*
NS_NewSVGPolygonFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
nsIFrame*
NS_NewSVGCircleFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
nsIFrame*
NS_NewSVGEllipseFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
nsIFrame*
NS_NewSVGLineFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
nsIFrame*
NS_NewSVGRectFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
NS_NewSVGPathGeometryFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
nsIFrame*
NS_NewSVGGFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
nsIFrame*
@ -201,8 +191,6 @@ nsIFrame*
NS_NewSVGForeignObjectFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
#endif
nsIFrame*
NS_NewSVGPathFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
nsIFrame*
NS_NewSVGGlyphFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame* parent, nsStyleContext* aContext);
nsIFrame*
NS_NewSVGTextFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
@ -7707,28 +7695,22 @@ nsCSSFrameConstructor::ConstructSVGFrame(nsFrameConstructorState& aState,
else if (aTag == nsSVGAtoms::g) {
newFrame = NS_NewSVGGFrame(mPresShell, aContent, aStyleContext);
}
else if (aTag == nsSVGAtoms::polygon)
newFrame = NS_NewSVGPolygonFrame(mPresShell, aContent, aStyleContext);
else if (aTag == nsSVGAtoms::polyline)
newFrame = NS_NewSVGPolylineFrame(mPresShell, aContent, aStyleContext);
else if (aTag == nsSVGAtoms::circle)
newFrame = NS_NewSVGCircleFrame(mPresShell, aContent, aStyleContext);
else if (aTag == nsSVGAtoms::polygon ||
aTag == nsSVGAtoms::polyline ||
aTag == nsSVGAtoms::circle ||
aTag == nsSVGAtoms::ellipse ||
aTag == nsSVGAtoms::line ||
aTag == nsSVGAtoms::rect ||
aTag == nsSVGAtoms::path)
newFrame = NS_NewSVGPathGeometryFrame(mPresShell, aContent, aStyleContext);
else if (aTag == nsSVGAtoms::defs) {
newFrame = NS_NewSVGContainerFrame(mPresShell, aContent, aStyleContext);
}
else if (aTag == nsSVGAtoms::ellipse)
newFrame = NS_NewSVGEllipseFrame(mPresShell, aContent, aStyleContext);
else if (aTag == nsSVGAtoms::line)
newFrame = NS_NewSVGLineFrame(mPresShell, aContent, aStyleContext);
else if (aTag == nsSVGAtoms::rect)
newFrame = NS_NewSVGRectFrame(mPresShell, aContent, aStyleContext);
#ifdef MOZ_SVG_FOREIGNOBJECT
else if (aTag == nsSVGAtoms::foreignObject) {
newFrame = NS_NewSVGForeignObjectFrame(mPresShell, aContent, aStyleContext);
}
#endif
else if (aTag == nsSVGAtoms::path)
newFrame = NS_NewSVGPathFrame(mPresShell, aContent, aStyleContext);
else if (aTag == nsSVGAtoms::text) {
newFrame = NS_NewSVGTextFrame(mPresShell, aContent, aStyleContext);
}

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

@ -67,10 +67,8 @@ REQUIRES = xpcom \
$(NULL)
CPPSRCS = \
nsSVGCircleFrame.cpp \
nsSVGClipPathFrame.cpp \
nsSVGContainerFrame.cpp \
nsSVGEllipseFrame.cpp \
nsSVGFilterFrame.cpp \
nsSVGGFrame.cpp \
nsSVGGenericContainerFrame.cpp \
@ -80,17 +78,12 @@ CPPSRCS = \
nsSVGImageFrame.cpp \
nsSVGInnerSVGFrame.cpp \
nsSVGLeafFrame.cpp \
nsSVGLineFrame.cpp \
nsSVGMarkerFrame.cpp \
nsSVGMaskFrame.cpp \
nsSVGOuterSVGFrame.cpp \
nsSVGPaintServerFrame.cpp \
nsSVGPathFrame.cpp \
nsSVGPathGeometryFrame.cpp \
nsSVGPatternFrame.cpp \
nsSVGPolygonFrame.cpp \
nsSVGPolylineFrame.cpp \
nsSVGRectFrame.cpp \
nsSVGStopFrame.cpp \
nsSVGTextFrame.cpp \
nsSVGTextPathFrame.cpp \

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

@ -1,132 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla SVG project.
*
* The Initial Developer of the Original Code is
* Crocodile Clips Ltd..
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsSVGPathGeometryFrame.h"
#include "nsIDOMSVGCircleElement.h"
#include "nsSVGElement.h"
#include "nsSVGUtils.h"
class nsSVGCircleFrame : public nsSVGPathGeometryFrame
{
protected:
friend nsIFrame*
NS_NewSVGCircleFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
nsSVGCircleFrame(nsStyleContext* aContext) : nsSVGPathGeometryFrame(aContext) {}
public:
/**
* Get the "type" of the frame
*
* @see nsLayoutAtoms::svgCircleFrame
*/
virtual nsIAtom* GetType() const;
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const
{
return MakeFrameName(NS_LITERAL_STRING("SVGCircle"), aResult);
}
#endif
// nsIFrame interface:
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
// nsSVGPathGeometryFrame methods:
virtual void ConstructPath(cairo_t *aCtx);
};
//----------------------------------------------------------------------
// Implementation
nsIFrame*
NS_NewSVGCircleFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext)
{
nsCOMPtr<nsIDOMSVGCircleElement> circle = do_QueryInterface(aContent);
if (!circle) {
#ifdef DEBUG
printf("warning: trying to construct an SVGCircleFrame for a content element that doesn't support the right interfaces\n");
#endif
return nsnull;
}
return new (aPresShell) nsSVGCircleFrame(aContext);
}
nsIAtom *
nsSVGCircleFrame::GetType() const
{
return nsLayoutAtoms::svgCircleFrame;
}
//----------------------------------------------------------------------
// nsIFrame methods:
NS_IMETHODIMP
nsSVGCircleFrame::AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType)
{
if (aNameSpaceID == kNameSpaceID_None &&
(aAttribute == nsGkAtoms::cx ||
aAttribute == nsGkAtoms::cy ||
aAttribute == nsGkAtoms::r)) {
UpdateGraphic();
return NS_OK;
}
return nsSVGPathGeometryFrame::AttributeChanged(aNameSpaceID,
aAttribute, aModType);
}
//----------------------------------------------------------------------
// nsSVGPathGeometryFrame methods:
void
nsSVGCircleFrame::ConstructPath(cairo_t *aCtx)
{
float x, y, r;
nsSVGElement *element = NS_STATIC_CAST(nsSVGElement*, mContent);
element->GetAnimatedLengthValues(&x, &y, &r, nsnull);
cairo_arc(aCtx, x, y, r, 0, 2*M_PI);
}

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

@ -1,135 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla SVG project.
*
* The Initial Developer of the Original Code is
* Crocodile Clips Ltd..
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* William Cook <william.cook@crocodile-clips.com> (original author)
* Alex Fritze <alex.fritze@crocodile-clips.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsSVGPathGeometryFrame.h"
#include "nsIDOMSVGEllipseElement.h"
#include "nsSVGElement.h"
#include "nsSVGUtils.h"
class nsSVGEllipseFrame : public nsSVGPathGeometryFrame
{
friend nsIFrame*
NS_NewSVGEllipseFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
nsSVGEllipseFrame(nsStyleContext* aContext) : nsSVGPathGeometryFrame(aContext) {}
/**
* Get the "type" of the frame
*
* @see nsLayoutAtoms::svgEllipseFrame
*/
virtual nsIAtom* GetType() const;
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const
{
return MakeFrameName(NS_LITERAL_STRING("SVGEllipse"), aResult);
}
#endif
// nsIFrame interface:
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
// nsSVGPathGeometryFrame methods:
virtual void ConstructPath(cairo_t *aCtx);
};
//----------------------------------------------------------------------
// Implementation
nsIFrame*
NS_NewSVGEllipseFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext)
{
nsCOMPtr<nsIDOMSVGEllipseElement> ellipse = do_QueryInterface(aContent);
if (!ellipse) {
#ifdef DEBUG
printf("warning: trying to construct an SVGEllipseFrame for a content element that doesn't support the right interfaces\n");
#endif
return nsnull;
}
return new (aPresShell) nsSVGEllipseFrame(aContext);
}
//----------------------------------------------------------------------
// nsIFrame methods:
nsIAtom *
nsSVGEllipseFrame::GetType() const
{
return nsLayoutAtoms::svgEllipseFrame;
}
NS_IMETHODIMP
nsSVGEllipseFrame::AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType)
{
if (aNameSpaceID == kNameSpaceID_None &&
(aAttribute == nsGkAtoms::cx ||
aAttribute == nsGkAtoms::cy ||
aAttribute == nsGkAtoms::rx ||
aAttribute == nsGkAtoms::ry)) {
UpdateGraphic();
return NS_OK;
}
return nsSVGPathGeometryFrame::AttributeChanged(aNameSpaceID,
aAttribute, aModType);
}
//----------------------------------------------------------------------
// nsISVGPathGeometrySource methods:
void
nsSVGEllipseFrame::ConstructPath(cairo_t *aCtx)
{
float x, y, rx, ry;
nsSVGElement *element = NS_STATIC_CAST(nsSVGElement*, mContent);
element->GetAnimatedLengthValues(&x, &y, &rx, &ry, nsnull);
cairo_save(aCtx);
cairo_translate(aCtx, x, y);
cairo_scale(aCtx, rx, ry);
cairo_arc(aCtx, 0, 0, 1, 0, 2 * M_PI);
cairo_restore(aCtx);
}

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

@ -96,7 +96,6 @@ public:
virtual nsresult GetFillPaintType() { return eStyleSVGPaintType_Color; }
// nsSVGPathGeometryFrame methods:
virtual void ConstructPath(cairo_t *aCtx);
virtual PRUint16 GetHittestMask();
// nsIFrame interface:
@ -211,27 +210,6 @@ nsSVGImageFrame::AttributeChanged(PRInt32 aNameSpaceID,
aAttribute, aModType);
}
//----------------------------------------------------------------------
// nsISVGPathGeometrySource methods:
/* For the purposes of the update/invalidation logic pretend to
be a rectangle. */
void
nsSVGImageFrame::ConstructPath(cairo_t *aCtx)
{
float x, y, width, height;
nsSVGElement *element = NS_STATIC_CAST(nsSVGElement*, mContent);
element->GetAnimatedLengthValues(&x, &y, &width, &height, nsnull);
/* In a perfect world, this would be handled by the DOM, and
return a DOM exception. */
if (width == 0 || height == 0)
return;
cairo_rectangle(aCtx, x, y, width, height);
}
//----------------------------------------------------------------------
// nsISVGChildFrame methods:
NS_IMETHODIMP
@ -482,6 +460,9 @@ nsSVGImageFrame::ConvertFrame(gfxIImageFrame *aNewFrame)
return NS_OK;
}
//----------------------------------------------------------------------
// nsSVGPathGeometryFrame methods:
// Lie about our fill/stroke so that hit detection works properly
PRUint16

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

@ -1,159 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla SVG project.
*
* The Initial Developer of the Original Code is
* Crocodile Clips Ltd..
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* William Cook <william.cook@crocodile-clips.com> (original author)
* Alex Fritze <alex.fritze@crocodile-clips.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsSVGPathGeometryFrame.h"
#include "nsIDOMSVGLineElement.h"
#include "nsSVGElement.h"
#include "nsSVGMarkerFrame.h"
class nsSVGLineFrame : public nsSVGPathGeometryFrame
{
friend nsIFrame*
NS_NewSVGLineFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
nsSVGLineFrame(nsStyleContext* aContext) : nsSVGPathGeometryFrame(aContext) {}
/**
* Get the "type" of the frame
*
* @see nsLayoutAtoms::svgLineFrame
*/
virtual nsIAtom* GetType() const;
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const
{
return MakeFrameName(NS_LITERAL_STRING("SVGLine"), aResult);
}
#endif
// nsIFrame interface:
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
// nsSVGPathGeometryFrame methods
virtual PRBool IsMarkable() { return PR_TRUE; }
virtual void GetMarkPoints(nsVoidArray *aMarks);
virtual void ConstructPath(cairo_t *aCtx);
};
//----------------------------------------------------------------------
// Implementation
nsIFrame*
NS_NewSVGLineFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext)
{
nsCOMPtr<nsIDOMSVGLineElement> line = do_QueryInterface(aContent);
if (!line) {
#ifdef DEBUG
printf("warning: trying to construct an SVGLineFrame for a content element that doesn't support the right interfaces\n");
#endif
return nsnull;
}
return new (aPresShell) nsSVGLineFrame(aContext);
}
//----------------------------------------------------------------------
// nsIFrame methods:
nsIAtom *
nsSVGLineFrame::GetType() const
{
return nsLayoutAtoms::svgLineFrame;
}
NS_IMETHODIMP
nsSVGLineFrame::AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType)
{
if (aNameSpaceID == kNameSpaceID_None &&
(aAttribute == nsGkAtoms::x1 ||
aAttribute == nsGkAtoms::y1 ||
aAttribute == nsGkAtoms::x2 ||
aAttribute == nsGkAtoms::y2)) {
UpdateGraphic();
return NS_OK;
}
return nsSVGPathGeometryFrame::AttributeChanged(aNameSpaceID,
aAttribute, aModType);
}
//----------------------------------------------------------------------
// nsISVGPathGeometrySource methods:
void
nsSVGLineFrame::ConstructPath(cairo_t *aCtx)
{
float x1, y1, x2, y2;
nsSVGElement *element = NS_STATIC_CAST(nsSVGElement*, mContent);
element->GetAnimatedLengthValues(&x1, &y1, &x2, &y2, nsnull);
// move to start coordinates then draw line to end coordinates
cairo_move_to(aCtx, x1, y1);
cairo_line_to(aCtx, x2, y2);
}
//----------------------------------------------------------------------
// nsSVGPathGeometry methods:
void
nsSVGLineFrame::GetMarkPoints(nsVoidArray *aMarks) {
float x1, y1, x2, y2;
nsSVGElement *element = NS_STATIC_CAST(nsSVGElement*, mContent);
element->GetAnimatedLengthValues(&x1, &y1, &x2, &y2, nsnull);
nsSVGMark *m1, *m2;
m1 = new nsSVGMark();
m2 = new nsSVGMark();
m1->x = x1;
m1->y = y1;
m2->x = x2;
m2->y = y2;
m1->angle = m2->angle = atan2(y2-y1, x2-x1);
aMarks->AppendElement(m1);
aMarks->AppendElement(m2);
}

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

@ -41,6 +41,7 @@
#include "nsISVGRendererCanvas.h"
#include "nsSVGMatrix.h"
#include "nsSVGMarkerElement.h"
#include "nsSVGPathGeometryElement.h"
NS_INTERFACE_MAP_BEGIN(nsSVGMarkerFrame)
NS_INTERFACE_MAP_ENTRY(nsISVGValue)

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

@ -49,10 +49,7 @@ class nsISVGRendererCanvas;
class nsSVGPathGeometryFrame;
class nsIURI;
class nsIContent;
struct nsSVGMark {
float x, y, angle;
};
struct nsSVGMark;
typedef nsSVGContainerFrame nsSVGMarkerFrameBase;

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

@ -1,596 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla SVG project.
*
* The Initial Developer of the Original Code is
* Crocodile Clips Ltd..
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
* Daniele Nicolodi <daniele@grinta.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsSVGPathGeometryFrame.h"
#include "nsIDOMSVGAnimatedPathData.h"
#include "nsIDOMSVGPathSegList.h"
#include "nsIDOMSVGPathSeg.h"
#include "nsIDOMSVGMatrix.h"
#include "nsISupports.h"
#include "nsLayoutAtoms.h"
#include "nsSVGUtils.h"
#include "nsINameSpaceManager.h"
#include "nsGkAtoms.h"
#include "nsSVGPathElement.h"
#include "nsSVGMarkerFrame.h"
class nsSVGPathFrame : public nsSVGPathGeometryFrame
{
protected:
friend nsIFrame*
NS_NewSVGPathFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
public:
nsSVGPathFrame(nsStyleContext* aContext) : nsSVGPathGeometryFrame(aContext) {}
// nsIFrame interface:
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
// nsSVGPathGeometryFrame methods
virtual PRBool IsMarkable() { return PR_TRUE; }
virtual void GetMarkPoints(nsVoidArray *aMarks);
virtual void ConstructPath(cairo_t *aCtx);
/**
* Get the "type" of the frame
*
* @see nsLayoutAtoms::svgPathFrame
*/
virtual nsIAtom* GetType() const;
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const
{
return MakeFrameName(NS_LITERAL_STRING("SVGPath"), aResult);
}
#endif
};
//----------------------------------------------------------------------
// Implementation
nsIFrame*
NS_NewSVGPathFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext)
{
nsCOMPtr<nsIDOMSVGAnimatedPathData> anim_data = do_QueryInterface(aContent);
if (!anim_data) {
#ifdef DEBUG
printf("warning: trying to construct an SVGPathFrame for a content element that doesn't support the right interfaces\n");
#endif
return nsnull;
}
return new (aPresShell) nsSVGPathFrame(aContext);
}
//----------------------------------------------------------------------
// nsISVGFrame methods:
NS_IMETHODIMP
nsSVGPathFrame::AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType)
{
if (aNameSpaceID == kNameSpaceID_None &&
aAttribute == nsGkAtoms::d) {
UpdateGraphic();
return NS_OK;
}
return nsSVGPathGeometryFrame::AttributeChanged(aNameSpaceID,
aAttribute, aModType);
}
//----------------------------------------------------------------------
// nsISVGPathGeometrySource methods:
static double
CalcVectorAngle(double ux, double uy, double vx, double vy)
{
double ta = atan2(uy, ux);
double tb = atan2(vy, vx);
if (tb >= ta)
return tb-ta;
return 2 * M_PI - (ta-tb);
}
void
nsSVGPathFrame::ConstructPath(cairo_t *aCtx)
{
nsSVGPathElement *element = NS_STATIC_CAST(nsSVGPathElement*, mContent);
element->mPathData.Playback(aCtx);
}
//----------------------------------------------------------------------
// nsSVGPathGeometry methods:
void
nsSVGPathFrame::GetMarkPoints(nsVoidArray *aMarks) {
nsCOMPtr<nsIDOMSVGPathSegList> segmentList;
nsCOMPtr<nsIDOMSVGAnimatedPathData> anim_data = do_QueryInterface(mContent);
NS_ASSERTION(anim_data,"wrong content element");
anim_data->GetAnimatedPathSegList(getter_AddRefs(segmentList));
NS_ASSERTION(segmentList, "no pathseglist");
if (!segmentList) return;
PRUint32 count;
segmentList->GetNumberOfItems(&count);
nsCOMPtr<nsIDOMSVGPathSeg> segment;
float cx = 0.0f; // current point
float cy = 0.0f;
float cx1 = 0.0f; // last controlpoint (for s,S,t,T)
float cy1 = 0.0f;
PRUint16 lastSegmentType = nsIDOMSVGPathSeg::PATHSEG_UNKNOWN;
float px, py; // subpath initial point
float pathAngle;
PRUint32 pathIndex;
float prevAngle = 0, startAngle, endAngle;
PRBool newSegment = PR_FALSE;
PRUint32 i;
for (i = 0; i < count; ++i) {
nsCOMPtr<nsIDOMSVGPathSeg> segment;
segmentList->GetItem(i, getter_AddRefs(segment));
PRUint16 type = nsIDOMSVGPathSeg::PATHSEG_UNKNOWN;
segment->GetPathSegType(&type);
float x, y;
PRBool absCoords = PR_FALSE;
switch (type) {
case nsIDOMSVGPathSeg::PATHSEG_CLOSEPATH:
{
x = px;
y = py;
startAngle = endAngle = atan2(y - cy, x - cx);
}
break;
case nsIDOMSVGPathSeg::PATHSEG_MOVETO_ABS:
absCoords = PR_TRUE;
case nsIDOMSVGPathSeg::PATHSEG_MOVETO_REL:
{
if (!absCoords) {
nsCOMPtr<nsIDOMSVGPathSegMovetoRel> moveseg = do_QueryInterface(segment);
NS_ASSERTION(moveseg, "interface not implemented");
moveseg->GetX(&x);
moveseg->GetY(&y);
x += cx;
y += cy;
} else {
nsCOMPtr<nsIDOMSVGPathSegMovetoAbs> moveseg = do_QueryInterface(segment);
NS_ASSERTION(moveseg, "interface not implemented");
moveseg->GetX(&x);
moveseg->GetY(&y);
}
px = x;
py = y;
startAngle = endAngle = prevAngle;
newSegment = PR_TRUE;
}
break;
case nsIDOMSVGPathSeg::PATHSEG_LINETO_ABS:
absCoords = PR_TRUE;
case nsIDOMSVGPathSeg::PATHSEG_LINETO_REL:
{
if (!absCoords) {
nsCOMPtr<nsIDOMSVGPathSegLinetoRel> lineseg = do_QueryInterface(segment);
NS_ASSERTION(lineseg, "interface not implemented");
lineseg->GetX(&x);
lineseg->GetY(&y);
x += cx;
y += cy;
} else {
nsCOMPtr<nsIDOMSVGPathSegLinetoAbs> lineseg = do_QueryInterface(segment);
NS_ASSERTION(lineseg, "interface not implemented");
lineseg->GetX(&x);
lineseg->GetY(&y);
}
startAngle = endAngle = atan2(y - cy, x - cx);
}
break;
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS:
absCoords = PR_TRUE;
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_REL:
{
float x1, y1, x2, y2;
if (!absCoords) {
nsCOMPtr<nsIDOMSVGPathSegCurvetoCubicRel> curveseg = do_QueryInterface(segment);
NS_ASSERTION(curveseg, "interface not implemented");
curveseg->GetX(&x);
curveseg->GetY(&y);
curveseg->GetX1(&x1);
curveseg->GetY1(&y1);
curveseg->GetX2(&x2);
curveseg->GetY2(&y2);
x += cx;
y += cy;
x1 += cx;
y1 += cy;
x2 += cx;
y2 += cy;
} else {
nsCOMPtr<nsIDOMSVGPathSegCurvetoCubicAbs> curveseg = do_QueryInterface(segment);
NS_ASSERTION(curveseg, "interface not implemented");
curveseg->GetX(&x);
curveseg->GetY(&y);
curveseg->GetX1(&x1);
curveseg->GetY1(&y1);
curveseg->GetX2(&x2);
curveseg->GetY2(&y2);
}
cx1 = x2;
cy1 = y2;
if (x1 == cx && y1 == cy) {
x1 = x2;
y1 = y2;
}
if (x2 == x && y2 == y) {
x2 = x1;
y2 = y1;
}
startAngle = atan2(y1 - cy, x1 - cx);
endAngle = atan2(y - y2, x - x2);
}
break;
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS:
absCoords = PR_TRUE;
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_REL:
{
float x1, y1;
if (!absCoords) {
nsCOMPtr<nsIDOMSVGPathSegCurvetoQuadraticRel> curveseg = do_QueryInterface(segment);
NS_ASSERTION(curveseg, "interface not implemented");
curveseg->GetX(&x);
curveseg->GetY(&y);
curveseg->GetX1(&x1);
curveseg->GetY1(&y1);
x += cx;
y += cy;
x1 += cx;
y1 += cy;
} else {
nsCOMPtr<nsIDOMSVGPathSegCurvetoQuadraticAbs> curveseg = do_QueryInterface(segment);
NS_ASSERTION(curveseg, "interface not implemented");
curveseg->GetX(&x);
curveseg->GetY(&y);
curveseg->GetX1(&x1);
curveseg->GetY1(&y1);
}
cx1 = x1;
cy1 = y1;
startAngle = atan2(y1 - cy, x1 - cx);
endAngle = atan2(y - y1, x - x1);
}
break;
case nsIDOMSVGPathSeg::PATHSEG_ARC_ABS:
absCoords = PR_TRUE;
case nsIDOMSVGPathSeg::PATHSEG_ARC_REL:
{
float r1, r2, angle;
PRBool largeArcFlag, sweepFlag;
if (!absCoords) {
nsCOMPtr<nsIDOMSVGPathSegArcRel> arcseg = do_QueryInterface(segment);
NS_ASSERTION(arcseg, "interface not implemented");
arcseg->GetX(&x);
arcseg->GetY(&y);
arcseg->GetR1(&r1);
arcseg->GetR2(&r2);
arcseg->GetAngle(&angle);
arcseg->GetLargeArcFlag(&largeArcFlag);
arcseg->GetSweepFlag(&sweepFlag);
x += cx;
y += cy;
} else {
nsCOMPtr<nsIDOMSVGPathSegArcAbs> arcseg = do_QueryInterface(segment);
NS_ASSERTION(arcseg, "interface not implemented");
arcseg->GetX(&x);
arcseg->GetY(&y);
arcseg->GetR1(&r1);
arcseg->GetR2(&r2);
arcseg->GetAngle(&angle);
arcseg->GetLargeArcFlag(&largeArcFlag);
arcseg->GetSweepFlag(&sweepFlag);
}
/* check for degenerate ellipse */
if (r1 == 0.0 || r2 == 0.0) {
startAngle = endAngle = atan2(y - cy, x - cx);
break;
}
r1 = fabs(r1); r2 = fabs(r2);
float xp, yp, cxp, cyp;
/* slope fun&games ... see SVG spec, section F.6 */
angle = angle*M_PI/180.0;
xp = cos(angle)*(cx-x)/2.0 + sin(angle)*(cy-y)/2.0;
yp = -sin(angle)*(cx-x)/2.0 + cos(angle)*(cy-y)/2.0;
/* make sure radii are large enough */
float root, numerator = r1*r1*r2*r2 - r1*r1*yp*yp - r2*r2*xp*xp;
if (numerator < 0.0) {
float s = sqrt(1.0 - numerator/(r1*r1*r2*r2));
r1 *= s;
r2 *= s;
root = 0.0;
} else {
root = sqrt(numerator/(r1*r1*yp*yp + r2*r2*xp*xp));
if (largeArcFlag == sweepFlag)
root = -root;
}
cxp = root*r1*yp/r2;
cyp = -root*r2*xp/r1;
float theta, delta;
theta = CalcVectorAngle(1.0, 0.0, (xp-cxp)/r1, (yp-cyp)/r2);
delta = CalcVectorAngle((xp-cxp)/r1, (yp-cyp)/r2,
(-xp-cxp)/r1, (-yp-cyp)/r2);
if (!sweepFlag && delta > 0)
delta -= 2.0*M_PI;
else if (sweepFlag && delta < 0)
delta += 2.0*M_PI;
float tx1, ty1, tx2, ty2;
tx1 = -cos(angle)*r1*sin(theta) - sin(angle)*r2*cos(theta);
ty1 = -sin(angle)*r1*sin(theta) + cos(angle)*r2*cos(theta);
tx2 = -cos(angle)*r1*sin(theta+delta) - sin(angle)*r2*cos(theta+delta);
ty2 = -sin(angle)*r1*sin(theta+delta) + cos(angle)*r2*cos(theta+delta);
if (delta < 0.0f) {
tx1 = -tx1;
ty1 = -ty1;
tx2 = -tx2;
ty2 = -ty2;
}
startAngle = atan2(ty1, tx1);
endAngle = atan2(ty2, tx2);
}
break;
case nsIDOMSVGPathSeg::PATHSEG_LINETO_HORIZONTAL_ABS:
absCoords = PR_TRUE;
case nsIDOMSVGPathSeg::PATHSEG_LINETO_HORIZONTAL_REL:
{
y = cy;
if (!absCoords) {
nsCOMPtr<nsIDOMSVGPathSegLinetoHorizontalRel> lineseg = do_QueryInterface(segment);
NS_ASSERTION(lineseg, "interface not implemented");
lineseg->GetX(&x);
x += cx;
} else {
nsCOMPtr<nsIDOMSVGPathSegLinetoHorizontalAbs> lineseg = do_QueryInterface(segment);
NS_ASSERTION(lineseg, "interface not implemented");
lineseg->GetX(&x);
}
startAngle = endAngle = atan2(0, x - cx);
}
break;
case nsIDOMSVGPathSeg::PATHSEG_LINETO_VERTICAL_ABS:
absCoords = PR_TRUE;
case nsIDOMSVGPathSeg::PATHSEG_LINETO_VERTICAL_REL:
{
x = cx;
if (!absCoords) {
nsCOMPtr<nsIDOMSVGPathSegLinetoVerticalRel> lineseg = do_QueryInterface(segment);
NS_ASSERTION(lineseg, "interface not implemented");
lineseg->GetY(&y);
y += cy;
} else {
nsCOMPtr<nsIDOMSVGPathSegLinetoVerticalAbs> lineseg = do_QueryInterface(segment);
NS_ASSERTION(lineseg, "interface not implemented");
lineseg->GetY(&y);
}
startAngle = endAngle = atan2(y - cy, 0);
}
break;
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
absCoords = PR_TRUE;
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
{
float x1, y1, x2, y2;
if (lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_REL ||
lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS ||
lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_REL ||
lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS ) {
// the first controlpoint is the reflection of the last one about the current point:
x1 = 2*cx - cx1;
y1 = 2*cy - cy1;
}
else {
// the first controlpoint is equal to the current point:
x1 = cx;
y1 = cy;
}
if (!absCoords) {
nsCOMPtr<nsIDOMSVGPathSegCurvetoCubicSmoothRel> curveseg = do_QueryInterface(segment);
NS_ASSERTION(curveseg, "interface not implemented");
curveseg->GetX(&x);
curveseg->GetY(&y);
curveseg->GetX2(&x2);
curveseg->GetY2(&y2);
x += cx;
y += cy;
x2 += cx;
y2 += cy;
} else {
nsCOMPtr<nsIDOMSVGPathSegCurvetoCubicSmoothAbs> curveseg = do_QueryInterface(segment);
NS_ASSERTION(curveseg, "interface not implemented");
curveseg->GetX(&x);
curveseg->GetY(&y);
curveseg->GetX2(&x2);
curveseg->GetY2(&y2);
}
cx1 = x2;
cy1 = y2;
if (x1 == cx && y1 == cy) {
x1 = x2;
y1 = y2;
}
if (x2 == x && y2 == y) {
x2 = x1;
y2 = y1;
}
startAngle = atan2(y1 - cy, x1 - cx);
endAngle = atan2(y - y2, x - x2);
}
break;
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
absCoords = PR_TRUE;
case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
{
float x1, y1;
if (lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_REL ||
lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS ||
lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL ||
lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS ) {
// the first controlpoint is the reflection of the last one about the current point:
x1 = 2*cx - cx1;
y1 = 2*cy - cy1;
}
else {
// the first controlpoint is equal to the current point:
x1 = cx;
y1 = cy;
}
if (!absCoords) {
nsCOMPtr<nsIDOMSVGPathSegCurvetoQuadraticSmoothRel> curveseg = do_QueryInterface(segment);
NS_ASSERTION(curveseg, "interface not implemented");
curveseg->GetX(&x);
curveseg->GetY(&y);
x += cx;
y += cy;
} else {
nsCOMPtr<nsIDOMSVGPathSegCurvetoQuadraticSmoothAbs> curveseg = do_QueryInterface(segment);
NS_ASSERTION(curveseg, "interface not implemented");
curveseg->GetX(&x);
curveseg->GetY(&y);
}
cx1 = x1;
cy1 = y1;
startAngle = atan2(y1 - cy, x1 - cx);
endAngle = atan2(y - y1, x - x1);
}
break;
default:
NS_ASSERTION(1==0, "unknown path segment");
break;
}
lastSegmentType = type;
if (newSegment &&
type != nsIDOMSVGPathSeg::PATHSEG_MOVETO_ABS &&
type != nsIDOMSVGPathSeg::PATHSEG_MOVETO_REL) {
pathIndex = aMarks->Count() - 1;
pathAngle = startAngle;
((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = pathAngle;
newSegment = PR_FALSE;
prevAngle = endAngle;
} else if (type == nsIDOMSVGPathSeg::PATHSEG_MOVETO_ABS ||
type == nsIDOMSVGPathSeg::PATHSEG_MOVETO_REL) {
if (aMarks->Count())
((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = prevAngle;
} else {
((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle =
nsSVGUtils::AngleBisect(prevAngle, startAngle);
prevAngle = endAngle;
}
nsSVGMark *mark = new nsSVGMark;
mark->x = x;
mark->y = y;
aMarks->AppendElement(mark);
if (type == nsIDOMSVGPathSeg::PATHSEG_CLOSEPATH) {
prevAngle = nsSVGUtils::AngleBisect(endAngle, pathAngle);
((nsSVGMark *)aMarks->ElementAt(pathIndex))->angle = prevAngle;
}
cx = x;
cy = y;
}
if (aMarks->Count())
((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = prevAngle;
}
nsIAtom *
nsSVGPathFrame::GetType() const
{
return nsLayoutAtoms::svgPathFrame;
}

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

@ -63,6 +63,7 @@
#include "nsSVGOuterSVGFrame.h"
#include "nsSVGRect.h"
#include "nsISVGCairoCanvas.h"
#include "nsSVGPathGeometryElement.h"
struct nsSVGMarkerProperty {
nsSVGMarkerFrame *mMarkerStart;
@ -76,6 +77,17 @@ struct nsSVGMarkerProperty {
{}
};
//----------------------------------------------------------------------
// Implementation
nsIFrame*
NS_NewSVGPathGeometryFrame(nsIPresShell* aPresShell,
nsIContent* aContent,
nsStyleContext* aContext)
{
return new (aPresShell) nsSVGPathGeometryFrame(aContext);
}
////////////////////////////////////////////////////////////////////////
// nsSVGPathGeometryFrame
@ -134,9 +146,11 @@ nsSVGPathGeometryFrame::AttributeChanged(PRInt32 aNameSpaceID,
PRInt32 aModType)
{
if (aNameSpaceID == kNameSpaceID_None &&
aAttribute == nsGkAtoms::transform)
(NS_STATIC_CAST(nsSVGPathGeometryElement*,
mContent)->IsDependentAttribute(aAttribute) ||
aAttribute == nsGkAtoms::transform))
UpdateGraphic();
return NS_OK;
}
@ -271,7 +285,7 @@ nsSVGPathGeometryFrame::PaintSVG(nsISVGRendererCanvas* canvas)
/* render */
Render(canvas);
if (IsMarkable()) {
if (NS_STATIC_CAST(nsSVGPathGeometryElement*, mContent)->IsMarkable()) {
// Marker Property is added lazily and may have been removed by a restyle
UpdateMarkerProperty();
nsSVGMarkerProperty *property = GetMarkerProperty();
@ -283,7 +297,8 @@ nsSVGPathGeometryFrame::PaintSVG(nsISVGRendererCanvas* canvas)
float strokeWidth = GetStrokeWidth();
nsVoidArray marks;
GetMarkPoints(&marks);
NS_STATIC_CAST(nsSVGPathGeometryElement*,
mContent)->GetMarkPoints(&marks);
PRUint32 num = marks.Count();
@ -346,7 +361,7 @@ nsSVGPathGeometryFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit)
NS_IMETHODIMP_(nsRect)
nsSVGPathGeometryFrame::GetCoveredRegion()
{
if (IsMarkable()) {
if (NS_STATIC_CAST(nsSVGPathGeometryElement*, mContent)->IsMarkable()) {
nsSVGMarkerProperty *property = GetMarkerProperty();
if (!property ||
@ -360,7 +375,7 @@ nsSVGPathGeometryFrame::GetCoveredRegion()
float strokeWidth = GetStrokeWidth();
nsVoidArray marks;
GetMarkPoints(&marks);
NS_STATIC_CAST(nsSVGPathGeometryElement*, mContent)->GetMarkPoints(&marks);
PRUint32 num = marks.Count();
@ -666,7 +681,7 @@ nsSVGPathGeometryFrame::GeneratePath(cairo_t *ctx, nsISVGCairoCanvas* aCanvas)
cairo_set_matrix(ctx, &matrix);
cairo_new_path(ctx);
ConstructPath(ctx);
NS_STATIC_CAST(nsSVGPathGeometryElement*, mContent)->ConstructPath(ctx);
}

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

@ -62,11 +62,10 @@ typedef nsSVGGeometryFrame nsSVGPathGeometryFrameBase;
class nsSVGPathGeometryFrame : public nsSVGPathGeometryFrameBase,
public nsISVGChildFrame
{
protected:
public:
nsSVGPathGeometryFrame(nsStyleContext* aContext);
virtual ~nsSVGPathGeometryFrame();
public:
// nsISupports interface:
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef() { return 1; }
@ -126,15 +125,12 @@ protected:
virtual nsresult UpdateGraphic(PRBool suppressInvalidation = PR_FALSE);
protected:
virtual PRBool IsMarkable() { return PR_FALSE; }
virtual void GetMarkPoints(nsVoidArray *aMarks) {}
virtual void ConstructPath(cairo_t *aCtx) = 0;
virtual PRUint16 GetHittestMask();
private:
void Render(nsISVGRendererCanvas *aCanvas);
void GeneratePath(cairo_t *ctx, nsISVGCairoCanvas* aCanvas);
private:
nsSVGMarkerProperty *GetMarkerProperty();
void GetMarkerFromStyle(nsSVGMarkerFrame **aResult,
nsSVGMarkerProperty *property,

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

@ -1,227 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla SVG project.
*
* The Initial Developer of the Original Code is
* Crocodile Clips Ltd..
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsSVGPathGeometryFrame.h"
#include "nsIDOMSVGAnimatedPoints.h"
#include "nsIDOMSVGPointList.h"
#include "nsIDOMSVGPoint.h"
#include "nsLayoutAtoms.h"
#include "nsSVGUtils.h"
#include "nsINameSpaceManager.h"
#include "nsGkAtoms.h"
#include "nsSVGMarkerFrame.h"
class nsSVGPolygonFrame : public nsSVGPathGeometryFrame
{
protected:
friend nsIFrame*
NS_NewSVGPolygonFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
NS_IMETHOD InitSVG();
public:
nsSVGPolygonFrame(nsStyleContext* aContext) : nsSVGPathGeometryFrame(aContext) {}
// nsIFrame interface:
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
nsCOMPtr<nsIDOMSVGPointList> mPoints;
// nsSVGPathGeometry methods
virtual PRBool IsMarkable() { return PR_TRUE; }
virtual void GetMarkPoints(nsVoidArray *aMarks);
virtual void ConstructPath(cairo_t *aCtx);
/**
* Get the "type" of the frame
*
* @see nsLayoutAtoms::svgPolygonFrame
*/
virtual nsIAtom* GetType() const;
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const
{
return MakeFrameName(NS_LITERAL_STRING("SVGPolygon"), aResult);
}
#endif
};
//----------------------------------------------------------------------
// Implementation
nsIFrame*
NS_NewSVGPolygonFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext)
{
nsCOMPtr<nsIDOMSVGAnimatedPoints> anim_points = do_QueryInterface(aContent);
if (!anim_points) {
#ifdef DEBUG
printf("warning: trying to construct an SVGPolygonFrame for a content element that doesn't support the right interfaces\n");
#endif
return nsnull;
}
return new (aPresShell) nsSVGPolygonFrame(aContext);
}
NS_IMETHODIMP
nsSVGPolygonFrame::InitSVG()
{
nsresult rv = nsSVGPathGeometryFrame::InitSVG();
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIDOMSVGAnimatedPoints> anim_points = do_QueryInterface(mContent);
NS_ASSERTION(anim_points,"wrong content element");
anim_points->GetPoints(getter_AddRefs(mPoints));
NS_ASSERTION(mPoints, "no points");
if (!mPoints) return NS_ERROR_FAILURE;
return NS_OK;
}
//----------------------------------------------------------------------
// nsIFrame methods:
NS_IMETHODIMP
nsSVGPolygonFrame::AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType)
{
if (aNameSpaceID == kNameSpaceID_None &&
aAttribute == nsGkAtoms::points) {
UpdateGraphic();
return NS_OK;
}
return nsSVGPathGeometryFrame::AttributeChanged(aNameSpaceID,
aAttribute, aModType);
}
//----------------------------------------------------------------------
// nsISVGPathGeometrySource methods:
void
nsSVGPolygonFrame::ConstructPath(cairo_t *aCtx)
{
if (!mPoints)
return;
PRUint32 count;
mPoints->GetNumberOfItems(&count);
if (count == 0)
return;
PRUint32 i;
for (i = 0; i < count; ++i) {
nsCOMPtr<nsIDOMSVGPoint> point;
mPoints->GetItem(i, getter_AddRefs(point));
float x, y;
point->GetX(&x);
point->GetY(&y);
if (i == 0)
cairo_move_to(aCtx, x, y);
else
cairo_line_to(aCtx, x, y);
}
// the difference between a polyline and a polygon is that the
// polygon is closed:
cairo_close_path(aCtx);
}
//----------------------------------------------------------------------
// nsSVGPathGeometry methods:
void
nsSVGPolygonFrame::GetMarkPoints(nsVoidArray *aMarks) {
if (!mPoints)
return;
PRUint32 count;
mPoints->GetNumberOfItems(&count);
if (count == 0)
return;
float px = 0.0, py = 0.0, prevAngle, startAngle;
nsCOMPtr<nsIDOMSVGPoint> point;
for (PRUint32 i = 0; i < count; ++i) {
mPoints->GetItem(i, getter_AddRefs(point));
float x, y;
point->GetX(&x);
point->GetY(&y);
float angle = atan2(y-py, x-px);
if (i == 1)
startAngle = angle;
else if (i > 1)
((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle =
nsSVGUtils::AngleBisect(prevAngle, angle);
nsSVGMark *mark;
mark = new nsSVGMark;
mark->x = x;
mark->y = y;
aMarks->AppendElement(mark);
prevAngle = angle;
px = x;
py = y;
}
float nx, ny, angle;
mPoints->GetItem(0, getter_AddRefs(point));
point->GetX(&nx);
point->GetY(&ny);
angle = atan2(ny - py, nx - px);
((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle =
nsSVGUtils::AngleBisect(prevAngle, angle);
((nsSVGMark *)aMarks->ElementAt(0))->angle =
nsSVGUtils::AngleBisect(angle, startAngle);
}
nsIAtom *
nsSVGPolygonFrame::GetType() const
{
return nsLayoutAtoms::svgPolygonFrame;
}

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

@ -1,215 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla SVG project.
*
* The Initial Developer of the Original Code is
* Crocodile Clips Ltd..
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsSVGPathGeometryFrame.h"
#include "nsIDOMSVGAnimatedPoints.h"
#include "nsIDOMSVGPointList.h"
#include "nsIDOMSVGPoint.h"
#include "nsLayoutAtoms.h"
#include "nsSVGUtils.h"
#include "nsINameSpaceManager.h"
#include "nsGkAtoms.h"
#include "nsSVGMarkerFrame.h"
class nsSVGPolylineFrame : public nsSVGPathGeometryFrame
{
protected:
friend nsIFrame*
NS_NewSVGPolylineFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
NS_IMETHOD InitSVG();
public:
nsSVGPolylineFrame(nsStyleContext* aContext) : nsSVGPathGeometryFrame(aContext) {}
/**
* Get the "type" of the frame
*
* @see nsLayoutAtoms::svgPolylineFrame
*/
virtual nsIAtom* GetType() const;
// nsIFrame interface:
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const
{
return MakeFrameName(NS_LITERAL_STRING("SVGPolyline"), aResult);
}
#endif
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
nsCOMPtr<nsIDOMSVGPointList> mPoints;
// nsSVGPathGeometryFrame methods
virtual PRBool IsMarkable() { return PR_TRUE; }
virtual void GetMarkPoints(nsVoidArray *aMarks);
virtual void ConstructPath(cairo_t *aCtx);
};
//----------------------------------------------------------------------
// Implementation
nsIFrame*
NS_NewSVGPolylineFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext)
{
nsCOMPtr<nsIDOMSVGAnimatedPoints> anim_points = do_QueryInterface(aContent);
if (!anim_points) {
#ifdef DEBUG
printf("warning: trying to construct an SVGPolylineFrame for a content element that doesn't support the right interfaces\n");
#endif
return nsnull;
}
return new (aPresShell) nsSVGPolylineFrame(aContext);
}
NS_IMETHODIMP
nsSVGPolylineFrame::InitSVG()
{
nsresult rv = nsSVGPathGeometryFrame::InitSVG();
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIDOMSVGAnimatedPoints> anim_points = do_QueryInterface(mContent);
NS_ASSERTION(anim_points,"wrong content element");
anim_points->GetPoints(getter_AddRefs(mPoints));
NS_ASSERTION(mPoints, "no points");
if (!mPoints) return NS_ERROR_FAILURE;
return NS_OK;
}
nsIAtom *
nsSVGPolylineFrame::GetType() const
{
return nsLayoutAtoms::svgPolylineFrame;
}
//----------------------------------------------------------------------
// nsIFrame methods:
NS_IMETHODIMP
nsSVGPolylineFrame::AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType)
{
if (aNameSpaceID == kNameSpaceID_None &&
aAttribute == nsGkAtoms::points) {
UpdateGraphic();
return NS_OK;
}
return nsSVGPathGeometryFrame::AttributeChanged(aNameSpaceID,
aAttribute, aModType);
}
//----------------------------------------------------------------------
// nsISVGPathGeometrySource methods:
void
nsSVGPolylineFrame::ConstructPath(cairo_t *aCtx)
{
if (!mPoints)
return;
PRUint32 count;
mPoints->GetNumberOfItems(&count);
if (count == 0)
return;
PRUint32 i;
for (i = 0; i < count; ++i) {
nsCOMPtr<nsIDOMSVGPoint> point;
mPoints->GetItem(i, getter_AddRefs(point));
float x, y;
point->GetX(&x);
point->GetY(&y);
if (i == 0)
cairo_move_to(aCtx, x, y);
else
cairo_line_to(aCtx, x, y);
}
}
//----------------------------------------------------------------------
// nsSVGPathGeometry methods:
void
nsSVGPolylineFrame::GetMarkPoints(nsVoidArray *aMarks) {
if (!mPoints)
return;
PRUint32 count;
mPoints->GetNumberOfItems(&count);
if (count == 0)
return;
float px = 0.0, py = 0.0, prevAngle;
for (PRUint32 i = 0; i < count; ++i) {
nsCOMPtr<nsIDOMSVGPoint> point;
mPoints->GetItem(i, getter_AddRefs(point));
float x, y;
point->GetX(&x);
point->GetY(&y);
float angle = atan2(y-py, x-px);
if (i == 1)
((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = angle;
else if (i > 1)
((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle =
nsSVGUtils::AngleBisect(prevAngle, angle);
nsSVGMark *mark;
mark = new nsSVGMark;
mark->x = x;
mark->y = y;
aMarks->AppendElement(mark);
prevAngle = angle;
px = x;
py = y;
}
((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = prevAngle;
}

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

@ -1,194 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla SVG project.
*
* The Initial Developer of the Original Code is
* Crocodile Clips Ltd..
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* William Cook <william.cook@crocodile-clips.com> (original author)
* Håkan Waara <hwaara@chello.se>
* Alex Fritze <alex.fritze@crocodile-clips.com>
* Jonathan Watt <jonathan.watt@strath.ac.uk>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsSVGPathGeometryFrame.h"
#include "nsIDOMSVGRectElement.h"
#include "nsSVGElement.h"
class nsSVGRectFrame : public nsSVGPathGeometryFrame
{
protected:
friend nsIFrame*
NS_NewSVGRectFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext);
nsSVGRectFrame(nsStyleContext* aContext) : nsSVGPathGeometryFrame(aContext) {}
public:
/**
* Get the "type" of the frame
*
* @see nsLayoutAtoms::svgRectFrame
*/
virtual nsIAtom* GetType() const;
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const
{
return MakeFrameName(NS_LITERAL_STRING("SVGRect"), aResult);
}
#endif
// nsIFrame interface:
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
// nsSVGPathGeometryFrame interface:
virtual void ConstructPath(cairo_t *aCtx);
};
//----------------------------------------------------------------------
// Implementation
nsIFrame*
NS_NewSVGRectFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext)
{
nsCOMPtr<nsIDOMSVGRectElement> Rect = do_QueryInterface(aContent);
if (!Rect) {
NS_ASSERTION(Rect != nsnull, "wrong content element");
return nsnull;
}
return new (aPresShell) nsSVGRectFrame(aContext);
}
//----------------------------------------------------------------------
// nsIFrame methods:
NS_IMETHODIMP
nsSVGRectFrame::AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType)
{
if (aNameSpaceID == kNameSpaceID_None &&
(aAttribute == nsGkAtoms::x ||
aAttribute == nsGkAtoms::y ||
aAttribute == nsGkAtoms::width ||
aAttribute == nsGkAtoms::height ||
aAttribute == nsGkAtoms::rx ||
aAttribute == nsGkAtoms::ry)) {
UpdateGraphic();
return NS_OK;
}
return nsSVGPathGeometryFrame::AttributeChanged(aNameSpaceID,
aAttribute, aModType);
}
//----------------------------------------------------------------------
// nsISVGPathGeometrySource methods:
void
nsSVGRectFrame::ConstructPath(cairo_t *aCtx)
{
float x, y, width, height, rx, ry;
nsSVGElement *element = NS_STATIC_CAST(nsSVGElement*, mContent);
element->GetAnimatedLengthValues(&x, &y, &width, &height, &rx, &ry, nsnull);
/* In a perfect world, this would be handled by the DOM, and
return a DOM exception. */
if (width <= 0 || height <= 0 || ry < 0 || rx < 0)
return;
/* Clamp rx and ry to half the rect's width and height respectively. */
float halfWidth = width/2;
float halfHeight = height/2;
if (rx > halfWidth)
rx = halfWidth;
if (ry > halfHeight)
ry = halfHeight;
/* If either the 'rx' or the 'ry' attribute isn't set in the markup, then we
have to set it to the value of the other. We do this after clamping rx and
ry since omitting one of the attributes implicitly means they should both
be the same. */
PRBool hasRx = mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::rx);
PRBool hasRy = mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::ry);
if (hasRx && !hasRy)
ry = rx;
else if (hasRy && !hasRx)
rx = ry;
/* However, we may now have made rx > width/2 or else ry > height/2. (If this
is the case, we know we must be giving rx and ry the same value.) */
if (rx > halfWidth)
rx = ry = halfWidth;
else if (ry > halfHeight)
rx = ry = halfHeight;
if (rx == 0 && ry == 0) {
cairo_rectangle(aCtx, x, y, width, height);
} else {
// Conversion factor used for ellipse to bezier conversion.
// Gives radial error of 0.0273% in circular case.
// See comp.graphics.algorithms FAQ 4.04
const float magic = 4*(sqrt(2.)-1)/3;
cairo_move_to(aCtx, x+rx, y);
cairo_line_to(aCtx, x+width-rx, y);
cairo_curve_to(aCtx,
x+width-rx + magic*rx, y,
x+width, y+ry-magic*ry,
x+width, y+ry);
cairo_line_to(aCtx, x+width, y+height-ry);
cairo_curve_to(aCtx,
x+width, y+height-ry + magic*ry,
x+width-rx + magic*rx, y+height,
x+width-rx, y+height);
cairo_line_to(aCtx, x+rx, y+height);
cairo_curve_to(aCtx,
x+rx - magic*rx, y+height,
x, y+height-ry + magic*ry,
x, y+height-ry);
cairo_line_to(aCtx, x, y+ry);
cairo_curve_to(aCtx,
x, y+ry - magic*ry,
x+rx - magic*rx, y,
x+rx, y);
cairo_close_path(aCtx);
}
}
nsIAtom *
nsSVGRectFrame::GetType() const
{
return nsLayoutAtoms::svgRectFrame;
}