// http://crbug.com/165432 // Limit extreme dash path effects to avoid exhausting the system memory. static void test_crbug_165432(skiatest::Reporter* reporter) { SkPath path; path.moveTo(0, 0); path.lineTo(10000000, 0); SkScalar intervals[] = { 0.5f, 0.5f }; SkDashPathEffect dash(intervals, 2, 0); SkPaint paint; paint.setStyle(SkPaint::kStroke_Style); paint.setPathEffect(&dash); SkPath filteredPath; SkStrokeRec rec(paint); REPORTER_ASSERT(reporter, !dash.filterPath(&filteredPath, path, &rec, NULL)); REPORTER_ASSERT(reporter, filteredPath.isEmpty()); }
SkPath create_concave_path(const SkPoint& offset) { SkPath concavePath; concavePath.moveTo(kMin, kMin); concavePath.lineTo(kMid, 105.0f); concavePath.lineTo(kMax, kMin); concavePath.lineTo(295.0f, kMid); concavePath.lineTo(kMax, kMax); concavePath.lineTo(kMid, 295.0f); concavePath.lineTo(kMin, kMax); concavePath.lineTo(105.0f, kMid); concavePath.close(); concavePath.offset(offset.fX, offset.fY); return concavePath; }
static SkPathEffect* make_warp_pe() { SkPath path; path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1])); for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2) path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1])); path.close(); path.offset(SkIntToScalar(-6), 0); SkPathEffect* outer = new SkPath1DPathEffect(path, SkIntToScalar(12), gPhase, SkPath1DPathEffect::kMorph_Style); SkPathEffect* inner = new SkCornerPathEffect(SkIntToScalar(CORNER_RADIUS)); SkPathEffect* pe = new SkComposePathEffect(outer, inner); outer->unref(); inner->unref(); return pe; }
static void test4(SkCanvas* canvas) { SkPaint paint; paint.setAntiAlias(true); SkPoint pts[] = { {10, 160}, {610, 160}, {610, 160}, {10, 160}, {610, 160}, {610, 160}, {610, 199}, {610, 199}, {10, 198}, {610, 198}, {610, 199}, {10, 199}, {10, 160}, {10, 160}, {10, 199}, {10, 199} }; char verbs[] = { 0, 1, 1, 1, 4, 0, 1, 1, 1, 4, 0, 1, 1, 1, 4, 0, 1, 1, 1, 4 }; SkPath path; SkPoint* ptPtr = pts; for (size_t i = 0; i < sizeof(verbs); ++i) { switch ((SkPath::Verb) verbs[i]) { case SkPath::kMove_Verb: path.moveTo(ptPtr->fX, ptPtr->fY); ++ptPtr; break; case SkPath::kLine_Verb: path.lineTo(ptPtr->fX, ptPtr->fY); ++ptPtr; break; case SkPath::kClose_Verb: path.close(); break; default: SkASSERT(false); break; } } SkRect clip = {0, 130, 772, 531}; canvas->clipRect(clip); canvas->drawPath(path, paint); }
// Extremely large path_length/dash_length ratios may cause infinite looping // in SkDashPathEffect::filterPath() due to single precision rounding. // The test is quite expensive, but it should get much faster after the fix // for http://crbug.com/165432 goes in. static void test_infinite_dash(skiatest::Reporter* reporter) { SkPath path; path.moveTo(0, 0); path.lineTo(5000000, 0); SkScalar intervals[] = { 0.2f, 0.2f }; SkDashPathEffect dash(intervals, 2, 0); SkPath filteredPath; SkPaint paint; paint.setStyle(SkPaint::kStroke_Style); paint.setPathEffect(&dash); paint.getFillPath(path, &filteredPath); // If we reach this, we passed. REPORTER_ASSERT(reporter, true); }
void onDraw(SkCanvas* canvas) override { SkPaint p; p.setColor(SK_ColorRED); p.setAntiAlias(true); canvas->clear(0xFFFFFFFF); canvas->save(); canvas->rotate(1); const SkScalar R = 115.2f, C = 128.0f; SkPath path; path.moveTo(C + R, C); for (int i = 1; i < 8; ++i) { SkScalar a = 2.6927937f * i; SkScalar cosine; SkScalar sine = SkScalarSinCos(a, &cosine); path.lineTo(C + R * cosine, C + R * sine); } canvas->drawPath(path, p); canvas->restore(); canvas->save(); canvas->translate(200, 0); canvas->rotate(1); p.setStyle(SkPaint::kStroke_Style); p.setStrokeWidth(5); canvas->drawPath(path, p); canvas->restore(); // The following two paths test if we correctly cumulates the alpha on the middle pixel // column where the left rect and the right rect abut. p.setStyle(SkPaint::kFill_Style); canvas->translate(0, 300); path.reset(); path.addRect({20, 20, 100.4999f, 100}); path.addRect({100.5001f, 20, 200, 100}); canvas->drawPath(path, p); canvas->translate(300, 0); path.reset(); path.addRect({20, 20, 100.1f, 100}); path.addRect({100.9f, 20, 200, 100}); canvas->drawPath(path, p); }
void WebTestThemeControlWin::triangle(int x0, int y0, int x1, int y1, int x2, int y2, SkColor color) { SkPath path; SkPaint paint; paint.setColor(color); paint.setStyle(SkPaint::kFill_Style); path.incReserve(4); path.moveTo(SkIntToScalar(x0), SkIntToScalar(y0)); path.lineTo(SkIntToScalar(x1), SkIntToScalar(y1)); path.lineTo(SkIntToScalar(x2), SkIntToScalar(y2)); path.close(); m_canvas->drawPath(path, paint); paint.setColor(m_edgeColor); paint.setStyle(SkPaint::kStroke_Style); m_canvas->drawPath(path, paint); }
// Creates a star type shape using a SkPath static SkPath create_star() { static const int kNumPoints = 5; SkPath concavePath; SkPoint points[kNumPoints] = {{0, SkIntToScalar(-50)} }; SkMatrix rot; rot.setRotate(SkIntToScalar(360) / kNumPoints); for (int i = 1; i < kNumPoints; ++i) { rot.mapPoints(points + i, points + i - 1, 1); } concavePath.moveTo(points[0]); for (int i = 0; i < kNumPoints; ++i) { concavePath.lineTo(points[(2 * i) % kNumPoints]); } concavePath.setFillType(SkPath::kEvenOdd_FillType); SkASSERT(!concavePath.isConvex()); concavePath.close(); return concavePath; }
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(); }
// An edge collapse event causes an edge to become collinear, requiring // its event to be removed. static SkPath create_path_26() { SkPath path; path.moveTo( 43.44110107421875, 148.15106201171875); path.lineTo( 44.64471435546875, 148.16748046875); path.lineTo( 46.35009765625, 147.403076171875); path.lineTo( 46.45404052734375, 148.34906005859375); path.lineTo( 45.0400390625, 148.54205322265625); path.lineTo( 44.624053955078125, 148.9810791015625); path.lineTo( 44.59405517578125, 149.16107177734375); path.lineTo( 44.877044677734375, 149.62005615234375); path.lineTo(144.373016357421875, 68.8070068359375); return path; }
// A path which contains out-of-range colinear intersections. static SkPath create_path_23() { SkPath path; path.moveTo( 0, 63.39080047607421875); path.lineTo(-0.70804601907730102539, 63.14350128173828125); path.lineTo(-7.8608899287380243391e-17, 64.14080047607421875); path.moveTo( 0, 64.14080047607421875); path.lineTo(44.285900115966796875, 64.14080047607421875); path.lineTo( 0, 62.64080047607421875); path.moveTo(21.434900283813476562, -0.24732701480388641357); path.lineTo(-0.70804601907730102539, 63.14350128173828125); path.lineTo(0.70804601907730102539, 63.6381988525390625); return path; }
static void test_nan_antihair() { SkBitmap bm; bm.allocN32Pixels(20, 20); SkCanvas canvas(bm); SkPath path; path.moveTo(0, 0); path.lineTo(10, SK_ScalarNaN); SkPaint paint; paint.setAntiAlias(true); paint.setStyle(SkPaint::kStroke_Style); // before our fix to SkScan_Antihair.cpp to check for integral NaN (0x800...) // this would trigger an assert/crash. // // see rev. 3558 canvas.drawPath(path, paint); }
// Handle the case where edge.dist(edge.fTop) != 0.0. static SkPath create_path_12() { SkPath path; path.moveTo( 0.0f, 400.0f); path.lineTo( 138.0f, 202.0f); path.lineTo( 0.0f, 202.0f); path.moveTo( 12.62693023681640625f, 250.57464599609375f); path.lineTo( 8.13896942138671875f, 254.556884765625f); path.lineTo(-18.15641021728515625f, 220.40203857421875f); path.lineTo(-15.986493110656738281f, 219.6513519287109375f); path.moveTo( 36.931194305419921875f, 282.485504150390625f); path.lineTo( 15.617521286010742188f, 261.2901611328125f); path.lineTo( 10.3829498291015625f, 252.565765380859375f); path.lineTo(-16.165292739868164062f, 222.646026611328125f); return path; }
static void testTightBoundsLines(PathOpsThreadState* data) { SkRandom ran; for (int index = 0; index < 1000; ++index) { SkPath path; int contourCount = ran.nextRangeU(1, 10); for (int cIndex = 0; cIndex < contourCount; ++cIndex) { int lineCount = ran.nextRangeU(1, 10); path.moveTo(ran.nextRangeF(-1000, 1000), ran.nextRangeF(-1000, 1000)); for (int lIndex = 0; lIndex < lineCount; ++lIndex) { path.lineTo(ran.nextRangeF(-1000, 1000), ran.nextRangeF(-1000, 1000)); } if (ran.nextBool()) { path.close(); } } SkRect classicBounds = path.getBounds(); SkRect tightBounds; REPORTER_ASSERT(data->fReporter, TightBounds(path, &tightBounds)); REPORTER_ASSERT(data->fReporter, classicBounds == tightBounds); } }
static sk_sp<SkPathEffect> make_pe(int flags, SkScalar phase) { if (flags == 1) { return SkCornerPathEffect::Make(SkIntToScalar(CORNER_RADIUS)); } SkPath path; path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1])); for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2) path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1])); path.close(); path.offset(SkIntToScalar(-6), 0); auto outer = SkPath1DPathEffect::Make(path, 12, phase, SkPath1DPathEffect::kRotate_Style); if (flags == 2) return outer; auto inner = SkCornerPathEffect::Make(SkIntToScalar(CORNER_RADIUS)); return SkComposePathEffect::Make(outer, inner); }
SkPath ValueTraits<ShapeValue>::As<SkPath>(const ShapeValue& shape) { SkPath path; if (!shape.fVertices.empty()) { // conservatively assume all cubics path.incReserve(1 + SkToU32(shape.fVertices.size() * 3)); path.moveTo(shape.fVertices.front().fVertex); } const auto& addCubic = [&](size_t from, size_t to) { const auto c0 = shape.fVertices[from].fVertex + shape.fVertices[from].fOutPoint, c1 = shape.fVertices[to].fVertex + shape.fVertices[to].fInPoint; if (c0 == shape.fVertices[from].fVertex && c1 == shape.fVertices[to].fVertex) { // If the control points are coincident, we can power-reduce to a straight line. // TODO: we could also do that when the controls are on the same line as the // vertices, but it's unclear how common that case is. path.lineTo(shape.fVertices[to].fVertex); } else { path.cubicTo(c0, c1, shape.fVertices[to].fVertex); } }; for (size_t i = 1; i < shape.fVertices.size(); ++i) { addCubic(i - 1, i); } if (!shape.fVertices.empty() && shape.fClosed) { addCubic(shape.fVertices.size() - 1, 0); path.close(); } path.setIsVolatile(shape.fVolatile); path.shrinkToFit(); return path; }
// TODO: expand the testing to include the different ops & AA types! static void emit_clip(SkCanvas* canvas, ClipType clip) { switch (clip) { case kNone_ClipType: break; case kRect_ClipType: { SkRect r = SkRect::MakeLTRB(10, 10, 90, 90); canvas->clipRect(r, SkRegion::kIntersect_Op, true); break; } case kRRect_ClipType: { SkRect r = SkRect::MakeLTRB(10, 10, 90, 90); SkRRect rr; rr.setRectXY(r, 10, 10); canvas->clipRRect(rr, SkRegion::kIntersect_Op, true); break; } case kPath_ClipType: { SkPath p; p.moveTo(5.0f, 5.0f); p.lineTo(50.0f, 50.0f); p.lineTo(100.0f, 5.0f); p.close(); canvas->clipPath(p, SkRegion::kIntersect_Op, true); break; } case kRegion_ClipType: { SkIRect rects[2] = { { 1, 1, 55, 55 }, { 45, 45, 99, 99 }, }; SkRegion r; r.setRects(rects, 2); canvas->clipRegion(r, SkRegion::kIntersect_Op); break; } default: SkASSERT(0); } }
int sk_test_multi_line(caskbench_context_t *ctx) { int w = ctx->canvas_width; int h = ctx->canvas_height; double x = (double)rnd()/RAND_MAX * w; double y = (double)rnd()/RAND_MAX * h; SkPath path; path.moveTo(x, y); for (int i=0; i<ctx->size; i++) { x = (double)rnd()/RAND_MAX * w; y = (double)rnd()/RAND_MAX * h; path.lineTo(x, y); } skiaRandomizePaintColor(ctx); ctx->skia_canvas->drawPath(path, *(ctx->skia_paint)); return 1; }
static SkPath make_path() { SkPath path; uint8_t numOps; fuzz->nextRange(&numOps, 0, 30); for (uint8_t i = 0; i < numOps; ++i) { uint8_t op; fuzz->nextRange(&op, 0, 5); SkScalar a, b, c, d, e, f; switch (op) { case 0: fuzz->next(&a, &b); path.moveTo(a, b); break; case 1: fuzz->next(&a, &b); path.lineTo(a, b); break; case 2: fuzz->next(&a, &b, &c, &d); path.quadTo(a, b, c, d); break; case 3: fuzz->next(&a, &b, &c, &d, &e); path.conicTo(a, b, c, d, e); break; case 4: fuzz->next(&a, &b, &c, &d, &e, &f); path.cubicTo(a, b, c, d, e, f); break; case 5: default: fuzz->next(&a, &b, &c, &d, &e); path.arcTo(a, b, c, d, e); break; } } path.close(); return path; }
// This test case including path coords and matrix taken from crbug.com/627443. // Because of inaccuracies in large floating point values this causes the // the path renderer to attempt to add a path DF to its atlas that is larger // than the plot size which used to crash rather than fail gracefully. static void test_far_from_origin(GrDrawContext* drawContext, GrPathRenderer* pr, GrResourceProvider* rp) { SkPath path; path.lineTo(49.0255089839f, 0.473541f); static constexpr SkScalar mvals[] = {14.0348252854f, 2.13026182736f, 13.6122547187f, 118.309922702f, 1912337682.09f, 2105391889.87f}; SkMatrix matrix; matrix.setAffine(mvals); SkMatrix inverse; SkAssertResult(matrix.invert(&inverse)); path.transform(inverse); SkStrokeRec rec(SkStrokeRec::kFill_InitStyle); rec.setStrokeStyle(1.f); rec.setStrokeParams(SkPaint::kRound_Cap, SkPaint::kRound_Join, 1.f); GrStyle style(rec, nullptr); GrShape shape(path, style); shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, 1.f); GrPaint paint; paint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode)); GrNoClip noClip; GrPathRenderer::DrawPathArgs args; args.fPaint = &paint; args.fUserStencilSettings = &GrUserStencilSettings::kUnused; args.fDrawContext = drawContext; args.fClip = &noClip; args.fResourceProvider = rp; args.fViewMatrix = &matrix; args.fShape = &shape; args.fAntiAlias = true; args.fGammaCorrect = false; args.fColor = 0x0; pr->drawPath(args); }
void onDraw(SkCanvas* canvas) override { SkRect r = { 10, 10, 100, 60 }; SkPath path; path.addRect(r); test_rev(canvas, path); canvas->translate(0, 100); path.offset(20, 20); path.addRect(r); test_rev(canvas, path); canvas->translate(0, 100); path.reset(); path.moveTo(10, 10); path.lineTo(30, 30); path.addOval(r); r.offset(50, 20); path.addOval(r); test_rev(canvas, path); path = hiragino_maru_goth_pro_e(); canvas->translate(0, 100); test_rev(canvas, path); }
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); }
static void dontFailOne(skiatest::Reporter* reporter, int index) { SkPath path; int f = (int) (index % finitePtsCount); int g = (int) ((f + 1) % finitePtsCount); switch (index % 11) { case 0: path.lineTo(finitePts[f]); break; case 1: path.quadTo(finitePts[f], finitePts[f]); break; case 2: path.quadTo(finitePts[f], finitePts[g]); break; case 3: path.quadTo(finitePts[g], finitePts[f]); break; case 4: path.cubicTo(finitePts[f], finitePts[f], finitePts[f]); break; case 5: path.cubicTo(finitePts[f], finitePts[f], finitePts[g]); break; case 6: path.cubicTo(finitePts[f], finitePts[g], finitePts[f]); break; case 7: path.cubicTo(finitePts[f], finitePts[g], finitePts[g]); break; case 8: path.cubicTo(finitePts[g], finitePts[f], finitePts[f]); break; case 9: path.cubicTo(finitePts[g], finitePts[f], finitePts[g]); break; case 10: path.moveTo(finitePts[f]); break; } SkPath result; result.setFillType(SkPath::kWinding_FillType); bool success = Simplify(path, &result); REPORTER_ASSERT(reporter, success); REPORTER_ASSERT(reporter, result.getFillType() != SkPath::kWinding_FillType); reporter->bumpTestCount(); }
void SkTestFont::init(const SkScalar* pts, const unsigned char* verbs) { fPaths = new SkPath* [fCharCodesCount]; for (unsigned index = 0; index < fCharCodesCount; ++index) { SkPath* path = new SkPath; SkPath::Verb verb; while ((verb = (SkPath::Verb) *verbs++) != SkPath::kDone_Verb) { switch (verb) { case SkPath::kMove_Verb: path->moveTo(pts[0], pts[1]); pts += 2; break; case SkPath::kLine_Verb: path->lineTo(pts[0], pts[1]); pts += 2; break; case SkPath::kQuad_Verb: path->quadTo(pts[0], pts[1], pts[2], pts[3]); pts += 4; break; case SkPath::kCubic_Verb: path->cubicTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]); pts += 6; break; case SkPath::kClose_Verb: path->close(); break; default: SkDEBUGFAIL("bad verb"); return; } } // This should make SkPath::getBounds() queries threadsafe. path->updateBoundsCache(); fPaths[index] = path; } }
PathIterBench(bool raw) { fName.printf("pathiter_%s", raw ? "raw" : "consume"); fRaw = raw; SkRandom rand; for (int i = 0; i < 1000; ++i) { SkPoint pts[4]; int n = rand_pts(rand, pts); switch (n) { case 1: fPath.moveTo(pts[0]); break; case 2: fPath.lineTo(pts[1]); break; case 3: fPath.quadTo(pts[1], pts[2]); break; case 4: fPath.cubicTo(pts[1], pts[2], pts[3]); break; } } }
static void test_stroke(SkCanvas* canvas) { if (true) { SkPath path; dump(path); path.reset(); path.moveTo(0, 0); dump(path); path.reset(); path.moveTo(100, 100); dump(path); path.reset(); path.moveTo(0, 0); path.moveTo(100, 100); dump(path); path.reset(); path.moveTo(0, 0); path.lineTo(100, 100); dump(path); path.reset(); path.moveTo(0, 0); path.lineTo(100, 100); path.moveTo(200, 200); dump(path); } #if 0 // TEST 1 - The rectangle as it's expected to look var canvas = document.createElement('canvas'); document.body.appendChild(canvas); var ctx = canvas.getContext("2d"); #else SkJSCanvas ctx(canvas); #endif ctx.save(); ctx.lineWidth = 2; ctx.beginPath(); ctx.moveTo(10, 100); ctx.lineTo(150, 100); ctx.lineTo(150, 15); ctx.lineTo(10, 15); ctx.closePath(); // no extra moveTo here // ctx.moveTo(175, 125); ctx.stroke(); ctx.restore(); ctx.fillText("As Expected", 10, 10); #if 0 // TEST 2 - Includes an extra moveTo call before stroke; the rectangle appears larger canvas = document.createElement('canvas'); document.body.appendChild(canvas); ctx = canvas.getContext("2d"); #else canvas->translate(200, 0); #endif ctx.save(); ctx.lineWidth = 2; ctx.beginPath(); ctx.moveTo(10, 100); ctx.lineTo(150, 100); ctx.lineTo(150, 15); ctx.lineTo(10, 15); ctx.closePath(); ctx.moveTo(175, 125); ctx.stroke(); ctx.restore(); ctx.fillText("Larger Rectangle", 10, 10); #if 0 // TEST 3 - Identical to test 2 except the line width is 1 canvas = document.createElement('canvas'); document.body.appendChild(canvas); ctx = canvas.getContext("2d"); #else canvas->translate(200, 0); #endif ctx.save(); ctx.lineWidth = 1; ctx.beginPath(); ctx.moveTo(10, 100); ctx.lineTo(150, 100); ctx.lineTo(150, 15); ctx.lineTo(10, 15); ctx.closePath(); ctx.moveTo(175, 125); ctx.stroke(); ctx.restore(); ctx.fillText("As Expected - line width 1", 10, 10); }
void SkJSCanvas::lineTo(double x, double y) { fPath.lineTo(SkDoubleToScalar(x), SkDoubleToScalar(y)); }
void onDrawContent(SkCanvas* canvas) override { SkPaint paintFill; SkPaint paintStroke; SkPath path; canvas->save(); canvas->translate(150, 150); canvas->scale(0.4f, 0.4f); canvas->rotate(-180.f/2.f); paintFill.setAntiAlias(true); paintFill.setColor(SK_ColorBLACK); paintStroke.setAntiAlias(true); paintStroke.setStyle(SkPaint::kStroke_Style); paintStroke.setColor(SK_ColorBLACK); paintStroke.setStrokeWidth(8); paintStroke.setStrokeCap(SkPaint::kRound_Cap); // Hour marks SkRect rect; #ifndef USE_PATH rect = SkRect::MakeLTRB(200-4, -4, 240+4, 4); SkRRect rrect; SkVector radii[4] = {{4,4}, {4,4}, {4,4}, {4,4}}; rrect.setRectRadii(rect, radii); #endif canvas->save(); for (int i=0;i<12;i++){ canvas->rotate(180.f/6.f); #ifdef USE_PATH path.reset(); path.moveTo(200,0); path.lineTo(240,0); canvas->drawPath(path, paintStroke); #else canvas->drawRRect(rrect, paintFill); #endif } canvas->restore(); // Minute marks canvas->save(); #ifdef USE_PATH paintStroke.setStrokeWidth(5); #else rect = SkRect::MakeLTRB(231.5f, -2.5f, 242.5, 2.5f); radii[0] = SkPoint::Make(2.5f,2.5f); radii[1] = SkPoint::Make(2.5f,2.5f); radii[2] = SkPoint::Make(2.5f,2.5f); radii[3] = SkPoint::Make(2.5f,2.5f); rrect.setRectRadii(rect, radii); #endif for (int i=0;i<60;i++){ if (i%5 == 0) { canvas->rotate(180.f/30.f); continue; } #ifdef USE_PATH path.reset(); path.moveTo(234,0); path.lineTo(240,0); canvas->drawPath(path, paintStroke); #else canvas->drawRRect(rrect, paintFill); #endif canvas->rotate(180.f/30.f); } canvas->restore(); SkTime::DateTime time; SkTime::GetDateTime(&time); time.fHour = time.fHour >= 12 ? time.fHour-12 : time.fHour; paintFill.setColor(SK_ColorBLACK); // Write hours canvas->save(); canvas->rotate(time.fHour*(180.f/6.f) + time.fMinute*(180.f/360.f) + time.fSecond*(180.f/21600.f) ); #ifdef USE_PATH paintStroke.setStrokeWidth(14); path.reset(); path.moveTo(-20,0); path.lineTo(80,0); canvas->drawPath(path, paintStroke); #else rect = SkRect::MakeLTRB(-20-7, -7, 80+7, 7); radii[0] = SkPoint::Make(7,7); radii[1] = SkPoint::Make(7,7); radii[2] = SkPoint::Make(7,7); radii[3] = SkPoint::Make(7,7); rrect.setRectRadii(rect, radii); canvas->drawRRect(rrect, paintFill); #endif canvas->restore(); // Write minutes canvas->save(); canvas->rotate(time.fMinute*(180.f/30.f) + time.fSecond*(180.f/1800.f) ); #ifdef USE_PATH paintStroke.setStrokeWidth(10); path.reset(); path.moveTo(-56,0); path.lineTo(224,0); canvas->drawPath(path, paintStroke); #else rect = SkRect::MakeLTRB(-56-5, -5, 224+5, 5); radii[0] = SkPoint::Make(5,5); radii[1] = SkPoint::Make(5,5); radii[2] = SkPoint::Make(5,5); radii[3] = SkPoint::Make(5,5); rrect.setRectRadii(rect, radii); canvas->drawRRect(rrect, paintFill); #endif canvas->restore(); // Write seconds canvas->save(); canvas->rotate(time.fSecond*(180.f/30.f)); paintFill.setColor(0xffd40000); paintStroke.setColor(0xffd40000); paintStroke.setStrokeWidth(6); #ifdef USE_PATH path.reset(); path.moveTo(-60,0); path.lineTo(166,0); canvas->drawPath(path, paintStroke); #else rect = SkRect::MakeLTRB(-60-3, -3, 166+3, 3); radii[0] = SkPoint::Make(3,3); radii[1] = SkPoint::Make(3,3); radii[2] = SkPoint::Make(3,3); radii[3] = SkPoint::Make(3,3); rrect.setRectRadii(rect, radii); canvas->drawRRect(rrect, paintFill); #endif rect = SkRect::MakeLTRB(-20, -20, 20, 20); #ifdef USE_PATH path.reset(); path.arcTo(rect, 0, 0, false); path.addOval(rect, SkPath::kCCW_Direction); path.arcTo(rect, 360, 0, true); canvas->drawPath(path, paintFill); #else canvas->drawOval(rect, paintFill); #endif rect = SkRect::MakeLTRB(-20+190, -20, 20+190, 20); #ifdef USE_PATH path.reset(); path.arcTo(rect, 0, 0, false); path.addOval(rect, SkPath::kCCW_Direction); path.arcTo(rect, 360, 0, true); canvas->drawPath(path, paintStroke); #else canvas->drawOval(rect, paintStroke); #endif paintFill.setColor(0xff505050); #ifdef USE_PATH rect = SkRect::MakeLTRB(-6, -6, 6, 6); path.arcTo(rect, 0, 0, false); path.addOval(rect, SkPath::kCCW_Direction); path.arcTo(rect, 360, 0, true); canvas->drawPath(path, paintFill); #else canvas->drawOval(rect, paintFill); rect = SkRect::MakeLTRB(-6, -6, 6, 6); canvas->drawOval(rect, paintFill); #endif canvas->restore(); paintStroke.setStrokeWidth(18); paintStroke.setColor(0xff325FA2); rect = SkRect::MakeLTRB(-284, -284, 284, 284); #ifdef USE_PATH path.reset(); path.arcTo(rect, 0, 0, false); path.addOval(rect, SkPath::kCCW_Direction); path.arcTo(rect, 360, 0, true); canvas->drawPath(path, paintStroke); #else canvas->drawOval(rect, paintStroke); #endif canvas->restore(); this->inval(nullptr); }
static void do_fuzz(SkCanvas* canvas) { SkPath path; SkPaint paint; paint.setAntiAlias(true); for (int i=0;i<100;i++) { switch (R(33)) { case 0: paint.setColor(make_fill()); break; case 1: paint.setAlpha(gRand.nextU() & 0xFF); break; case 2: { SkXfermode::Mode mode; switch (R(3)) { case 0: mode = SkXfermode::kSrc_Mode; break; case 1: mode = SkXfermode::kXor_Mode; break; case 2: default: // silence warning mode = SkXfermode::kSrcOver_Mode; break; } paint.setXfermodeMode(mode); } break; case 3: switch (R(2)) { case 0: paint.setStrokeCap(SkPaint::kRound_Cap); break; case 1: paint.setStrokeCap(SkPaint::kButt_Cap); break; } break; case 4: switch (R(2)) { case 0: paint.setStrokeJoin(SkPaint::kRound_Join); break; case 1: paint.setStrokeJoin(SkPaint::kMiter_Join); break; } break; case 5: paint.setStrokeWidth(make_number()); break; case 6: paint.setStrokeMiter(make_number()); break; case 7: if (quick == true) break; SkSafeUnref(paint.setMaskFilter(SkBlurMaskFilter::Create(kNormal_SkBlurStyle, make_number()))); break; case 8: if (quick == true) break; //ctx.shadowColor = make_fill(); break; case 9: if (quick == true) break; //ctx.shadowOffsetX = make_number(); //ctx.shadowOffsetY = make_number(); break; case 10: canvas->restore(); break; case 11: canvas->rotate(make_number()); break; case 12: canvas->save(); break; case 13: canvas->scale(-1,-1); break; case 14: if (quick == true) break; if (transval == 0) { transval = make_number(); canvas->translate(transval,0); } else { canvas->translate(-transval,0); transval = 0; } break; case 15: { SkRect r; r.set(make_number(),make_number(),make_number(),make_number()); SkPaint::Style s = paint.getStyle(); paint.setStyle(SkPaint::kFill_Style); canvas->drawRect(r, paint); paint.setStyle(s); // clearrect } break; case 16: if (quick == true) break; // ctx.drawImage(imgObj,make_number(),make_number(),make_number(),make_number(),make_number(),make_number(),make_number(),make_number()); break; case 17: { SkRect r; r.set(make_number(),make_number(),make_number(),make_number()); SkPaint::Style s = paint.getStyle(); paint.setStyle(SkPaint::kFill_Style); canvas->drawRect(r, paint); paint.setStyle(s); } break; case 18: path.reset(); break; case 19: // ctx.clip() is evil. break; case 20: path.close(); break; case 21: { SkPaint::Style s = paint.getStyle(); paint.setStyle(SkPaint::kFill_Style); canvas->drawPath(path, paint); paint.setStyle(s); } break; case 22: { SkPaint::Style s = paint.getStyle(); paint.setStyle(SkPaint::kFill_Style); canvas->drawPath(path, paint); paint.setStyle(s); } break; case 23: { SkRect r; r.set(make_number(),make_number(),make_number(),make_number()); SkPaint::Style s = paint.getStyle(); paint.setStyle(SkPaint::kStroke_Style); canvas->drawRect(r, paint); paint.setStyle(s); } break; case 24: if (quick == true) break; //ctx.arc(make_number(),make_number(),make_number(),make_number(),make_number(),true); break; case 25: if (quick == true) break; //ctx.arcTo(make_number(),make_number(),make_number(),make_number(),make_number()); break; case 26: if (quick == true) break; //ctx.bezierCurveTo(make_number(),make_number(),make_number(),make_number(),make_number(),make_number()); break; case 27: path.lineTo(make_number(),make_number()); break; case 28: path.moveTo(make_number(),make_number()); break; case 29: if (quick == true) break; path.quadTo(make_number(),make_number(),make_number(),make_number()); break; case 30: { if (quick == true) break; SkMatrix matrix; set2x3(&matrix, make_number(),make_number(),make_number(),make_number(),make_number(),make_number()); canvas->concat(matrix); } break; case 31: { if (quick == true) break; SkMatrix matrix; set2x3(&matrix, make_number(),make_number(),make_number(),make_number(),make_number(),make_number()); canvas->setMatrix(matrix); } break; case 32: if (scale_large == true) { switch (scval) { case 0: canvas->scale(-1000000000,1); canvas->scale(-1000000000,1); scval = 1; break; case 1: canvas->scale(-.000000001f,1); scval = 2; break; case 2: canvas->scale(-.000000001f,1); scval = 0; break; } } break; } } }
static void draw_vector_logo(SkCanvas* canvas, const SkRect& viewBox) { constexpr char kSkiaStr[] = "SKIA"; constexpr SkScalar kGradientPad = .1f; constexpr SkScalar kVerticalSpacing = 0.25f; constexpr SkScalar kAccentScale = 1.20f; SkPaint paint; paint.setAntiAlias(true); paint.setSubpixelText(true); paint.setFakeBoldText(true); sk_tool_utils::set_portable_typeface(&paint); SkPath path; SkRect iBox, skiBox, skiaBox; paint.getTextPath("SKI", 3, 0, 0, &path); TightBounds(path, &skiBox); paint.getTextPath("I", 1, 0, 0, &path); TightBounds(path, &iBox); iBox.offsetTo(skiBox.fRight - iBox.width(), iBox.fTop); const size_t textLen = strlen(kSkiaStr); paint.getTextPath(kSkiaStr, textLen, 0, 0, &path); TightBounds(path, &skiaBox); skiaBox.outset(0, 2 * iBox.width() * (kVerticalSpacing + 1)); const SkScalar accentSize = iBox.width() * kAccentScale; const SkScalar underlineY = iBox.bottom() + (kVerticalSpacing + SkScalarSqrt(3) / 2) * accentSize; SkMatrix m; m.setRectToRect(skiaBox, viewBox, SkMatrix::kFill_ScaleToFit); SkAutoCanvasRestore acr(canvas, true); canvas->concat(m); canvas->drawCircle(iBox.centerX(), iBox.y() - (0.5f + kVerticalSpacing) * accentSize, accentSize / 2, paint); path.reset(); path.moveTo(iBox.centerX() - accentSize / 2, iBox.bottom() + kVerticalSpacing * accentSize); path.rLineTo(accentSize, 0); path.lineTo(iBox.centerX(), underlineY); canvas->drawPath(path, paint); SkRect underlineRect = SkRect::MakeLTRB(iBox.centerX() - iBox.width() * accentSize * 3, underlineY, iBox.centerX(), underlineY + accentSize / 10); const SkPoint pts1[] = { SkPoint::Make(underlineRect.x(), 0), SkPoint::Make(iBox.centerX(), 0) }; const SkScalar pos1[] = { 0, 0.75f }; const SkColor colors1[] = { SK_ColorTRANSPARENT, SK_ColorBLACK }; SkASSERT(SK_ARRAY_COUNT(pos1) == SK_ARRAY_COUNT(colors1)); paint.setShader(SkGradientShader::MakeLinear(pts1, colors1, pos1, SK_ARRAY_COUNT(pos1), SkShader::kClamp_TileMode)); canvas->drawRect(underlineRect, paint); const SkPoint pts2[] = { SkPoint::Make(iBox.x() - iBox.width() * kGradientPad, 0), SkPoint::Make(iBox.right() + iBox.width() * kGradientPad, 0) }; const SkScalar pos2[] = { 0, .01f, 1.0f/3, 1.0f/3, 2.0f/3, 2.0f/3, .99f, 1 }; const SkColor colors2[] = { SK_ColorBLACK, 0xffca5139, 0xffca5139, 0xff8dbd53, 0xff8dbd53, 0xff5460a5, 0xff5460a5, SK_ColorBLACK }; SkASSERT(SK_ARRAY_COUNT(pos2) == SK_ARRAY_COUNT(colors2)); paint.setShader(SkGradientShader::MakeLinear(pts2, colors2, pos2, SK_ARRAY_COUNT(pos2), SkShader::kClamp_TileMode)); canvas->drawText(kSkiaStr, textLen, 0, 0, paint); }