зеркало из https://github.com/mozilla/moz-skia.git
255 строки
7.3 KiB
C++
255 строки
7.3 KiB
C++
#include "SampleCode.h"
|
|
#include "SkView.h"
|
|
#include "SkCanvas.h"
|
|
#include "SkGradientShader.h"
|
|
#include "SkGraphics.h"
|
|
#include "SkImageDecoder.h"
|
|
#include "SkPath.h"
|
|
#include "SkRegion.h"
|
|
#include "SkShader.h"
|
|
#include "SkUtils.h"
|
|
#include "SkXfermode.h"
|
|
#include "SkColorPriv.h"
|
|
#include "SkColorFilter.h"
|
|
#include "SkTime.h"
|
|
#include "SkRandom.h"
|
|
|
|
#include "SkLineClipper.h"
|
|
#include "SkEdgeClipper.h"
|
|
|
|
#define AUTO_ANIMATE true
|
|
|
|
static int test0(SkPoint pts[], SkRect* clip) {
|
|
pts[0].set(200000, 140);
|
|
pts[1].set(-740000, 483);
|
|
pts[2].set(1.00000102e-06f, 9.10000017e-05f);
|
|
clip->set(0, 0, 640, 480);
|
|
return 2;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void drawQuad(SkCanvas* canvas, const SkPoint pts[3], const SkPaint& p) {
|
|
SkPath path;
|
|
path.moveTo(pts[0]);
|
|
path.quadTo(pts[1], pts[2]);
|
|
canvas->drawPath(path, p);
|
|
}
|
|
|
|
static void drawCubic(SkCanvas* canvas, const SkPoint pts[4], const SkPaint& p) {
|
|
SkPath path;
|
|
path.moveTo(pts[0]);
|
|
path.cubicTo(pts[1], pts[2], pts[3]);
|
|
canvas->drawPath(path, p);
|
|
}
|
|
|
|
typedef void (*clipper_proc)(const SkPoint src[], const SkRect& clip,
|
|
SkCanvas*, const SkPaint&, const SkPaint&);
|
|
|
|
static void check_clipper(int count, const SkPoint pts[], const SkRect& clip) {
|
|
for (int i = 0; i < count; i++) {
|
|
SkASSERT(pts[i].fX >= clip.fLeft);
|
|
SkASSERT(pts[i].fX <= clip.fRight);
|
|
SkASSERT(pts[i].fY >= clip.fTop);
|
|
SkASSERT(pts[i].fY <= clip.fBottom);
|
|
}
|
|
|
|
if (count > 1) {
|
|
sk_assert_monotonic_y(pts, count);
|
|
}
|
|
}
|
|
|
|
static void line_intersector(const SkPoint src[], const SkRect& clip,
|
|
SkCanvas* canvas, const SkPaint& p0, const SkPaint& p1) {
|
|
canvas->drawPoints(SkCanvas::kLines_PointMode, 2, src, p1);
|
|
|
|
SkPoint dst[2];
|
|
if (SkLineClipper::IntersectLine(src, clip, dst)) {
|
|
check_clipper(2, dst, clip);
|
|
canvas->drawPoints(SkCanvas::kLines_PointMode, 2, dst, p0);
|
|
}
|
|
}
|
|
|
|
static void line_clipper(const SkPoint src[], const SkRect& clip,
|
|
SkCanvas* canvas, const SkPaint& p0, const SkPaint& p1) {
|
|
canvas->drawPoints(SkCanvas::kLines_PointMode, 2, src, p1);
|
|
|
|
SkPoint dst[SkLineClipper::kMaxPoints];
|
|
int count = SkLineClipper::ClipLine(src, clip, dst);
|
|
for (int i = 0; i < count; i++) {
|
|
check_clipper(2, &dst[i], clip);
|
|
canvas->drawPoints(SkCanvas::kLines_PointMode, 2, &dst[i], p0);
|
|
}
|
|
}
|
|
|
|
static void quad_clipper(const SkPoint src[], const SkRect& clip,
|
|
SkCanvas* canvas, const SkPaint& p0, const SkPaint& p1) {
|
|
drawQuad(canvas, src, p1);
|
|
|
|
SkEdgeClipper clipper;
|
|
if (clipper.clipQuad(src, clip)) {
|
|
SkPoint pts[4];
|
|
SkPath::Verb verb;
|
|
while ((verb = clipper.next(pts)) != SkPath::kDone_Verb) {
|
|
switch (verb) {
|
|
case SkPath::kLine_Verb:
|
|
check_clipper(2, pts, clip);
|
|
canvas->drawPoints(SkCanvas::kLines_PointMode, 2, pts, p0);
|
|
break;
|
|
case SkPath::kQuad_Verb:
|
|
check_clipper(3, pts, clip);
|
|
drawQuad(canvas, pts, p0);
|
|
break;
|
|
default:
|
|
SkASSERT(!"unexpected verb");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void cubic_clipper(const SkPoint src[], const SkRect& clip,
|
|
SkCanvas* canvas, const SkPaint& p0, const SkPaint& p1) {
|
|
drawCubic(canvas, src, p1);
|
|
|
|
SkEdgeClipper clipper;
|
|
if (clipper.clipCubic(src, clip)) {
|
|
SkPoint pts[4];
|
|
SkPath::Verb verb;
|
|
while ((verb = clipper.next(pts)) != SkPath::kDone_Verb) {
|
|
switch (verb) {
|
|
case SkPath::kLine_Verb:
|
|
check_clipper(2, pts, clip);
|
|
canvas->drawPoints(SkCanvas::kLines_PointMode, 2, pts, p0);
|
|
break;
|
|
case SkPath::kCubic_Verb:
|
|
// check_clipper(4, pts, clip);
|
|
drawCubic(canvas, pts, p0);
|
|
break;
|
|
default:
|
|
SkASSERT(!"unexpected verb");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static const clipper_proc gProcs[] = {
|
|
line_intersector,
|
|
line_clipper,
|
|
quad_clipper,
|
|
cubic_clipper
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
enum {
|
|
W = 640/3,
|
|
H = 480/3
|
|
};
|
|
|
|
class LineClipperView : public SkView {
|
|
SkMSec fNow;
|
|
int fCounter;
|
|
int fProcIndex;
|
|
SkRect fClip;
|
|
SkRandom fRand;
|
|
SkPoint fPts[4];
|
|
|
|
void randPts() {
|
|
for (int i = 0; i < SK_ARRAY_COUNT(fPts); i++) {
|
|
fPts[i].set(fRand.nextUScalar1() * 640,
|
|
fRand.nextUScalar1() * 480);
|
|
}
|
|
fCounter += 1;
|
|
}
|
|
|
|
public:
|
|
LineClipperView() {
|
|
fProcIndex = 0;
|
|
fCounter = 0;
|
|
|
|
int x = (640 - W)/2;
|
|
int y = (480 - H)/2;
|
|
fClip.set(SkIntToScalar(x), SkIntToScalar(y),
|
|
SkIntToScalar(x + W), SkIntToScalar(y + H));
|
|
this->randPts();
|
|
}
|
|
|
|
protected:
|
|
// overrides from SkEventSink
|
|
virtual bool onQuery(SkEvent* evt) {
|
|
if (SampleCode::TitleQ(*evt)) {
|
|
SampleCode::TitleR(evt, "LineClipper");
|
|
return true;
|
|
}
|
|
return this->INHERITED::onQuery(evt);
|
|
}
|
|
|
|
void drawBG(SkCanvas* canvas) {
|
|
canvas->drawColor(SK_ColorWHITE);
|
|
}
|
|
|
|
static void drawVLine(SkCanvas* canvas, SkScalar x, const SkPaint& paint) {
|
|
canvas->drawLine(x, -999, x, 999, paint);
|
|
}
|
|
|
|
static void drawHLine(SkCanvas* canvas, SkScalar y, const SkPaint& paint) {
|
|
canvas->drawLine(-999, y, 999, y, paint);
|
|
}
|
|
|
|
virtual void onDraw(SkCanvas* canvas) {
|
|
this->drawBG(canvas);
|
|
|
|
SkMSec now = SampleCode::GetAnimTime();
|
|
if (fNow != now) {
|
|
fNow = now;
|
|
this->randPts();
|
|
this->inval(NULL);
|
|
}
|
|
|
|
// fProcIndex = test0(fPts, &fClip);
|
|
|
|
SkPaint paint, paint1;
|
|
|
|
drawVLine(canvas, fClip.fLeft + SK_ScalarHalf, paint);
|
|
drawVLine(canvas, fClip.fRight - SK_ScalarHalf, paint);
|
|
drawHLine(canvas, fClip.fTop + SK_ScalarHalf, paint);
|
|
drawHLine(canvas, fClip.fBottom - SK_ScalarHalf, paint);
|
|
|
|
paint.setColor(SK_ColorLTGRAY);
|
|
canvas->drawRect(fClip, paint);
|
|
|
|
paint.setAntiAlias(true);
|
|
paint.setColor(SK_ColorBLUE);
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
// paint.setStrokeWidth(SkIntToScalar(3));
|
|
paint.setStrokeCap(SkPaint::kRound_Cap);
|
|
|
|
paint1.setAntiAlias(true);
|
|
paint1.setColor(SK_ColorRED);
|
|
paint1.setStyle(SkPaint::kStroke_Style);
|
|
gProcs[fProcIndex](fPts, fClip, canvas, paint, paint1);
|
|
}
|
|
|
|
virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
|
|
// fProcIndex = (fProcIndex + 1) % SK_ARRAY_COUNT(gProcs);
|
|
if (x < 50 && y < 50) {
|
|
this->randPts();
|
|
}
|
|
this->inval(NULL);
|
|
return NULL;
|
|
}
|
|
|
|
virtual bool onClick(Click* click) {
|
|
return false;
|
|
}
|
|
|
|
private:
|
|
typedef SkView INHERITED;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static SkView* MyFactory() { return new LineClipperView; }
|
|
static SkViewRegister reg(MyFactory);
|
|
|