DEF_TEST(contour_measure, reporter) { SkPath path; path.addCircle(0, 0, 100); path.addCircle(0, 0, 10); SkContourMeasureIter fact(path, false); path.reset(); // we should not need the path avert we created the factory auto cm0 = fact.next(); auto cm1 = fact.next(); REPORTER_ASSERT(reporter, cm0->isClosed()); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(cm0->length(), 200 * SK_ScalarPI, 1.5f)); test_90_degrees(cm0, 100, reporter); REPORTER_ASSERT(reporter, cm1->isClosed()); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(cm1->length(), 20 * SK_ScalarPI, 0.5f)); test_90_degrees(cm1, 10, reporter); auto cm2 = fact.next(); REPORTER_ASSERT(reporter, !cm2); test_empty_contours(reporter); test_MLM_contours(reporter); }
void draw_fill(SkCanvas* canvas, const SkRect& rect, SkScalar width) { if (rect.isEmpty()) { return; } SkPaint paint; paint.setColor(0x1f1f0f0f); paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(width); SkPath path; SkScalar maxSide = SkTMax(rect.width(), rect.height()) / 2; SkPoint center = { rect.fLeft + maxSide, rect.fTop + maxSide }; path.addCircle(center.fX, center.fY, maxSide); canvas->drawPath(path, paint); paint.setStyle(SkPaint::kFill_Style); path.reset(); path.addCircle(center.fX, center.fY, maxSide - width / 2); paint.setColor(0x3f0f1f3f); canvas->drawPath(path, paint); path.reset(); path.setFillType(SkPath::kEvenOdd_FillType); path.addCircle(center.fX, center.fY, maxSide + width / 2); SkRect outside = SkRect::MakeXYWH(center.fX - maxSide - width, center.fY - maxSide - width, (maxSide + width) * 2, (maxSide + width) * 2); path.addRect(outside); canvas->drawPath(path, paint); }
void makePath() { if (fPath.isEmpty()) { const SkScalar radius = SkIntToScalar(45); fPath.addCircle(SkIntToScalar(50), SkIntToScalar(50), radius); fPath.addCircle(SkIntToScalar(100), SkIntToScalar(100), radius); } }
FillTypeView() { const SkScalar radius = SkIntToScalar(45); fPath.addCircle(SkIntToScalar(50), SkIntToScalar(50), radius); fPath.addCircle(SkIntToScalar(100), SkIntToScalar(100), radius); this->setBGColor(0xFFDDDDDD); }
void onOnceBeforeDraw() override { fX1 = 80; fX2 = 120; fY = 50; fR = 40; fCircle1.addCircle(fX1, fY, fR, SkPath::kCW_Direction); fCircle2.addCircle(fX2, fY, fR, SkPath::kCW_Direction); }
virtual void onDraw(SkCanvas* canvas) { SkPath path; path.addCircle(SkIntToScalar(50), SkIntToScalar(50), SkIntToScalar(40)); path.toggleInverseFillType(); SkRect clipR = { 0, 0, SkIntToScalar(100), SkIntToScalar(200) }; canvas->translate(SkIntToScalar(10), SkIntToScalar(10)); for (int doclip = 0; doclip <= 1; ++doclip) { for (int aa = 0; aa <= 1; ++aa) { SkPaint paint; paint.setAntiAlias(SkToBool(aa)); canvas->save(); canvas->clipRect(clipR); const SkRect* clipPtr = doclip ? &clipR : NULL; show(canvas, path, paint, clipPtr, clipR.fTop, clipR.centerY()); show(canvas, path, paint, clipPtr, clipR.centerY(), clipR.fBottom); canvas->restore(); canvas->translate(SkIntToScalar(110), 0); } } }
static void TestOverflowHitTest() { SkPath path; #ifdef SK_SCALAR_IS_FLOATx path.addCircle(0, 0, 70000, SkPath::kCCW_Direction); SkASSERT(HitTestPath(path, 40000, 40000)); #endif }
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(); }
static void TestOverflowHitTest() { SkPath path; #ifdef SK_SCALAR_IS_FLOATx // FIXME: unclear when if ever this can be enabled path.addCircle(0, 0, 70000, SkPath::kCCW_Direction); SkASSERT(HitTestPath(path, 40000, 40000)); #endif }
virtual void onDraw(SkCanvas* canvas) { SkMatrix m; m.reset(); m.setRotate(33 * SK_Scalar1); m.postScale(3000 * SK_Scalar1, 3000 * SK_Scalar1); m.postTranslate(6000 * SK_Scalar1, -5000 * SK_Scalar1); canvas->concat(m); SkPaint paint; paint.setColor(SK_ColorRED); paint.setAntiAlias(true); bool success = m.invert(&m); SkASSERT(success); (void) success; // silence compiler :( SkPath path; SkPoint pt = {10 * SK_Scalar1, 10 * SK_Scalar1}; SkScalar small = 1 / (500 * SK_Scalar1); m.mapPoints(&pt, 1); path.addCircle(pt.fX, pt.fY, small); canvas->drawPath(path, paint); pt.set(30 * SK_Scalar1, 10 * SK_Scalar1); m.mapPoints(&pt, 1); SkRect rect = {pt.fX - small, pt.fY - small, pt.fX + small, pt.fY + small}; canvas->drawRect(rect, paint); SkBitmap bmp; bmp.setConfig(SkBitmap::kARGB_8888_Config, 2, 2); bmp.allocPixels(); bmp.lockPixels(); uint32_t* pixels = reinterpret_cast<uint32_t*>(bmp.getPixels()); pixels[0] = SkPackARGB32(0xFF, 0xFF, 0x00, 0x00); pixels[1] = SkPackARGB32(0xFF, 0x00, 0xFF, 0x00); pixels[2] = SkPackARGB32(0x80, 0x00, 0x00, 0x00); pixels[3] = SkPackARGB32(0xFF, 0x00, 0x00, 0xFF); bmp.unlockPixels(); pt.set(30 * SK_Scalar1, 30 * SK_Scalar1); m.mapPoints(&pt, 1); SkShader* shader = SkShader::CreateBitmapShader( bmp, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); SkMatrix s; s.reset(); s.setScale(SK_Scalar1 / 1000, SK_Scalar1 / 1000); shader->setLocalMatrix(s); paint.setShader(shader)->unref(); paint.setAntiAlias(false); paint.setFilterLevel(SkPaint::kLow_FilterLevel); rect.setLTRB(pt.fX - small, pt.fY - small, pt.fX + small, pt.fY + small); canvas->drawRect(rect, paint); }
static SkPathEffect* MakeTileEffect() { SkMatrix m; m.setScale(SkIntToScalar(12), SkIntToScalar(12)); SkPath path; path.addCircle(0, 0, SkIntToScalar(5)); return SkPath2DPathEffect::Create(m, path); }
static sk_sp<SkPathEffect> make_tile_effect() { SkMatrix m; m.setScale(1.f, 1.f); SkPath path; path.addCircle(0, 0, SkIntToScalar(5)); return SkPath2DPathEffect::Make(m, path); }
virtual void onDraw(SkCanvas* canvas) { SkScalar x = SkIntToScalar(100); SkScalar y = SkIntToScalar(88); SkPaint paint; paint.setAntiAlias(true); paint.setTextSize(SkIntToScalar(100)); paint.setStrokeWidth(SkIntToScalar(5)); SkTypeface* face = SkTypeface::CreateFromName("Papyrus", SkTypeface::kNormal); SkSafeUnref(paint.setTypeface(face)); show_bold(canvas, "Hello", 5, x, y, paint); face = SkTypeface::CreateFromName("Hiragino Maru Gothic Pro", SkTypeface::kNormal); SkSafeUnref(paint.setTypeface(face)); const unsigned char hyphen[] = { 0xE3, 0x83, 0xBC }; show_bold(canvas, hyphen, SK_ARRAY_COUNT(hyphen), x + SkIntToScalar(300), y, paint); paint.setStyle(SkPaint::kStrokeAndFill_Style); SkPath path; path.setFillType(SkPath::kWinding_FillType); path.addCircle(x, y + SkIntToScalar(200), SkIntToScalar(50), SkPath::kCW_Direction); path.addCircle(x, y + SkIntToScalar(200), SkIntToScalar(40), SkPath::kCCW_Direction); canvas->drawPath(path, paint); SkPath path2; path2.setFillType(SkPath::kWinding_FillType); path2.addCircle(x + SkIntToScalar(120), y + SkIntToScalar(200), SkIntToScalar(50), SkPath::kCCW_Direction); path2.addCircle(x + SkIntToScalar(120), y + SkIntToScalar(200), SkIntToScalar(40), SkPath::kCW_Direction); canvas->drawPath(path2, paint); path2.reset(); path2.addCircle(x + SkIntToScalar(240), y + SkIntToScalar(200), SkIntToScalar(50), SkPath::kCCW_Direction); canvas->drawPath(path2, paint); SkASSERT(path2.cheapIsDirection(SkPath::kCCW_Direction)); path2.reset(); SkASSERT(!path2.cheapComputeDirection(NULL)); path2.addCircle(x + SkIntToScalar(360), y + SkIntToScalar(200), SkIntToScalar(50), SkPath::kCW_Direction); SkASSERT(path2.cheapIsDirection(SkPath::kCW_Direction)); canvas->drawPath(path2, paint); }
StrokePathView() { // test_blur(); fWidth = SkIntToScalar(120); #if 0 const char str[] = "M 0, 3" "C 10, -10, 30, -10, 0, 28" "C -30, -10, -10, -10, 0, 3" "Z"; SkParsePath::FromSVGString(str, &fPath); #else fPath.addCircle(0, 0, SkIntToScalar(50), SkPath::kCW_Direction); fPath.addCircle(0, SkIntToScalar(-50), SkIntToScalar(30), SkPath::kCW_Direction); #endif scale_to_width(&fPath, fWidth); const SkRect& bounds = fPath.getBounds(); fPath.offset(-bounds.fLeft, -bounds.fTop); }
void SkPathStroker::quadTo(const SkPoint& pt1, const SkPoint& pt2) { bool degenerateAB = SkPath::IsLineDegenerate(fPrevPt, pt1); bool degenerateBC = SkPath::IsLineDegenerate(pt1, pt2); if (degenerateAB | degenerateBC) { if (degenerateAB ^ degenerateBC) { this->lineTo(pt2); } return; } SkVector normalAB, unitAB, normalBC, unitBC; this->preJoinTo(pt1, &normalAB, &unitAB, false); { SkPoint pts[3], tmp[5]; pts[0] = fPrevPt; pts[1] = pt1; pts[2] = pt2; if (SkChopQuadAtMaxCurvature(pts, tmp) == 2) { unitBC.setNormalize(pts[2].fX - pts[1].fX, pts[2].fY - pts[1].fY); unitBC.rotateCCW(); if (normals_too_pinchy(unitAB, unitBC)) { normalBC = unitBC; normalBC.scale(fRadius); fOuter.lineTo(tmp[2].fX + normalAB.fX, tmp[2].fY + normalAB.fY); fOuter.lineTo(tmp[2].fX + normalBC.fX, tmp[2].fY + normalBC.fY); fOuter.lineTo(tmp[4].fX + normalBC.fX, tmp[4].fY + normalBC.fY); fInner.lineTo(tmp[2].fX - normalAB.fX, tmp[2].fY - normalAB.fY); fInner.lineTo(tmp[2].fX - normalBC.fX, tmp[2].fY - normalBC.fY); fInner.lineTo(tmp[4].fX - normalBC.fX, tmp[4].fY - normalBC.fY); fExtra.addCircle(tmp[2].fX, tmp[2].fY, fRadius, SkPath::kCW_Direction); } else { this->quad_to(&tmp[0], normalAB, unitAB, &normalBC, &unitBC, kMaxQuadSubdivide); SkVector n = normalBC; SkVector u = unitBC; this->quad_to(&tmp[2], n, u, &normalBC, &unitBC, kMaxQuadSubdivide); } } else { this->quad_to(pts, normalAB, unitAB, &normalBC, &unitBC, kMaxQuadSubdivide); } } this->postJoinTo(pt2, normalBC, unitBC); }
AAClipRegionBench(void* param) : INHERITED(param) { SkPath path; // test conversion of a complex clip to a aaclip path.addCircle(0, 0, SkIntToScalar(200)); path.addCircle(0, 0, SkIntToScalar(180)); // evenodd means we've constructed basically a stroked circle path.setFillType(SkPath::kEvenOdd_FillType); SkIRect bounds; path.getBounds().roundOut(&bounds); fRegion.setPath(path, SkRegion(bounds)); }
DEF_TEST(BuilderIssue3838_2, reporter) { SkPath path; path.addCircle(100, 100, 50); SkOpBuilder builder; builder.add(path, kUnion_SkPathOp); builder.add(path, kUnion_SkPathOp); SkPath result; builder.resolve(&result); int pixelDiff = comparePaths(reporter, __FUNCTION__, path, result); REPORTER_ASSERT(reporter, pixelDiff == 0); }
void onOnceBeforeDraw() override { // test_blur(); fWidth = SkIntToScalar(120); #if 0 const char str[] = "M 0, 3" "C 10, -10, 30, -10, 0, 28" "C -30, -10, -10, -10, 0, 3" "Z"; SkParsePath::FromSVGString(str, &fPath); #else fPath.addCircle(0, 0, SkIntToScalar(50), SkPath::kCW_Direction); fPath.addCircle(0, SkIntToScalar(-50), SkIntToScalar(30), SkPath::kCW_Direction); #endif scale_to_width(&fPath, fWidth); const SkRect& bounds = fPath.getBounds(); fPath.offset(-bounds.fLeft, -bounds.fTop); this->setBGColor(0xFFDDDDDD); }
PathTexture* CircleShapeCache::getCircle(float radius, SkPaint* paint) { CircleShapeCacheEntry entry(radius, paint); PathTexture* texture = get(entry); if (!texture) { SkPath path; path.addCircle(radius, radius, radius, SkPath::kCW_Direction); texture = addTexture(entry, &path, paint); } return texture; }
static void test_convexity(skiatest::Reporter* reporter) { static const SkPath::Convexity C = SkPath::kConcave_Convexity; static const SkPath::Convexity V = SkPath::kConvex_Convexity; SkPath path; REPORTER_ASSERT(reporter, V == SkPath::ComputeConvexity(path)); path.addCircle(0, 0, 10); REPORTER_ASSERT(reporter, V == SkPath::ComputeConvexity(path)); path.addCircle(0, 0, 10); // 2nd circle REPORTER_ASSERT(reporter, C == SkPath::ComputeConvexity(path)); path.reset(); path.addRect(0, 0, 10, 10, SkPath::kCCW_Direction); REPORTER_ASSERT(reporter, V == SkPath::ComputeConvexity(path)); path.reset(); path.addRect(0, 0, 10, 10, SkPath::kCW_Direction); REPORTER_ASSERT(reporter, V == SkPath::ComputeConvexity(path)); static const struct { const char* fPathStr; SkPath::Convexity fExpectedConvexity; } gRec[] = { { "", SkPath::kConvex_Convexity }, { "0 0", SkPath::kConvex_Convexity }, { "0 0 10 10", SkPath::kConvex_Convexity }, { "0 0 10 10 20 20 0 0 10 10", SkPath::kConcave_Convexity }, { "0 0 10 10 10 20", SkPath::kConvex_Convexity }, { "0 0 10 10 10 0", SkPath::kConvex_Convexity }, { "0 0 10 10 10 0 0 10", SkPath::kConcave_Convexity }, { "0 0 10 0 0 10 -10 -10", SkPath::kConcave_Convexity }, }; for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { SkPath path; setFromString(&path, gRec[i].fPathStr); SkPath::Convexity c = SkPath::ComputeConvexity(path); REPORTER_ASSERT(reporter, c == gRec[i].fExpectedConvexity); } }
void onOnceBeforeDraw() override { this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD)); fCirclePath.addCircle(SkIntToScalar(20), SkIntToScalar(20), SkIntToScalar(10) ); fRect.set(SkIntToScalar(10), SkIntToScalar(10), SkIntToScalar(30), SkIntToScalar(30)); fBitmap.allocPixels(SkImageInfo::Make(20, 20, SkColorType::kAlpha_8_SkColorType, kPremul_SkAlphaType)); SkCanvas canvas(fBitmap); canvas.clear(0x0); SkPaint p; canvas.drawRect(SkRect::MakeXYWH(10, 0, 10, 10), p); canvas.drawRect(SkRect::MakeXYWH(0, 10, 10, 10), p); }
void onDraw(SkCanvas* canvas) override { SkPaint p; p.setColor(SK_ColorRED); p.setAntiAlias(true); canvas->save(); SkPath path; path.addCircle(100, 100, 30); path.setFillType(SkPath::kInverseWinding_FillType); canvas->drawPath(path, p); canvas->restore(); }
void draw(SkCanvas* canvas) { auto debugster = [](const char* prefix, const SkPath& path) -> void { const SkRect& bounds = path.getBounds(); SkDebugf("%s bounds = %g, %g, %g, %g\n", prefix, bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); }; SkPath path; debugster("empty", path); path.addCircle(50, 45, 25); debugster("circle", path); SkMatrix matrix; matrix.setRotate(45, 50, 45); path.transform(matrix); debugster("rotated circle", path); }
PathTexture* PathCache::getCircle(float radius, const SkPaint* paint) { PathDescription entry(kShapeCircle, paint); entry.shape.circle.mRadius = radius; PathTexture* texture = get(entry); if (!texture) { SkPath path; path.addCircle(radius, radius, radius, SkPath::kCW_Direction); texture = addTexture(entry, &path, paint); } return texture; }
// aaclip.setRegion should create idential masks to the region static void test_rgn(skiatest::Reporter* reporter) { SkRandom rand; for (int i = 0; i < 1000; i++) { SkRegion rgn; make_rand_rgn(&rgn, rand); REPORTER_ASSERT(reporter, equalsAAClip(rgn)); } { SkRegion rgn; SkPath path; path.addCircle(0, 0, SkIntToScalar(30)); setRgnToPath(&rgn, path); REPORTER_ASSERT(reporter, equalsAAClip(rgn)); path.reset(); path.moveTo(0, 0); path.lineTo(SkIntToScalar(100), 0); path.lineTo(SkIntToScalar(100 - 20), SkIntToScalar(20)); path.lineTo(SkIntToScalar(20), SkIntToScalar(20)); setRgnToPath(&rgn, path); REPORTER_ASSERT(reporter, equalsAAClip(rgn)); } }
static SkPathEffect* MakeDotEffect(SkScalar radius, const SkMatrix& matrix) { SkPath path; path.addCircle(0, 0, radius); return SkPath2DPathEffect::Create(matrix, path); }
// Building aaclip meant aa-scan-convert a path into a huge clip. // the old algorithm sized the supersampler to the size of the clip, which overflowed // its internal 16bit coordinates. The fix was to intersect the clip+path_bounds before // sizing the supersampler. // // Before the fix, the following code would assert in debug builds. // static void test_crbug_422693(skiatest::Reporter* reporter) { SkRasterClip rc(SkIRect::MakeLTRB(-25000, -25000, 25000, 25000)); SkPath path; path.addCircle(50, 50, 50); rc.op(path, rc.getBounds().size(), SkRegion::kIntersect_Op, true); }
static void TestPathMeasure(skiatest::Reporter* reporter) { SkPath path; path.moveTo(0, 0); path.lineTo(SK_Scalar1, 0); path.lineTo(SK_Scalar1, SK_Scalar1); path.lineTo(0, SK_Scalar1); SkPathMeasure meas(path, true); SkScalar length = meas.getLength(); SkASSERT(length == SK_Scalar1*4); path.reset(); path.moveTo(0, 0); path.lineTo(SK_Scalar1*3, SK_Scalar1*4); meas.setPath(&path, false); length = meas.getLength(); REPORTER_ASSERT(reporter, length == SK_Scalar1*5); path.reset(); path.addCircle(0, 0, SK_Scalar1); meas.setPath(&path, true); length = meas.getLength(); // SkDebugf("circle arc-length = %g\n", length); // Test the behavior following a close not followed by a move. path.reset(); path.lineTo(SK_Scalar1, 0); path.lineTo(SK_Scalar1, SK_Scalar1); path.lineTo(0, SK_Scalar1); path.close(); path.lineTo(-SK_Scalar1, 0); meas.setPath(&path, false); length = meas.getLength(); REPORTER_ASSERT(reporter, length == SK_Scalar1 * 4); meas.nextContour(); length = meas.getLength(); REPORTER_ASSERT(reporter, length == SK_Scalar1); SkPoint position; SkVector tangent; REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(position.fX, -SK_ScalarHalf, SkFloatToScalar(0.0001f))); REPORTER_ASSERT(reporter, position.fY == 0); REPORTER_ASSERT(reporter, tangent.fX == -SK_Scalar1); REPORTER_ASSERT(reporter, tangent.fY == 0); // Test degenerate paths path.reset(); path.moveTo(0, 0); path.lineTo(0, 0); path.lineTo(SK_Scalar1, 0); path.quadTo(SK_Scalar1, 0, SK_Scalar1, 0); path.quadTo(SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1 * 2); path.cubicTo(SK_Scalar1, SK_Scalar1 * 2, SK_Scalar1, SK_Scalar1 * 2, SK_Scalar1, SK_Scalar1 * 2); path.cubicTo(SK_Scalar1*2, SK_Scalar1 * 2, SK_Scalar1*3, SK_Scalar1 * 2, SK_Scalar1*4, SK_Scalar1 * 2); meas.setPath(&path, false); length = meas.getLength(); REPORTER_ASSERT(reporter, length == SK_Scalar1 * 6); REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(position.fX, SK_ScalarHalf, SkFloatToScalar(0.0001f))); REPORTER_ASSERT(reporter, position.fY == 0); REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1); REPORTER_ASSERT(reporter, tangent.fY == 0); REPORTER_ASSERT(reporter, meas.getPosTan(SkFloatToScalar(2.5f), &position, &tangent)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(position.fX, SK_Scalar1, SkFloatToScalar(0.0001f))); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(position.fY, SkFloatToScalar(1.5f))); REPORTER_ASSERT(reporter, tangent.fX == 0); REPORTER_ASSERT(reporter, tangent.fY == SK_Scalar1); REPORTER_ASSERT(reporter, meas.getPosTan(SkFloatToScalar(4.5f), &position, &tangent)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(position.fX, SkFloatToScalar(2.5f), SkFloatToScalar(0.0001f))); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(position.fY, SkFloatToScalar(2.0f), SkFloatToScalar(0.0001f))); REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1); REPORTER_ASSERT(reporter, tangent.fY == 0); path.reset(); path.moveTo(0, 0); path.lineTo(SK_Scalar1, 0); path.moveTo(SK_Scalar1, SK_Scalar1); path.moveTo(SK_Scalar1 * 2, SK_Scalar1 * 2); path.lineTo(SK_Scalar1, SK_Scalar1 * 2); meas.setPath(&path, false); length = meas.getLength(); REPORTER_ASSERT(reporter, length == SK_Scalar1); REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(position.fX, SK_ScalarHalf, SkFloatToScalar(0.0001f))); REPORTER_ASSERT(reporter, position.fY == 0); REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1); REPORTER_ASSERT(reporter, tangent.fY == 0); meas.nextContour(); length = meas.getLength(); REPORTER_ASSERT(reporter, length == SK_Scalar1); REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(position.fX, SkFloatToScalar(1.5f), SkFloatToScalar(0.0001f))); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(position.fY, SkFloatToScalar(2.0f), SkFloatToScalar(0.0001f))); REPORTER_ASSERT(reporter, tangent.fX == -SK_Scalar1); REPORTER_ASSERT(reporter, tangent.fY == 0); test_small_segment(reporter); test_small_segment2(reporter); test_small_segment3(reporter); }
static void TestPathMeasure(skiatest::Reporter* reporter) { SkPath path; path.moveTo(0, 0); path.lineTo(SK_Scalar1, 0); path.lineTo(SK_Scalar1, SK_Scalar1); path.lineTo(0, SK_Scalar1); SkPathMeasure meas(path, true); SkScalar length = meas.getLength(); SkASSERT(length == SK_Scalar1*4); path.reset(); path.moveTo(0, 0); path.lineTo(SK_Scalar1*3, SK_Scalar1*4); meas.setPath(&path, false); length = meas.getLength(); REPORTER_ASSERT(reporter, length == SK_Scalar1*5); path.reset(); path.addCircle(0, 0, SK_Scalar1); meas.setPath(&path, true); length = meas.getLength(); // SkDebugf("circle arc-length = %g\n", length); for (int i = 0; i < 8; i++) { SkScalar d = length * i / 8; SkPoint p; SkVector v; meas.getPosTan(d, &p, &v); #if 0 SkDebugf("circle arc-length=%g, pos[%g %g] tan[%g %g]\n", d, p.fX, p.fY, v.fX, v.fY); #endif } // Test the behavior following a close not followed by a move. path.reset(); path.lineTo(SK_Scalar1, 0); path.lineTo(SK_Scalar1, SK_Scalar1); path.lineTo(0, SK_Scalar1); path.close(); path.lineTo(-SK_Scalar1, 0); meas.setPath(&path, false); length = meas.getLength(); REPORTER_ASSERT(reporter, length == SK_Scalar1 * 4); meas.nextContour(); length = meas.getLength(); REPORTER_ASSERT(reporter, length == SK_Scalar1); SkPoint position; SkVector tangent; REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(position.fX, -SK_ScalarHalf, SK_Scalar1 * 0.0001)); REPORTER_ASSERT(reporter, position.fY == 0); REPORTER_ASSERT(reporter, tangent.fX == -SK_Scalar1); REPORTER_ASSERT(reporter, tangent.fY == 0); // Test degenerate paths path.reset(); path.moveTo(0, 0); path.lineTo(0, 0); path.lineTo(SK_Scalar1, 0); path.quadTo(SK_Scalar1, 0, SK_Scalar1, 0); path.quadTo(SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1 * 2); path.cubicTo(SK_Scalar1, SK_Scalar1 * 2, SK_Scalar1, SK_Scalar1 * 2, SK_Scalar1, SK_Scalar1 * 2); path.cubicTo(SK_Scalar1*2, SK_Scalar1 * 2, SK_Scalar1*3, SK_Scalar1 * 2, SK_Scalar1*4, SK_Scalar1 * 2); meas.setPath(&path, false); length = meas.getLength(); REPORTER_ASSERT(reporter, length == SK_Scalar1 * 6); REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(position.fX, SK_ScalarHalf, SK_Scalar1 * 0.0001)); REPORTER_ASSERT(reporter, position.fY == 0); REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1); REPORTER_ASSERT(reporter, tangent.fY == 0); REPORTER_ASSERT(reporter, meas.getPosTan(SK_Scalar1 * 2.5f, &position, &tangent)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(position.fX, SK_Scalar1, SK_Scalar1 * 0.0001)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(position.fY, SK_Scalar1 * 1.5f)); REPORTER_ASSERT(reporter, tangent.fX == 0); REPORTER_ASSERT(reporter, tangent.fY == SK_Scalar1); REPORTER_ASSERT(reporter, meas.getPosTan(SK_Scalar1 * 4.5f, &position, &tangent)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(position.fX, SK_Scalar1 * 2.5f, SK_Scalar1 * 0.0001)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(position.fY, SK_Scalar1 * 2.0f, SK_Scalar1 * 0.0001)); REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1); REPORTER_ASSERT(reporter, tangent.fY == 0); path.reset(); path.moveTo(0, 0); path.lineTo(SK_Scalar1, 0); path.moveTo(SK_Scalar1, SK_Scalar1); path.moveTo(SK_Scalar1 * 2, SK_Scalar1 * 2); path.lineTo(SK_Scalar1, SK_Scalar1 * 2); meas.setPath(&path, false); length = meas.getLength(); REPORTER_ASSERT(reporter, length == SK_Scalar1); REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(position.fX, SK_ScalarHalf, SK_Scalar1 * 0.0001)); REPORTER_ASSERT(reporter, position.fY == 0); REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1); REPORTER_ASSERT(reporter, tangent.fY == 0); meas.nextContour(); length = meas.getLength(); REPORTER_ASSERT(reporter, length == SK_Scalar1); REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(position.fX, SK_Scalar1 * 1.5f, SK_Scalar1 * 0.0001)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(position.fY, SK_Scalar1 * 2.0f, SK_Scalar1 * 0.0001)); REPORTER_ASSERT(reporter, tangent.fX == -SK_Scalar1); REPORTER_ASSERT(reporter, tangent.fY == 0); }
ShadowsGM() { this->setBGColor(0xFFDDDDDD); fCirclePath.addCircle(SkIntToScalar(20), SkIntToScalar(20), SkIntToScalar(10) ); fRect.set(SkIntToScalar(10), SkIntToScalar(10), SkIntToScalar(30), SkIntToScalar(30)); }