static void show_stroke(SkCanvas* canvas, bool doAA, SkScalar strokeWidth, int n) { SkRandom rand; SkPaint paint; paint.setAntiAlias(doAA); paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(strokeWidth); for (int i = 0; i < n; ++i) { SkRect r; SkPath p; r.setXYWH(rand.nextSScalar1() * W, rand.nextSScalar1() * H, rand.nextUScalar1() * W, rand.nextUScalar1() * H); paint.setColor(rand.nextU()); canvas->drawRect(r, paint); r.setXYWH(rand.nextSScalar1() * W, rand.nextSScalar1() * H, rand.nextUScalar1() * W, rand.nextUScalar1() * H); paint.setColor(rand.nextU()); p.addOval(r); canvas->drawPath(p, paint); const SkScalar minx = -SkIntToScalar(W)/4; const SkScalar maxx = 5*SkIntToScalar(W)/4; const SkScalar miny = -SkIntToScalar(H)/4; const SkScalar maxy = 5*SkIntToScalar(H)/4; paint.setColor(rand.nextU()); canvas->drawLine(randRange(rand, minx, maxx), randRange(rand, miny, maxy), randRange(rand, minx, maxx), randRange(rand, miny, maxy), paint); } }
virtual void onDraw(int loops, SkCanvas* canvas) { const SkIPoint dim = this->getSize(); SkRandom rand; SkPaint paint(fPaint); this->setupPaint(&paint); // explicitly need these paint.setAlpha(fPaint.getAlpha()); paint.setAntiAlias(kBW != fFQ); paint.setLCDRenderText(kLCD == fFQ); const SkScalar x0 = SkIntToScalar(-10); const SkScalar y0 = SkIntToScalar(-10); paint.setTextSize(SkIntToScalar(12)); for (int i = 0; i < loops; i++) { SkScalar x = x0 + rand.nextUScalar1() * dim.fX; SkScalar y = y0 + rand.nextUScalar1() * dim.fY; canvas->drawString(fText, x, y, paint); } paint.setTextSize(SkIntToScalar(48)); for (int i = 0; i < loops / 4 ; i++) { SkScalar x = x0 + rand.nextUScalar1() * dim.fX; SkScalar y = y0 + rand.nextUScalar1() * dim.fY; canvas->drawString(fText, x, y, paint); } }
LineBench(SkScalar width, bool doAA) { fStrokeWidth = width; fDoAA = doAA; fName.printf("lines_%g_%s", width, doAA ? "AA" : "BW"); SkRandom rand; for (int i = 0; i < PTS; ++i) { fPts[i].set(rand.nextUScalar1() * 640, rand.nextUScalar1() * 480); } }
static void make_tris(Rec* rec) { int n = 10; SkRandom rand; rec->fMode = SkCanvas::kTriangles_VertexMode; rec->fCount = n * 3; rec->fVerts = new SkPoint[rec->fCount]; for (int i = 0; i < n; i++) { SkPoint* v = &rec->fVerts[i*3]; for (int j = 0; j < 3; j++) { v[j].set(rand.nextUScalar1() * 250, rand.nextUScalar1() * 250); } } }
void randPts() { for (size_t i = 0; i < SK_ARRAY_COUNT(fPts); i++) { fPts[i].set(fRand.nextUScalar1() * 640, fRand.nextUScalar1() * 480); } fCounter += 1; }
void onDelayedSetup() override { if (!fInit) { SkRandom rand; static const SkScalar kMinOffset = 0; static const SkScalar kMaxOffset = 100 * SK_Scalar1; static const SkScalar kOffsetRange = kMaxOffset - kMinOffset; for (int i = 0; i < N; ++i) { fRects[i].fLeft = -kMinOffset - SkScalarMul(rand.nextUScalar1(), kOffsetRange); fRects[i].fTop = -kMinOffset - SkScalarMul(rand.nextUScalar1(), kOffsetRange); fRects[i].fRight = W + kMinOffset + SkScalarMul(rand.nextUScalar1(), kOffsetRange); fRects[i].fBottom = H + kMinOffset + SkScalarMul(rand.nextUScalar1(), kOffsetRange); fColors[i] = rand.nextU() | 0xFF000000; } fInit = true; } }
virtual void onDraw(SkCanvas* canvas) { const SkIPoint dim = this->getSize(); SkRandom rand; SkPaint paint(fPaint); this->setupPaint(&paint); // explicitly need these paint.setColor(fPaint.getColor()); paint.setAntiAlias(kBW != fFQ); paint.setLCDRenderText(kLCD == fFQ); const SkScalar x0 = SkIntToScalar(-10); const SkScalar y0 = SkIntToScalar(-10); if (fDoPos) { // realistically, the matrix is often at least translated, so we // do that since it exercises different code in drawPosText. canvas->translate(SK_Scalar1, SK_Scalar1); } for (int i = 0; i < N; i++) { if (fDoPos) { canvas->drawPosText(fText.c_str(), fText.size(), fPos, paint); } else { SkScalar x = x0 + rand.nextUScalar1() * dim.fX; SkScalar y = y0 + rand.nextUScalar1() * dim.fY; canvas->drawText(fText.c_str(), fText.size(), x, y, paint); } } }
void onDraw(SkCanvas* canvas) override { canvas->translate(20, 20); SkRect r = SkRect::MakeWH(1000, 1000); SkPaint paint; paint.setAntiAlias(true); paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(15); const SkScalar inset = paint.getStrokeWidth() + 4; const SkScalar sweepAngle = 345; SkRandom rand; SkScalar sign = 1; while (r.width() > paint.getStrokeWidth() * 3) { paint.setColor(sk_tool_utils::color_to_565(rand.nextU() | (0xFF << 24))); SkScalar startAngle = rand.nextUScalar1() * 360; SkScalar speed = SkScalarSqrt(16 / r.width()) * 0.5f; startAngle += fRotate * 360 * speed * sign; SkPath path; path.addArc(r, startAngle, sweepAngle); canvas->drawPath(path, paint); r.inset(inset, inset); sign = -sign; } }
virtual void onDraw(SkCanvas* canvas) { SkPaint paint; this->setupPaint(&paint); paint.setAntiAlias(true); SkRandom rand; for (int i = 0; i < SkBENCHLOOP(3); i++) { SkRect r = SkRect::MakeWH(rand.nextUScalar1() * 400, rand.nextUScalar1() * 400); r.offset(fRadius, fRadius); if (fRadius > 0) { SkMorphologyImageFilter* mf = NULL; switch (fStyle) { case kDilate_MT: mf = new SkDilateImageFilter(SkScalarFloorToInt(fRadius), SkScalarFloorToInt(fRadius)); break; case kErode_MT: mf = new SkErodeImageFilter(SkScalarFloorToInt(fRadius), SkScalarFloorToInt(fRadius)); break; } paint.setImageFilter(mf)->unref(); } canvas->drawOval(r, paint); } }
void onDrawContent(SkCanvas* canvas) override { test_huge_stroke(canvas); return; canvas->translate(SkIntToScalar(10), SkIntToScalar(10)); SkPaint paint; paint.setAntiAlias(true); if (true) { canvas->drawColor(SK_ColorBLACK); paint.setTextSize(24); paint.setColor(SK_ColorWHITE); canvas->translate(10, 30); static const SkBlurStyle gStyle[] = { kNormal_SkBlurStyle, kInner_SkBlurStyle, kOuter_SkBlurStyle, kSolid_SkBlurStyle, }; for (int x = 0; x < 5; x++) { SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(4)); for (int y = 0; y < 10; y++) { if (x) { paint.setMaskFilter(SkBlurMaskFilter::Make(gStyle[x - 1], sigma)); } canvas->drawString("Title Bar", x*SkIntToScalar(100), y*SkIntToScalar(30), paint); sigma *= 0.75f; } } return; } paint.setColor(SK_ColorBLUE); #if 1 SkPath p; float r = rand.nextUScalar1() + 0.5f; SkScalar x = 0, y = 0; p.moveTo(x, y); #if 0 p.cubicTo(x-75*r, y+75*r, x-40*r, y+125*r, x, y+85*r); p.cubicTo(x+40*r, y+125*r, x+75*r, y+75*r, x, y); #else p.cubicTo(x+75*r, y+75*r, x+40*r, y+125*r, x, y+85*r); p.cubicTo(x-40*r, y+125*r, x-75*r, y+75*r, x, y); #endif p.close(); fPath = p; fPath.offset(100, 0); #endif fPath.setFillType(SkPath::kWinding_FillType); drawSet(canvas, &paint); canvas->translate(0, fPath.getBounds().height() * 5 / 4); fPath.setFillType(SkPath::kEvenOdd_FillType); drawSet(canvas, &paint); }
void onDraw(const int loops, SkCanvas* canvas) override { const char* text = "Hamburgefons"; size_t len = strlen(text); SkISize size = canvas->getDeviceSize(); SkRandom random; for (int i = 0; i < loops; ++i) { SkPaint paint; paint.setXfermode(fXfermode.get()); paint.setColor(random.nextU()); if (fAA) { // Draw text to exercise AA code paths. paint.setAntiAlias(true); paint.setTextSize(random.nextRangeScalar(12, 96)); SkScalar x = random.nextRangeScalar(0, (SkScalar)size.fWidth), y = random.nextRangeScalar(0, (SkScalar)size.fHeight); for (int j = 0; j < 1000; ++j) { canvas->drawText(text, len, x, y, paint); } } else { // Draw rects to exercise non-AA code paths. SkScalar w = random.nextRangeScalar(50, 100); SkScalar h = random.nextRangeScalar(50, 100); SkRect rect = SkRect::MakeXYWH( random.nextUScalar1() * (size.fWidth - w), random.nextUScalar1() * (size.fHeight - h), w, h ); for (int j = 0; j < 1000; ++j) { canvas->drawRect(rect, paint); } } } }
void onDraw(int loops, SkCanvas* canvas) override { SkPaint paint; this->setupPaint(&paint); paint.setAntiAlias(true); SkRandom rand; for (int i = 0; i < loops; i++) { SkRect r = SkRect::MakeWH(rand.nextUScalar1() * 400, rand.nextUScalar1() * 400); r.offset(fRadius, fRadius); if (fRadius > 0) { sk_sp<SkImageFilter> mf; switch (fStyle) { case kDilate_MT: mf = SkDilateImageFilter::Make(SkScalarFloorToInt(fRadius), SkScalarFloorToInt(fRadius), nullptr); break; case kErode_MT: mf = SkErodeImageFilter::Make(SkScalarFloorToInt(fRadius), SkScalarFloorToInt(fRadius), nullptr); break; } paint.setImageFilter(std::move(mf)); } canvas->drawOval(r, paint); } }
DrawAtlasDrawable(DrawAtlasProc proc, const SkRect& r) : fProc(proc), fBounds(r), fUseColors(false) { SkRandom rand; fAtlas = make_atlas(kAtlasSize, kCellSize); const SkScalar kMaxSpeed = 5; const SkScalar cell = SkIntToScalar(kCellSize); int i = 0; for (int y = 0; y < kAtlasSize; y += kCellSize) { for (int x = 0; x < kAtlasSize; x += kCellSize) { const SkScalar sx = SkIntToScalar(x); const SkScalar sy = SkIntToScalar(y); fTex[i].setXYWH(sx, sy, cell, cell); fRec[i].fCenter.set(sx + cell/2, sy + 3*cell/4); fRec[i].fVelocity.fX = rand.nextSScalar1() * kMaxSpeed; fRec[i].fVelocity.fY = rand.nextSScalar1() * kMaxSpeed; fRec[i].fScale = 1; fRec[i].fDScale = rand.nextSScalar1() / 16; fRec[i].fRadian = 0; fRec[i].fDRadian = rand.nextSScalar1() / 8; fRec[i].fAlpha = rand.nextUScalar1(); fRec[i].fDAlpha = rand.nextSScalar1() / 10; i += 1; } } }
void onDraw(SkCanvas* canvas) override { SkPath path; SkRandom rand; int scale = 300; for (int i = 0; i < 4; ++i) { // get the random values deterministically SkScalar randoms[12]; for (int index = 0; index < (int) SK_ARRAY_COUNT(randoms); ++index) { randoms[index] = rand.nextUScalar1(); } path.lineTo(randoms[0] * scale, randoms[1] * scale); path.quadTo(randoms[2] * scale, randoms[3] * scale, randoms[4] * scale, randoms[5] * scale); path.cubicTo(randoms[6] * scale, randoms[7] * scale, randoms[8] * scale, randoms[9] * scale, randoms[10] * scale, randoms[11] * scale); } path.setFillType(SkPath::kEvenOdd_FillType); path.offset(SkIntToScalar(20), SkIntToScalar(20)); test_hittest(canvas, path); canvas->translate(SkIntToScalar(scale), 0); path.setFillType(SkPath::kWinding_FillType); test_hittest(canvas, path); }
static void test_memory_pool(skiatest::Reporter* reporter) { // prealloc and min alloc sizes for the pool static const size_t gSizes[][2] = { {0, 0}, {10 * sizeof(A), 20 * sizeof(A)}, {100 * sizeof(A), 100 * sizeof(A)}, {500 * sizeof(A), 500 * sizeof(A)}, {10000 * sizeof(A), 0}, {1, 100 * sizeof(A)}, }; // different percentages of creation vs deletion static const float gCreateFraction[] = {1.f, .95f, 0.75f, .5f}; // number of create/destroys per test static const int kNumIters = 20000; // check that all the values stored in A objects are correct after this // number of iterations static const int kCheckPeriod = 500; SkRandom r; for (size_t s = 0; s < SK_ARRAY_COUNT(gSizes); ++s) { A::SetAllocator(gSizes[s][0], gSizes[s][1]); for (size_t c = 0; c < SK_ARRAY_COUNT(gCreateFraction); ++c) { SkTDArray<Rec> instanceRecs; for (int i = 0; i < kNumIters; ++i) { float createOrDestroy = r.nextUScalar1(); if (createOrDestroy < gCreateFraction[c] || 0 == instanceRecs.count()) { Rec* rec = instanceRecs.append(); rec->fInstance = A::Create(&r); rec->fValue = static_cast<int>(r.nextU()); rec->fInstance->setValues(rec->fValue); } else { int d = r.nextRangeU(0, instanceRecs.count() - 1); Rec& rec = instanceRecs[d]; REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue)); delete rec.fInstance; instanceRecs.removeShuffle(d); } if (0 == i % kCheckPeriod) { for (int r = 0; r < instanceRecs.count(); ++r) { Rec& rec = instanceRecs[r]; REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue)); } } } for (int i = 0; i < instanceRecs.count(); ++i) { Rec& rec = instanceRecs[i]; REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue)); delete rec.fInstance; } #ifdef SK_ENABLE_INST_COUNT REPORTER_ASSERT(reporter, !A::GetInstanceCount()); #endif } } }
virtual void onDraw(int loops, SkCanvas* canvas) { SkPaint paint; this->setupPaint(&paint); paint.setAntiAlias(true); SkRandom rand; for (int i = 0; i < loops; i++) { SkRect r = SkRect::MakeWH(rand.nextUScalar1() * 400, rand.nextUScalar1() * 400); paint.setImageFilter(fFilter); canvas->drawOval(r, paint); } }
static void show_fill(SkCanvas* canvas, bool doAA) { SkRandom rand; SkPaint paint; paint.setAntiAlias(doAA); for (int i = 0; i < 50; ++i) { SkRect r; SkPath p; r.setXYWH(rand.nextSScalar1() * W, rand.nextSScalar1() * H, rand.nextUScalar1() * W, rand.nextUScalar1() * H); paint.setColor(rand.nextU()); canvas->drawRect(r, paint); r.setXYWH(rand.nextSScalar1() * W, rand.nextSScalar1() * H, rand.nextUScalar1() * W, rand.nextUScalar1() * H); paint.setColor(rand.nextU()); p.addOval(r); canvas->drawPath(p, paint); } }
DEF_TEST(Color4f_premul, reporter) { SkRandom rand; for (int i = 0; i < 1000000; ++i) { // First just test opaque colors, so that the premul should be exact SkColor4f c4 { 1, rand.nextUScalar1(), rand.nextUScalar1(), rand.nextUScalar1() }; SkPM4f pm4 = c4.premul(); REPORTER_ASSERT(reporter, pm4.a() == c4.fA); REPORTER_ASSERT(reporter, pm4.r() == c4.fA * c4.fR); REPORTER_ASSERT(reporter, pm4.g() == c4.fA * c4.fG); REPORTER_ASSERT(reporter, pm4.b() == c4.fA * c4.fB); // We compare with a tolerance, in case our premul multiply is implemented at slightly // different precision than the test code. c4.fA = rand.nextUScalar1(); pm4 = c4.premul(); REPORTER_ASSERT(reporter, pm4.fVec[SK_A_INDEX] == c4.fA); REPORTER_ASSERT(reporter, nearly_equal(pm4.r(), c4.fA * c4.fR)); REPORTER_ASSERT(reporter, nearly_equal(pm4.g(), c4.fA * c4.fG)); REPORTER_ASSERT(reporter, nearly_equal(pm4.b(), c4.fA * c4.fB)); } }
SkRect draw(SkCanvas* canvas, const SkPaint& paint) override { SkRandom random; SkPoint points[500]; SkRect bounds = SkRect::MakeWH(50, 50); int count = SkToInt(SK_ARRAY_COUNT(points)); if (SkCanvas::kPoints_PointMode != fMode) { count = SkTMin(count, 10); } for (int p = 0; p < count; ++p) { points[p].fX = random.nextUScalar1() * bounds.width(); points[p].fY = random.nextUScalar1() * bounds.width(); } canvas->drawPoints(fMode, count, points, paint); return bounds; }
static void rand_op(SkCanvas* canvas, SkRandom& rand) { SkPaint paint; SkRect rect = SkRect::MakeWH(50, 50); SkScalar unit = rand.nextUScalar1(); if (unit <= 0.3) { // SkDebugf("save\n"); canvas->save(); } else if (unit <= 0.6) { // SkDebugf("restore\n"); canvas->restore(); } else if (unit <= 0.9) { // SkDebugf("clip\n"); canvas->clipRect(rect); } else { // SkDebugf("draw\n"); canvas->drawPaint(paint); } }
void onDraw(int loops, SkCanvas* canvas) override { SkPaint paint; this->setupPaint(&paint); paint.setAntiAlias(true); SkRandom rand; for (int i = 0; i < loops; i++) { SkRect r = SkRect::MakeWH(rand.nextUScalar1() * 400, rand.nextUScalar1() * 400); r.offset(fRadius, fRadius); if (fRadius > 0) { paint.setMaskFilter(SkMaskFilter::MakeBlur(fStyle, SkBlurMask::ConvertRadiusToSigma(fRadius))); } canvas->drawOval(r, paint); } }
virtual void onDraw(SkCanvas* canvas) { SkPaint paint; this->setupPaint(&paint); paint.setAntiAlias(true); SkRandom rand; for (int i = 0; i < SkBENCHLOOP(10); i++) { SkRect r = SkRect::MakeWH(rand.nextUScalar1() * 400, rand.nextUScalar1() * 400); r.offset(fRadius, fRadius); if (fRadius > 0) { SkMaskFilter* mf = SkBlurMaskFilter::Create(fRadius, fStyle, 0); paint.setMaskFilter(mf)->unref(); } canvas->drawOval(r, paint); } }
static void test_conic(skiatest::Reporter* reporter) { SkRandom rand; for (int i = 0; i < 1000; ++i) { SkPoint pts[3]; for (int j = 0; j < 3; ++j) { pts[j].set(rand.nextSScalar1() * 100, rand.nextSScalar1() * 100); } for (int k = 0; k < 10; ++k) { SkScalar w = rand.nextUScalar1() * 2; SkConic conic(pts, w); const SkScalar dt = SK_Scalar1 / 128; SkScalar t = dt; for (int j = 1; j < 128; ++j) { test_conic_eval_pos(reporter, conic, t); test_conic_eval_tan(reporter, conic, t); t += dt; } } } }
virtual void onDraw(const int loops, SkCanvas* canvas) { SkPaint paint; this->setupPaint(&paint); paint.setAntiAlias(true); SkRandom rand; for (int i = 0; i < loops; i++) { SkRect r = SkRect::MakeWH(rand.nextUScalar1() * 400, rand.nextUScalar1() * 400); r.offset(fRadius, fRadius); if (fRadius > 0) { SkMaskFilter* mf = SkBlurMaskFilter::Create(fStyle, SkBlurMask::ConvertRadiusToSigma(fRadius), fFlags); paint.setMaskFilter(mf)->unref(); } canvas->drawOval(r, paint); } }
virtual void onDraw(SkCanvas* canvas) { SkIPoint dim = this->getSize(); SkRandom rand; SkPaint paint(fPaint); this->setupPaint(&paint); const SkBitmap& bitmap = fBitmap; const SkScalar x0 = SkIntToScalar(-bitmap.width() / 2); const SkScalar y0 = SkIntToScalar(-bitmap.height() / 2); for (int i = 0; i < N; i++) { SkScalar x = x0 + rand.nextUScalar1() * dim.fX; SkScalar y = y0 + rand.nextUScalar1() * dim.fY; if (fForceUpdate) bitmap.notifyPixelsChanged(); canvas->drawBitmap(bitmap, x, y, &paint); } }
virtual void onDraw(SkCanvas* canvas) { SkPath path; SkRandom rand; int scale = 300; for (int i = 0; i < 4; ++i) { path.lineTo(rand.nextUScalar1() * scale, rand.nextUScalar1() * scale); path.quadTo(rand.nextUScalar1() * scale, rand.nextUScalar1() * scale, rand.nextUScalar1() * scale, rand.nextUScalar1() * scale); path.cubicTo(rand.nextUScalar1() * scale, rand.nextUScalar1() * scale, rand.nextUScalar1() * scale, rand.nextUScalar1() * scale, rand.nextUScalar1() * scale, rand.nextUScalar1() * scale); } path.setFillType(SkPath::kEvenOdd_FillType); path.offset(SkIntToScalar(20), SkIntToScalar(20)); test_hittest(canvas, path); canvas->translate(SkIntToScalar(scale), 0); path.setFillType(SkPath::kWinding_FillType); test_hittest(canvas, path); }
virtual void onDraw(SkCanvas* canvas) { drawBG(canvas); //return; canvas->translate(SkIntToScalar(10), SkIntToScalar(10)); SkPaint paint; paint.setAntiAlias(true); if (true) { canvas->drawColor(SK_ColorBLACK); paint.setTextSize(24); paint.setColor(SK_ColorWHITE); canvas->translate(10, 30); static const SkBlurMaskFilter::BlurStyle gStyle[] = { SkBlurMaskFilter::kNormal_BlurStyle, SkBlurMaskFilter::kInner_BlurStyle, SkBlurMaskFilter::kOuter_BlurStyle, SkBlurMaskFilter::kSolid_BlurStyle, }; for (int x = 0; x < 5; x++) { SkMaskFilter* mf; SkScalar radius = 4; for (int y = 0; y < 10; y++) { if (x) { mf = SkBlurMaskFilter::Create(radius, gStyle[x - 1]); paint.setMaskFilter(mf)->unref(); } canvas->drawText("Title Bar", 9, x*100, y*30, paint); radius *= 0.75f; } } return; } paint.setColor(SK_ColorBLUE); #if 1 SkPath p; float r = rand.nextUScalar1() + 0.5f; SkScalar x = 0, y = 0; p.moveTo(x, y); #if 0 p.cubicTo(x-75*r, y+75*r, x-40*r, y+125*r, x, y+85*r); p.cubicTo(x+40*r, y+125*r, x+75*r, y+75*r, x, y); #else p.cubicTo(x+75*r, y+75*r, x+40*r, y+125*r, x, y+85*r); p.cubicTo(x-40*r, y+125*r, x-75*r, y+75*r, x, y); #endif p.close(); fPath = p; fPath.offset(100, 0); #endif fPath.setFillType(SkPath::kWinding_FillType); drawSet(canvas, &paint); canvas->translate(0, fPath.getBounds().height() * 5 / 4); fPath.setFillType(SkPath::kEvenOdd_FillType); drawSet(canvas, &paint); }
static int R(float x) { return (int)floor(SkScalarToFloat(gRand.nextUScalar1()) * x); }
static SkScalar nextScalarRange(SkRandom& rand, SkScalar min, SkScalar max) { return min + SkScalarMul(rand.nextUScalar1(), max - min); }
virtual void onDrawContent(SkCanvas* canvas) { SkPaint paint; paint.setAntiAlias(true); paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(-1); canvas->save(); canvas->scale(1000 * SK_Scalar1, 1000 * SK_Scalar1); SkRandom rand; SkPath curves; SkPath hulls; SkPath ctrlPts; for (int i = 0; i < 100; ++i) { SkScalar pts[] = { rand.nextUScalar1(), rand.nextUScalar1(), rand.nextUScalar1(), rand.nextUScalar1(), rand.nextUScalar1(), rand.nextUScalar1(), rand.nextUScalar1(), rand.nextUScalar1() }; curves.moveTo(pts[0], pts[1]); curves.cubicTo(pts[2], pts[3], pts[4], pts[5], pts[6], pts[7]); hulls.moveTo(pts[0], pts[1]); hulls.lineTo(pts[2], pts[3]); hulls.lineTo(pts[4], pts[5]); hulls.lineTo(pts[6], pts[7]); ctrlPts.addCircle(pts[0], pts[1], SK_Scalar1 / 200); ctrlPts.addCircle(pts[2], pts[3], SK_Scalar1 / 200); ctrlPts.addCircle(pts[4], pts[5], SK_Scalar1 / 200); ctrlPts.addCircle(pts[6], pts[7], SK_Scalar1 / 200); } for (int i = 0; i < 100; ++i) { SkScalar pts[] = { rand.nextUScalar1(), rand.nextUScalar1(), rand.nextUScalar1(), rand.nextUScalar1(), rand.nextUScalar1(), rand.nextUScalar1(), }; curves.moveTo(pts[0], pts[1]); curves.quadTo(pts[2], pts[3], pts[4], pts[5]); hulls.moveTo(pts[0], pts[1]); hulls.lineTo(pts[2], pts[3]); hulls.lineTo(pts[4], pts[5]); ctrlPts.addCircle(pts[0], pts[1], SK_Scalar1 / 200); ctrlPts.addCircle(pts[2], pts[3], SK_Scalar1 / 200); ctrlPts.addCircle(pts[4], pts[5], SK_Scalar1 / 200); } for (int i = 0; i < 100; ++i) { SkScalar pts[] = { rand.nextUScalar1(), rand.nextUScalar1(), rand.nextUScalar1(), rand.nextUScalar1(), }; curves.moveTo(pts[0], pts[1]); curves.lineTo(pts[2], pts[3]); ctrlPts.addCircle(pts[0], pts[1], SK_Scalar1 / 200); ctrlPts.addCircle(pts[2], pts[3], SK_Scalar1 / 200); } paint.setColor(SK_ColorBLACK); canvas->drawPath(curves, paint); paint.setColor(SK_ColorRED); //canvas->drawPath(hulls, paint); paint.setStyle(SkPaint::kFill_Style); paint.setColor(SK_ColorBLUE); //canvas->drawPath(ctrlPts, paint); canvas->restore(); }