зеркало из https://github.com/mozilla/moz-skia.git
first support at shape ops support for quads
git-svn-id: http://skia.googlecode.com/svn/trunk@3520 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
d3b9fbbc48
Коммит
a5764233aa
|
@ -1,9 +1,11 @@
|
||||||
#include "CurveIntersection.h"
|
#include "CurveIntersection.h"
|
||||||
|
#include "Intersections.h"
|
||||||
#include "LineIntersection.h"
|
#include "LineIntersection.h"
|
||||||
#include "SkPath.h"
|
#include "SkPath.h"
|
||||||
#include "SkRect.h"
|
#include "SkRect.h"
|
||||||
#include "SkTArray.h"
|
#include "SkTArray.h"
|
||||||
#include "SkTDArray.h"
|
#include "SkTDArray.h"
|
||||||
|
#include "ShapeOps.h"
|
||||||
#include "TSearch.h"
|
#include "TSearch.h"
|
||||||
|
|
||||||
namespace UnitTest {
|
namespace UnitTest {
|
||||||
|
|
|
@ -0,0 +1,176 @@
|
||||||
|
#include "EdgeDemo.h"
|
||||||
|
#include "EdgeWalker_Test.h"
|
||||||
|
#include "ShapeOps.h"
|
||||||
|
#import "SkCanvas.h"
|
||||||
|
#import "SkPaint.h"
|
||||||
|
|
||||||
|
// Three circles bounce inside a rectangle. The circles describe three, four
|
||||||
|
// or five points which in turn describe a polygon. The polygon points
|
||||||
|
// bounce inside the circles. The circles rotate and scale over time. The
|
||||||
|
// polygons are combined into a single path, simplified, and stroked.
|
||||||
|
static bool drawCircles(SkCanvas* canvas, int step)
|
||||||
|
{
|
||||||
|
const int circles = 3;
|
||||||
|
int scales[circles];
|
||||||
|
int angles[circles];
|
||||||
|
int locs[circles * 2];
|
||||||
|
int pts[circles * 2 * 4];
|
||||||
|
int c, p;
|
||||||
|
for (c = 0; c < circles; ++c) {
|
||||||
|
scales[c] = abs(10 - (step + c * 4) % 21);
|
||||||
|
angles[c] = (step + c * 6) % 600;
|
||||||
|
locs[c * 2] = abs(130 - (step + c * 9) % 261);
|
||||||
|
locs[c * 2 + 1] = abs(170 - (step + c * 11) % 341);
|
||||||
|
for (p = 0; p < 4; ++p) {
|
||||||
|
pts[c * 8 + p * 2] = abs(90 - ((step + c * 121 + p * 13) % 190));
|
||||||
|
pts[c * 8 + p * 2 + 1] = abs(110 - ((step + c * 223 + p * 17) % 230));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SkPath path, out;
|
||||||
|
for (c = 0; c < circles; ++c) {
|
||||||
|
for (p = 0; p < 4; ++p) {
|
||||||
|
SkScalar x = pts[c * 8 + p * 2];
|
||||||
|
SkScalar y = pts[c * 8 + p * 2 + 1];
|
||||||
|
x *= 3 + scales[c] / 10.0f;
|
||||||
|
y *= 3 + scales[c] / 10.0f;
|
||||||
|
SkScalar angle = angles[c] * 3.1415f * 2 / 600;
|
||||||
|
SkScalar temp = x * cos(angle) - y * sin(angle);
|
||||||
|
y = x * sin(angle) + y * cos(angle);
|
||||||
|
x = temp;
|
||||||
|
x += locs[c * 2] * 200 / 130.0f;
|
||||||
|
y += locs[c * 2 + 1] * 200 / 170.0f;
|
||||||
|
x += 50;
|
||||||
|
// y += 200;
|
||||||
|
if (p == 0) {
|
||||||
|
path.moveTo(x, y);
|
||||||
|
} else {
|
||||||
|
path.lineTo(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
path.close();
|
||||||
|
}
|
||||||
|
showPath(path, "original:");
|
||||||
|
simplify(path, true, out);
|
||||||
|
showPath(out, "simplified:");
|
||||||
|
SkPaint paint;
|
||||||
|
paint.setAntiAlias(true);
|
||||||
|
paint.setStyle(SkPaint::kStroke_Style);
|
||||||
|
paint.setStrokeWidth(3);
|
||||||
|
paint.setColor(0x3F007fbF);
|
||||||
|
canvas->drawPath(path, paint);
|
||||||
|
paint.setColor(0xFF60FF00);
|
||||||
|
paint.setStrokeWidth(1);
|
||||||
|
canvas->drawPath(out, paint);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void createStar(SkPath& path, SkScalar innerRadius, SkScalar outerRadius,
|
||||||
|
SkScalar startAngle, int points, SkPoint center) {
|
||||||
|
SkScalar angle = startAngle;
|
||||||
|
for (int index = 0; index < points * 2; ++index) {
|
||||||
|
SkScalar radius = index & 1 ? outerRadius : innerRadius;
|
||||||
|
SkScalar x = radius * cos(angle);
|
||||||
|
SkScalar y = radius * sin(angle);
|
||||||
|
x += center.fX;
|
||||||
|
y += center.fY;
|
||||||
|
if (index == 0) {
|
||||||
|
path.moveTo(x, y);
|
||||||
|
} else {
|
||||||
|
path.lineTo(x, y);
|
||||||
|
}
|
||||||
|
angle += 3.1415f / points;
|
||||||
|
}
|
||||||
|
path.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool drawStars(SkCanvas* canvas, int step)
|
||||||
|
{
|
||||||
|
SkPath path, out;
|
||||||
|
const int stars = 25;
|
||||||
|
int pts[stars];
|
||||||
|
static bool initialize = true;
|
||||||
|
int s;
|
||||||
|
for (s = 0; s < stars; ++s) {
|
||||||
|
pts[s] = 4 + (s % 7);
|
||||||
|
}
|
||||||
|
SkPoint locs[stars];
|
||||||
|
SkScalar angles[stars];
|
||||||
|
SkScalar innerRadius[stars];
|
||||||
|
SkScalar outerRadius[stars];
|
||||||
|
const int width = 640;
|
||||||
|
const int height = 480;
|
||||||
|
const int margin = 30;
|
||||||
|
const int minRadius = 120;
|
||||||
|
const int maxInner = 800;
|
||||||
|
const int maxOuter = 1153;
|
||||||
|
for (s = 0; s < stars; ++s) {
|
||||||
|
int starW = width - margin * 2 + (SkScalar) s * (stars - s) / stars;
|
||||||
|
locs[s].fX = (int) (step * (1.3f * (s + 1) / stars) + s * 121) % (starW * 2);
|
||||||
|
if (locs[s].fX > starW) {
|
||||||
|
locs[s].fX = starW * 2 - locs[s].fX;
|
||||||
|
}
|
||||||
|
locs[s].fX += margin;
|
||||||
|
int starH = height - margin * 2 + (SkScalar) s * s / stars;
|
||||||
|
locs[s].fY = (int) (step * (1.7f * (s + 1) / stars) + s * 183) % (starH * 2);
|
||||||
|
if (locs[s].fY > starH) {
|
||||||
|
locs[s].fY = starH * 2 - locs[s].fY;
|
||||||
|
}
|
||||||
|
locs[s].fY += margin;
|
||||||
|
angles[s] = ((step + s * 47) % (360 * 4)) * 3.1415f / 180 / 4;
|
||||||
|
innerRadius[s] = (step + s * 30) % (maxInner * 2);
|
||||||
|
if (innerRadius[s] > maxInner) {
|
||||||
|
innerRadius[s] = (maxInner * 2) - innerRadius[s];
|
||||||
|
}
|
||||||
|
innerRadius[s] = innerRadius[s] / 4 + minRadius;
|
||||||
|
outerRadius[s] = (step + s * 70) % (maxOuter * 2);
|
||||||
|
if (outerRadius[s] > maxOuter) {
|
||||||
|
outerRadius[s] = (maxOuter * 2) - outerRadius[s];
|
||||||
|
}
|
||||||
|
outerRadius[s] = outerRadius[s] / 4 + minRadius;
|
||||||
|
createStar(path, innerRadius[s] / 4.0f, outerRadius[s] / 4.0f,
|
||||||
|
angles[s], pts[s], locs[s]);
|
||||||
|
}
|
||||||
|
#define SHOW_PATH 0
|
||||||
|
#if SHOW_PATH
|
||||||
|
showPath(path, "original:");
|
||||||
|
#endif
|
||||||
|
#define TEST_SIMPLIFY 01
|
||||||
|
#if TEST_SIMPLIFY
|
||||||
|
simplify(path, true, out);
|
||||||
|
#if SHOW_PATH
|
||||||
|
showPath(out, "simplified:");
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
SkPaint paint;
|
||||||
|
paint.setAntiAlias(true);
|
||||||
|
paint.setStyle(SkPaint::kStroke_Style);
|
||||||
|
paint.setStrokeWidth(6);
|
||||||
|
paint.setColor(0x1F003f7f);
|
||||||
|
canvas->drawPath(path, paint);
|
||||||
|
paint.setColor(0xFF305F00);
|
||||||
|
paint.setStrokeWidth(1);
|
||||||
|
#if TEST_SIMPLIFY
|
||||||
|
canvas->drawPath(out, paint);
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool (*drawDemos[])(SkCanvas* , int) = {
|
||||||
|
drawStars,
|
||||||
|
drawCircles
|
||||||
|
};
|
||||||
|
|
||||||
|
static size_t drawDemosCount = sizeof(drawDemos) / sizeof(drawDemos[0]);
|
||||||
|
|
||||||
|
static bool (*firstTest)(SkCanvas* , int) = 0;
|
||||||
|
|
||||||
|
|
||||||
|
bool DrawEdgeDemo(SkCanvas* canvas, int step) {
|
||||||
|
size_t index = 0;
|
||||||
|
if (firstTest) {
|
||||||
|
while (index < drawDemosCount && drawDemos[index] != firstTest) {
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (*drawDemos[index])(canvas, step);
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
class SkCanvas;
|
||||||
|
|
||||||
|
bool DrawEdgeDemo(SkCanvas* canvas, int step);
|
|
@ -1,7 +1,5 @@
|
||||||
#include "EdgeWalker_Test.h"
|
#include "EdgeDemo.h"
|
||||||
#include "ShapeOps.h"
|
|
||||||
#import "SkCanvas.h"
|
#import "SkCanvas.h"
|
||||||
#import "SkPaint.h"
|
|
||||||
#import "SkWindow.h"
|
#import "SkWindow.h"
|
||||||
#include "SkGraphics.h"
|
#include "SkGraphics.h"
|
||||||
#include "SkCGUtils.h"
|
#include "SkCGUtils.h"
|
||||||
|
@ -14,66 +12,13 @@ public:
|
||||||
};
|
};
|
||||||
protected:
|
protected:
|
||||||
virtual void onDraw(SkCanvas* canvas) {
|
virtual void onDraw(SkCanvas* canvas) {
|
||||||
// Three circles bounce inside a rectangle. The circles describe three, four
|
static int step = 0;
|
||||||
// or five points which in turn describe a polygon. The polygon points
|
canvas->drawColor(SK_ColorWHITE);
|
||||||
// bounce inside the circles. The circles rotate and scale over time. The
|
if (DrawEdgeDemo(canvas, step)) {
|
||||||
// polygons are combined into a single path, simplified, and stroked.
|
++step;
|
||||||
static int step = 0;
|
inval(NULL);
|
||||||
const int circles = 3;
|
|
||||||
int scales[circles];
|
|
||||||
int angles[circles];
|
|
||||||
int locs[circles * 2];
|
|
||||||
int pts[circles * 2 * 4];
|
|
||||||
int c, p;
|
|
||||||
for (c = 0; c < circles; ++c) {
|
|
||||||
scales[c] = abs(10 - (step + c * 4) % 21);
|
|
||||||
angles[c] = (step + c * 6) % 600;
|
|
||||||
locs[c * 2] = abs(130 - (step + c * 9) % 261);
|
|
||||||
locs[c * 2 + 1] = abs(170 - (step + c * 11) % 341);
|
|
||||||
for (p = 0; p < 4; ++p) {
|
|
||||||
pts[c * 8 + p * 2] = abs(90 - ((step + c * 121 + p * 13) % 190));
|
|
||||||
pts[c * 8 + p * 2 + 1] = abs(110 - ((step + c * 223 + p * 17) % 230));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SkPath path, out;
|
|
||||||
for (c = 0; c < circles; ++c) {
|
|
||||||
for (p = 0; p < 4; ++p) {
|
|
||||||
SkScalar x = pts[c * 8 + p * 2];
|
|
||||||
SkScalar y = pts[c * 8 + p * 2 + 1];
|
|
||||||
x *= 3 + scales[c] / 10.0f;
|
|
||||||
y *= 3 + scales[c] / 10.0f;
|
|
||||||
SkScalar angle = angles[c] * 3.1415f * 2 / 600;
|
|
||||||
SkScalar temp = x * cos(angle) - y * sin(angle);
|
|
||||||
y = x * sin(angle) + y * cos(angle);
|
|
||||||
x = temp;
|
|
||||||
x += locs[c * 2] * 200 / 130.0f;
|
|
||||||
y += locs[c * 2 + 1] * 200 / 170.0f;
|
|
||||||
x += 50;
|
|
||||||
// y += 200;
|
|
||||||
if (p == 0) {
|
|
||||||
path.moveTo(x, y);
|
|
||||||
} else {
|
|
||||||
path.lineTo(x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
path.close();
|
|
||||||
}
|
|
||||||
showPath(path, "original:");
|
|
||||||
simplify(path, true, out);
|
|
||||||
showPath(out, "simplified:");
|
|
||||||
SkPaint paint;
|
|
||||||
paint.setAntiAlias(true);
|
|
||||||
paint.setStyle(SkPaint::kStroke_Style);
|
|
||||||
paint.setStrokeWidth(3);
|
|
||||||
paint.setColor(0x3F007fbF);
|
|
||||||
canvas->drawPath(path, paint);
|
|
||||||
paint.setColor(0xFF60FF00);
|
|
||||||
paint.setStrokeWidth(1);
|
|
||||||
canvas->drawColor(SK_ColorWHITE);
|
|
||||||
canvas->drawPath(out, paint);
|
|
||||||
++step;
|
|
||||||
inval(NULL);
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
typedef SkView INHERITED;
|
typedef SkView INHERITED;
|
||||||
};
|
};
|
||||||
|
@ -97,6 +42,7 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
#import "SimpleApp.h"
|
#import "SimpleApp.h"
|
||||||
|
|
||||||
@implementation SimpleNSView
|
@implementation SimpleNSView
|
||||||
|
|
||||||
- (id)initWithDefaults {
|
- (id)initWithDefaults {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "CurveIntersection.h"
|
#include "CurveIntersection.h"
|
||||||
|
#include "Intersections.h"
|
||||||
#include "LineIntersection.h"
|
#include "LineIntersection.h"
|
||||||
#include "SkPath.h"
|
#include "SkPath.h"
|
||||||
#include "SkRect.h"
|
#include "SkRect.h"
|
||||||
|
@ -15,14 +16,13 @@
|
||||||
#include "ShapeOps.h"
|
#include "ShapeOps.h"
|
||||||
#include "TSearch.h"
|
#include "TSearch.h"
|
||||||
|
|
||||||
#if 0 // set to 1 for no debugging whatsoever
|
#if 01 // set to 1 for no debugging whatsoever
|
||||||
const bool gShowDebugf = false; // FIXME: remove once debugging is complete
|
const bool gShowDebugf = false; // FIXME: remove once debugging is complete
|
||||||
|
|
||||||
#define DEBUG_DUMP 0
|
#define DEBUG_DUMP 0
|
||||||
#define DEBUG_ADD 0
|
#define DEBUG_ADD 0
|
||||||
#define DEBUG_ADD_INTERSECTING_TS 0
|
#define DEBUG_ADD_INTERSECTING_TS 0
|
||||||
#define DEBUG_ADD_BOTTOM_TS 0
|
#define DEBUG_ADD_BOTTOM_TS 0
|
||||||
#define COMPARE_DOUBLE 0
|
|
||||||
#define DEBUG_ABOVE_BELOW 0
|
#define DEBUG_ABOVE_BELOW 0
|
||||||
#define DEBUG_ACTIVE_LESS_THAN 0
|
#define DEBUG_ACTIVE_LESS_THAN 0
|
||||||
#define DEBUG_SORT_HORIZONTAL 0
|
#define DEBUG_SORT_HORIZONTAL 0
|
||||||
|
@ -38,9 +38,8 @@ const bool gShowDebugf = true; // FIXME: remove once debugging is complete
|
||||||
#define DEBUG_ADD 01
|
#define DEBUG_ADD 01
|
||||||
#define DEBUG_ADD_INTERSECTING_TS 0
|
#define DEBUG_ADD_INTERSECTING_TS 0
|
||||||
#define DEBUG_ADD_BOTTOM_TS 0
|
#define DEBUG_ADD_BOTTOM_TS 0
|
||||||
#define COMPARE_DOUBLE 0
|
|
||||||
#define DEBUG_ABOVE_BELOW 01
|
#define DEBUG_ABOVE_BELOW 01
|
||||||
#define DEBUG_ACTIVE_LESS_THAN 01
|
#define DEBUG_ACTIVE_LESS_THAN 0
|
||||||
#define DEBUG_SORT_HORIZONTAL 01
|
#define DEBUG_SORT_HORIZONTAL 01
|
||||||
#define DEBUG_OUT 01
|
#define DEBUG_OUT 01
|
||||||
#define DEBUG_OUT_LESS_THAN 0
|
#define DEBUG_OUT_LESS_THAN 0
|
||||||
|
@ -49,57 +48,101 @@ const bool gShowDebugf = true; // FIXME: remove once debugging is complete
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// FIXME: not wild about this -- for SkScalars backed by floats, would like to
|
|
||||||
// represent deltas in terms of number of significant matching bits
|
|
||||||
#define MIN_PT_DELTA 0.000001
|
|
||||||
|
|
||||||
static int LineIntersect(const SkPoint a[2], const SkPoint b[2],
|
static int LineIntersect(const SkPoint a[2], const SkPoint b[2],
|
||||||
double aRange[2], double bRange[2]) {
|
Intersections& intersections) {
|
||||||
_Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}};
|
const _Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}};
|
||||||
_Line bLine = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}};
|
const _Line bLine = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}};
|
||||||
return intersect(aLine, bLine, aRange, bRange);
|
return intersect(aLine, bLine, intersections.fT[0], intersections.fT[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int QuadLineIntersect(const SkPoint a[3], const SkPoint b[2],
|
||||||
|
Intersections& intersections) {
|
||||||
|
const Quadratic aQuad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}};
|
||||||
|
const _Line bLine = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}};
|
||||||
|
return intersect(aQuad, bLine, intersections);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int CubicLineIntersect(const SkPoint a[2], const SkPoint b[3],
|
||||||
|
Intersections& intersections) {
|
||||||
|
const Cubic aCubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY},
|
||||||
|
{a[3].fX, a[3].fY}};
|
||||||
|
const _Line bLine = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}};
|
||||||
|
intersections.fUsed = intersect(aCubic, bLine, intersections.fT[0], intersections.fT[1]);
|
||||||
|
return intersections.fUsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int QuadIntersect(const SkPoint a[3], const SkPoint b[3],
|
||||||
|
Intersections& intersections) {
|
||||||
|
const Quadratic aQuad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}};
|
||||||
|
const Quadratic bQuad = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}, {b[2].fX, b[2].fY}};
|
||||||
|
return intersect(aQuad, bQuad, intersections);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int CubicIntersect(const SkPoint a[4], const SkPoint b[4],
|
||||||
|
Intersections& intersections) {
|
||||||
|
const Cubic aCubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY},
|
||||||
|
{a[3].fX, a[3].fY}};
|
||||||
|
const Cubic bCubic = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}, {b[2].fX, b[2].fY},
|
||||||
|
{b[3].fX, b[3].fY}};
|
||||||
|
return intersect(aCubic, bCubic, intersections);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int LineIntersect(const SkPoint a[2], SkScalar left, SkScalar right,
|
static int LineIntersect(const SkPoint a[2], SkScalar left, SkScalar right,
|
||||||
SkScalar y, double aRange[2]) {
|
SkScalar y, double aRange[2]) {
|
||||||
_Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}};
|
const _Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}};
|
||||||
return horizontalLineIntersect(aLine, left, right, y, aRange);
|
return horizontalLineIntersect(aLine, left, right, y, aRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LineXYAtT(const SkPoint a[2], double t, SkPoint* out) {
|
static void LineXYAtT(const SkPoint a[2], double t, SkPoint* out) {
|
||||||
_Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}};
|
const _Line line = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}};
|
||||||
double x, y;
|
double x, y;
|
||||||
xy_at_t(aLine, t, x, y);
|
xy_at_t(line, t, x, y);
|
||||||
out->fX = SkDoubleToScalar(x);
|
out->fX = SkDoubleToScalar(x);
|
||||||
out->fY = SkDoubleToScalar(y);
|
out->fY = SkDoubleToScalar(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if COMPARE_DOUBLE
|
static void QuadXYAtT(const SkPoint a[3], double t, SkPoint* out) {
|
||||||
static void LineXYAtT(const SkPoint a[2], double t, _Point* out) {
|
const Quadratic quad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}};
|
||||||
_Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}};
|
double x, y;
|
||||||
xy_at_t(aLine, t, out->x, out->y);
|
xy_at_t(quad, t, x, y);
|
||||||
|
out->fX = SkDoubleToScalar(x);
|
||||||
|
out->fY = SkDoubleToScalar(y);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0 // unused for now
|
static void CubicXYAtT(const SkPoint a[4], double t, SkPoint* out) {
|
||||||
static SkScalar LineXAtT(const SkPoint a[2], double t) {
|
const Cubic cubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY},
|
||||||
_Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}};
|
{a[3].fX, a[3].fY}};
|
||||||
double x;
|
double x, y;
|
||||||
xy_at_t(aLine, t, x, *(double*) 0);
|
xy_at_t(cubic, t, x, y);
|
||||||
return SkDoubleToScalar(x);
|
out->fX = SkDoubleToScalar(x);
|
||||||
|
out->fY = SkDoubleToScalar(y);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static SkScalar LineYAtT(const SkPoint a[2], double t) {
|
static SkScalar LineYAtT(const SkPoint a[2], double t) {
|
||||||
_Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}};
|
const _Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}};
|
||||||
double y;
|
double y;
|
||||||
xy_at_t(aLine, t, *(double*) 0, y);
|
xy_at_t(aLine, t, *(double*) 0, y);
|
||||||
return SkDoubleToScalar(y);
|
return SkDoubleToScalar(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SkScalar QuadYAtT(const SkPoint a[3], double t) {
|
||||||
|
const Quadratic quad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}};
|
||||||
|
double y;
|
||||||
|
xy_at_t(quad, t, *(double*) 0, y);
|
||||||
|
return SkDoubleToScalar(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SkScalar CubicYAtT(const SkPoint a[4], double t) {
|
||||||
|
const Cubic cubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY},
|
||||||
|
{a[3].fX, a[3].fY}};
|
||||||
|
double y;
|
||||||
|
xy_at_t(cubic, t, *(double*) 0, y);
|
||||||
|
return SkDoubleToScalar(y);
|
||||||
|
}
|
||||||
|
|
||||||
static void LineSubDivide(const SkPoint a[2], double startT, double endT,
|
static void LineSubDivide(const SkPoint a[2], double startT, double endT,
|
||||||
SkPoint sub[2]) {
|
SkPoint sub[2]) {
|
||||||
_Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}};
|
const _Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}};
|
||||||
_Line dst;
|
_Line dst;
|
||||||
sub_divide(aLine, startT, endT, dst);
|
sub_divide(aLine, startT, endT, dst);
|
||||||
sub[0].fX = SkDoubleToScalar(dst[0].x);
|
sub[0].fX = SkDoubleToScalar(dst[0].x);
|
||||||
|
@ -108,14 +151,35 @@ static void LineSubDivide(const SkPoint a[2], double startT, double endT,
|
||||||
sub[1].fY = SkDoubleToScalar(dst[1].y);
|
sub[1].fY = SkDoubleToScalar(dst[1].y);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if COMPARE_DOUBLE
|
static void QuadSubDivide(const SkPoint a[3], double startT, double endT,
|
||||||
static void LineSubDivide(const SkPoint a[2], double startT, double endT,
|
SkPoint sub[3]) {
|
||||||
_Line& dst) {
|
const Quadratic aQuad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}};
|
||||||
_Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}};
|
Quadratic dst;
|
||||||
sub_divide(aLine, startT, endT, dst);
|
sub_divide(aQuad, startT, endT, dst);
|
||||||
|
sub[0].fX = SkDoubleToScalar(dst[0].x);
|
||||||
|
sub[0].fY = SkDoubleToScalar(dst[0].y);
|
||||||
|
sub[1].fX = SkDoubleToScalar(dst[1].x);
|
||||||
|
sub[1].fY = SkDoubleToScalar(dst[1].y);
|
||||||
|
sub[2].fX = SkDoubleToScalar(dst[2].x);
|
||||||
|
sub[2].fY = SkDoubleToScalar(dst[2].y);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
static void CubicSubDivide(const SkPoint a[4], double startT, double endT,
|
||||||
|
SkPoint sub[4]) {
|
||||||
|
const Cubic aCubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY},
|
||||||
|
{a[3].fX, a[3].fY}};
|
||||||
|
Cubic dst;
|
||||||
|
sub_divide(aCubic, startT, endT, dst);
|
||||||
|
sub[0].fX = SkDoubleToScalar(dst[0].x);
|
||||||
|
sub[0].fY = SkDoubleToScalar(dst[0].y);
|
||||||
|
sub[1].fX = SkDoubleToScalar(dst[1].x);
|
||||||
|
sub[1].fY = SkDoubleToScalar(dst[1].y);
|
||||||
|
sub[2].fX = SkDoubleToScalar(dst[2].x);
|
||||||
|
sub[2].fY = SkDoubleToScalar(dst[2].y);
|
||||||
|
sub[3].fX = SkDoubleToScalar(dst[3].x);
|
||||||
|
sub[3].fY = SkDoubleToScalar(dst[3].y);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
list of edges
|
list of edges
|
||||||
bounds for edge
|
bounds for edge
|
||||||
|
@ -204,11 +268,11 @@ public:
|
||||||
: fFill(fill) {
|
: fFill(fill) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void addLine(const SkPoint line[2], int id, bool closeCall) {
|
void addCurve(const SkPoint line[4], SkPath::Verb verb, int id,
|
||||||
|
bool closeCall) {
|
||||||
OutEdge& newEdge = fEdges.push_back();
|
OutEdge& newEdge = fEdges.push_back();
|
||||||
newEdge.fPts[0] = line[0];
|
memcpy(newEdge.fPts, line, (verb + 1) * sizeof(SkPoint));
|
||||||
newEdge.fPts[1] = line[1];
|
newEdge.fVerb = verb;
|
||||||
newEdge.fVerb = SkPath::kLine_Verb;
|
|
||||||
newEdge.fID = id;
|
newEdge.fID = id;
|
||||||
newEdge.fCloseCall = closeCall;
|
newEdge.fCloseCall = closeCall;
|
||||||
}
|
}
|
||||||
|
@ -255,7 +319,8 @@ public:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
int closeEdgeIndex = -listIndex - 1;
|
int closeEdgeIndex = -listIndex - 1;
|
||||||
SkPoint firstPt, lastLine[2];
|
SkPoint firstPt, lastCurve[4];
|
||||||
|
uint8_t lastVerb;
|
||||||
bool doMove = true;
|
bool doMove = true;
|
||||||
int edgeIndex;
|
int edgeIndex;
|
||||||
do {
|
do {
|
||||||
|
@ -269,49 +334,80 @@ public:
|
||||||
start = &ptArray[0];
|
start = &ptArray[0];
|
||||||
end = &ptArray[verb];
|
end = &ptArray[verb];
|
||||||
}
|
}
|
||||||
switch (verb) {
|
if (doMove) {
|
||||||
case SkPath::kLine_Verb:
|
firstPt = *start;
|
||||||
bool gap;
|
simple.moveTo(start->fX, start->fY);
|
||||||
if (doMove) {
|
if (gShowDebugf) {
|
||||||
firstPt = *start;
|
SkDebugf("%s moveTo (%g,%g)\n", __FUNCTION__,
|
||||||
simple.moveTo(start->fX, start->fY);
|
start->fX, start->fY);
|
||||||
if (gShowDebugf) {
|
}
|
||||||
SkDebugf("%s moveTo (%g,%g)\n", __FUNCTION__,
|
lastCurve[0] = *start;
|
||||||
start->fX, start->fY);
|
if (verb == SkPath::kQuad_Verb) {
|
||||||
}
|
lastCurve[1] = ptArray[1];
|
||||||
lastLine[0] = *start;
|
} else if (verb == SkPath::kCubic_Verb) {
|
||||||
lastLine[1] = *end;
|
if (advance < 0) {
|
||||||
doMove = false;
|
lastCurve[1] = ptArray[2];
|
||||||
break;
|
lastCurve[2] = ptArray[1];
|
||||||
|
} else {
|
||||||
|
lastCurve[1] = ptArray[1];
|
||||||
|
lastCurve[2] = ptArray[2];
|
||||||
}
|
}
|
||||||
gap = lastLine[1] != *start;
|
}
|
||||||
if (gap) {
|
lastCurve[verb] = *end;
|
||||||
// FIXME: see comment in bridge -- this probably
|
lastVerb = verb;
|
||||||
// conceals errors
|
doMove = false;
|
||||||
SkASSERT(fFill && UlpsDiff(lastLine[1].fY, start->fY) <= 10);
|
} else {
|
||||||
simple.lineTo(lastLine[1].fX, lastLine[1].fY);
|
bool gap = lastCurve[verb] != *start;
|
||||||
if (gShowDebugf) {
|
if (gap) {
|
||||||
SkDebugf("%s lineTo x (%g,%g)\n", __FUNCTION__,
|
// FIXME: see comment in bridge -- this probably
|
||||||
lastLine[1].fX, lastLine[1].fY);
|
// conceals errors
|
||||||
}
|
SkASSERT(fFill && UlpsDiff(lastCurve[lastVerb].fY, start->fY) <= 10);
|
||||||
|
switch (lastVerb) {
|
||||||
|
case SkPath::kLine_Verb:
|
||||||
|
simple.lineTo(lastCurve[1].fX, lastCurve[1].fY);
|
||||||
|
break;
|
||||||
|
case SkPath::kQuad_Verb:
|
||||||
|
simple.quadTo(lastCurve[1].fX, lastCurve[1].fY,
|
||||||
|
lastCurve[2].fX, lastCurve[2].fY);
|
||||||
|
break;
|
||||||
|
case SkPath::kCubic_Verb:
|
||||||
|
simple.cubicTo(lastCurve[1].fX, lastCurve[1].fY,
|
||||||
|
lastCurve[2].fX, lastCurve[2].fY,
|
||||||
|
lastCurve[3].fX, lastCurve[3].fY);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (gap || !extendLine(lastLine, *end)) {
|
if (gShowDebugf) {
|
||||||
// FIXME: see comment in bridge -- this probably
|
const char* verbStr[] = {"", "line", "quad", "cubic"};
|
||||||
// conceals errors
|
SkDebugf("%s %sTo-1 (%g,%g)\n", __FUNCTION__,
|
||||||
SkASSERT(lastLine[1] == *start ||
|
verbStr[lastVerb], lastCurve[lastVerb].fX,
|
||||||
(fFill && UlpsDiff(lastLine[1].fY, start->fY) <= 10));
|
lastCurve[lastVerb].fY);
|
||||||
simple.lineTo(start->fX, start->fY);
|
|
||||||
if (gShowDebugf) {
|
|
||||||
SkDebugf("%s lineTo (%g,%g)\n", __FUNCTION__,
|
|
||||||
start->fX, start->fY);
|
|
||||||
}
|
|
||||||
lastLine[0] = *start;
|
|
||||||
}
|
}
|
||||||
lastLine[1] = *end;
|
}
|
||||||
break;
|
if (gap || lastVerb != SkPath::kLine_Verb || !extendLine(lastCurve, *end)) {
|
||||||
default:
|
// FIXME: see comment in bridge -- this probably
|
||||||
// FIXME: add other curve types
|
// conceals errors
|
||||||
;
|
SkASSERT(lastCurve[lastVerb] == *start ||
|
||||||
|
(fFill && UlpsDiff(lastCurve[lastVerb].fY, start->fY) <= 10));
|
||||||
|
simple.lineTo(start->fX, start->fY);
|
||||||
|
if (gShowDebugf) {
|
||||||
|
SkDebugf("%s lineTo (%g,%g)\n", __FUNCTION__,
|
||||||
|
start->fX, start->fY);
|
||||||
|
}
|
||||||
|
lastCurve[0] = *start;
|
||||||
|
}
|
||||||
|
if (verb == SkPath::kQuad_Verb) {
|
||||||
|
lastCurve[1] = ptArray[1];
|
||||||
|
} else if (verb == SkPath::kCubic_Verb) {
|
||||||
|
if (advance < 0) {
|
||||||
|
lastCurve[1] = ptArray[2];
|
||||||
|
lastCurve[2] = ptArray[1];
|
||||||
|
} else {
|
||||||
|
lastCurve[1] = ptArray[1];
|
||||||
|
lastCurve[2] = ptArray[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastCurve[verb] = *end;
|
||||||
|
lastVerb = verb;
|
||||||
}
|
}
|
||||||
if (advance < 0) {
|
if (advance < 0) {
|
||||||
edgeIndex = fTops[listIndex];
|
edgeIndex = fTops[listIndex];
|
||||||
|
@ -329,11 +425,26 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (edgeIndex == closeEdgeIndex || edgeIndex == 0) {
|
if (edgeIndex == closeEdgeIndex || edgeIndex == 0) {
|
||||||
if (lastLine[1] != firstPt) {
|
if (lastCurve[lastVerb] != firstPt) {
|
||||||
simple.lineTo(lastLine[1].fX, lastLine[1].fY);
|
switch (lastVerb) {
|
||||||
|
case SkPath::kLine_Verb:
|
||||||
|
simple.lineTo(lastCurve[1].fX, lastCurve[1].fY);
|
||||||
|
break;
|
||||||
|
case SkPath::kQuad_Verb:
|
||||||
|
simple.quadTo(lastCurve[1].fX, lastCurve[1].fY,
|
||||||
|
lastCurve[2].fX, lastCurve[2].fY);
|
||||||
|
break;
|
||||||
|
case SkPath::kCubic_Verb:
|
||||||
|
simple.cubicTo(lastCurve[1].fX, lastCurve[1].fY,
|
||||||
|
lastCurve[2].fX, lastCurve[2].fY,
|
||||||
|
lastCurve[3].fX, lastCurve[3].fY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (gShowDebugf) {
|
if (gShowDebugf) {
|
||||||
SkDebugf("%s lineTo last (%g, %g)\n", __FUNCTION__,
|
const char* verbStr[] = {"", "line", "quad", "cubic"};
|
||||||
lastLine[1].fX, lastLine[1].fY);
|
SkDebugf("%s %sTo last (%g, %g)\n", __FUNCTION__,
|
||||||
|
verbStr[lastVerb],
|
||||||
|
lastCurve[lastVerb].fX, lastCurve[lastVerb].fY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
simple.lineTo(firstPt.fX, firstPt.fY);
|
simple.lineTo(firstPt.fX, firstPt.fY);
|
||||||
|
@ -525,13 +636,24 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG_DUMP
|
#if DEBUG_DUMP
|
||||||
// FIXME: pass current verb as parameter
|
void dump(const SkPoint* pts, SkPath::Verb verb) {
|
||||||
void dump(const SkPoint* pts) {
|
|
||||||
const char className[] = "Intercepts";
|
const char className[] = "Intercepts";
|
||||||
const int tab = 8;
|
const int tab = 8;
|
||||||
for (int i = 0; i < fTs.count(); ++i) {
|
for (int i = 0; i < fTs.count(); ++i) {
|
||||||
SkPoint out;
|
SkPoint out;
|
||||||
LineXYAtT(pts, fTs[i], &out);
|
switch (verb) {
|
||||||
|
case SkPath::kLine_Verb:
|
||||||
|
LineXYAtT(pts, fTs[i], &out);
|
||||||
|
break;
|
||||||
|
case SkPath::kQuad_Verb:
|
||||||
|
QuadXYAtT(pts, fTs[i], &out);
|
||||||
|
break;
|
||||||
|
case SkPath::kCubic_Verb:
|
||||||
|
CubicXYAtT(pts, fTs[i], &out);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SkASSERT(0);
|
||||||
|
}
|
||||||
SkDebugf("%*s.fTs[%d]=%1.9g (%1.9g,%1.9g)\n", tab + sizeof(className),
|
SkDebugf("%*s.fTs[%d]=%1.9g (%1.9g,%1.9g)\n", tab + sizeof(className),
|
||||||
className, i, fTs[i], out.fX, out.fY);
|
className, i, fTs[i], out.fX, out.fY);
|
||||||
}
|
}
|
||||||
|
@ -682,7 +804,7 @@ struct InEdge {
|
||||||
SkDebugf("%*s.fIntercepts[%d]:\n", tab + sizeof(className),
|
SkDebugf("%*s.fIntercepts[%d]:\n", tab + sizeof(className),
|
||||||
className, i);
|
className, i);
|
||||||
// FIXME: take current verb into consideration
|
// FIXME: take current verb into consideration
|
||||||
fIntercepts[i].dump(pts);
|
fIntercepts[i].dump(pts, (SkPath::Verb) *verbs);
|
||||||
pts += *verbs++;
|
pts += *verbs++;
|
||||||
}
|
}
|
||||||
for (i = 0; i < fPts.count(); ++i) {
|
for (i = 0; i < fPts.count(); ++i) {
|
||||||
|
@ -938,12 +1060,6 @@ public:
|
||||||
rh.ID(), rh.fAbove.fX, rh.fAbove.fY, rh.fBelow.fX, rh.fBelow.fY,
|
rh.ID(), rh.fAbove.fX, rh.fAbove.fY, rh.fBelow.fX, rh.fBelow.fY,
|
||||||
UlpsDiff((check.fY - fAbove.fY) * (fBelow.fX - fAbove.fX),
|
UlpsDiff((check.fY - fAbove.fY) * (fBelow.fX - fAbove.fX),
|
||||||
(fBelow.fY - fAbove.fY) * (check.fX - fAbove.fX)));
|
(fBelow.fY - fAbove.fY) * (check.fX - fAbove.fX)));
|
||||||
#endif
|
|
||||||
#if COMPARE_DOUBLE
|
|
||||||
SkASSERT(((check.fY - fAbove.fY) * (fBelow.fX - fAbove.fX)
|
|
||||||
< (fBelow.fY - fAbove.fY) * (check.fX - fAbove.fX))
|
|
||||||
== ((check.fY - fDAbove.y) * (fDBelow.x - fDAbove.x)
|
|
||||||
< (fDBelow.y - fDAbove.y) * (check.fX - fDAbove.x)));
|
|
||||||
#endif
|
#endif
|
||||||
return (check.fY - fAbove.fY) * (fBelow.fX - fAbove.fX)
|
return (check.fY - fAbove.fY) * (fBelow.fX - fAbove.fX)
|
||||||
< (fBelow.fY - fAbove.fY) * (check.fX - fAbove.fX);
|
< (fBelow.fY - fAbove.fY) * (check.fX - fAbove.fX);
|
||||||
|
@ -962,12 +1078,6 @@ public:
|
||||||
UlpsDiff((rh.fBelow.fY - rh.fAbove.fY) * (check.fX - rh.fAbove.fX),
|
UlpsDiff((rh.fBelow.fY - rh.fAbove.fY) * (check.fX - rh.fAbove.fX),
|
||||||
(check.fY - rh.fAbove.fY) * (rh.fBelow.fX - rh.fAbove.fX)),
|
(check.fY - rh.fAbove.fY) * (rh.fBelow.fX - rh.fAbove.fX)),
|
||||||
UlpsDiff(fBelow.fX, rh.fBelow.fX), UlpsDiff(fBelow.fY, rh.fBelow.fY));
|
UlpsDiff(fBelow.fX, rh.fBelow.fX), UlpsDiff(fBelow.fY, rh.fBelow.fY));
|
||||||
#endif
|
|
||||||
#if COMPARE_DOUBLE
|
|
||||||
SkASSERT(((rh.fBelow.fY - rh.fAbove.fY) * (check.fX - rh.fAbove.fX)
|
|
||||||
< (check.fY - rh.fAbove.fY) * (rh.fBelow.fX - rh.fAbove.fX))
|
|
||||||
== ((rh.fDBelow.y - rh.fDAbove.y) * (check.fX - rh.fDAbove.x)
|
|
||||||
< (check.fY - rh.fDAbove.y) * (rh.fDBelow.x - rh.fDAbove.x)));
|
|
||||||
#endif
|
#endif
|
||||||
return (rh.fBelow.fY - rh.fAbove.fY) * (check.fX - rh.fAbove.fX)
|
return (rh.fBelow.fY - rh.fAbove.fY) * (check.fX - rh.fAbove.fX)
|
||||||
< (check.fY - rh.fAbove.fY) * (rh.fBelow.fX - rh.fAbove.fX);
|
< (check.fY - rh.fAbove.fY) * (rh.fBelow.fX - rh.fAbove.fX);
|
||||||
|
@ -1059,46 +1169,49 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void calcLeft() {
|
void calcLeft() {
|
||||||
|
void (*xyAtTFunc)(const SkPoint a[], double t, SkPoint* out);
|
||||||
switch (fWorkEdge.verb()) {
|
switch (fWorkEdge.verb()) {
|
||||||
case SkPath::kLine_Verb: {
|
case SkPath::kLine_Verb:
|
||||||
// OPTIMIZATION: if fXAbove, fXBelow have already been computed
|
xyAtTFunc = LineXYAtT;
|
||||||
// for the fTIndex, don't do it again
|
break;
|
||||||
// For identical x, this lets us know which edge is first.
|
case SkPath::kQuad_Verb:
|
||||||
// If both edges have T values < 1, check x at next T (fXBelow).
|
xyAtTFunc = QuadXYAtT;
|
||||||
int add = (fTIndex <= fTs->count()) - 1;
|
break;
|
||||||
double tAbove = t(fTIndex + add);
|
case SkPath::kCubic_Verb:
|
||||||
// OPTIMIZATION: may not need Y
|
xyAtTFunc = CubicXYAtT;
|
||||||
LineXYAtT(fWorkEdge.fPts, tAbove, &fAbove);
|
|
||||||
double tBelow = t(fTIndex - ~add);
|
|
||||||
LineXYAtT(fWorkEdge.fPts, tBelow, &fBelow);
|
|
||||||
SkASSERT(tAbove != tBelow);
|
|
||||||
while (fAbove.fY == fBelow.fY) {
|
|
||||||
if (add < 0) {
|
|
||||||
add -= 1;
|
|
||||||
SkASSERT(fTIndex + add >= 0);
|
|
||||||
tAbove = t(fTIndex + add);
|
|
||||||
LineXYAtT(fWorkEdge.fPts, tAbove, &fAbove);
|
|
||||||
} else {
|
|
||||||
add += 1;
|
|
||||||
SkASSERT(fTIndex - ~add <= fTs->count() + 1);
|
|
||||||
tBelow = t(fTIndex - ~add);
|
|
||||||
LineXYAtT(fWorkEdge.fPts, tBelow, &fBelow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if COMPARE_DOUBLE
|
|
||||||
LineXYAtT(fWorkEdge.fPts, tAbove, &fDAbove);
|
|
||||||
LineXYAtT(fWorkEdge.fPts, tBelow, &fDBelow);
|
|
||||||
#endif
|
|
||||||
#if DEBUG_ABOVE_BELOW
|
|
||||||
fTAbove = tAbove;
|
|
||||||
fTBelow = tBelow;
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
// FIXME: add support for all curve types
|
|
||||||
SkASSERT(0);
|
SkASSERT(0);
|
||||||
}
|
}
|
||||||
|
// OPTIMIZATION: if fXAbove, fXBelow have already been computed
|
||||||
|
// for the fTIndex, don't do it again
|
||||||
|
// For identical x, this lets us know which edge is first.
|
||||||
|
// If both edges have T values < 1, check x at next T (fXBelow).
|
||||||
|
int add = (fTIndex <= fTs->count()) - 1;
|
||||||
|
double tAbove = t(fTIndex + add);
|
||||||
|
(*xyAtTFunc)(fWorkEdge.fPts, tAbove, &fAbove);
|
||||||
|
double tBelow = t(fTIndex - ~add);
|
||||||
|
(*xyAtTFunc)(fWorkEdge.fPts, tBelow, &fBelow);
|
||||||
|
SkASSERT(tAbove != tBelow);
|
||||||
|
// FIXME: this can loop forever
|
||||||
|
// need a break if we hit the end
|
||||||
|
while (fAbove.fY == fBelow.fY) {
|
||||||
|
if (add < 0 || fTIndex == fTs->count()) {
|
||||||
|
add -= 1;
|
||||||
|
SkASSERT(fTIndex + add >= 0);
|
||||||
|
tAbove = t(fTIndex + add);
|
||||||
|
(*xyAtTFunc)(fWorkEdge.fPts, tAbove, &fAbove);
|
||||||
|
} else {
|
||||||
|
add += 1;
|
||||||
|
SkASSERT(fTIndex - ~add <= fTs->count() + 1);
|
||||||
|
tBelow = t(fTIndex - ~add);
|
||||||
|
(*xyAtTFunc)(fWorkEdge.fPts, tBelow, &fBelow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if DEBUG_ABOVE_BELOW
|
||||||
|
fTAbove = tAbove;
|
||||||
|
fTBelow = tBelow;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool done(SkScalar bottom) const {
|
bool done(SkScalar bottom) const {
|
||||||
|
@ -1107,7 +1220,19 @@ public:
|
||||||
|
|
||||||
void fixBelow() {
|
void fixBelow() {
|
||||||
if (fFixBelow) {
|
if (fFixBelow) {
|
||||||
LineXYAtT(fWorkEdge.fPts, nextT(), &fBelow);
|
switch (fWorkEdge.verb()) {
|
||||||
|
case SkPath::kLine_Verb:
|
||||||
|
LineXYAtT(fWorkEdge.fPts, nextT(), &fBelow);
|
||||||
|
break;
|
||||||
|
case SkPath::kQuad_Verb:
|
||||||
|
QuadXYAtT(fWorkEdge.fPts, nextT(), &fBelow);
|
||||||
|
break;
|
||||||
|
case SkPath::kCubic_Verb:
|
||||||
|
CubicXYAtT(fWorkEdge.fPts, nextT(), &fBelow);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SkASSERT(0);
|
||||||
|
}
|
||||||
fFixBelow = false;
|
fFixBelow = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1136,17 +1261,9 @@ public:
|
||||||
// t values, since the same t values could exist intersecting non-coincident
|
// t values, since the same t values could exist intersecting non-coincident
|
||||||
// edges.
|
// edges.
|
||||||
bool isCoincidentWith(const ActiveEdge* edge, SkScalar y) const {
|
bool isCoincidentWith(const ActiveEdge* edge, SkScalar y) const {
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (!fAbove.equalsWithinTolerance(edge->fAbove, MIN_PT_DELTA)
|
|
||||||
|| !fBelow.equalsWithinTolerance(edge->fBelow, MIN_PT_DELTA)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (fAbove != edge->fAbove || fBelow != edge->fBelow) {
|
if (fAbove != edge->fAbove || fBelow != edge->fBelow) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
uint8_t verb = fDone ? fWorkEdge.lastVerb() : fWorkEdge.verb();
|
uint8_t verb = fDone ? fWorkEdge.lastVerb() : fWorkEdge.verb();
|
||||||
uint8_t edgeVerb = edge->fDone ? edge->fWorkEdge.lastVerb()
|
uint8_t edgeVerb = edge->fDone ? edge->fWorkEdge.lastVerb()
|
||||||
: edge->fWorkEdge.verb();
|
: edge->fWorkEdge.verb();
|
||||||
|
@ -1298,10 +1415,6 @@ public:
|
||||||
const SkTDArray<double>* fTs;
|
const SkTDArray<double>* fTs;
|
||||||
SkPoint fAbove;
|
SkPoint fAbove;
|
||||||
SkPoint fBelow;
|
SkPoint fBelow;
|
||||||
#if COMPARE_DOUBLE
|
|
||||||
_Point fDAbove;
|
|
||||||
_Point fDBelow;
|
|
||||||
#endif
|
|
||||||
#if DEBUG_ABOVE_BELOW
|
#if DEBUG_ABOVE_BELOW
|
||||||
double fTAbove;
|
double fTAbove;
|
||||||
double fTBelow;
|
double fTBelow;
|
||||||
|
@ -1375,6 +1488,34 @@ static void addBottomT(InEdge** currentPtr, InEdge** lastPtr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void debugShowLineIntersection(int pts, const WorkEdge& wt,
|
||||||
|
const WorkEdge& wn, const double wtTs[2], const double wnTs[2]) {
|
||||||
|
#if DEBUG_ADD_INTERSECTING_TS
|
||||||
|
if (!pts) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SkPoint wtOutPt, wnOutPt;
|
||||||
|
LineXYAtT(wt.fPts, wtTs[0], &wtOutPt);
|
||||||
|
LineXYAtT(wn.fPts, wnTs[0], &wnOutPt);
|
||||||
|
SkDebugf("%s wtTs[0]=%g (%g,%g, %g,%g) (%g,%g) (%d,%d)\n",
|
||||||
|
__FUNCTION__,
|
||||||
|
wtTs[0], wt.fPts[0].fX, wt.fPts[0].fY,
|
||||||
|
wt.fPts[1].fX, wt.fPts[1].fY, wtOutPt.fX, wtOutPt.fY,
|
||||||
|
test->fID, next->fID);
|
||||||
|
if (pts == 2) {
|
||||||
|
SkDebugf("%s wtTs[1]=%g\n", __FUNCTION__, wtTs[1]);
|
||||||
|
}
|
||||||
|
SkDebugf("%s wnTs[0]=%g (%g,%g, %g,%g) (%g,%g) (%d,%d)\n",
|
||||||
|
__FUNCTION__,
|
||||||
|
wnTs[0], wn.fPts[0].fX, wn.fPts[0].fY,
|
||||||
|
wn.fPts[1].fX, wn.fPts[1].fY, wnOutPt.fX, wnOutPt.fY,
|
||||||
|
test->fID, next->fID);
|
||||||
|
if (pts == 2) {
|
||||||
|
SkDebugf("%s wnTs[1]=%g\n", __FUNCTION__, wnTs[1]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void addIntersectingTs(InEdge** currentPtr, InEdge** lastPtr) {
|
static void addIntersectingTs(InEdge** currentPtr, InEdge** lastPtr) {
|
||||||
InEdge** testPtr = currentPtr - 1;
|
InEdge** testPtr = currentPtr - 1;
|
||||||
// FIXME: lastPtr should be past the point of interest, so
|
// FIXME: lastPtr should be past the point of interest, so
|
||||||
|
@ -1395,39 +1536,75 @@ static void addIntersectingTs(InEdge** currentPtr, InEdge** lastPtr) {
|
||||||
wt.init(test);
|
wt.init(test);
|
||||||
wn.init(next);
|
wn.init(next);
|
||||||
do {
|
do {
|
||||||
if (wt.verb() == SkPath::kLine_Verb
|
int pts;
|
||||||
&& wn.verb() == SkPath::kLine_Verb) {
|
Intersections ts;
|
||||||
double wtTs[2], wnTs[2];
|
bool swap = false;
|
||||||
int pts = LineIntersect(wt.fPts, wn.fPts, wtTs, wnTs);
|
switch (wt.verb()) {
|
||||||
if (pts) {
|
case SkPath::kLine_Verb:
|
||||||
#if DEBUG_ADD_INTERSECTING_TS
|
switch (wn.verb()) {
|
||||||
SkPoint wtOutPt, wnOutPt;
|
case SkPath::kLine_Verb: {
|
||||||
LineXYAtT(wt.fPts, wtTs[0], &wtOutPt);
|
pts = LineIntersect(wt.fPts, wn.fPts, ts);
|
||||||
LineXYAtT(wn.fPts, wnTs[0], &wnOutPt);
|
debugShowLineIntersection(pts, wt, wn,
|
||||||
SkDebugf("%s wtTs[0]=%g (%g,%g, %g,%g) (%g,%g) (%d,%d)\n",
|
ts.fT[0], ts.fT[1]);
|
||||||
__FUNCTION__,
|
break;
|
||||||
wtTs[0], wt.fPts[0].fX, wt.fPts[0].fY,
|
}
|
||||||
wt.fPts[1].fX, wt.fPts[1].fY, wtOutPt.fX, wtOutPt.fY,
|
case SkPath::kQuad_Verb: {
|
||||||
test->fID, next->fID);
|
swap = true;
|
||||||
if (pts == 2) {
|
pts = QuadLineIntersect(wn.fPts, wt.fPts, ts);
|
||||||
SkDebugf("%s wtTs[1]=%g\n", __FUNCTION__, wtTs[1]);
|
break;
|
||||||
|
}
|
||||||
|
case SkPath::kCubic_Verb: {
|
||||||
|
swap = true;
|
||||||
|
pts = CubicLineIntersect(wn.fPts, wt.fPts, ts);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
SkASSERT(0);
|
||||||
}
|
}
|
||||||
SkDebugf("%s wnTs[0]=%g (%g,%g, %g,%g) (%g,%g) (%d,%d)\n",
|
break;
|
||||||
__FUNCTION__,
|
case SkPath::kQuad_Verb:
|
||||||
wnTs[0], wn.fPts[0].fX, wn.fPts[0].fY,
|
switch (wn.verb()) {
|
||||||
wn.fPts[1].fX, wn.fPts[1].fY, wnOutPt.fX, wnOutPt.fY,
|
case SkPath::kLine_Verb: {
|
||||||
test->fID, next->fID);
|
pts = QuadLineIntersect(wt.fPts, wn.fPts, ts);
|
||||||
if (pts == 2) {
|
break;
|
||||||
SkDebugf("%s wnTs[1]=%g\n", __FUNCTION__, wnTs[1]);
|
}
|
||||||
|
case SkPath::kQuad_Verb: {
|
||||||
|
pts = QuadIntersect(wt.fPts, wn.fPts, ts);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SkPath::kCubic_Verb: {
|
||||||
|
// FIXME: promote quad to cubic
|
||||||
|
pts = CubicIntersect(wt.fPts, wn.fPts, ts);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
SkASSERT(0);
|
||||||
}
|
}
|
||||||
#endif
|
break;
|
||||||
test->add(wtTs, pts, wt.verbIndex());
|
case SkPath::kCubic_Verb:
|
||||||
next->add(wnTs, pts, wn.verbIndex());
|
switch (wn.verb()) {
|
||||||
}
|
case SkPath::kLine_Verb: {
|
||||||
} else {
|
pts = CubicLineIntersect(wt.fPts, wn.fPts, ts);
|
||||||
// FIXME: add all combinations of curve types
|
break;
|
||||||
SkASSERT(0);
|
}
|
||||||
|
case SkPath::kQuad_Verb: {
|
||||||
|
// FIXME: promote quad to cubic
|
||||||
|
pts = CubicIntersect(wt.fPts, wn.fPts, ts);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SkPath::kCubic_Verb: {
|
||||||
|
pts = CubicIntersect(wt.fPts, wn.fPts, ts);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
SkASSERT(0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SkASSERT(0);
|
||||||
}
|
}
|
||||||
|
test->add(ts.fT[swap], pts, wt.verbIndex());
|
||||||
|
next->add(ts.fT[!swap], pts, wn.verbIndex());
|
||||||
} while (wt.bottom() <= wn.bottom() ? wt.advance() : wn.advance());
|
} while (wt.bottom() <= wn.bottom() ? wt.advance() : wn.advance());
|
||||||
} while (nextPtr != lastPtr);
|
} while (nextPtr != lastPtr);
|
||||||
}
|
}
|
||||||
|
@ -1495,14 +1672,25 @@ static SkScalar computeInterceptBottom(SkTDArray<ActiveEdge>& activeEdges,
|
||||||
const SkTDArray<double>& fTs = intercepts.fTs;
|
const SkTDArray<double>& fTs = intercepts.fTs;
|
||||||
size_t count = fTs.count();
|
size_t count = fTs.count();
|
||||||
for (size_t index = 0; index < count; ++index) {
|
for (size_t index = 0; index < count; ++index) {
|
||||||
if (wt.verb() == SkPath::kLine_Verb) {
|
SkScalar yIntercept;
|
||||||
SkScalar yIntercept = LineYAtT(wt.fPts, fTs[index]);
|
switch (wt.verb()) {
|
||||||
if (yIntercept > y && bottom > yIntercept) {
|
case SkPath::kLine_Verb: {
|
||||||
bottom = yIntercept;
|
yIntercept = LineYAtT(wt.fPts, fTs[index]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
case SkPath::kQuad_Verb: {
|
||||||
// FIXME: add all curve types
|
yIntercept = QuadYAtT(wt.fPts, fTs[index]);
|
||||||
SkASSERT(0);
|
break;
|
||||||
|
}
|
||||||
|
case SkPath::kCubic_Verb: {
|
||||||
|
yIntercept = CubicYAtT(wt.fPts, fTs[index]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
SkASSERT(0); // should never get here
|
||||||
|
}
|
||||||
|
if (yIntercept > y && bottom > yIntercept) {
|
||||||
|
bottom = yIntercept;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (wt.advance());
|
} while (wt.advance());
|
||||||
|
@ -1805,13 +1993,8 @@ static void stitchEdge(SkTDArray<ActiveEdge*>& edgeList, SkScalar y,
|
||||||
bool closer = (winding & windingMask) == 0;
|
bool closer = (winding & windingMask) == 0;
|
||||||
SkASSERT(!opener | !closer);
|
SkASSERT(!opener | !closer);
|
||||||
bool inWinding = opener | closer;
|
bool inWinding = opener | closer;
|
||||||
SkPoint clippedPts[2];
|
SkPoint clippedPts[4];
|
||||||
const SkPoint* clipped = NULL;
|
const SkPoint* clipped = NULL;
|
||||||
#if COMPARE_DOUBLE
|
|
||||||
_Line dPoints;
|
|
||||||
_Line clippedDPts;
|
|
||||||
const _Point* dClipped = NULL;
|
|
||||||
#endif
|
|
||||||
uint8_t verb = wt.verb();
|
uint8_t verb = wt.verb();
|
||||||
bool moreToDo, aboveBottom;
|
bool moreToDo, aboveBottom;
|
||||||
do {
|
do {
|
||||||
|
@ -1821,80 +2004,69 @@ static void stitchEdge(SkTDArray<ActiveEdge*>& edgeList, SkScalar y,
|
||||||
double nextT;
|
double nextT;
|
||||||
do {
|
do {
|
||||||
nextT = activePtr->nextT();
|
nextT = activePtr->nextT();
|
||||||
if (verb == SkPath::kLine_Verb) {
|
// FIXME: obtuse: want efficient way to say
|
||||||
// FIXME: obtuse: want efficient way to say
|
// !currentT && currentT != 1 || !nextT && nextT != 1
|
||||||
// !currentT && currentT != 1 || !nextT && nextT != 1
|
if (currentT * nextT != 0 || currentT + nextT != 1) {
|
||||||
if (currentT * nextT != 0 || currentT + nextT != 1) {
|
// OPTIMIZATION: if !inWinding, we only need
|
||||||
// OPTIMIZATION: if !inWinding, we only need
|
// clipped[1].fY
|
||||||
// clipped[1].fY
|
switch (verb) {
|
||||||
LineSubDivide(points, currentT, nextT, clippedPts);
|
case SkPath::kLine_Verb:
|
||||||
clipped = clippedPts;
|
LineSubDivide(points, currentT, nextT, clippedPts);
|
||||||
#if COMPARE_DOUBLE
|
break;
|
||||||
LineSubDivide(points, currentT, nextT, clippedDPts);
|
case SkPath::kQuad_Verb:
|
||||||
dClipped = clippedDPts;
|
QuadSubDivide(points, currentT, nextT, clippedPts);
|
||||||
#endif
|
break;
|
||||||
} else {
|
case SkPath::kCubic_Verb:
|
||||||
clipped = points;
|
CubicSubDivide(points, currentT, nextT, clippedPts);
|
||||||
#if COMPARE_DOUBLE
|
break;
|
||||||
dPoints[0].x = SkScalarToDouble(points[0].fX);
|
default:
|
||||||
dPoints[0].y = SkScalarToDouble(points[1].fY);
|
SkASSERT(0);
|
||||||
dPoints[1].x = SkScalarToDouble(points[0].fX);
|
break;
|
||||||
dPoints[1].y = SkScalarToDouble(points[1].fY);
|
|
||||||
dClipped = dPoints;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (inWinding && !activePtr->fSkip && (fill ? clipped[0].fY
|
|
||||||
!= clipped[1].fY : clipped[0] != clipped[1])) {
|
|
||||||
if (gShowDebugf) {
|
|
||||||
SkDebugf("%*s line %1.9g,%1.9g %1.9g,%1.9g edge=%d"
|
|
||||||
" v=%d t=(%1.9g,%1.9g)\n", tab, "",
|
|
||||||
clipped[0].fX, clipped[0].fY,
|
|
||||||
clipped[1].fX, clipped[1].fY,
|
|
||||||
activePtr->ID(),
|
|
||||||
activePtr->fWorkEdge.fVerb
|
|
||||||
- activePtr->fWorkEdge.fEdge->fVerbs.begin(),
|
|
||||||
currentT, nextT);
|
|
||||||
}
|
|
||||||
outBuilder.addLine(clipped,
|
|
||||||
activePtr->fWorkEdge.fEdge->fID,
|
|
||||||
activePtr->fCloseCall);
|
|
||||||
} else {
|
|
||||||
if (gShowDebugf) {
|
|
||||||
SkDebugf("%*s skip %1.9g,%1.9g %1.9g,%1.9g"
|
|
||||||
" edge=%d v=%d t=(%1.9g,%1.9g)\n", tab, "",
|
|
||||||
clipped[0].fX, clipped[0].fY,
|
|
||||||
clipped[1].fX, clipped[1].fY,
|
|
||||||
activePtr->ID(),
|
|
||||||
activePtr->fWorkEdge.fVerb
|
|
||||||
- activePtr->fWorkEdge.fEdge->fVerbs.begin(),
|
|
||||||
currentT, nextT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// by advancing fAbove/fBelow, the next call to sortHorizontal
|
|
||||||
// will use these values if they're still valid instead of
|
|
||||||
// recomputing
|
|
||||||
#if COMPARE_DOUBLE
|
|
||||||
SkASSERT((clipped[1].fY > activePtr->fBelow.fY
|
|
||||||
&& bottom >= activePtr->fBelow.fY)
|
|
||||||
== (dClipped[1].y > activePtr->fDBelow.y
|
|
||||||
&& bottom >= activePtr->fDBelow.y));
|
|
||||||
#endif
|
|
||||||
if (clipped[1].fY > activePtr->fBelow.fY
|
|
||||||
&& bottom >= activePtr->fBelow.fY ) {
|
|
||||||
activePtr->fAbove = activePtr->fBelow;
|
|
||||||
activePtr->fBelow = clipped[1];
|
|
||||||
#if COMPARE_DOUBLE
|
|
||||||
activePtr->fDAbove = activePtr->fDBelow;
|
|
||||||
activePtr->fDBelow = dClipped[1];
|
|
||||||
#endif
|
|
||||||
#if DEBUG_ABOVE_BELOW
|
|
||||||
activePtr->fTAbove = activePtr->fTBelow;
|
|
||||||
activePtr->fTBelow = nextT;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
clipped = clippedPts;
|
||||||
} else {
|
} else {
|
||||||
// FIXME: add all curve types
|
clipped = points;
|
||||||
SkASSERT(0);
|
}
|
||||||
|
if (inWinding && !activePtr->fSkip && (fill ? clipped[0].fY
|
||||||
|
!= clipped[verb].fY : clipped[0] != clipped[verb])) {
|
||||||
|
if (gShowDebugf) {
|
||||||
|
const char* verbStr[] = {"", "Line", "Quad", "Cubic"};
|
||||||
|
SkDebugf("%*s add%s %1.9g,%1.9g %1.9g,%1.9g edge=%d"
|
||||||
|
" v=%d t=(%1.9g,%1.9g)\n", tab, "",
|
||||||
|
verbStr[verb], clipped[0].fX, clipped[0].fY,
|
||||||
|
clipped[verb].fX, clipped[verb].fY,
|
||||||
|
activePtr->ID(),
|
||||||
|
activePtr->fWorkEdge.fVerb
|
||||||
|
- activePtr->fWorkEdge.fEdge->fVerbs.begin(),
|
||||||
|
currentT, nextT);
|
||||||
|
}
|
||||||
|
outBuilder.addCurve(clipped, (SkPath::Verb) verb,
|
||||||
|
activePtr->fWorkEdge.fEdge->fID,
|
||||||
|
activePtr->fCloseCall);
|
||||||
|
} else {
|
||||||
|
if (gShowDebugf ) {
|
||||||
|
const char* verbStr[] = {"", "Line", "Quad", "Cubic"};
|
||||||
|
SkDebugf("%*s skip%s %1.9g,%1.9g %1.9g,%1.9g"
|
||||||
|
" edge=%d v=%d t=(%1.9g,%1.9g)\n", tab, "",
|
||||||
|
verbStr[verb], clipped[0].fX, clipped[0].fY,
|
||||||
|
clipped[verb].fX, clipped[verb].fY,
|
||||||
|
activePtr->ID(),
|
||||||
|
activePtr->fWorkEdge.fVerb
|
||||||
|
- activePtr->fWorkEdge.fEdge->fVerbs.begin(),
|
||||||
|
currentT, nextT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// by advancing fAbove/fBelow, the next call to sortHorizontal
|
||||||
|
// will use these values if they're still valid instead of
|
||||||
|
// recomputing
|
||||||
|
if (clipped[1].fY > activePtr->fBelow.fY
|
||||||
|
&& bottom >= activePtr->fBelow.fY ) {
|
||||||
|
activePtr->fAbove = activePtr->fBelow;
|
||||||
|
activePtr->fBelow = clipped[1];
|
||||||
|
#if DEBUG_ABOVE_BELOW
|
||||||
|
activePtr->fTAbove = activePtr->fTBelow;
|
||||||
|
activePtr->fTBelow = nextT;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
currentT = nextT;
|
currentT = nextT;
|
||||||
moreToDo = activePtr->advanceT();
|
moreToDo = activePtr->advanceT();
|
||||||
|
|
|
@ -703,12 +703,6 @@ path.lineTo(497.278107, -113.884933);
|
||||||
path.lineTo(449.18222, -45.6723022);
|
path.lineTo(449.18222, -45.6723022);
|
||||||
path.lineTo(340.41568, -170.97171);
|
path.lineTo(340.41568, -170.97171);
|
||||||
path.close();
|
path.close();
|
||||||
path.moveTo(301.372925, -213.590073);
|
|
||||||
path.lineTo(348.294434, -271.975586);
|
|
||||||
path.lineTo(395.215973, -330.361145);
|
|
||||||
path.lineTo(400.890381, -263.276855);
|
|
||||||
path.lineTo(301.372925, -213.590073);
|
|
||||||
path.close();
|
|
||||||
path.moveTo(326.610535, 34.0393639);
|
path.moveTo(326.610535, 34.0393639);
|
||||||
path.lineTo(371.334595, -14.9620667);
|
path.lineTo(371.334595, -14.9620667);
|
||||||
path.lineTo(416.058624, -63.9634857);
|
path.lineTo(416.058624, -63.9634857);
|
||||||
|
@ -765,7 +759,7 @@ static void (*simplifyTests[])() = {
|
||||||
|
|
||||||
static size_t simplifyTestsCount = sizeof(simplifyTests) / sizeof(simplifyTests[0]);
|
static size_t simplifyTestsCount = sizeof(simplifyTests) / sizeof(simplifyTests[0]);
|
||||||
|
|
||||||
static void (*firstTest)() = 0;
|
static void (*firstTest)() = testSimplifySkinnyTriangle12;
|
||||||
|
|
||||||
void SimplifyPolygonPaths_Test() {
|
void SimplifyPolygonPaths_Test() {
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
#include "EdgeWalker_Test.h"
|
||||||
|
#include "Intersection_Tests.h"
|
||||||
|
|
||||||
|
static void testSimplifyQuadratic1() {
|
||||||
|
SkPath path, out;
|
||||||
|
path.moveTo(0, 0);
|
||||||
|
path.quadTo(1, 0, 1, 1);
|
||||||
|
path.close();
|
||||||
|
path.moveTo(1, 0);
|
||||||
|
path.quadTo(0, 0, 0, 1);
|
||||||
|
path.close();
|
||||||
|
testSimplify(path, true, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void testSimplifyQuadratic2() {
|
||||||
|
SkPath path, out;
|
||||||
|
path.moveTo(0, 0);
|
||||||
|
path.quadTo(20, 0, 20, 20);
|
||||||
|
path.close();
|
||||||
|
path.moveTo(20, 0);
|
||||||
|
path.quadTo(0, 0, 0, 20);
|
||||||
|
path.close();
|
||||||
|
testSimplify(path, true, out);
|
||||||
|
drawAsciiPaths(path, out, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void testSimplifyQuadratic3() {
|
||||||
|
SkPath path, out;
|
||||||
|
path.moveTo(0, 0);
|
||||||
|
path.quadTo(20, 0, 20, 20);
|
||||||
|
path.close();
|
||||||
|
path.moveTo(0, 20);
|
||||||
|
path.quadTo(0, 0, 20, 0);
|
||||||
|
path.close();
|
||||||
|
testSimplify(path, true, out);
|
||||||
|
drawAsciiPaths(path, out, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void (*simplifyTests[])() = {
|
||||||
|
testSimplifyQuadratic3,
|
||||||
|
testSimplifyQuadratic2,
|
||||||
|
testSimplifyQuadratic1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static size_t simplifyTestsCount = sizeof(simplifyTests) / sizeof(simplifyTests[0]);
|
||||||
|
|
||||||
|
static void (*firstTest)() = 0;
|
||||||
|
|
||||||
|
void SimplifyQuadraticPaths_Test() {
|
||||||
|
size_t index = 0;
|
||||||
|
if (firstTest) {
|
||||||
|
while (index < simplifyTestsCount && simplifyTests[index] != firstTest) {
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool firstTestComplete = false;
|
||||||
|
for ( ; index < simplifyTestsCount; ++index) {
|
||||||
|
(*simplifyTests[index])();
|
||||||
|
if (simplifyTests[index] == testSimplifyQuadratic1) {
|
||||||
|
SkDebugf("%s last fast quad test\n", __FUNCTION__);
|
||||||
|
}
|
||||||
|
firstTestComplete = true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,10 +19,12 @@ void Intersection_Tests() {
|
||||||
LineQuadraticIntersection_Test();
|
LineQuadraticIntersection_Test();
|
||||||
LineCubicIntersection_Test();
|
LineCubicIntersection_Test();
|
||||||
|
|
||||||
|
SimplifyQuadraticPaths_Test();
|
||||||
|
|
||||||
SimplifyPolygonPaths_Test();
|
SimplifyPolygonPaths_Test();
|
||||||
SimplifyRectangularPaths_Test();
|
SimplifyRectangularPaths_Test();
|
||||||
SimplifyQuadralateralPaths_Test();
|
SimplifyQuadralateralPaths_Test();
|
||||||
|
|
||||||
SimplifyDegenerate4x4TrianglesThreaded_Test();
|
SimplifyDegenerate4x4TrianglesThreaded_Test();
|
||||||
SimplifyNondegenerate4x4TrianglesThreaded_Test();
|
SimplifyNondegenerate4x4TrianglesThreaded_Test();
|
||||||
Simplify4x4QuadralateralsThreaded_Test();
|
Simplify4x4QuadralateralsThreaded_Test();
|
||||||
|
|
|
@ -16,6 +16,7 @@ void SimplifyDegenerate4x4TrianglesThreaded_Test();
|
||||||
void SimplifyNondegenerate4x4TrianglesThreaded_Test();
|
void SimplifyNondegenerate4x4TrianglesThreaded_Test();
|
||||||
void SimplifyPolygonPaths_Test();
|
void SimplifyPolygonPaths_Test();
|
||||||
void SimplifyQuadralateralPaths_Test();
|
void SimplifyQuadralateralPaths_Test();
|
||||||
|
void SimplifyQuadraticPaths_Test();
|
||||||
void Simplify4x4QuadralateralsThreaded_Test();
|
void Simplify4x4QuadralateralsThreaded_Test();
|
||||||
void SimplifyRectangularPaths_Test();
|
void SimplifyRectangularPaths_Test();
|
||||||
void QuadraticBezierClip_Test();
|
void QuadraticBezierClip_Test();
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef Intersections_DEFINE
|
||||||
|
#define Intersections_DEFINE
|
||||||
|
|
||||||
class Intersections {
|
class Intersections {
|
||||||
public:
|
public:
|
||||||
Intersections()
|
Intersections()
|
||||||
|
@ -43,7 +46,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
double fT[2][9];
|
double fT[2][9];
|
||||||
private:
|
|
||||||
int fUsed;
|
int fUsed;
|
||||||
|
private:
|
||||||
int fSwap;
|
int fSwap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -56,14 +56,17 @@ path.lineTo( 9.030045, -163.413132);
|
||||||
path.close();
|
path.close();
|
||||||
</div>
|
</div>
|
||||||
<div id="test_4div">
|
<div id="test_4div">
|
||||||
path.moveTo( -5503.40843,1749.49658);
|
path.moveTo(340.41568, -170.97171);
|
||||||
path.lineTo(-5503.40843,1749.49718);
|
path.lineTo(418.846893, -142.428329);
|
||||||
|
path.lineTo(497.278107, -113.884933);
|
||||||
|
path.lineTo(449.18222, -45.6723022);
|
||||||
|
path.lineTo(340.41568, -170.97171);
|
||||||
path.close();
|
path.close();
|
||||||
path.moveTo( -5503.40843,1749.49658);
|
path.moveTo(326.610535, 34.0393639);
|
||||||
path.lineTo(-5503.40729,1749.50314);
|
path.lineTo(371.334595, -14.9620667);
|
||||||
path.close();
|
path.lineTo(416.058624, -63.9634857);
|
||||||
path.moveTo( -5503.40729,1749.50314);
|
path.lineTo(460.782654, -112.96492);
|
||||||
path.lineTo(-5503.40729,1749.50361);
|
path.lineTo(326.610535, 34.0393639);
|
||||||
path.close();
|
path.close();
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -12,13 +12,43 @@
|
||||||
'../experimental/SimpleCocoaApp', # needed to get SimpleApp.h
|
'../experimental/SimpleCocoaApp', # needed to get SimpleApp.h
|
||||||
],
|
],
|
||||||
'sources': [
|
'sources': [
|
||||||
|
'../experimental/Intersection/ConvexHull.cpp',
|
||||||
|
'../experimental/Intersection/CubeRoot.cpp',
|
||||||
|
'../experimental/Intersection/CubicBezierClip.cpp',
|
||||||
|
'../experimental/Intersection/CubicIntersection.cpp',
|
||||||
|
'../experimental/Intersection/CubicReduceOrder.cpp',
|
||||||
|
'../experimental/Intersection/CubicSubDivide.cpp',
|
||||||
|
'../experimental/Intersection/CubicUtilities.cpp',
|
||||||
'../experimental/Intersection/DataTypes.cpp',
|
'../experimental/Intersection/DataTypes.cpp',
|
||||||
|
'../experimental/Intersection/EdgeDemo.cpp',
|
||||||
|
'../experimental/Intersection/EdgeDemoApp.mm',
|
||||||
'../experimental/Intersection/EdgeWalker.cpp',
|
'../experimental/Intersection/EdgeWalker.cpp',
|
||||||
'../experimental/Intersection/EdgeWalker_TestUtility.cpp',
|
'../experimental/Intersection/EdgeWalker_TestUtility.cpp',
|
||||||
|
'../experimental/Intersection/Extrema.cpp',
|
||||||
|
'../experimental/Intersection/LineCubicIntersection.cpp
|
||||||
'../experimental/Intersection/LineIntersection.cpp',
|
'../experimental/Intersection/LineIntersection.cpp',
|
||||||
'../experimental/Intersection/LineParameterization.cpp',
|
'../experimental/Intersection/LineParameterization.cpp',
|
||||||
|
'../experimental/Intersection/LineQuadraticIntersection.cpp',
|
||||||
'../experimental/Intersection/LineUtilities.cpp',
|
'../experimental/Intersection/LineUtilities.cpp',
|
||||||
'../experimental/Intersection/EdgeDemoApp.mm',
|
'../experimental/Intersection/QuadraticBezierClip.cpp',
|
||||||
|
'../experimental/Intersection/QuadraticIntersection.cpp',
|
||||||
|
'../experimental/Intersection/QuadraticReduceOrder.cpp',
|
||||||
|
'../experimental/Intersection/QuadraticSubDivide.cpp',
|
||||||
|
'../experimental/Intersection/QuadraticUtilities.cpp',
|
||||||
|
'../experimental/Intersection/CubicIntersection.h',
|
||||||
|
'../experimental/Intersection/CubicUtilities.h',
|
||||||
|
'../experimental/Intersection/CurveIntersection.h',
|
||||||
|
'../experimental/Intersection/DataTypes.h',
|
||||||
|
'../experimental/Intersection/EdgeDemo.h',
|
||||||
|
'../experimental/Intersection/Extrema.h',
|
||||||
|
'../experimental/Intersection/Intersections.h',
|
||||||
|
'../experimental/Intersection/IntersectionUtilities.h',
|
||||||
|
'../experimental/Intersection/LineIntersection.h',
|
||||||
|
'../experimental/Intersection/LineParameters.h',
|
||||||
|
'../experimental/Intersection/LineUtilities.h',
|
||||||
|
'../experimental/Intersection/QuadraticUtilities.h',
|
||||||
|
'../experimental/Intersection/ShapeOps.h',
|
||||||
|
'../experimental/Intersection/TSearch.h',
|
||||||
],
|
],
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
'core.gyp:core',
|
'core.gyp:core',
|
||||||
|
@ -44,16 +74,16 @@
|
||||||
'sources': [
|
'sources': [
|
||||||
|
|
||||||
# Mac files
|
# Mac files
|
||||||
'../src/utils/mac/SkEventNotifier.h',
|
'../src/views/mac/SkEventNotifier.h',
|
||||||
'../src/utils/mac/SkEventNotifier.mm',
|
'../src/views/mac/SkEventNotifier.mm',
|
||||||
'../src/utils/mac/skia_mac.mm',
|
'../src/views/mac/skia_mac.mm',
|
||||||
'../src/utils/mac/SkNSView.h',
|
'../src/views/mac/SkNSView.h',
|
||||||
'../src/utils/mac/SkNSView.mm',
|
'../src/views/mac/SkNSView.mm',
|
||||||
'../src/utils/mac/SkOptionsTableView.h',
|
'../src/views/mac/SkOptionsTableView.h',
|
||||||
'../src/utils/mac/SkOptionsTableView.mm',
|
'../src/views/mac/SkOptionsTableView.mm',
|
||||||
'../src/utils/mac/SkOSWindow_Mac.mm',
|
'../src/views/mac/SkOSWindow_Mac.mm',
|
||||||
'../src/utils/mac/SkTextFieldCell.h',
|
'../src/views/mac/SkTextFieldCell.h',
|
||||||
'../src/utils/mac/SkTextFieldCell.m',
|
'../src/views/mac/SkTextFieldCell.m',
|
||||||
],
|
],
|
||||||
'libraries': [
|
'libraries': [
|
||||||
'$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework',
|
'$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework',
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
'../experimental/Intersection/EdgeWalkerPolygons_Mismatches.cpp',
|
'../experimental/Intersection/EdgeWalkerPolygons_Mismatches.cpp',
|
||||||
'../experimental/Intersection/EdgeWalkerPolygons_Test.cpp',
|
'../experimental/Intersection/EdgeWalkerPolygons_Test.cpp',
|
||||||
'../experimental/Intersection/EdgeWalkerQuadralaterals_Test.cpp',
|
'../experimental/Intersection/EdgeWalkerQuadralaterals_Test.cpp',
|
||||||
|
'../experimental/Intersection/EdgeWalkerQuadratics_Test.cpp',
|
||||||
'../experimental/Intersection/EdgeWalkerRectangles_Test.cpp',
|
'../experimental/Intersection/EdgeWalkerRectangles_Test.cpp',
|
||||||
'../experimental/Intersection/Extrema.cpp',
|
'../experimental/Intersection/Extrema.cpp',
|
||||||
'../experimental/Intersection/Inline_Tests.cpp',
|
'../experimental/Intersection/Inline_Tests.cpp',
|
||||||
|
@ -65,6 +66,27 @@
|
||||||
'../experimental/Intersection/QuadraticUtilities.cpp',
|
'../experimental/Intersection/QuadraticUtilities.cpp',
|
||||||
'../experimental/Intersection/RectUtilities.cpp',
|
'../experimental/Intersection/RectUtilities.cpp',
|
||||||
'../experimental/Intersection/TestUtilities.cpp',
|
'../experimental/Intersection/TestUtilities.cpp',
|
||||||
|
'../experimental/Intersection/CubicIntersection.h',
|
||||||
|
'../experimental/Intersection/CubicIntersection_TestData.h',
|
||||||
|
'../experimental/Intersection/CubicUtilities.h',
|
||||||
|
'../experimental/Intersection/CurveIntersection.h',
|
||||||
|
'../experimental/Intersection/DataTypes.h',
|
||||||
|
'../experimental/Intersection/EdgeMain.h',
|
||||||
|
'../experimental/Intersection/EdgeWalker_Test.h',
|
||||||
|
'../experimental/Intersection/EdgeWalkerPolygons_Mismatches.h',
|
||||||
|
'../experimental/Intersection/Extrema.h',
|
||||||
|
'../experimental/Intersection/Intersection_Tests.h',
|
||||||
|
'../experimental/Intersection/Intersections.h',
|
||||||
|
'../experimental/Intersection/IntersectionUtilities.h',
|
||||||
|
'../experimental/Intersection/LineIntersection.h',
|
||||||
|
'../experimental/Intersection/LineParameters.h',
|
||||||
|
'../experimental/Intersection/LineUtilities.h',
|
||||||
|
'../experimental/Intersection/Parameterization_Test.h',
|
||||||
|
'../experimental/Intersection/QuadraticIntersection_TestData.h',
|
||||||
|
'../experimental/Intersection/QuadraticUtilities.h',
|
||||||
|
'../experimental/Intersection/ShapeOps.h',
|
||||||
|
'../experimental/Intersection/TestUtilities.h',
|
||||||
|
'../experimental/Intersection/TSearch.h',
|
||||||
],
|
],
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
'core.gyp:core',
|
'core.gyp:core',
|
||||||
|
|
Загрузка…
Ссылка в новой задаче