void draw(SkCanvas* canvas) { SkPaint paint; SkPath path; paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(4); path.moveTo(0, 0); path.arcTo({20, 20, 120, 120}, -90, 90, false); canvas->drawPath(path, paint); path.rewind(); path.arcTo({120, 20, 220, 120}, -90, 90, false); canvas->drawPath(path, paint); path.rewind(); path.moveTo(0, 0); path.arcTo({20, 120, 120, 220}, -90, 90, true); canvas->drawPath(path, paint); }
PathTexture* PathCache::getArc(float width, float height, float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) { PathDescription entry(kShapeArc, paint); entry.shape.arc.mWidth = width; entry.shape.arc.mHeight = height; entry.shape.arc.mStartAngle = startAngle; entry.shape.arc.mSweepAngle = sweepAngle; entry.shape.arc.mUseCenter = useCenter; PathTexture* texture = get(entry); if (!texture) { SkPath path; SkRect r; r.set(0.0f, 0.0f, width, height); if (useCenter) { path.moveTo(r.centerX(), r.centerY()); } path.arcTo(r, startAngle, sweepAngle, !useCenter); if (useCenter) { path.close(); } texture = addTexture(entry, &path, paint); } return texture; }
static SkPath make_path() { SkPath path; int numOps = R(30); for (int i = 0; i < numOps; ++i) { switch (R(6)) { case 0: path.moveTo(make_scalar(), make_scalar()); break; case 1: path.lineTo(make_scalar(), make_scalar()); break; case 2: path.quadTo(make_scalar(), make_scalar(), make_scalar(), make_scalar()); break; case 3: path.conicTo(make_scalar(), make_scalar(), make_scalar(), make_scalar(), make_scalar()); break; case 4: path.cubicTo(make_scalar(), make_scalar(), make_scalar(), make_scalar(), make_scalar(), make_scalar()); break; case 5: default: path.arcTo(make_scalar(), make_scalar(), make_scalar(), make_scalar(), make_scalar()); break; } } path.close(); return path; }
static void draw_sweep(SkCanvas* c, int width, int height, SkScalar angle) { SkRect r; SkPaint p; p.setAntiAlias(true); // p.setDither(true); p.setStrokeWidth(SkIntToScalar(width/10)); p.setStyle(SkPaint::kStroke_Style); r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height)); // SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN, SK_ColorCYAN }; SkColor colors[] = { 0x4c737373, 0x4c737373, 0xffffd300 }; SkShader* s = SkGradientShader::CreateSweep(r.centerX(), r.centerY(), colors, NULL, SK_ARRAY_COUNT(colors)); p.setShader(s)->unref(); SkAutoCanvasRestore acr(c, true); c->translate(r.centerX(), r.centerY()); c->rotate(angle); c->translate(-r.centerX(), -r.centerY()); SkRect bounds = r; r.inset(p.getStrokeWidth(), p.getStrokeWidth()); SkRect innerBounds = r; if (true) { c->drawOval(r, p); } else { SkScalar x = r.centerX(); SkScalar y = r.centerY(); SkScalar radius = r.width() / 2; SkScalar thickness = p.getStrokeWidth(); SkScalar sweep = SkFloatToScalar(360.0f); SkPath path; path.moveTo(x + radius, y); // outer top path.lineTo(x + radius + thickness, y); // outer arc path.arcTo(bounds, 0, sweep, false); // inner arc path.arcTo(innerBounds, sweep, -sweep, false); path.close(); } }
void mbe_arc(mbe_t *mbe, co_aix x, co_aix y, co_aix radius, co_aix angle_start, co_aix angle_stop) { SkPoint point; SkPath *subpath = mbe->subpath; SkRect rect; SkScalar x0, y0; SkScalar ang_start, ang_stop; SkScalar sweep; SkScalar r; /* radius */ subpath->getLastPt(&point); x0 = point.fX; y0 = point.fX; r = CO_AIX_2_SKSCALAR(radius); ang_start = CO_AIX_2_SKSCALAR(angle_start * 180 / PI); ang_stop = CO_AIX_2_SKSCALAR(angle_stop * 180 / PI); /* Skia can only draw an arc in clockwise directly. We negative * start and stop point to draw the arc in the mirror along x-axis * in a sub-path. Then, the sub-path are reflected along x-axis, * again. We get a right path, and add it to the path of mbe_t. */ if(ang_start > ang_stop) { SkPath tmppath; SkMatrix matrix; co_aix reflect[6] = { 1, 0, 0, 0, -1, 0}; rect.set(-r, -r, r, r); sweep = ang_start - ang_stop; tmppath.arcTo(rect, -ang_start, sweep, false); reflect[2] = x; reflect[5] = y; MB_MATRIX_2_SKMATRIX(matrix, reflect); subpath->addPath(tmppath, matrix); } else { rect.set(x0 - r, y0 - r, x0 + r, y0 + r); sweep = ang_stop - ang_start; subpath->arcTo(rect, ang_start, sweep, false); } }
static void fuzz_drawPath(Fuzz* fuzz) { SkPaint p; init_paint(fuzz, &p); sk_sp<SkSurface> surface; init_surface(fuzz, &surface); // TODO(kjlubick): put the ability to fuzz a path in shared file, with // other common things (e.g. rects, lines) uint8_t i, j; fuzz->nextRange(&i, 0, 10); // set i to number of operations to perform SkPath path; SkScalar a, b, c, d, e, f; for (int k = 0; k < i; ++k) { fuzz->nextRange(&j, 0, 5); // set j to choose operation to perform switch (j) { 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: fuzz->next(&a, &b, &c, &d, &e); path.arcTo(a, b, c, d, e); break; } } path.close(); SkCanvas* cnv = surface->getCanvas(); cnv->drawPath(path, p); bool bl; fuzz->next(&bl); cnv->clipPath(path, kIntersect_SkClipOp, bl); }
void draw(SkCanvas* canvas) { const char* verbNames[] = { "move", "line", "quad", "conic", "cubic", "close", "done" }; const int pointCount[] = { 1 , 2 , 3 , 3 , 4 , 1 , 0 }; SkPath path; path.arcTo(20, 0, 20, 20, 20); SkPath::Iter iter(path, false); SkPath::Verb verb; do { SkPoint points[4]; verb = iter.next(points); SkDebugf("%s ", verbNames[(int) verb]); for (int i = 0; i < pointCount[(int) verb]; ++i) { SkDebugf("{%g, %g}, ", points[i].fX, points[i].fY); } if (SkPath::kConic_Verb == verb) { SkDebugf("weight = %g", iter.conicWeight()); } SkDebugf("\n"); } while (SkPath::kDone_Verb != verb); }
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; }
PathTexture* ArcShapeCache::getArc(float width, float height, float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) { ArcShapeCacheEntry entry(width, height, startAngle, sweepAngle, useCenter, paint); PathTexture* texture = get(entry); if (!texture) { SkPath path; SkRect r; r.set(0.0f, 0.0f, width, height); if (useCenter) { path.moveTo(r.centerX(), r.centerY()); } path.arcTo(r, startAngle, sweepAngle, !useCenter); if (useCenter) { path.close(); } texture = addTexture(entry, &path, paint); } return texture; }
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); }
virtual void onDrawContent(SkCanvas* canvas) { const char text[] = "Shaded Text"; const int textLen = SK_ARRAY_COUNT(text) - 1; static int pointSize = 36; int w = pointSize * textLen; int h = pointSize; SkPoint pts[2] = { { 0, 0 }, { SkIntToScalar(w), SkIntToScalar(h) } }; SkScalar textBase = SkIntToScalar(h/2); SkShader::TileMode tileModes[] = { SkShader::kClamp_TileMode, SkShader::kRepeat_TileMode, SkShader::kMirror_TileMode }; static const int gradCount = SK_ARRAY_COUNT(gGradData) * SK_ARRAY_COUNT(gGradMakers); static const int bmpCount = SK_ARRAY_COUNT(tileModes) * SK_ARRAY_COUNT(tileModes); SkShader* shaders[gradCount + bmpCount]; int shdIdx = 0; for (size_t d = 0; d < SK_ARRAY_COUNT(gGradData); ++d) { for (size_t m = 0; m < SK_ARRAY_COUNT(gGradMakers); ++m) { shaders[shdIdx++] = gGradMakers[m](pts, gGradData[d], SkShader::kClamp_TileMode); } } for (size_t tx = 0; tx < SK_ARRAY_COUNT(tileModes); ++tx) { for (size_t ty = 0; ty < SK_ARRAY_COUNT(tileModes); ++ty) { shaders[shdIdx++] = MakeBitmapShader(tileModes[tx], tileModes[ty], w/8, h); } } SkPaint paint; paint.setDither(true); paint.setAntiAlias(true); paint.setTextSize(SkIntToScalar(pointSize)); canvas->save(); canvas->translate(SkIntToScalar(20), SkIntToScalar(10)); SkPath path; path.arcTo(SkRect::MakeXYWH(SkIntToScalar(-40), SkIntToScalar(15), SkIntToScalar(300), SkIntToScalar(90)), SkIntToScalar(225), SkIntToScalar(90), false); path.close(); static const int testsPerCol = 8; static const int rowHeight = 60; static const int colWidth = 300; canvas->save(); for (size_t s = 0; s < SK_ARRAY_COUNT(shaders); s++) { canvas->save(); size_t i = 2*s; canvas->translate(SkIntToScalar((i / testsPerCol) * colWidth), SkIntToScalar((i % testsPerCol) * rowHeight)); paint.setShader(shaders[s])->unref(); canvas->drawText(text, textLen, 0, textBase, paint); canvas->restore(); canvas->save(); ++i; canvas->translate(SkIntToScalar((i / testsPerCol) * colWidth), SkIntToScalar((i % testsPerCol) * rowHeight)); canvas->drawTextOnPath(text, textLen, path, NULL, paint); canvas->restore(); } canvas->restore(); }
void onDraw(SkCanvas* canvas) override { static const char kText[] = "SKIA"; static const int kTextLen = SK_ARRAY_COUNT(kText) - 1; static const int kPointSize = 55; SkTDArray<LabeledMatrix> matrices; matrices.append()->fMatrix.reset(); matrices.top().fLabel = "Identity"; matrices.append()->fMatrix.setScale(1.2f, 0.8f); matrices.top().fLabel = "Scale"; matrices.append()->fMatrix.setRotate(10.f); matrices.top().fLabel = "Rotate"; matrices.append()->fMatrix.reset(); matrices.top().fMatrix.setPerspX(-0.0015f); matrices.top().fMatrix.setPerspY(+0.0015f); matrices.top().fLabel = "Persp"; SkTDArray<LabeledMatrix> localMatrices; localMatrices.append()->fMatrix.reset(); localMatrices.top().fLabel = "Identity"; localMatrices.append()->fMatrix.setScale(2.5f, 0.2f); localMatrices.top().fLabel = "Scale"; localMatrices.append()->fMatrix.setRotate(45.f); localMatrices.top().fLabel = "Rotate"; localMatrices.append()->fMatrix.reset(); localMatrices.top().fMatrix.setPerspX(-0.007f); localMatrices.top().fMatrix.setPerspY(+0.008f); localMatrices.top().fLabel = "Persp"; static SkBitmap bmp; if (bmp.isNull()) { makebm(&bmp, kPointSize / 2, kPointSize / 2); } SkPaint fillPaint; fillPaint.setAntiAlias(true); sk_tool_utils::set_portable_typeface_always(&fillPaint); fillPaint.setTextSize(SkIntToScalar(kPointSize)); fillPaint.setFilterQuality(kLow_SkFilterQuality); SkPaint outlinePaint; outlinePaint.setAntiAlias(true); sk_tool_utils::set_portable_typeface_always(&outlinePaint); outlinePaint.setTextSize(SkIntToScalar(kPointSize)); outlinePaint.setStyle(SkPaint::kStroke_Style); outlinePaint.setStrokeWidth(0.f); SkScalar w = fillPaint.measureText(kText, kTextLen); static SkScalar kPadY = 0.5f * kPointSize; static SkScalar kPadX = 1.5f * kPointSize; SkPaint strokePaint(fillPaint); strokePaint.setStyle(SkPaint::kStroke_Style); strokePaint.setStrokeWidth(kPointSize * 0.1f); SkPaint labelPaint; labelPaint.setColor(0xff000000); labelPaint.setAntiAlias(true); sk_tool_utils::set_portable_typeface_always(&labelPaint); labelPaint.setTextSize(12.f); canvas->translate(15.f, 15.f); canvas->drawBitmap(bmp, 0, 0); canvas->translate(0, bmp.height() + labelPaint.getTextSize() + 15.f); static const char kLabelLabel[] = "localM / canvasM"; canvas->drawText(kLabelLabel, strlen(kLabelLabel), 0, 0, labelPaint); canvas->translate(0, 15.f); canvas->save(); SkScalar maxLabelW = 0; canvas->translate(0, kPadY / 2 + kPointSize); for (int lm = 0; lm < localMatrices.count(); ++lm) { canvas->drawText(matrices[lm].fLabel, strlen(matrices[lm].fLabel), 0, labelPaint.getTextSize() - 1, labelPaint); SkScalar labelW = labelPaint.measureText(matrices[lm].fLabel, strlen(matrices[lm].fLabel)); maxLabelW = SkMaxScalar(maxLabelW, labelW); canvas->translate(0.f, 2 * kPointSize + 2.5f * kPadY); } canvas->restore(); canvas->translate(maxLabelW + kPadX / 2.f, 0.f); for (int s = 0; s < 2; ++s) { SkPaint& paint = s ? strokePaint : fillPaint; SkScalar columnH = 0; for (int m = 0; m < matrices.count(); ++m) { columnH = 0; canvas->save(); canvas->drawText(matrices[m].fLabel, strlen(matrices[m].fLabel), 0, labelPaint.getTextSize() - 1, labelPaint); canvas->translate(0, kPadY / 2 + kPointSize); columnH += kPadY / 2 + kPointSize; for (int lm = 0; lm < localMatrices.count(); ++lm) { paint.setShader( SkShader::CreateBitmapShader(bmp, SkShader::kMirror_TileMode, SkShader::kRepeat_TileMode, &localMatrices[lm].fMatrix))->unref(); canvas->save(); canvas->concat(matrices[m].fMatrix); canvas->drawText(kText, kTextLen, 0, 0, paint); canvas->drawText(kText, kTextLen, 0, 0, outlinePaint); canvas->restore(); SkPath path; path.arcTo(SkRect::MakeXYWH(-0.1f * w, 0.f, 1.2f * w, 2.f * kPointSize), 225.f, 359.f, false); path.close(); canvas->translate(0.f, kPointSize + kPadY); columnH += kPointSize + kPadY; canvas->save(); canvas->concat(matrices[m].fMatrix); canvas->drawTextOnPath(kText, kTextLen, path, NULL, paint); canvas->drawTextOnPath(kText, kTextLen, path, NULL, outlinePaint); canvas->restore(); SkPaint stroke; stroke.setStyle(SkPaint::kStroke_Style); canvas->translate(0.f, kPointSize + kPadY); columnH += kPointSize + kPadY; } canvas->restore(); canvas->translate(w + kPadX, 0.f); } if (0 == s) { canvas->drawLine(0.f, -kPadY, 0.f, columnH + kPadY, outlinePaint); canvas->translate(kPadX / 2, 0.f); static const char kFillLabel[] = "Filled"; static const char kStrokeLabel[] = "Stroked"; SkScalar y = columnH + kPadY / 2; SkScalar fillX = -outlinePaint.measureText(kFillLabel, strlen(kFillLabel)) - kPadX; SkScalar strokeX = kPadX; canvas->drawText(kFillLabel, strlen(kFillLabel), fillX, y, labelPaint); canvas->drawText(kStrokeLabel, strlen(kStrokeLabel), strokeX, y, labelPaint); } } }
SkPath makePath() { SkPath path; for (uint32_t cIndex = 0; cIndex < fPathContourCount; ++cIndex) { uint32_t segments = makeSegmentCount(); for (uint32_t sIndex = 0; sIndex < segments; ++sIndex) { RandomAddPath addPathType = makeAddPathType(); ++fAddCount; if (fPrintName) { SkDebugf("%.*s%s\n", fPathDepth * 3, fTab, gRandomAddPathNames[addPathType]); } switch (addPathType) { case kAddArc: { SkRect oval = makeRect(); SkScalar startAngle = makeAngle(); SkScalar sweepAngle = makeAngle(); path.addArc(oval, startAngle, sweepAngle); validate(path); } break; case kAddRoundRect1: { SkRect rect = makeRect(); SkScalar rx = makeScalar(), ry = makeScalar(); SkPath::Direction dir = makeDirection(); path.addRoundRect(rect, rx, ry, dir); validate(path); } break; case kAddRoundRect2: { SkRect rect = makeRect(); SkScalar radii[8]; makeScalarArray(SK_ARRAY_COUNT(radii), radii); SkPath::Direction dir = makeDirection(); path.addRoundRect(rect, radii, dir); validate(path); } break; case kAddRRect: { SkRRect rrect = makeRRect(); SkPath::Direction dir = makeDirection(); path.addRRect(rrect, dir); validate(path); } break; case kAddPoly: { SkTDArray<SkPoint> points; makePointArray(&points); bool close = makeBool(); path.addPoly(&points[0], points.count(), close); validate(path); } break; case kAddPath1: if (fPathDepth < fPathDepthLimit) { ++fPathDepth; SkPath src = makePath(); validate(src); SkScalar dx = makeScalar(); SkScalar dy = makeScalar(); SkPath::AddPathMode mode = makeAddPathMode(); path.addPath(src, dx, dy, mode); --fPathDepth; validate(path); } break; case kAddPath2: if (fPathDepth < fPathDepthLimit) { ++fPathDepth; SkPath src = makePath(); validate(src); SkPath::AddPathMode mode = makeAddPathMode(); path.addPath(src, mode); --fPathDepth; validate(path); } break; case kAddPath3: if (fPathDepth < fPathDepthLimit) { ++fPathDepth; SkPath src = makePath(); validate(src); SkMatrix matrix = makeMatrix(); SkPath::AddPathMode mode = makeAddPathMode(); path.addPath(src, matrix, mode); --fPathDepth; validate(path); } break; case kReverseAddPath: if (fPathDepth < fPathDepthLimit) { ++fPathDepth; SkPath src = makePath(); validate(src); path.reverseAddPath(src); --fPathDepth; validate(path); } break; case kMoveToPath: { SkScalar x = makeScalar(); SkScalar y = makeScalar(); path.moveTo(x, y); validate(path); } break; case kRMoveToPath: { SkScalar x = makeScalar(); SkScalar y = makeScalar(); path.rMoveTo(x, y); validate(path); } break; case kLineToPath: { SkScalar x = makeScalar(); SkScalar y = makeScalar(); path.lineTo(x, y); validate(path); } break; case kRLineToPath: { SkScalar x = makeScalar(); SkScalar y = makeScalar(); path.rLineTo(x, y); validate(path); } break; case kQuadToPath: { SkPoint pt[2]; makePointArray(SK_ARRAY_COUNT(pt), pt); path.quadTo(pt[0], pt[1]); validate(path); } break; case kRQuadToPath: { SkPoint pt[2]; makePointArray(SK_ARRAY_COUNT(pt), pt); path.rQuadTo(pt[0].fX, pt[0].fY, pt[1].fX, pt[1].fY); validate(path); } break; case kConicToPath: { SkPoint pt[2]; makePointArray(SK_ARRAY_COUNT(pt), pt); SkScalar weight = makeScalar(); path.conicTo(pt[0], pt[1], weight); validate(path); } break; case kRConicToPath: { SkPoint pt[2]; makePointArray(SK_ARRAY_COUNT(pt), pt); SkScalar weight = makeScalar(); path.rConicTo(pt[0].fX, pt[0].fY, pt[1].fX, pt[1].fY, weight); validate(path); } break; case kCubicToPath: { SkPoint pt[3]; makePointArray(SK_ARRAY_COUNT(pt), pt); path.cubicTo(pt[0], pt[1], pt[2]); validate(path); } break; case kRCubicToPath: { SkPoint pt[3]; makePointArray(SK_ARRAY_COUNT(pt), pt); path.rCubicTo(pt[0].fX, pt[0].fY, pt[1].fX, pt[1].fY, pt[2].fX, pt[2].fY); validate(path); } break; case kArcToPath: { SkPoint pt[2]; makePointArray(SK_ARRAY_COUNT(pt), pt); SkScalar radius = makeScalar(); path.arcTo(pt[0], pt[1], radius); validate(path); } break; case kArcTo2Path: { SkRect oval = makeRect(); SkScalar startAngle = makeAngle(); SkScalar sweepAngle = makeAngle(); bool forceMoveTo = makeBool(); path.arcTo(oval, startAngle, sweepAngle, forceMoveTo); validate(path); } break; case kClosePath: path.close(); validate(path); break; } } } return path; }
void onDraw(SkCanvas* canvas) override { const char text[] = "Shaded Text"; const int textLen = SK_ARRAY_COUNT(text) - 1; const int pointSize = 36; const int w = pointSize * textLen; const int h = pointSize; SkPoint pts[2] = { { 0, 0 }, { SkIntToScalar(w), SkIntToScalar(h) } }; SkScalar textBase = SkIntToScalar(h/2); SkShader::TileMode tileModes[] = { SkShader::kClamp_TileMode, SkShader::kRepeat_TileMode, SkShader::kMirror_TileMode }; static const int gradCount = SK_ARRAY_COUNT(gGradData) * SK_ARRAY_COUNT(gGradMakers); static const int bmpCount = SK_ARRAY_COUNT(tileModes) * SK_ARRAY_COUNT(tileModes); sk_sp<SkShader> shaders[gradCount + bmpCount]; int shdIdx = 0; for (size_t d = 0; d < SK_ARRAY_COUNT(gGradData); ++d) { for (size_t m = 0; m < SK_ARRAY_COUNT(gGradMakers); ++m) { shaders[shdIdx++] = gGradMakers[m](pts, gGradData[d], SkShader::kClamp_TileMode); } } SkBitmap bm; makebm(&bm, w/16, h/4); for (size_t tx = 0; tx < SK_ARRAY_COUNT(tileModes); ++tx) { for (size_t ty = 0; ty < SK_ARRAY_COUNT(tileModes); ++ty) { shaders[shdIdx++] = SkShader::MakeBitmapShader(bm, tileModes[tx], tileModes[ty]); } } SkPaint paint; paint.setDither(true); paint.setAntiAlias(true); sk_tool_utils::set_portable_typeface(&paint); paint.setTextSize(SkIntToScalar(pointSize)); canvas->save(); canvas->translate(SkIntToScalar(20), SkIntToScalar(10)); SkPath path; path.arcTo(SkRect::MakeXYWH(SkIntToScalar(-40), SkIntToScalar(15), SkIntToScalar(300), SkIntToScalar(90)), SkIntToScalar(225), SkIntToScalar(90), false); path.close(); static const int testsPerCol = 8; static const int rowHeight = 60; static const int colWidth = 300; canvas->save(); for (int s = 0; s < static_cast<int>(SK_ARRAY_COUNT(shaders)); s++) { canvas->save(); int i = 2*s; canvas->translate(SkIntToScalar((i / testsPerCol) * colWidth), SkIntToScalar((i % testsPerCol) * rowHeight)); paint.setShader(shaders[s]); canvas->drawText(text, textLen, 0, textBase, paint); canvas->restore(); canvas->save(); ++i; canvas->translate(SkIntToScalar((i / testsPerCol) * colWidth), SkIntToScalar((i % testsPerCol) * rowHeight)); canvas->drawTextOnPath(text, textLen, path, nullptr, paint); canvas->restore(); } canvas->restore(); }
void WRasterImage::Impl::drawPlainPath(SkPath &p, const WPainterPath& path) { const std::vector<WPainterPath::Segment>& segments = path.segments(); if (segments.size() > 0 && segments[0].type() != WPainterPath::Segment::MoveTo) p.moveTo(SkDoubleToScalar(0), SkDoubleToScalar(0)); for (unsigned i = 0; i < segments.size(); ++i) { const WPainterPath::Segment s = segments[i]; switch (s.type()) { case WPainterPath::Segment::MoveTo: p.moveTo(SkDoubleToScalar(s.x()), SkDoubleToScalar(s.y())); break; case WPainterPath::Segment::LineTo: p.lineTo(SkDoubleToScalar(s.x()), SkDoubleToScalar(s.y())); break; case WPainterPath::Segment::CubicC1: { const double x1 = s.x(); const double y1 = s.y(); const double x2 = segments[i+1].x(); const double y2 = segments[i+1].y(); const double x3 = segments[i+2].x(); const double y3 = segments[i+2].y(); p.cubicTo(SkDoubleToScalar(x1), SkDoubleToScalar(y1), SkDoubleToScalar(x2), SkDoubleToScalar(y2), SkDoubleToScalar(x3), SkDoubleToScalar(y3)); i += 2; break; } case WPainterPath::Segment::CubicC2: case WPainterPath::Segment::CubicEnd: assert(false); case WPainterPath::Segment::ArcC: { const double x = s.x(); const double y = s.y(); const double width = segments[i+1].x(); const double height = segments[i+1].y(); const double startAngle = segments[i+2].x(); const double sweepAngle = segments[i+2].y(); SkRect rect = SkRect::MakeXYWH(SkDoubleToScalar(x - width), SkDoubleToScalar(y - height), SkDoubleToScalar(width * 2.0), SkDoubleToScalar(height * 2.0)); if (sweepAngle != 360) p.arcTo(rect, SkDoubleToScalar(-startAngle), SkDoubleToScalar(-sweepAngle), false); else p.addOval(rect, SkPath::kCCW_Direction); i += 2; break; } case WPainterPath::Segment::ArcR: case WPainterPath::Segment::ArcAngleSweep: assert(false); case WPainterPath::Segment::QuadC: { const double x1 = s.x(); const double y1 = s.y(); const double x2 = segments[i+1].x(); const double y2 = segments[i+1].y(); p.quadTo(SkDoubleToScalar(x1), SkDoubleToScalar(y1), SkDoubleToScalar(x2), SkDoubleToScalar(y2)); i += 1; break; } case WPainterPath::Segment::QuadEnd: assert(false); } } }