Backed out changeset 075fc0110d9f (bug 930468)

This commit is contained in:
Ed Morley 2013-10-24 18:44:52 +01:00
Родитель 37785a21ba
Коммит 0b37883d59
2 изменённых файлов: 0 добавлений и 293 удалений

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

@ -7,10 +7,7 @@
#include "gfx2DGlue.h"
#include "gfxPlatform.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/Types.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/RefPtr.h"
#include "nsError.h"
#include "nsString.h"
#include "nsSVGPathDataParser.h"
@ -244,35 +241,6 @@ ApproximateZeroLengthSubpathSquareCaps(const gfxPoint &aPoint, gfxContext *aCtx)
aCtx->MoveTo(aPoint);
}
static void
ApproximateZeroLengthSubpathSquareCaps(const Point& aPoint,
DrawTarget* aDT,
PathBuilder* aPB)
{
// Cairo's fixed point fractional part is 8 bits wide, so its device space
// coordinate granularity is 1/256 pixels. However, to prevent user space
// |aPoint| and |aPoint + tinyAdvance| being rounded to the same device
// coordinates, we double this for |tinyAdvance|:
Matrix currentTransform = aDT->GetTransform();
currentTransform.Invert();
Size tinyAdvance = currentTransform * Size(2.0/256.0, 0.0);
aPB->MoveTo(aPoint);
aPB->LineTo(aPoint + Point(tinyAdvance.width, tinyAdvance.height));
aPB->MoveTo(aPoint);
}
#define MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS_TO_DT \
do { \
if (capsAreSquare && !subpathHasLength && subpathContainsNonArc && \
SVGPathSegUtils::IsValidType(prevSegType) && \
(!IsMoveto(prevSegType) || \
segType == PATHSEG_CLOSEPATH)) { \
ApproximateZeroLengthSubpathSquareCaps(segStart, aDT, builder); \
} \
} while(0)
#define MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS \
do { \
if (capsAreSquare && !subpathHasLength && subpathContainsNonArc && \
@ -283,257 +251,6 @@ ApproximateZeroLengthSubpathSquareCaps(const Point& aPoint,
} \
} while(0)
TemporaryRef<Path>
SVGPathData::ConstructPath(DrawTarget *aDT,
FillRule aFillRule,
CapStyle aCapStyle) const
{
if (mData.IsEmpty() || !IsMoveto(SVGPathSegUtils::DecodeType(mData[0]))) {
return nullptr; // paths without an initial moveto are invalid
}
RefPtr<PathBuilder> builder = aDT->CreatePathBuilder(aFillRule);
bool capsAreSquare = aCapStyle == CAP_SQUARE;
bool subpathHasLength = false; // visual length
bool subpathContainsNonArc = false;
uint32_t segType = PATHSEG_UNKNOWN;
uint32_t prevSegType = PATHSEG_UNKNOWN;
Point pathStart(0.0, 0.0); // start point of [sub]path
Point segStart(0.0, 0.0);
Point segEnd;
Point cp1, cp2; // previous bezier's control points
Point tcp1, tcp2; // temporaries
// Regarding cp1 and cp2: If the previous segment was a cubic bezier curve,
// then cp2 is its second control point. If the previous segment was a
// quadratic curve, then cp1 is its (only) control point.
uint32_t i = 0;
while (i < mData.Length()) {
segType = SVGPathSegUtils::DecodeType(mData[i++]);
uint32_t argCount = SVGPathSegUtils::ArgCountForType(segType);
switch (segType)
{
case PATHSEG_CLOSEPATH:
// set this early to allow drawing of square caps for "M{x},{y} Z":
subpathContainsNonArc = true;
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS_TO_DT;
segEnd = pathStart;
builder->Close();
break;
case PATHSEG_MOVETO_ABS:
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS_TO_DT;
pathStart = segEnd = Point(mData[i], mData[i+1]);
builder->MoveTo(segEnd);
subpathHasLength = false;
subpathContainsNonArc = false;
break;
case PATHSEG_MOVETO_REL:
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS_TO_DT;
pathStart = segEnd = segStart + Point(mData[i], mData[i+1]);
builder->MoveTo(segEnd);
subpathHasLength = false;
subpathContainsNonArc = false;
break;
case PATHSEG_LINETO_ABS:
segEnd = Point(mData[i], mData[i+1]);
builder->LineTo(segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart);
}
subpathContainsNonArc = true;
break;
case PATHSEG_LINETO_REL:
segEnd = segStart + Point(mData[i], mData[i+1]);
builder->LineTo(segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart);
}
subpathContainsNonArc = true;
break;
case PATHSEG_CURVETO_CUBIC_ABS:
cp1 = Point(mData[i], mData[i+1]);
cp2 = Point(mData[i+2], mData[i+3]);
segEnd = Point(mData[i+4], mData[i+5]);
builder->BezierTo(cp1, cp2, segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart || segEnd != cp1 || segEnd != cp2);
}
subpathContainsNonArc = true;
break;
case PATHSEG_CURVETO_CUBIC_REL:
cp1 = segStart + Point(mData[i], mData[i+1]);
cp2 = segStart + Point(mData[i+2], mData[i+3]);
segEnd = segStart + Point(mData[i+4], mData[i+5]);
builder->BezierTo(cp1, cp2, segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart || segEnd != cp1 || segEnd != cp2);
}
subpathContainsNonArc = true;
break;
case PATHSEG_CURVETO_QUADRATIC_ABS:
cp1 = Point(mData[i], mData[i+1]);
// Convert quadratic curve to cubic curve:
tcp1 = segStart + (cp1 - segStart) * 2 / 3;
segEnd = Point(mData[i+2], mData[i+3]); // set before setting tcp2!
tcp2 = cp1 + (segEnd - cp1) / 3;
builder->BezierTo(tcp1, tcp2, segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart || segEnd != cp1);
}
subpathContainsNonArc = true;
break;
case PATHSEG_CURVETO_QUADRATIC_REL:
cp1 = segStart + Point(mData[i], mData[i+1]);
// Convert quadratic curve to cubic curve:
tcp1 = segStart + (cp1 - segStart) * 2 / 3;
segEnd = segStart + Point(mData[i+2], mData[i+3]); // set before setting tcp2!
tcp2 = cp1 + (segEnd - cp1) / 3;
builder->BezierTo(tcp1, tcp2, segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart || segEnd != cp1);
}
subpathContainsNonArc = true;
break;
case PATHSEG_ARC_ABS:
case PATHSEG_ARC_REL:
{
Point radii(mData[i], mData[i+1]);
segEnd = Point(mData[i+5], mData[i+6]);
if (segType == PATHSEG_ARC_REL) {
segEnd += segStart;
}
if (segEnd != segStart) {
if (radii.x == 0.0f || radii.y == 0.0f) {
builder->LineTo(segEnd);
} else {
nsSVGArcConverter converter(segStart, segEnd, radii, mData[i+2],
mData[i+3] != 0, mData[i+4] != 0);
while (converter.GetNextSegment(&cp1, &cp2, &segEnd)) {
builder->BezierTo(cp1, cp2, segEnd);
}
}
}
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart);
}
break;
}
case PATHSEG_LINETO_HORIZONTAL_ABS:
segEnd = Point(mData[i], segStart.y);
builder->LineTo(segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart);
}
subpathContainsNonArc = true;
break;
case PATHSEG_LINETO_HORIZONTAL_REL:
segEnd = segStart + Point(mData[i], 0.0f);
builder->LineTo(segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart);
}
subpathContainsNonArc = true;
break;
case PATHSEG_LINETO_VERTICAL_ABS:
segEnd = Point(segStart.x, mData[i]);
builder->LineTo(segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart);
}
subpathContainsNonArc = true;
break;
case PATHSEG_LINETO_VERTICAL_REL:
segEnd = segStart + Point(0.0f, mData[i]);
builder->LineTo(segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart);
}
subpathContainsNonArc = true;
break;
case PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
cp1 = SVGPathSegUtils::IsCubicType(prevSegType) ? segStart * 2 - cp2 : segStart;
cp2 = Point(mData[i], mData[i+1]);
segEnd = Point(mData[i+2], mData[i+3]);
builder->BezierTo(cp1, cp2, segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart || segEnd != cp1 || segEnd != cp2);
}
subpathContainsNonArc = true;
break;
case PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
cp1 = SVGPathSegUtils::IsCubicType(prevSegType) ? segStart * 2 - cp2 : segStart;
cp2 = segStart + Point(mData[i], mData[i+1]);
segEnd = segStart + Point(mData[i+2], mData[i+3]);
builder->BezierTo(cp1, cp2, segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart || segEnd != cp1 || segEnd != cp2);
}
subpathContainsNonArc = true;
break;
case PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
cp1 = SVGPathSegUtils::IsQuadraticType(prevSegType) ? segStart * 2 - cp1 : segStart;
// Convert quadratic curve to cubic curve:
tcp1 = segStart + (cp1 - segStart) * 2 / 3;
segEnd = Point(mData[i], mData[i+1]); // set before setting tcp2!
tcp2 = cp1 + (segEnd - cp1) / 3;
builder->BezierTo(tcp1, tcp2, segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart || segEnd != cp1);
}
subpathContainsNonArc = true;
break;
case PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
cp1 = SVGPathSegUtils::IsQuadraticType(prevSegType) ? segStart * 2 - cp1 : segStart;
// Convert quadratic curve to cubic curve:
tcp1 = segStart + (cp1 - segStart) * 2 / 3;
segEnd = segStart + Point(mData[i], mData[i+1]); // changed before setting tcp2!
tcp2 = cp1 + (segEnd - cp1) / 3;
builder->BezierTo(tcp1, tcp2, segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart || segEnd != cp1);
}
subpathContainsNonArc = true;
break;
default:
NS_NOTREACHED("Bad path segment type");
return nullptr; // according to spec we'd use everything up to the bad seg anyway
}
i += argCount;
prevSegType = segType;
segStart = segEnd;
}
NS_ABORT_IF_FALSE(i == mData.Length(), "Very, very bad - mData corrupt");
NS_ABORT_IF_FALSE(prevSegType == segType,
"prevSegType should be left at the final segType");
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS_TO_DT;
return builder->Finish();
}
void
SVGPathData::ConstructPath(gfxContext *aCtx) const
{

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

@ -11,8 +11,6 @@
#include "nsIContent.h"
#include "nsINode.h"
#include "nsIWeakReferenceUtils.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/RefPtr.h"
#include "nsSVGElement.h"
#include "nsTArray.h"
@ -82,11 +80,6 @@ class SVGPathData
// nsSVGPathDataParserToInternal will not keep wrappers in sync, so consumers
// are responsible for that!
typedef gfx::DrawTarget DrawTarget;
typedef gfx::Path Path;
typedef gfx::FillRule FillRule;
typedef gfx::CapStyle CapStyle;
public:
typedef const float* const_iterator;
@ -161,9 +154,6 @@ public:
ToPath(const gfxMatrix& aMatrix) const;
void ConstructPath(gfxContext *aCtx) const;
TemporaryRef<Path> ConstructPath(DrawTarget* aDT,
FillRule aFillRule,
CapStyle aCapStyle) const;
const_iterator begin() const { return mData.Elements(); }
const_iterator end() const { return mData.Elements() + mData.Length(); }