static void make_strip(Rec* rec, int texWidth, int texHeight) { const SkScalar tx = SkIntToScalar(texWidth); const SkScalar ty = SkIntToScalar(texHeight); const int n = 24; rec->fMode = SkCanvas::kTriangleStrip_VertexMode; rec->fCount = 2 * (n + 1); rec->fVerts = new SkPoint[rec->fCount]; rec->fTexs = new SkPoint[rec->fCount]; SkPoint* v = rec->fVerts; SkPoint* t = rec->fTexs; for (int i = 0; i < n; i++) { SkScalar cos; SkScalar sin = SkScalarSinCos(SK_ScalarPI * 2 * i / n, &cos); v[i*2 + 0].set(cos/2, sin/2); v[i*2 + 1].set(cos, sin); t[i*2 + 0].set(tx * i / n, ty); t[i*2 + 1].set(tx * i / n, 0); } v[2*n + 0] = v[0]; v[2*n + 1] = v[1]; t[2*n + 0].set(tx, ty); t[2*n + 1].set(tx, 0); SkMatrix m; m.setScale(SkIntToScalar(100), SkIntToScalar(100)); m.postTranslate(SkIntToScalar(110), SkIntToScalar(110)); m.mapPoints(v, rec->fCount); }
void make_fan(Rec* rec, int texWidth, int texHeight) { const SkScalar tx = SkIntToScalar(texWidth); const SkScalar ty = SkIntToScalar(texHeight); const int n = 24; rec->fMode = SkCanvas::kTriangleFan_VertexMode; rec->fCount = n + 2; rec->fVerts = new SkPoint[rec->fCount]; rec->fTexs = new SkPoint[rec->fCount]; SkPoint* v = rec->fVerts; SkPoint* t = rec->fTexs; v[0].set(0, 0); t[0].set(0, 0); for (int i = 0; i < n; i++) { SkScalar cos; SkScalar sin = SkScalarSinCos(SK_ScalarPI * 2 * i / n, &cos); v[i+1].set(cos, sin); t[i+1].set(i*tx/n, ty); } v[n+1] = v[1]; t[n+1].set(tx, ty); SkMatrix m; m.setScale(SkIntToScalar(100), SkIntToScalar(100)); m.postTranslate(SkIntToScalar(110), SkIntToScalar(110)); m.mapPoints(v, rec->fCount); }
virtual void onDrawContent(SkCanvas* canvas) { SkPaint paint; paint.setAntiAlias(true); paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(SkScalarHalf(SkIntToScalar(3))); paint.setStyle(SkPaint::kFill_Style); SkRect r; SkScalar l,t,x,y; l = SampleCode::GetAnimScalar(SkIntToScalar(10), SkIntToScalar(400)); t = SampleCode::GetAnimScalar(SkIntToScalar(5), SkIntToScalar(200)); canvas->translate(320,240); for (int i = 0; i < 35; i++) { paint.setColor(0xFFF00FF0 - i * 0x04000000); SkScalar step = SK_ScalarPI / (55 - i); SkScalar angle = t * step; x = (20 + SkIntToScalar(i) * 5) * SkScalarSinCos(angle, &y); y *= (20 + SkIntToScalar(i) * 5); r.set(x, y, x + SkIntToScalar(10), y + SkIntToScalar(10)); canvas->drawRect(r, paint); } this->inval(NULL); }
// draw a snowflake centered at the origin static void draw_snowflake(SkCanvas* canvas, const SkPaint& paint) { canvas->clipRect(SkRect::MakeLTRB(-kRadius-kPad, -kRadius-kPad, kRadius+kPad, kRadius+kPad)); SkScalar sin, cos, angle = 0.0f; for (int i = 0; i < kNumSpokes/2; ++i, angle += SK_ScalarPI/(kNumSpokes/2)) { sin = SkScalarSinCos(angle, &cos); sin *= kRadius; cos *= kRadius; // main spoke SkPath p; p.moveTo(-cos, -sin); p.lineTo(cos, sin); canvas->drawPath(p, paint); // fins on positive side const SkPoint posOffset = SkPoint::Make(0.5f * cos, 0.5f * sin); draw_fins(canvas, posOffset, angle, paint); // fins on negative side const SkPoint negOffset = SkPoint::Make(-0.5f * cos, -0.5f * sin); draw_fins(canvas, negOffset, angle+SK_ScalarPI, paint); } }
void SkColorMatrix::setRotate(Axis axis, SkScalar degrees) { SkScalar S, C; S = SkScalarSinCos(SkDegreesToRadians(degrees), &C); this->setSinCos(axis, S, C); }
void SkMatrix3D::setRotateZ(SkScalar degZ) { SkScalar s, c; s = SkScalarSinCos(SkDegreesToRadians(degZ), &c); this->setRow(0, c, -s, 0); this->setRow(1, s, c, 0); this->setRow(2, 0, 0, SK_Scalar1); }
void SkMatrix3D::setRotateY(SkScalar degY) { SkScalar s, c; s = SkScalarSinCos(SkDegreesToRadians(degY), &c); this->setRow(0, c, 0, -s); this->setRow(1, 0, SK_Scalar1, 0); this->setRow(2, s, 0, c); }
static void make_unit_star(SkPath* path, int n) { SkScalar rad = -SK_ScalarPI / 2; const SkScalar drad = (n >> 1) * SK_ScalarPI * 2 / n; path->moveTo(0, -SK_Scalar1); for (int i = 1; i < n; i++) { rad += drad; SkScalar cosV, sinV = SkScalarSinCos(rad, &cosV); path->lineTo(cosV, sinV); } path->close(); }
static void create_ngon(int n, SkPoint* pts, SkScalar width, SkScalar height) { float angleStep = 360.0f / n, angle = 0.0f, sin, cos; if ((n % 2) == 1) { angle = angleStep/2.0f; } for (int i = 0; i < n; ++i) { sin = SkScalarSinCos(SkDegreesToRadians(angle), &cos); pts[i].fX = -sin * width; pts[i].fY = cos * height; angle += angleStep; } }
static void draw_fins(SkCanvas* canvas, const SkPoint& offset, float angle, const SkPaint& paint) { SkScalar cos, sin; // first fin sin = SkScalarSinCos(angle + (SK_ScalarPI/4), &cos); sin *= kRadius / 2.0f; cos *= kRadius / 2.0f; SkPath p; p.moveTo(offset.fX, offset.fY); p.lineTo(offset.fX + cos, offset.fY + sin); canvas->drawPath(p, paint); // second fin sin = SkScalarSinCos(angle - (SK_ScalarPI/4), &cos); sin *= kRadius / 2.0f; cos *= kRadius / 2.0f; p.reset(); p.moveTo(offset.fX, offset.fY); p.lineTo(offset.fX + cos, offset.fY + sin); canvas->drawPath(p, paint); }
static void make_poly(SkPath* path, int n) { if (n <= 0) { return; } path->incReserve(n + 1); path->moveTo(SK_Scalar1, 0); SkScalar step = SK_ScalarPI * 2 / n; SkScalar angle = 0; for (int i = 1; i < n; i++) { angle += step; SkScalar c, s = SkScalarSinCos(angle, &c); path->lineTo(c, s); } path->close(); }
static SkScalar make_star(SkPath* path, int n) { const SkScalar c = SkIntToScalar(45); const SkScalar r = SkIntToScalar(20); SkScalar rad = -SK_ScalarPI / 2; const SkScalar drad = (n >> 1) * SK_ScalarPI * 2 / n; path->moveTo(c, c - r); for (int i = 1; i < n; i++) { rad += drad; SkScalar cosV, sinV = SkScalarSinCos(rad, &cosV); path->lineTo(c + SkScalarMul(cosV, r), c + SkScalarMul(sinV, r)); } path->close(); return r * 2 * 6 / 5; }
void onDraw(SkCanvas* canvas) override { SkPaint p; p.setColor(SK_ColorRED); p.setAntiAlias(true); canvas->clear(0xFFFFFFFF); canvas->save(); canvas->rotate(1); const SkScalar R = 115.2f, C = 128.0f; SkPath path; path.moveTo(C + R, C); for (int i = 1; i < 8; ++i) { SkScalar a = 2.6927937f * i; SkScalar cosine; SkScalar sine = SkScalarSinCos(a, &cosine); path.lineTo(C + R * cosine, C + R * sine); } canvas->drawPath(path, p); canvas->restore(); canvas->save(); canvas->translate(200, 0); canvas->rotate(1); p.setStyle(SkPaint::kStroke_Style); p.setStrokeWidth(5); canvas->drawPath(path, p); canvas->restore(); // The following two paths test if we correctly cumulates the alpha on the middle pixel // column where the left rect and the right rect abut. p.setStyle(SkPaint::kFill_Style); canvas->translate(0, 300); path.reset(); path.addRect({20, 20, 100.4999f, 100}); path.addRect({100.5001f, 20, 200, 100}); canvas->drawPath(path, p); canvas->translate(300, 0); path.reset(); path.addRect({20, 20, 100.1f, 100}); path.addRect({100.9f, 20, 200, 100}); canvas->drawPath(path, p); }
static void test_matrix_decomposition(skiatest::Reporter* reporter) { SkMatrix mat; SkScalar rotation0, scaleX, scaleY, rotation1; const float kRotation0 = 15.5f; const float kRotation1 = -50.f; const float kScale0 = 5000.f; const float kScale1 = 0.001f; // identity mat.reset(); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, SK_Scalar1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, SK_Scalar1)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // make sure it doesn't crash if we pass in NULLs REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, NULL, NULL, NULL, NULL)); // rotation only mat.setRotate(kRotation0); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, SkDegreesToRadians(kRotation0))); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, SK_Scalar1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, SK_Scalar1)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // uniform scale only mat.setScale(kScale0, kScale0); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // anisotropic scale only mat.setScale(kScale1, kScale0); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // rotation then uniform scale mat.setRotate(kRotation1); mat.postScale(kScale0, kScale0); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, SkDegreesToRadians(kRotation1))); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // uniform scale then rotation mat.setScale(kScale0, kScale0); mat.postRotate(kRotation1); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, SkDegreesToRadians(kRotation1))); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // rotation then uniform scale+reflection mat.setRotate(kRotation0); mat.postScale(kScale1, -kScale1); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, SkDegreesToRadians(kRotation0))); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, -kScale1)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // uniform scale+reflection, then rotate mat.setScale(kScale0, -kScale0); mat.postRotate(kRotation1); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, SkDegreesToRadians(-kRotation1))); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, -kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // rotation then anisotropic scale mat.setRotate(kRotation1); mat.postScale(kScale1, kScale0); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, SkDegreesToRadians(kRotation1))); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // anisotropic scale then rotation mat.setScale(kScale1, kScale0); mat.postRotate(kRotation0); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation1, SkDegreesToRadians(kRotation0))); // rotation, uniform scale, then different rotation mat.setRotate(kRotation1); mat.postScale(kScale0, kScale0); mat.postRotate(kRotation0); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, SkDegreesToRadians(kRotation0 + kRotation1))); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // rotation, anisotropic scale, then different rotation mat.setRotate(kRotation0); mat.postScale(kScale1, kScale0); mat.postRotate(kRotation1); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); // Because of the shear/skew we won't get the same results, so we need to multiply it out. // Generating the matrices requires doing a radian-to-degree calculation, then degree-to-radian // calculation (in setRotate()), which adds error, so this just computes the matrix elements // directly. SkScalar c0; SkScalar s0 = SkScalarSinCos(rotation0, &c0); SkScalar c1; SkScalar s1 = SkScalarSinCos(rotation1, &c1); // We do a relative check here because large scale factors cause problems with an absolute check REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleX], scaleX*c0*c1 - scaleY*s0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewX], -scaleX*s0*c1 - scaleY*c0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewY], scaleX*c0*s1 + scaleY*s0*c1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleY], -scaleX*s0*s1 + scaleY*c0*c1)); // try some random matrices SkMWCRandom rand; for (int m = 0; m < 1000; ++m) { SkScalar rot0 = rand.nextRangeF(-SK_ScalarPI, SK_ScalarPI); SkScalar sx = rand.nextRangeF(-3000.f, 3000.f); SkScalar sy = rand.nextRangeF(-3000.f, 3000.f); SkScalar rot1 = rand.nextRangeF(-SK_ScalarPI, SK_ScalarPI); mat.setRotate(rot0); mat.postScale(sx, sy); mat.postRotate(rot1); if (SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)) { SkScalar c0; SkScalar s0 = SkScalarSinCos(rotation0, &c0); SkScalar c1; SkScalar s1 = SkScalarSinCos(rotation1, &c1); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleX], scaleX*c0*c1 - scaleY*s0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewX], -scaleX*s0*c1 - scaleY*c0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewY], scaleX*c0*s1 + scaleY*s0*c1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleY], -scaleX*s0*s1 + scaleY*c0*c1)); } else { // if the matrix is degenerate, the basis vectors should be near-parallel or near-zero SkScalar perpdot = mat[SkMatrix::kMScaleX]*mat[SkMatrix::kMScaleY] - mat[SkMatrix::kMSkewX]*mat[SkMatrix::kMSkewY]; REPORTER_ASSERT(reporter, SkScalarNearlyZero(perpdot)); } } // translation shouldn't affect this mat.postTranslate(-1000.f, 1000.f); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); s0 = SkScalarSinCos(rotation0, &c0); s1 = SkScalarSinCos(rotation1, &c1); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleX], scaleX*c0*c1 - scaleY*s0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewX], -scaleX*s0*c1 - scaleY*c0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewY], scaleX*c0*s1 + scaleY*s0*c1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleY], -scaleX*s0*s1 + scaleY*c0*c1)); // perspective shouldn't affect this mat[SkMatrix::kMPersp0] = 12.f; mat[SkMatrix::kMPersp1] = 4.f; mat[SkMatrix::kMPersp2] = 1872.f; REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); s0 = SkScalarSinCos(rotation0, &c0); s1 = SkScalarSinCos(rotation1, &c1); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleX], scaleX*c0*c1 - scaleY*s0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewX], -scaleX*s0*c1 - scaleY*c0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewY], scaleX*c0*s1 + scaleY*s0*c1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleY], -scaleX*s0*s1 + scaleY*c0*c1)); // rotation, anisotropic scale + reflection, then different rotation mat.setRotate(kRotation0); mat.postScale(-kScale1, kScale0); mat.postRotate(kRotation1); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); s0 = SkScalarSinCos(rotation0, &c0); s1 = SkScalarSinCos(rotation1, &c1); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleX], scaleX*c0*c1 - scaleY*s0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewX], -scaleX*s0*c1 - scaleY*c0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewY], scaleX*c0*s1 + scaleY*s0*c1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleY], -scaleX*s0*s1 + scaleY*c0*c1)); // degenerate matrices // mostly zero entries mat.reset(); mat[SkMatrix::kMScaleX] = 0.f; REPORTER_ASSERT(reporter, !SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); mat.reset(); mat[SkMatrix::kMScaleY] = 0.f; REPORTER_ASSERT(reporter, !SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); mat.reset(); // linearly dependent entries mat[SkMatrix::kMScaleX] = 1.f; mat[SkMatrix::kMSkewX] = 2.f; mat[SkMatrix::kMSkewY] = 4.f; mat[SkMatrix::kMScaleY] = 8.f; REPORTER_ASSERT(reporter, !SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); }
static SkPoint unit_vec(int degrees) { SkScalar rad = SkDegreesToRadians(SkIntToScalar(degrees)); SkScalar s, c; s = SkScalarSinCos(rad, &c); return SkPoint::Make(c, s); }
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); } }