#include "src/gpu/ganesh/geometry/GrAAConvexTessellator.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPath.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/private/base/SkAssert.h"
#include "include/private/base/SkFloatingPoint.h"
#include "include/private/base/SkTPin.h"
#include "src/core/SkPathPriv.h"
#include "src/gpu/ganesh/geometry/GrPathUtils.h"
#include <algorithm>
static constexpr SkScalar kClose = …;
static constexpr SkScalar kCloseSqd = …;
static constexpr SkScalar kQuadTolerance = …;
static constexpr SkScalar kCubicTolerance = …;
static constexpr SkScalar kQuadToleranceSqd = …;
static constexpr SkScalar kCubicToleranceSqd = …;
static constexpr SkScalar kConicTolerance = …;
static constexpr SkScalar kRoundCapThreshold = …;
static constexpr SkScalar kCurveConnectionThreshold = …;
static bool intersect(const SkPoint& p0, const SkPoint& n0,
const SkPoint& p1, const SkPoint& n1,
SkScalar* t) { … }
static bool perp_intersect(const SkPoint& p0, const SkPoint& n0,
const SkPoint& p1, const SkPoint& perp,
SkScalar* t) { … }
static bool duplicate_pt(const SkPoint& p0, const SkPoint& p1) { … }
static bool points_are_colinear_and_b_is_middle(const SkPoint& a, const SkPoint& b,
const SkPoint& c, float* accumError) { … }
int GrAAConvexTessellator::addPt(const SkPoint& pt,
SkScalar depth,
SkScalar coverage,
bool movable,
CurveState curve) { … }
void GrAAConvexTessellator::popLastPt() { … }
void GrAAConvexTessellator::popFirstPtShuffle() { … }
void GrAAConvexTessellator::updatePt(int index,
const SkPoint& pt,
SkScalar depth,
SkScalar coverage) { … }
void GrAAConvexTessellator::addTri(int i0, int i1, int i2) { … }
void GrAAConvexTessellator::rewind() { … }
void GrAAConvexTessellator::computeNormals() { … }
void GrAAConvexTessellator::computeBisectors() { … }
bool GrAAConvexTessellator::createInsetRings(Ring& previousRing, SkScalar initialDepth,
SkScalar initialCoverage, SkScalar targetDepth,
SkScalar targetCoverage, Ring** finalRing) { … }
bool GrAAConvexTessellator::tessellate(const SkMatrix& m, const SkPath& path) { … }
SkScalar GrAAConvexTessellator::computeDepthFromEdge(int edgeIdx, const SkPoint& p) const { … }
bool GrAAConvexTessellator::computePtAlongBisector(int startIdx,
const SkVector& bisector,
int edgeIdx,
SkScalar desiredDepth,
SkPoint* result) const { … }
bool GrAAConvexTessellator::extractFromPath(const SkMatrix& m, const SkPath& path) { … }
GrAAConvexTessellator::Ring* GrAAConvexTessellator::getNextRing(Ring* lastRing) { … }
void GrAAConvexTessellator::fanRing(const Ring& ring) { … }
void GrAAConvexTessellator::createOuterRing(const Ring& previousRing, SkScalar outset,
SkScalar coverage, Ring* nextRing) { … }
void GrAAConvexTessellator::terminate(const Ring& ring) { … }
static SkScalar compute_coverage(SkScalar depth, SkScalar initialDepth, SkScalar initialCoverage,
SkScalar targetDepth, SkScalar targetCoverage) { … }
bool GrAAConvexTessellator::createInsetRing(const Ring& lastRing, Ring* nextRing,
SkScalar initialDepth, SkScalar initialCoverage,
SkScalar targetDepth, SkScalar targetCoverage,
bool forceNew) { … }
void GrAAConvexTessellator::validate() const { … }
void GrAAConvexTessellator::Ring::init(const GrAAConvexTessellator& tess) { … }
void GrAAConvexTessellator::Ring::init(const SkTDArray<SkVector>& norms,
const SkTDArray<SkVector>& bisectors) { … }
void GrAAConvexTessellator::Ring::computeNormals(const GrAAConvexTessellator& tess) { … }
void GrAAConvexTessellator::Ring::computeBisectors(const GrAAConvexTessellator& tess) { … }
#ifdef SK_DEBUG
bool GrAAConvexTessellator::Ring::isConvex(const GrAAConvexTessellator& tess) const { … }
#endif
void GrAAConvexTessellator::lineTo(const SkPoint& p, CurveState curve) { … }
void GrAAConvexTessellator::lineTo(const SkMatrix& m, const SkPoint& p, CurveState curve) { … }
void GrAAConvexTessellator::quadTo(const SkPoint pts[3]) { … }
void GrAAConvexTessellator::quadTo(const SkMatrix& m, const SkPoint srcPts[3]) { … }
void GrAAConvexTessellator::cubicTo(const SkMatrix& m, const SkPoint srcPts[4]) { … }
#include "src/core/SkGeometry.h"
void GrAAConvexTessellator::conicTo(const SkMatrix& m, const SkPoint srcPts[3], SkScalar w) { … }
#if GR_AA_CONVEX_TESSELLATOR_VIZ
static const SkScalar kPointRadius = 0.02f;
static const SkScalar kArrowStrokeWidth = 0.0f;
static const SkScalar kArrowLength = 0.2f;
static const SkScalar kEdgeTextSize = 0.1f;
static const SkScalar kPointTextSize = 0.02f;
static void draw_point(SkCanvas* canvas, const SkPoint& p, SkScalar paramValue, bool stroke) {
SkPaint paint;
SkASSERT(paramValue <= 1.0f);
int gs = int(255*paramValue);
paint.setARGB(255, gs, gs, gs);
canvas->drawCircle(p.fX, p.fY, kPointRadius, paint);
if (stroke) {
SkPaint stroke;
stroke.setColor(SK_ColorYELLOW);
stroke.setStyle(SkPaint::kStroke_Style);
stroke.setStrokeWidth(kPointRadius/3.0f);
canvas->drawCircle(p.fX, p.fY, kPointRadius, stroke);
}
}
static void draw_line(SkCanvas* canvas, const SkPoint& p0, const SkPoint& p1, SkColor color) {
SkPaint p;
p.setColor(color);
canvas->drawLine(p0.fX, p0.fY, p1.fX, p1.fY, p);
}
static void draw_arrow(SkCanvas*canvas, const SkPoint& p, const SkPoint &n,
SkScalar len, SkColor color) {
SkPaint paint;
paint.setColor(color);
paint.setStrokeWidth(kArrowStrokeWidth);
paint.setStyle(SkPaint::kStroke_Style);
canvas->drawLine(p.fX, p.fY,
p.fX + len * n.fX, p.fY + len * n.fY,
paint);
}
void GrAAConvexTessellator::Ring::draw(SkCanvas* canvas, const GrAAConvexTessellator& tess) const {
SkPaint paint;
paint.setTextSize(kEdgeTextSize);
for (int cur = 0; cur < fPts.count(); ++cur) {
int next = (cur + 1) % fPts.count();
draw_line(canvas,
tess.point(fPts[cur].fIndex),
tess.point(fPts[next].fIndex),
SK_ColorGREEN);
SkPoint mid = tess.point(fPts[cur].fIndex) + tess.point(fPts[next].fIndex);
mid.scale(0.5f);
if (fPts.count()) {
draw_arrow(canvas, mid, fPts[cur].fNorm, kArrowLength, SK_ColorRED);
mid.fX += (kArrowLength/2) * fPts[cur].fNorm.fX;
mid.fY += (kArrowLength/2) * fPts[cur].fNorm.fY;
}
SkString num;
num.printf("%d", this->origEdgeID(cur));
canvas->drawString(num, mid.fX, mid.fY, paint);
if (fPts.count()) {
draw_arrow(canvas, tess.point(fPts[cur].fIndex), fPts[cur].fBisector,
kArrowLength, SK_ColorBLUE);
}
}
}
void GrAAConvexTessellator::draw(SkCanvas* canvas) const {
for (int i = 0; i < fIndices.count(); i += 3) {
SkASSERT(fIndices[i] < this->numPts()) ;
SkASSERT(fIndices[i+1] < this->numPts()) ;
SkASSERT(fIndices[i+2] < this->numPts()) ;
draw_line(canvas,
this->point(this->fIndices[i]), this->point(this->fIndices[i+1]),
SK_ColorBLACK);
draw_line(canvas,
this->point(this->fIndices[i+1]), this->point(this->fIndices[i+2]),
SK_ColorBLACK);
draw_line(canvas,
this->point(this->fIndices[i+2]), this->point(this->fIndices[i]),
SK_ColorBLACK);
}
fInitialRing.draw(canvas, *this);
for (int i = 0; i < fRings.count(); ++i) {
fRings[i]->draw(canvas, *this);
}
for (int i = 0; i < this->numPts(); ++i) {
draw_point(canvas,
this->point(i), 0.5f + (this->depth(i)/(2 * kAntialiasingRadius)),
!this->movable(i));
SkPaint paint;
paint.setTextSize(kPointTextSize);
if (this->depth(i) <= -kAntialiasingRadius) {
paint.setColor(SK_ColorWHITE);
}
SkString num;
num.printf("%d", i);
canvas->drawString(num,
this->point(i).fX, this->point(i).fY+(kPointRadius/2.0f),
paint);
}
}
#endif