void PlatformGraphicsContextSkia::addInnerRoundedRectClip(const IntRect& rect, int thickness) { SkPath path; SkRect r(rect); path.addOval(r, SkPath::kCW_Direction); // Only perform the inset if we won't invert r if (2 * thickness < rect.width() && 2 * thickness < rect.height()) { // Adding one to the thickness doesn't make the border too thick as // it's painted over afterwards. But without this adjustment the // border appears a little anemic after anti-aliasing. r.inset(SkIntToScalar(thickness + 1), SkIntToScalar(thickness + 1)); path.addOval(r, SkPath::kCCW_Direction); } mCanvas->clipPath(path, SkRegion::kIntersect_Op, true); }
SkRect draw(SkCanvas* canvas, const SkPaint& paint) override { SkPath path; path.addCircle(15, 15, 10); path.addOval(SkRect::MakeXYWH(2, 2, 22, 37)); path.setFillType(SkPath::kEvenOdd_FillType); canvas->drawPath(path, paint); return path.getBounds(); }
// ensure that we don't accidentally screw up the bounds when the oval is // fractional, and the impl computes the center and radii, and uses them to // reconstruct the edges of the circle. // see bug# 1504910 static void test_circlebounds(SkCanvas* canvas) { #ifdef SK_SCALAR_IS_FLOAT SkRect r = { 1.39999998f, 1, 21.3999996f, 21 }; SkPath p; p.addOval(r); SkASSERT(r == p.getBounds()); #endif }
void drawRectSkeleton(SkCanvas* max, const SkRect& r) { SkPaint paint; this->setupSkeletonPaint(&paint); SkPath path; fRectAsOval ? path.addOval(r) : path.addRect(r); max->drawPath(path, paint); }
void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness) { if (paintingDisabled()) return; SkRect r(rect); if (!isRectSkiaSafe(getCTM(), r)) return; SkPath path; path.addOval(r, SkPath::kCW_Direction); // only perform the inset if we won't invert r if (2 * thickness < rect.width() && 2 * thickness < rect.height()) { r.inset(SkIntToScalar(thickness) ,SkIntToScalar(thickness)); path.addOval(r, SkPath::kCCW_Direction); } platformContext()->canvas()->clipPath(path); }
void SkBitmapDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) { CHECK_FOR_ANNOTATION(paint); SkPath path; path.addOval(oval); // call the VIRTUAL version, so any subclasses who do handle drawPath aren't // required to override drawOval. this->drawPath(draw, path, paint, NULL, true); }
void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness) { if (paintingDisabled()) return; SkRect r(rect); SkPath path; path.addOval(r, SkPath::kCW_Direction); // only perform the inset if we won't invert r if (2 * thickness < rect.width() && 2 * thickness < rect.height()) { // Adding one to the thickness doesn't make the border too thick as // it's painted over afterwards. But without this adjustment the // border appears a little anemic after anti-aliasing. r.inset(SkIntToScalar(thickness + 1), SkIntToScalar(thickness + 1)); path.addOval(r, SkPath::kCCW_Direction); } platformContext()->clipPathAntiAliased(path); }
TextOnPathView() { SkRect r; r.set(SkIntToScalar(100), SkIntToScalar(100), SkIntToScalar(300), SkIntToScalar(300)); fPath.addOval(r); fPath.offset(SkIntToScalar(-50), SkIntToScalar(-50)); fHOffset = SkIntToScalar(50); }
// we used to assert if the bounds of the device (clip) was larger than 32K // even when the path itself was smaller. We just draw and hope in the debug // version to not assert. static void test_giantaa() { const int W = 400; const int H = 400; SkAutoTUnref<SkCanvas> canvas(SkCanvas::NewRasterN32(33000, 10)); SkPaint paint; paint.setAntiAlias(true); SkPath path; path.addOval(SkRect::MakeXYWH(-10, -10, 20 + W, 20 + H)); canvas.get()->drawPath(path, paint); }
// we used to assert if the bounds of the device (clip) was larger than 32K // even when the path itself was smaller. We just draw and hope in the debug // version to not assert. static void test_giantaa() { const int W = 400; const int H = 400; auto surface(SkSurface::MakeRasterN32Premul(33000, 10)); SkPaint paint; paint.setAntiAlias(true); SkPath path; path.addOval(SkRect::MakeXYWH(-10, -10, 20 + W, 20 + H)); surface->getCanvas()->drawPath(path, paint); }
// we used to assert if the bounds of the device (clip) was larger than 32K // even when the path itself was smaller. We just draw and hope in the debug // version to not assert. static void test_giantaa(skiatest::Reporter* reporter) { const int W = 400; const int H = 400; SkAutoTUnref<SkCanvas> canvas(new_canvas(33000, 10)); canvas.get()->clear(SK_ColorTRANSPARENT); SkPaint paint; paint.setAntiAlias(true); SkPath path; path.addOval(SkRect::MakeXYWH(-10, -10, 20 + W, 20 + H)); canvas.get()->drawPath(path, paint); }
void GraphicsContext::clipOutEllipseInRect(const IntRect& rect) { if (paintingDisabled()) return; SkRect oval(rect); if (!isRectSkiaSafe(getCTM(), oval)) return; SkPath path; path.addOval(oval, SkPath::kCCW_Direction); platformContext()->canvas()->clipPath(path, SkRegion::kDifference_Op); }
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) { switch (fStyle) { case kRect_Style: canvas->drawRect(fRect, fPaint); break; case kOval_Style: canvas->drawOval(fRect, fPaint); break; case kRRect_Style: { SkScalar rx = fRect.width() / 5; SkScalar ry = fRect.height() / 5; if (rx < ry) { ry = rx; } else { rx = ry; } canvas->drawRoundRect(fRect, rx, ry, fPaint); break; } case kFrame_Style: { SkPath path; path.addOval(fRect, SkPath::kCW_Direction); SkRect r = fRect; r.inset(fRect.width()/6, 0); path.addOval(r, SkPath::kCCW_Direction); canvas->drawPath(path, fPaint); break; } } }
void Path::addArc(const FloatPoint& p, float r, float sa, float ea, bool clockwise) { SkScalar cx = SkFloatToScalar(p.x()); SkScalar cy = SkFloatToScalar(p.y()); SkScalar radius = SkFloatToScalar(r); SkRect oval; oval.set(cx - radius, cy - radius, cx + radius, cy + radius); float sweep = ea - sa; bool prependOval = false; /* Note if clockwise and the sign of the sweep disagree. This particular logic was deduced from http://canvex.lazyilluminati.com/misc/arc.html */ if (clockwise && (sweep > 0 || sweep < -g2PI)) { sweep = fmodf(sweep, g2PI) - g2PI; } else if (!clockwise && (sweep < 0 || sweep > g2PI)) { sweep = fmodf(sweep, g2PI) + g2PI; } // If the abs(sweep) >= 2PI, then we need to add a circle before we call // arcTo, since it treats the sweep mod 2PI. We don't have a prepend call, // so we just remember this, and at the end create a new path with an oval // and our current path, and then swap then. // if (sweep >= g2PI || sweep <= -g2PI) { prependOval = true; // SkDebugf("addArc sa=%g ea=%g cw=%d sweep %g treat as circle\n", sa, ea, clockwise, sweep); // now reduce sweep to just the amount we need, so that the current // point is left where the caller expects it. sweep = fmodf(sweep, g2PI); } sa = fast_mod(sa, g2PI); SkScalar startDegrees = SkFloatToScalar(sa * g180OverPI); SkScalar sweepDegrees = SkFloatToScalar(sweep * g180OverPI); // SkDebugf("addArc sa=%g ea=%g cw=%d sweep=%g ssweep=%g\n", sa, ea, clockwise, sweep, SkScalarToFloat(sweepDegrees)); m_path->arcTo(oval, startDegrees, sweepDegrees, false); if (prependOval) { SkPath tmp; tmp.addOval(oval); tmp.addPath(*m_path); m_path->swap(tmp); } }
PathTexture* OvalShapeCache::getOval(float width, float height, SkPaint* paint) { OvalShapeCacheEntry entry(width, height, paint); PathTexture* texture = get(entry); if (!texture) { SkPath path; SkRect r; r.set(0.0f, 0.0f, width, height); path.addOval(r, SkPath::kCW_Direction); texture = addTexture(entry, &path, paint); } return texture; }
PathTexture* PathCache::getOval(float width, float height, const SkPaint* paint) { PathDescription entry(kShapeOval, paint); entry.shape.oval.mWidth = width; entry.shape.oval.mHeight = height; PathTexture* texture = get(entry); if (!texture) { SkPath path; SkRect r; r.set(0.0f, 0.0f, width, height); path.addOval(r, SkPath::kCW_Direction); texture = addTexture(entry, &path, paint); } return texture; }
virtual void onDraw(SkCanvas* canvas) { SkPaint paint; paint.setAntiAlias(true); paint.setStyle(SkPaint::kStroke_Style); SkPath path; path.moveTo(20, 20); path.lineTo(70, 120); path.lineTo(120, 30); path.lineTo(170, 80); path.lineTo(240, 50); size_t i; canvas->save(); for (i = 0; i < SK_ARRAY_COUNT(gPE); i++) { gPE[i](&paint); canvas->drawPath(path, paint); canvas->translate(0, 75); } canvas->restore(); path.reset(); SkRect r = { 0, 0, 250, 120 }; path.addOval(r, SkPath::kCW_Direction); r.inset(50, 50); path.addRect(r, SkPath::kCCW_Direction); canvas->translate(320, 20); for (i = 0; i < SK_ARRAY_COUNT(gPE2); i++) { gPE2[i](&paint); canvas->drawPath(path, paint); canvas->translate(0, 160); } SkIRect rect = SkIRect::MakeXYWH(20, 20, 60, 60); for (i = 0; i < SK_ARRAY_COUNT(gPE); i++) { SkPaint p; p.setAntiAlias(true); p.setStyle(SkPaint::kFill_Style); gPE[i](&p); canvas->drawIRect(rect, p); canvas->translate(75, 0); } }
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); } }
static void TestParsePath(skiatest::Reporter* reporter) { for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) { SkPath path; bool success = SkParsePath::FromSVGString(gRec[i].fStr, &path); REPORTER_ASSERT(reporter, success); const SkRect& expectedBounds = gRec[i].fBounds; const SkRect& pathBounds = path.getBounds(); REPORTER_ASSERT(reporter, expectedBounds == pathBounds); test_to_from(reporter, path); } SkRect r; r.set(0, 0, SkFloatToScalar(10), SkFloatToScalar(10.5f)); SkPath p; p.addRect(r); test_to_from(reporter, p); p.addOval(r); test_to_from(reporter, p); p.addRoundRect(r, SkFloatToScalar(4), SkFloatToScalar(4.5f)); test_to_from(reporter, p); }
void drawRectSkeleton(SkCanvas* max, const SkRect& r) { SkPaint paint; this->setupSkeletonPaint(&paint); SkPath path; if (fUseGPU && fAA) { SkRect rr = r; rr.inset(SkIntToScalar(fZoom)/2, SkIntToScalar(fZoom)/2); path.addRect(rr); path.moveTo(rr.fLeft, rr.fTop); path.lineTo(rr.fRight, rr.fBottom); rr = r; rr.inset(-SkIntToScalar(fZoom)/2, -SkIntToScalar(fZoom)/2); path.addRect(rr); } else { fRectAsOval ? path.addOval(r) : path.addRect(r); if (fUseGPU) { path.moveTo(r.fLeft, r.fTop); path.lineTo(r.fRight, r.fBottom); } } max->drawPath(path, paint); }
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); }
// ensure that we don't accidentally screw up the bounds when the oval is // fractional, and the impl computes the center and radii, and uses them to // reconstruct the edges of the circle. // see bug# 1504910 static void test_circlebounds(SkCanvas*) { SkRect r = { 1.39999998f, 1, 21.3999996f, 21 }; SkPath p; p.addOval(r); SkASSERT(r == p.getBounds()); }
static void draw_oval(SkCanvas* canvas, bool showGL, int flags) { SkPaint paint; paint.setAntiAlias(true); SkRect r = SkRect::MakeLTRB(50, 70, 250, 370); setFade(&paint, showGL); canvas->drawOval(r, paint); if (showGL) { switch (flags) { case 0: { SkPath path; path.addOval(r); show_glframe(canvas, path); } break; case 1: case 3: { SkPath src, dst; src.addOval(r); tesselate(src, &dst); show_fan(canvas, dst, r.centerX(), r.centerY()); } break; case 2: { SkPaint p(paint); show_mesh(canvas, r); setGLFrame(&p); paint.setStyle(SkPaint::kFill_Style); canvas->drawCircle(r.centerX(), r.centerY(), 3, p); } break; } } canvas->translate(320, 0); paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(25); canvas->drawOval(r, paint); if (showGL) { switch (flags) { case 0: { SkPath path; SkScalar rad = paint.getStrokeWidth() / 2; r.outset(rad, rad); path.addOval(r); r.inset(rad*2, rad*2); path.addOval(r); show_glframe(canvas, path); } break; case 1: { SkPath path0, path1; SkScalar rad = paint.getStrokeWidth() / 2; r.outset(rad, rad); path0.addOval(r); r.inset(rad*2, rad*2); path1.addOval(r); show_mesh_between(canvas, path0, path1); } break; case 2: { SkPath path; path.addOval(r); show_glframe(canvas, path); SkScalar rad = paint.getStrokeWidth() / 2; r.outset(rad, rad); show_mesh(canvas, r); } break; case 3: { SkScalar rad = paint.getStrokeWidth() / 2; r.outset(rad, rad); SkPaint paint; paint.setAlpha(0x33); canvas->drawRect(r, paint); show_mesh(canvas, r); } break; } } }
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); } } }
void onDrawContent(SkCanvas* canvas) override { SkPath path; SkScalar width = fWidth; if (fCubicButton.fEnabled) { path.moveTo(fPts[0]); path.cubicTo(fPts[1], fPts[2], fPts[3]); setForGeometry(); draw_stroke(canvas, path, width, 950, false); } if (fConicButton.fEnabled) { path.moveTo(fPts[4]); path.conicTo(fPts[5], fPts[6], fWeight); setForGeometry(); draw_stroke(canvas, path, width, 950, false); } if (fQuadButton.fEnabled) { path.reset(); path.moveTo(fPts[7]); path.quadTo(fPts[8], fPts[9]); setForGeometry(); draw_stroke(canvas, path, width, 950, false); } if (fRRectButton.fEnabled) { SkScalar rad = 32; SkRect r; r.set(&fPts[10], 2); path.reset(); SkRRect rr; rr.setRectXY(r, rad, rad); path.addRRect(rr); setForGeometry(); draw_stroke(canvas, path, width, 950, false); path.reset(); SkRRect rr2; rr.inset(width/2, width/2, &rr2); path.addRRect(rr2, SkPath::kCCW_Direction); rr.inset(-width/2, -width/2, &rr2); path.addRRect(rr2, SkPath::kCW_Direction); SkPaint paint; paint.setAntiAlias(true); paint.setColor(0x40FF8844); canvas->drawPath(path, paint); } if (fCircleButton.fEnabled) { path.reset(); SkRect r; r.set(&fPts[12], 2); path.addOval(r); setForGeometry(); if (fCircleButton.fFill) { draw_fill(canvas, r, width); } else { draw_stroke(canvas, path, width, 950, false); } } if (fTextButton.fEnabled) { path.reset(); SkPaint paint; paint.setAntiAlias(true); paint.setTextSize(fTextSize); paint.getTextPath(fText.c_str(), fText.size(), 0, fTextSize, &path); setForText(); draw_stroke(canvas, path, width * fWidthScale / fTextSize, fTextSize, true); } if (fAnimate) { fWidth += fDWidth; if (fDWidth > 0 && fWidth > kWidthMax) { fDWidth = -fDWidth; } else if (fDWidth < 0 && fWidth < kWidthMin) { fDWidth = -fDWidth; } } setAsNeeded(); if (fConicButton.fEnabled) { draw_control(canvas, fWeightControl, fWeight, 0, 5, "weight"); } #ifdef SK_DEBUG draw_control(canvas, fErrorControl, gDebugStrokerError, kStrokerErrorMin, kStrokerErrorMax, "error"); #endif draw_control(canvas, fWidthControl, fWidth * fWidthScale, kWidthMin * fWidthScale, kWidthMax * fWidthScale, "width"); draw_button(canvas, fQuadButton); draw_button(canvas, fCubicButton); draw_button(canvas, fConicButton); draw_button(canvas, fRRectButton); draw_button(canvas, fCircleButton); draw_button(canvas, fTextButton); this->inval(NULL); }
static void test_clip_bound_opt(skiatest::Reporter* reporter) { // Test for crbug.com/229011 SkRect rect1 = SkRect::MakeXYWH(SkIntToScalar(4), SkIntToScalar(4), SkIntToScalar(2), SkIntToScalar(2)); SkRect rect2 = SkRect::MakeXYWH(SkIntToScalar(7), SkIntToScalar(7), SkIntToScalar(1), SkIntToScalar(1)); SkRect rect3 = SkRect::MakeXYWH(SkIntToScalar(6), SkIntToScalar(6), SkIntToScalar(1), SkIntToScalar(1)); SkPath invPath; invPath.addOval(rect1); invPath.setFillType(SkPath::kInverseEvenOdd_FillType); SkPath path; path.addOval(rect2); SkPath path2; path2.addOval(rect3); SkIRect clipBounds; SkPictureRecorder recorder; // Testing conservative-raster-clip that is enabled by PictureRecord { SkCanvas* canvas = recorder.beginRecording(10, 10); canvas->clipPath(invPath, SkRegion::kIntersect_Op); bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds); REPORTER_ASSERT(reporter, true == nonEmpty); REPORTER_ASSERT(reporter, 0 == clipBounds.fLeft); REPORTER_ASSERT(reporter, 0 == clipBounds.fTop); REPORTER_ASSERT(reporter, 10 == clipBounds.fBottom); REPORTER_ASSERT(reporter, 10 == clipBounds.fRight); } { SkCanvas* canvas = recorder.beginRecording(10, 10); canvas->clipPath(path, SkRegion::kIntersect_Op); canvas->clipPath(invPath, SkRegion::kIntersect_Op); bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds); REPORTER_ASSERT(reporter, true == nonEmpty); REPORTER_ASSERT(reporter, 7 == clipBounds.fLeft); REPORTER_ASSERT(reporter, 7 == clipBounds.fTop); REPORTER_ASSERT(reporter, 8 == clipBounds.fBottom); REPORTER_ASSERT(reporter, 8 == clipBounds.fRight); } { SkCanvas* canvas = recorder.beginRecording(10, 10); canvas->clipPath(path, SkRegion::kIntersect_Op); canvas->clipPath(invPath, SkRegion::kUnion_Op); bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds); REPORTER_ASSERT(reporter, true == nonEmpty); REPORTER_ASSERT(reporter, 0 == clipBounds.fLeft); REPORTER_ASSERT(reporter, 0 == clipBounds.fTop); REPORTER_ASSERT(reporter, 10 == clipBounds.fBottom); REPORTER_ASSERT(reporter, 10 == clipBounds.fRight); } { SkCanvas* canvas = recorder.beginRecording(10, 10); canvas->clipPath(path, SkRegion::kDifference_Op); bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds); REPORTER_ASSERT(reporter, true == nonEmpty); REPORTER_ASSERT(reporter, 0 == clipBounds.fLeft); REPORTER_ASSERT(reporter, 0 == clipBounds.fTop); REPORTER_ASSERT(reporter, 10 == clipBounds.fBottom); REPORTER_ASSERT(reporter, 10 == clipBounds.fRight); } { SkCanvas* canvas = recorder.beginRecording(10, 10); canvas->clipPath(path, SkRegion::kReverseDifference_Op); bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds); // True clip is actually empty in this case, but the best // determination we can make using only bounds as input is that the // clip is included in the bounds of 'path'. REPORTER_ASSERT(reporter, true == nonEmpty); REPORTER_ASSERT(reporter, 7 == clipBounds.fLeft); REPORTER_ASSERT(reporter, 7 == clipBounds.fTop); REPORTER_ASSERT(reporter, 8 == clipBounds.fBottom); REPORTER_ASSERT(reporter, 8 == clipBounds.fRight); } { SkCanvas* canvas = recorder.beginRecording(10, 10); canvas->clipPath(path, SkRegion::kIntersect_Op); canvas->clipPath(path2, SkRegion::kXOR_Op); bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds); REPORTER_ASSERT(reporter, true == nonEmpty); REPORTER_ASSERT(reporter, 6 == clipBounds.fLeft); REPORTER_ASSERT(reporter, 6 == clipBounds.fTop); REPORTER_ASSERT(reporter, 8 == clipBounds.fBottom); REPORTER_ASSERT(reporter, 8 == clipBounds.fRight); } }