SkRect draw(SkCanvas* canvas, const SkPaint& paint) override { SkRRect outerRRect; outerRRect.setRectXY(SkRect::MakeXYWH(0, 0, 50, 50), 5, 5); SkRRect innerRRect; innerRRect.setRectXY(SkRect::MakeXYWH(5, 8, 35, 30), 8, 3); canvas->drawDRRect(outerRRect, innerRRect, paint); return outerRRect.getBounds(); }
// Test that all the SkRRect entry points correctly handle un-sorted and // zero-sized input rects static void test_empty(skiatest::Reporter* reporter) { static const SkRect oooRects[] = { // out of order { 100, 0, 0, 100 }, // ooo horizontal { 0, 100, 100, 0 }, // ooo vertical { 100, 100, 0, 0 }, // ooo both }; static const SkRect emptyRects[] = { { 100, 100, 100, 200 }, // empty horizontal { 100, 100, 200, 100 }, // empty vertical { 100, 100, 100, 100 }, // empty both { 0, 0, 0, 0 } // setEmpty-empty }; static const SkVector radii[4] = { { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 } }; SkRRect r; for (size_t i = 0; i < SK_ARRAY_COUNT(oooRects); ++i) { r.setRect(oooRects[i]); REPORTER_ASSERT(reporter, !r.isEmpty()); r.setOval(oooRects[i]); REPORTER_ASSERT(reporter, !r.isEmpty()); r.setRectXY(oooRects[i], 1, 2); REPORTER_ASSERT(reporter, !r.isEmpty()); r.setNinePatch(oooRects[i], 0, 1, 2, 3); REPORTER_ASSERT(reporter, !r.isEmpty()); r.setRectRadii(oooRects[i], radii); REPORTER_ASSERT(reporter, !r.isEmpty()); } for (size_t i = 0; i < SK_ARRAY_COUNT(emptyRects); ++i) { r.setRect(emptyRects[i]); REPORTER_ASSERT(reporter, r.isEmpty()); r.setOval(emptyRects[i]); REPORTER_ASSERT(reporter, r.isEmpty()); r.setRectXY(emptyRects[i], 1, 2); REPORTER_ASSERT(reporter, r.isEmpty()); r.setNinePatch(emptyRects[i], 0, 1, 2, 3); REPORTER_ASSERT(reporter, r.isEmpty()); r.setRectRadii(emptyRects[i], radii); REPORTER_ASSERT(reporter, r.isEmpty()); } }
std::unique_ptr<GrFragmentProcessor> EllipticalRRectEffect::TestCreate(GrProcessorTestData* d) { SkScalar w = d->fRandom->nextRangeScalar(20.f, 1000.f); SkScalar h = d->fRandom->nextRangeScalar(20.f, 1000.f); SkVector r[4]; r[SkRRect::kUpperLeft_Corner].fX = d->fRandom->nextRangeF(kRadiusMin, 9.f); // ensure at least one corner really is elliptical do { r[SkRRect::kUpperLeft_Corner].fY = d->fRandom->nextRangeF(kRadiusMin, 9.f); } while (r[SkRRect::kUpperLeft_Corner].fY == r[SkRRect::kUpperLeft_Corner].fX); SkRRect rrect; if (d->fRandom->nextBool()) { // half the time create a four-radii rrect. r[SkRRect::kLowerRight_Corner].fX = d->fRandom->nextRangeF(kRadiusMin, 9.f); r[SkRRect::kLowerRight_Corner].fY = d->fRandom->nextRangeF(kRadiusMin, 9.f); r[SkRRect::kUpperRight_Corner].fX = r[SkRRect::kLowerRight_Corner].fX; r[SkRRect::kUpperRight_Corner].fY = r[SkRRect::kUpperLeft_Corner].fY; r[SkRRect::kLowerLeft_Corner].fX = r[SkRRect::kUpperLeft_Corner].fX; r[SkRRect::kLowerLeft_Corner].fY = r[SkRRect::kLowerRight_Corner].fY; rrect.setRectRadii(SkRect::MakeWH(w, h), r); } else { rrect.setRectXY(SkRect::MakeWH(w, h), r[SkRRect::kUpperLeft_Corner].fX, r[SkRRect::kUpperLeft_Corner].fY); } std::unique_ptr<GrFragmentProcessor> fp; do { GrClipEdgeType et = (GrClipEdgeType)d->fRandom->nextULessThan(kGrClipEdgeTypeCnt); fp = GrRRectEffect::Make(et, rrect, *d->caps()->shaderCaps()); } while (nullptr == fp); return fp; }
static void emit_draw(SkCanvas* canvas, DrawOpType draw, SkTDArray<DrawType>* expected) { switch (draw) { case kNone_DrawOpType: break; case kClear_DrawOpType: canvas->clear(SK_ColorRED); *expected->append() = DRAW_CLEAR; break; case kOval_DrawOpType: { SkRect r = SkRect::MakeLTRB(10, 10, 90, 90); SkPaint p; canvas->drawOval(r, p); *expected->append() = DRAW_OVAL; break; } case kRect_DrawOpType: { SkRect r = SkRect::MakeLTRB(10, 10, 90, 90); SkPaint p; canvas->drawRect(r, p); *expected->append() = DRAW_RECT; break; } case kRRect_DrawOpType: { SkRect r = SkRect::MakeLTRB(10.0f, 10.0f, 90.0f, 90.0f); SkRRect rr; rr.setRectXY(r, 5.0f, 5.0f); SkPaint p; canvas->drawRRect(rr, p); *expected->append() = DRAW_RRECT; break; } default: SkASSERT(0); } }
void onDraw(SkCanvas* canvas) override { canvas->scale(1.5f, 1.5f); canvas->translate(50,50); const float blurRadii[] = { 1,5,10,20 }; const int cornerRadii[] = { 1,5,10,20 }; const SkRect r = SkRect::MakeWH(SkIntToScalar(25), SkIntToScalar(25)); for (size_t i = 0; i < SK_ARRAY_COUNT(blurRadii); ++i) { SkAutoCanvasRestore autoRestore(canvas, true); canvas->translate(0, (r.height() + SkIntToScalar(50)) * i); for (size_t j = 0; j < SK_ARRAY_COUNT(cornerRadii); ++j) { for (int k = 0; k <= 1; k++) { SkMaskFilter* filter = SkBlurMaskFilter::Create( kNormal_SkBlurStyle, SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(blurRadii[i])), SkBlurMaskFilter::kHighQuality_BlurFlag); SkPaint paint; paint.setColor(SK_ColorBLACK); paint.setMaskFilter(filter)->unref(); bool useRadial = SkToBool(k); if (useRadial) { paint.setShader(MakeRadial()); } SkRRect rrect; rrect.setRectXY(r, SkIntToScalar(cornerRadii[j]), SkIntToScalar(cornerRadii[j])); canvas->drawRRect(rrect, paint); canvas->translate(r.width() + SkIntToScalar(50), 0); } } } }
static void draw_rrect(SkCanvas* canvas, const SkRect& r, const SkPaint& p) { SkScalar xRad = r.width() / 4.0f; SkScalar yRad = r.height() / 4.0f; SkRRect rr; rr.setRectXY(r, xRad, yRad); canvas->drawRRect(rr, p); }
static void draw_drrect(SkCanvas* canvas, const SkRect& r, const SkPaint& p) { SkScalar xRad = r.width() / 4.0f; SkScalar yRad = r.height() / 4.0f; SkRRect outer; outer.setRectXY(r, xRad, yRad); SkRRect inner = outer; inner.inset(xRad, yRad); canvas->drawDRRect(outer, inner, p); }
static void test_empty_crbug_458524(skiatest::Reporter* reporter) { SkRRect rr; const SkRect bounds = { 3709, 3709, 3709 + 7402, 3709 + 29825 }; const SkScalar rad = 40; rr.setRectXY(bounds, rad, rad); SkRRect other; SkMatrix matrix; matrix.setScale(0, 1); rr.transform(matrix, &other); REPORTER_ASSERT(reporter, SkRRect::kEmpty_Type == other.getType()); }
void draw(SkCanvas* canvas) { SkPaint paint; paint.setAntiAlias(true); paint.setTextSize(16); SkRRect rrect = SkRRect::MakeRectXY({30, 10, 100, 60}, 40, 30); canvas->drawRRect(rrect, paint); canvas->drawString(rrect.isOval() ? "oval" : "not oval", 64, 90, paint); rrect.setRectXY(rrect.getBounds(), 35, 25); canvas->translate(128, 0); canvas->drawRRect(rrect, paint); canvas->drawString(rrect.isOval() ? "oval" : "not oval", 64, 90, paint); }
// Two pictures with a round rect clip on the second one static void rrect_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) { canvas->drawPicture(pictures[0]); SkRect rect = pictures[0]->cullRect(); rect.inset(kInset, kInset); SkRRect rrect; rrect.setRectXY(rect, kInset, kInset); canvas->clipRRect(rrect); canvas->drawPicture(pictures[1]); }
static void test_empty_crbug_458524(skiatest::Reporter* reporter) { SkRRect rr; const SkRect bounds = { 3709, 3709, 3709 + 7402, 3709 + 29825 }; const SkScalar rad = 40; rr.setRectXY(bounds, rad, rad); path_contains_rrect_check(reporter, rr); SkRRect other; SkMatrix matrix; matrix.setScale(0, 1); rr.transform(matrix, &other); path_contains_rrect_check(reporter, rr); }
const GrFragmentProcessor* CircularRRectEffect::TestCreate(GrProcessorTestData* d) { SkScalar w = d->fRandom->nextRangeScalar(20.f, 1000.f); SkScalar h = d->fRandom->nextRangeScalar(20.f, 1000.f); SkScalar r = d->fRandom->nextRangeF(kRadiusMin, 9.f); SkRRect rrect; rrect.setRectXY(SkRect::MakeWH(w, h), r, r); GrFragmentProcessor* fp; do { GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt); fp = GrRRectEffect::Create(et, rrect); } while (nullptr == fp); return fp; }
std::unique_ptr<GrFragmentProcessor> CircularRRectEffect::TestCreate(GrProcessorTestData* d) { SkScalar w = d->fRandom->nextRangeScalar(20.f, 1000.f); SkScalar h = d->fRandom->nextRangeScalar(20.f, 1000.f); SkScalar r = d->fRandom->nextRangeF(kRadiusMin, 9.f); SkRRect rrect; rrect.setRectXY(SkRect::MakeWH(w, h), r, r); std::unique_ptr<GrFragmentProcessor> fp; do { GrClipEdgeType et = (GrClipEdgeType)d->fRandom->nextULessThan(kGrClipEdgeTypeCnt); fp = GrRRectEffect::Make(et, rrect, *d->caps()->shaderCaps()); } while (nullptr == fp); return fp; }
SkRRect makeRRect() { SkRRect rrect; RandomSetRRect rrectType = makeSetRRectType(); if (fPrintName) { SkDebugf("%.*s%s\n", fPathDepth * 3, fTab, gRandomSetRRectNames[rrectType]); } switch (rrectType) { case kSetEmpty: rrect.setEmpty(); break; case kSetRect: { SkRect rect = makeRect(); rrect.setRect(rect); } break; case kSetOval: { SkRect oval = makeRect(); rrect.setOval(oval); } break; case kSetRectXY: { SkRect rect = makeRect(); SkScalar xRad = makeScalar(); SkScalar yRad = makeScalar(); rrect.setRectXY(rect, xRad, yRad); } break; case kSetNinePatch: { SkRect rect = makeRect(); SkScalar leftRad = makeScalar(); SkScalar topRad = makeScalar(); SkScalar rightRad = makeScalar(); SkScalar bottomRad = makeScalar(); rrect.setNinePatch(rect, leftRad, topRad, rightRad, bottomRad); SkDebugf(""); // keep locals in scope } break; case kSetRectRadii: { SkRect rect = makeRect(); SkVector radii[4]; makeVectorArray(SK_ARRAY_COUNT(radii), radii); rrect.setRectRadii(rect, radii); } break; } return rrect; }
GrFragmentProcessor* CircularRRectEffect::TestCreate(SkRandom* random, GrContext*, const GrDrawTargetCaps& caps, GrTexture*[]) { SkScalar w = random->nextRangeScalar(20.f, 1000.f); SkScalar h = random->nextRangeScalar(20.f, 1000.f); SkScalar r = random->nextRangeF(kRadiusMin, 9.f); SkRRect rrect; rrect.setRectXY(SkRect::MakeWH(w, h), r, r); GrFragmentProcessor* fp; do { GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)random->nextULessThan(kGrProcessorEdgeTypeCnt); fp = GrRRectEffect::Create(et, rrect); } while (NULL == fp); return fp; }
static void drawshader_proc(SkCanvas* canvas, const SkBitmap& bm, const SkPoint& pos) { SkRect r = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) }; r.offset(pos.fX, pos.fY); SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); SkPaint paint; paint.setShader(s)->unref(); canvas->drawRect(r, paint); canvas->drawOval(r, paint); SkRRect rr; rr.setRectXY(r, 10, 10); canvas->drawRRect(rr, paint); }
static void AddShape(SkPath* path, const SkRect& rect, Shapes shape, SkPath::Direction dir) { switch (shape) { case kRect_Shape: path->addRect(rect, dir); break; case kRRect_Shape: { SkRRect rr; rr.setRectXY(rect, 5, 5); path->addRRect(rr, dir); break; } case kOval_Shape: path->addOval(rect, dir); break; default: break; } }
static void test_round_rect_transform(skiatest::Reporter* reporter) { SkRRect rrect; { SkRect r = { 0, 0, kWidth, kHeight }; rrect.setRectXY(r, SkIntToScalar(4), SkIntToScalar(7)); test_transform_helper(reporter, rrect); } { SkRect r = { SkIntToScalar(5), SkIntToScalar(15), SkIntToScalar(27), SkIntToScalar(34) }; SkVector radii[4] = { { 0, SkIntToScalar(1) }, { SkIntToScalar(2), SkIntToScalar(3) }, { SkIntToScalar(4), SkIntToScalar(5) }, { SkIntToScalar(6), SkIntToScalar(7) } }; rrect.setRectRadii(r, radii); test_transform_helper(reporter, rrect); } }
// 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); } }
DEF_TEST(RRectMaskCache, reporter) { SkResourceCache cache(1024); SkScalar sigma = 0.8f; SkRect rect = SkRect::MakeWH(100, 100); SkRRect rrect; rrect.setRectXY(rect, 30, 30); SkBlurStyle style = kNormal_SkBlurStyle; SkBlurQuality quality = kLow_SkBlurQuality; SkMask mask; SkCachedData* data = SkMaskCache::FindAndRef(sigma, style, quality, rrect, &mask, &cache); REPORTER_ASSERT(reporter, NULL == data); size_t size = 256; data = cache.newCachedData(size); memset(data->writable_data(), 0xff, size); mask.fBounds.setXYWH(0, 0, 100, 100); mask.fRowBytes = 100; mask.fFormat = SkMask::kBW_Format; SkMaskCache::Add(sigma, style, quality, rrect, mask, data, &cache); check_data(reporter, data, 2, kInCache, kLocked); data->unref(); check_data(reporter, data, 1, kInCache, kUnlocked); sk_bzero(&mask, sizeof(mask)); data = SkMaskCache::FindAndRef(sigma, style, quality, rrect, &mask, &cache); REPORTER_ASSERT(reporter, data); REPORTER_ASSERT(reporter, data->size() == size); REPORTER_ASSERT(reporter, mask.fBounds.top() == 0 && mask.fBounds.bottom() == 100); REPORTER_ASSERT(reporter, data->data() == (const void*)mask.fImage); check_data(reporter, data, 2, kInCache, kLocked); cache.purgeAll(); check_data(reporter, data, 1, kNotInCache, kLocked); data->unref(); }
static void test_really_a_rect(skiatest::Reporter* reporter) { SkRRect rrect; rrect.setRectXY(SkRect::MakeWH(100, 100), 5, 5); SkPath path; path.addRRect(rrect); SkAAClip clip; clip.setPath(path); REPORTER_ASSERT(reporter, clip.getBounds() == SkIRect::MakeWH(100, 100)); REPORTER_ASSERT(reporter, !clip.isRect()); // This rect should intersect the clip, but slice-out all of the "soft" parts, // leaving just a rect. const SkIRect ir = SkIRect::MakeLTRB(10, -10, 50, 90); clip.op(ir, SkRegion::kIntersect_Op); REPORTER_ASSERT(reporter, clip.getBounds() == SkIRect::MakeLTRB(10, 0, 50, 90)); // the clip recognized that that it is just a rect! REPORTER_ASSERT(reporter, clip.isRect()); }
GrFragmentProcessor* EllipticalRRectEffect::TestCreate(SkRandom* random, GrContext*, const GrDrawTargetCaps& caps, GrTexture*[]) { SkScalar w = random->nextRangeScalar(20.f, 1000.f); SkScalar h = random->nextRangeScalar(20.f, 1000.f); SkVector r[4]; r[SkRRect::kUpperLeft_Corner].fX = random->nextRangeF(kRadiusMin, 9.f); // ensure at least one corner really is elliptical do { r[SkRRect::kUpperLeft_Corner].fY = random->nextRangeF(kRadiusMin, 9.f); } while (r[SkRRect::kUpperLeft_Corner].fY == r[SkRRect::kUpperLeft_Corner].fX); SkRRect rrect; if (random->nextBool()) { // half the time create a four-radii rrect. r[SkRRect::kLowerRight_Corner].fX = random->nextRangeF(kRadiusMin, 9.f); r[SkRRect::kLowerRight_Corner].fY = random->nextRangeF(kRadiusMin, 9.f); r[SkRRect::kUpperRight_Corner].fX = r[SkRRect::kLowerRight_Corner].fX; r[SkRRect::kUpperRight_Corner].fY = r[SkRRect::kUpperLeft_Corner].fY; r[SkRRect::kLowerLeft_Corner].fX = r[SkRRect::kUpperLeft_Corner].fX; r[SkRRect::kLowerLeft_Corner].fY = r[SkRRect::kLowerRight_Corner].fY; rrect.setRectRadii(SkRect::MakeWH(w, h), r); } else { rrect.setRectXY(SkRect::MakeWH(w, h), r[SkRRect::kUpperLeft_Corner].fX, r[SkRRect::kUpperLeft_Corner].fY); } GrFragmentProcessor* fp; do { GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)random->nextULessThan(kGrProcessorEdgeTypeCnt); fp = GrRRectEffect::Create(et, rrect); } while (NULL == fp); return fp; }
PassOwnPtr<DragImage> DragImage::create(const KURL& url, const String& inLabel, const FontDescription& systemFont, float deviceScaleFactor) { const Font labelFont = deriveDragLabelFont(kDragLinkLabelFontSize, FontWeightBold, systemFont); const Font urlFont = deriveDragLabelFont(kDragLinkUrlFontSize, FontWeightNormal, systemFont); FontCachePurgePreventer fontCachePurgePreventer; bool drawURLString = true; bool clipURLString = false; bool clipLabelString = false; String urlString = url.string(); String label = inLabel.stripWhiteSpace(); if (label.isEmpty()) { drawURLString = false; label = urlString; } // First step is drawing the link drag image width. TextRun labelRun(label.impl()); TextRun urlRun(urlString.impl()); IntSize labelSize(labelFont.width(labelRun), labelFont.fontMetrics().ascent() + labelFont.fontMetrics().descent()); if (labelSize.width() > kMaxDragLabelStringWidth) { labelSize.setWidth(kMaxDragLabelStringWidth); clipLabelString = true; } IntSize urlStringSize; IntSize imageSize(labelSize.width() + kDragLabelBorderX * 2, labelSize.height() + kDragLabelBorderY * 2); if (drawURLString) { urlStringSize.setWidth(urlFont.width(urlRun)); urlStringSize.setHeight(urlFont.fontMetrics().ascent() + urlFont.fontMetrics().descent()); imageSize.setHeight(imageSize.height() + urlStringSize.height()); if (urlStringSize.width() > kMaxDragLabelStringWidth) { imageSize.setWidth(kMaxDragLabelWidth); clipURLString = true; } else imageSize.setWidth(std::max(labelSize.width(), urlStringSize.width()) + kDragLabelBorderX * 2); } // We now know how big the image needs to be, so we create and // fill the background IntSize scaledImageSize = imageSize; scaledImageSize.scale(deviceScaleFactor); OwnPtr<ImageBuffer> buffer(ImageBuffer::create(scaledImageSize)); if (!buffer) return nullptr; buffer->canvas()->scale(deviceScaleFactor, deviceScaleFactor); const float DragLabelRadius = 5; IntRect rect(IntPoint(), imageSize); SkPaint backgroundPaint; backgroundPaint.setColor(SkColorSetRGB(140, 140, 140)); SkRRect rrect; rrect.setRectXY(SkRect::MakeWH(imageSize.width(), imageSize.height()), DragLabelRadius, DragLabelRadius); buffer->canvas()->drawRRect(rrect, backgroundPaint); // Draw the text SkPaint textPaint; if (drawURLString) { if (clipURLString) urlString = StringTruncator::centerTruncate(urlString, imageSize.width() - (kDragLabelBorderX * 2.0f), urlFont); IntPoint textPos(kDragLabelBorderX, imageSize.height() - (kLabelBorderYOffset + urlFont.fontMetrics().descent())); TextRun textRun(urlString); urlFont.drawText(buffer->canvas(), TextRunPaintInfo(textRun), textPos, deviceScaleFactor, textPaint); } if (clipLabelString) label = StringTruncator::rightTruncate(label, imageSize.width() - (kDragLabelBorderX * 2.0f), labelFont); bool hasStrongDirectionality; TextRun textRun = textRunWithDirectionality(label, &hasStrongDirectionality); IntPoint textPos(kDragLabelBorderX, kDragLabelBorderY + labelFont.fontDescription().computedPixelSize()); if (hasStrongDirectionality && textRun.direction() == RTL) { float textWidth = labelFont.width(textRun); int availableWidth = imageSize.width() - kDragLabelBorderX * 2; textPos.setX(availableWidth - ceilf(textWidth)); } labelFont.drawBidiText(buffer->canvas(), TextRunPaintInfo(textRun), FloatPoint(textPos), Font::DoNotPaintIfFontNotReady, deviceScaleFactor, textPaint); RefPtr<Image> image = buffer->newImageSnapshot(); return DragImage::create(image.get(), DoNotRespectImageOrientation, deviceScaleFactor); }
void drawFocusRingPrimitive<SkRect>(const SkRect& rect, SkCanvas* canvas, const SkPaint& paint, float cornerRadius) { SkRRect rrect; rrect.setRectXY(rect, SkFloatToScalar(cornerRadius), SkFloatToScalar(cornerRadius)); canvas->drawRRect(rrect, paint); }
SkRect draw(SkCanvas* canvas, const SkPaint& paint) override { SkRRect rrect; rrect.setRectXY(SkRect::MakeXYWH(0, 0, 50, 50), 10, 10); canvas->drawRRect(rrect, paint); return rrect.getBounds(); }
void onDraw(SkCanvas* canvas) override { SkRandom rand(1); canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1); const SkRect rect = SkRect::MakeLTRB(-20, -30, 20, 30); SkRRect circleRect; circleRect.setRectXY(rect, 5, 5); const SkScalar kXStart = 60.0f; const SkScalar kYStart = 80.0f; const int kXStep = 150; const int kYStep = 160; int maxX = fMatrices.count(); SkPaint rectPaint; rectPaint.setAntiAlias(true); rectPaint.setStyle(SkPaint::kStroke_Style); rectPaint.setStrokeWidth(SkIntToScalar(0)); rectPaint.setColor(sk_tool_utils::color_to_565(SK_ColorLTGRAY)); int testCount = 0; for (int i = 0; i < fPaints.count(); ++i) { for (int j = 0; j < fMatrices.count(); ++j) { canvas->save(); SkMatrix mat = fMatrices[j]; // position the roundrect, and make it at off-integer coords. mat.postTranslate(kXStart + SK_Scalar1 * kXStep * (testCount % maxX) + SK_Scalar1 / 4, kYStart + SK_Scalar1 * kYStep * (testCount / maxX) + 3 * SK_Scalar1 / 4); canvas->concat(mat); SkColor color = gen_color(&rand); fPaints[i].setColor(color); canvas->drawRect(rect, rectPaint); canvas->drawRRect(circleRect, fPaints[i]); canvas->restore(); ++testCount; } } // special cases // non-scaled tall and skinny roundrect for (int i = 0; i < fPaints.count(); ++i) { SkRect rect = SkRect::MakeLTRB(-20, -60, 20, 60); SkRRect ellipseRect; ellipseRect.setRectXY(rect, 5, 10); canvas->save(); // position the roundrect, and make it at off-integer coords. canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.55f + SK_Scalar1 / 4, kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4); SkColor color = gen_color(&rand); fPaints[i].setColor(color); canvas->drawRect(rect, rectPaint); canvas->drawRRect(ellipseRect, fPaints[i]); canvas->restore(); } // non-scaled wide and short roundrect for (int i = 0; i < fPaints.count(); ++i) { SkRect rect = SkRect::MakeLTRB(-80, -30, 80, 30); SkRRect ellipseRect; ellipseRect.setRectXY(rect, 20, 5); canvas->save(); // position the roundrect, and make it at off-integer coords. canvas->translate(kXStart + SK_Scalar1 * kXStep * 4 + SK_Scalar1 / 4, kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 + SK_ScalarHalf * kYStep); SkColor color = gen_color(&rand); fPaints[i].setColor(color); canvas->drawRect(rect, rectPaint); canvas->drawRRect(ellipseRect, fPaints[i]); canvas->restore(); } // super skinny roundrect for (int i = 0; i < fPaints.count(); ++i) { SkRect rect = SkRect::MakeLTRB(0, -60, 1, 60); SkRRect circleRect; circleRect.setRectXY(rect, 5, 5); canvas->save(); // position the roundrect, and make it at off-integer coords. canvas->translate(kXStart + SK_Scalar1 * kXStep * 3.25f + SK_Scalar1 / 4, kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4); SkColor color = gen_color(&rand); fPaints[i].setColor(color); canvas->drawRRect(circleRect, fPaints[i]); canvas->restore(); } // super short roundrect for (int i = 0; i < fPaints.count(); ++i) { SkRect rect = SkRect::MakeLTRB(-80, -1, 80, 0); SkRRect circleRect; circleRect.setRectXY(rect, 5, 5); canvas->save(); // position the roundrect, and make it at off-integer coords. canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.5f + SK_Scalar1 / 4, kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 + SK_ScalarHalf * kYStep); SkColor color = gen_color(&rand); fPaints[i].setColor(color); canvas->drawRRect(circleRect, fPaints[i]); canvas->restore(); } // radial gradient SkPoint center = SkPoint::Make(SkIntToScalar(0), SkIntToScalar(0)); SkColor colors[] = { SK_ColorBLUE, SK_ColorRED, SK_ColorGREEN }; SkScalar pos[] = { 0, SK_ScalarHalf, SK_Scalar1 }; auto shader = SkGradientShader::MakeRadial(center, 20, colors, pos, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode); for (int i = 0; i < fPaints.count(); ++i) { canvas->save(); // position the path, and make it at off-integer coords. canvas->translate(kXStart + SK_Scalar1 * kXStep * 0 + SK_Scalar1 / 4, kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 + SK_ScalarHalf * kYStep); SkColor color = gen_color(&rand); fPaints[i].setColor(color); fPaints[i].setShader(shader); canvas->drawRect(rect, rectPaint); canvas->drawRRect(circleRect, fPaints[i]); fPaints[i].setShader(nullptr); canvas->restore(); } // strokes and radii { SkScalar radii[][2] = { {10,10}, {5,15}, {5,15}, {5,15} }; SkScalar strokeWidths[] = { 20, 10, 20, 40 }; for (int i = 0; i < 4; ++i) { SkRRect circleRect; circleRect.setRectXY(rect, radii[i][0], radii[i][1]); canvas->save(); // position the roundrect, and make it at off-integer coords. canvas->translate(kXStart + SK_Scalar1 * kXStep * 5 + SK_Scalar1 / 4, kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 + SK_ScalarHalf * kYStep); SkColor color = gen_color(&rand); SkPaint p; p.setAntiAlias(true); p.setStyle(SkPaint::kStroke_Style); p.setStrokeWidth(strokeWidths[i]); p.setColor(color); canvas->drawRRect(circleRect, p); canvas->restore(); } } // test old entry point ( https://bug.skia.org/3786 ) { canvas->save(); canvas->translate(kXStart + SK_Scalar1 * kXStep * 5 + SK_Scalar1 / 4, kYStart + SK_Scalar1 * kYStep * 4 + SK_Scalar1 / 4 + SK_ScalarHalf * kYStep); const SkColor color = gen_color(&rand); SkPaint p; p.setColor(color); const SkRect oooRect = { 20, 30, -20, -30 }; // intentionally out of order canvas->drawRoundRect(oooRect, 10, 10, p); canvas->restore(); } // rrect with stroke > radius/2 { SkRect smallRect = { -30, -20, 30, 20 }; SkRRect circleRect; circleRect.setRectXY(smallRect, 5, 5); canvas->save(); // position the roundrect, and make it at off-integer coords. canvas->translate(kXStart + SK_Scalar1 * kXStep * 5 + SK_Scalar1 / 4, kYStart - SK_Scalar1 * kYStep + 73 * SK_Scalar1 / 4 + SK_ScalarHalf * kYStep); SkColor color = gen_color(&rand); SkPaint p; p.setAntiAlias(true); p.setStyle(SkPaint::kStroke_Style); p.setStrokeWidth(25); p.setColor(color); canvas->drawRRect(circleRect, p); canvas->restore(); } }
SkRRect create_rrect(const SkPoint& offset) { SkRRect rrect; rrect.setRectXY(create_rect(offset), 10, 10); return rrect; }
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); }