virtual void getWarpParams(WarpFrameT& warpFrame, SkMatrix& warpMatrix) const { SkPath bSkeleton, tSkeleton; SkRect r; r.set(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(600), SkIntToScalar(340)); //bottom { SkRect rb(r); rb.inset(SkIntToScalar(-240), SkIntToScalar(-140)); SkPath tmp; tmp.addArc(rb, SkIntToScalar(0), SkIntToScalar(180)); bSkeleton.reverseAddPath(tmp); warpFrame.push_back(bSkeleton); } //top { SkPath tmp; tmp.addArc(r, SkIntToScalar(0), SkIntToScalar(180)); tSkeleton.reverseAddPath(tmp); warpFrame.push_back(tSkeleton); } }
void GraphicsContext::strokeArc(const IntRect& r, int startAngle, int angleSpan) { if (paintingDisabled()) return; SkPaint paint; SkRect oval = r; if (strokeStyle() == NoStroke) { // Stroke using the fill color. // TODO(brettw) is this really correct? It seems unreasonable. platformContext()->setupPaintForFilling(&paint); paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(WebCoreFloatToSkScalar(strokeThickness())); } else platformContext()->setupPaintForStroking(&paint, 0, 0); // We do this before converting to scalar, so we don't overflow SkFixed. startAngle = fastMod(startAngle, 360); angleSpan = fastMod(angleSpan, 360); SkPath path; path.addArc(oval, SkIntToScalar(-startAngle), SkIntToScalar(-angleSpan)); if (!isPathSkiaSafe(getCTM(), path)) return; platformContext()->canvas()->drawPath(path, 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; } }
static void textStrokePath(SkCanvas* canvas) { SkPaint paint; SkPath path; SkRect rect; canvas->save(); canvas->scale(SkIntToScalar(250),SkIntToScalar(250)); rect.set(0.0f, 0.21f, 0.78f, 0.99f); path.addArc(rect, SkIntToScalar(280), SkIntToScalar(350)); paint.setAntiAlias(true); paint.setStyle(SkPaint::kStroke_Style); paint.setColor(0xFFFF0000); paint.setTextSize(0.085f); paint.setStrokeWidth(.005f); canvas->drawPath(path, paint); paint.setLooper(SkBlurDrawLooper::Create(SK_ColorBLACK, SkBlurMask::ConvertRadiusToSigma(0.002f), 0.0f, 0.0f))->unref(); const char* text = "DRAWING STROKED TEXT WITH A BLUR ON A PATH"; size_t len = strlen(text); canvas->drawTextOnPathHV(text, len, path, 0, -0.025f, paint); canvas->restore(); }
void ACanvasSkia::DrawEllipse(ARect r) { _clip(); _SetPaint_Draw(); SkPath path; path.addArc(ToSkRect(r),0,360); m_pCanvas->drawPath(path,m_Paint); Reset(); }
void onOnceBeforeDraw() override { { SkPath* lineAnglesPath = &fPaths.push_back(); enum { kNumAngles = 15, kRadius = 40, }; for (int i = 0; i < kNumAngles; ++i) { SkScalar angle = SK_ScalarPI * SkIntToScalar(i) / kNumAngles; SkScalar x = kRadius * SkScalarCos(angle); SkScalar y = kRadius * SkScalarSin(angle); lineAnglesPath->moveTo(x, y); lineAnglesPath->lineTo(-x, -y); } } { SkPath* kindaTightQuad = &fPaths.push_back(); kindaTightQuad->moveTo(0, -10 * SK_Scalar1); kindaTightQuad->quadTo(SkIntToScalar(100), SkIntToScalar(100), -10 * SK_Scalar1, 0); } { SkPath* tightQuad = &fPaths.push_back(); tightQuad->moveTo(0, -5 * SK_Scalar1); tightQuad->quadTo(SkIntToScalar(100), SkIntToScalar(100), -5 * SK_Scalar1, 0); } { SkPath* tighterQuad = &fPaths.push_back(); tighterQuad->moveTo(0, -2 * SK_Scalar1); tighterQuad->quadTo(SkIntToScalar(100), SkIntToScalar(100), -2 * SK_Scalar1, 0); } { SkPath* unevenTighterQuad = &fPaths.push_back(); unevenTighterQuad->moveTo(0, -1 * SK_Scalar1); SkPoint p; p.set(-2 * SK_Scalar1 + 3 * SkIntToScalar(102) / 4, SkIntToScalar(75)); unevenTighterQuad->quadTo(SkIntToScalar(100), SkIntToScalar(100), p.fX, p.fY); } { SkPath* reallyTightQuad = &fPaths.push_back(); reallyTightQuad->moveTo(0, -1 * SK_Scalar1); reallyTightQuad->quadTo(SkIntToScalar(100), SkIntToScalar(100), -1 * SK_Scalar1, 0); } { SkPath* closedQuad = &fPaths.push_back(); closedQuad->moveTo(0, -0); closedQuad->quadTo(SkIntToScalar(100), SkIntToScalar(100), 0, 0); } { SkPath* unevenClosedQuad = &fPaths.push_back(); unevenClosedQuad->moveTo(0, -0); unevenClosedQuad->quadTo(SkIntToScalar(100), SkIntToScalar(100), SkIntToScalar(75), SkIntToScalar(75)); } // Two problem cases for gpu hairline renderer found by shapeops testing. These used // to assert that the computed bounding box didn't contain all the vertices. { SkPath* problem1 = &fPaths.push_back(); problem1->moveTo(SkIntToScalar(4), SkIntToScalar(6)); problem1->cubicTo(SkIntToScalar(5), SkIntToScalar(6), SkIntToScalar(5), SkIntToScalar(4), SkIntToScalar(4), SkIntToScalar(0)); problem1->close(); } { SkPath* problem2 = &fPaths.push_back(); problem2->moveTo(SkIntToScalar(5), SkIntToScalar(1)); problem2->lineTo(4.32787323f, 1.67212653f); problem2->cubicTo(2.75223875f, 3.24776125f, 3.00581908f, 4.51236057f, 3.7580452f, 4.37367964f); problem2->cubicTo(4.66472578f, 3.888381f, 5.f, 2.875f, 5.f, 1.f); problem2->close(); } // Three paths that show the same bug (missing end caps) { // A caret (crbug.com/131770) SkPath* bug0 = &fPaths.push_back(); bug0->moveTo(6.5f,5.5f); bug0->lineTo(3.5f,0.5f); bug0->moveTo(0.5f,5.5f); bug0->lineTo(3.5f,0.5f); } { // An X (crbug.com/137317) SkPath* bug1 = &fPaths.push_back(); bug1->moveTo(1, 1); bug1->lineTo(6, 6); bug1->moveTo(1, 6); bug1->lineTo(6, 1); } { // A right angle (crbug.com/137465 and crbug.com/256776) SkPath* bug2 = &fPaths.push_back(); bug2->moveTo(5.5f, 5.5f); bug2->lineTo(5.5f, 0.5f); bug2->lineTo(0.5f, 0.5f); } { // Arc example to test imperfect truncation bug (crbug.com/295626) static const SkScalar kRad = SkIntToScalar(2000); static const SkScalar kStartAngle = 262.59717f; static const SkScalar kSweepAngle = SkScalarHalf(17.188717f); SkPath* bug = &fPaths.push_back(); // Add a circular arc SkRect circle = SkRect::MakeLTRB(-kRad, -kRad, kRad, kRad); bug->addArc(circle, kStartAngle, kSweepAngle); // Now add the chord that should cap the circular arc SkScalar cosV, sinV = SkScalarSinCos(SkDegreesToRadians(kStartAngle), &cosV); SkPoint p0 = SkPoint::Make(kRad * cosV, kRad * sinV); sinV = SkScalarSinCos(SkDegreesToRadians(kStartAngle + kSweepAngle), &cosV); SkPoint p1 = SkPoint::Make(kRad * cosV, kRad * sinV); bug->moveTo(p0); bug->lineTo(p1); } }
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; }