static void test_small_segment() { SkPath path; const SkPoint pts[] = { { 100000, 100000}, // big jump between these points, makes a big segment { 1.0005f, 0.9999f }, // tiny (non-zero) jump between these points { SK_Scalar1, SK_Scalar1 }, }; path.moveTo(pts[0]); for (size_t i = 1; i < SK_ARRAY_COUNT(pts); ++i) { path.lineTo(pts[i]); } SkPathMeasure meas(path, false); /* this would assert (before a fix) because we added a segment with the same length as the prev segment, due to the follow (bad) pattern d = distance(pts[0], pts[1]); distance += d; seg->fDistance = distance; SkASSERT(d > 0); // TRUE SkASSERT(seg->fDistance > prevSeg->fDistance); // FALSE This 2nd assert failes because (distance += d) didn't affect distance because distance >>> d. */ meas.getLength(); }
void ACanvasSkia::FillPolygon(APoint* pts,int count) { if( count == 1 ) { _clip(); _SetPaint_Fill(); m_pCanvas->drawPoint(SkIntToScalar(pts[0].x),SkIntToScalar(pts[0].y),m_Paint); Reset(); } else if( count < 1 ) { //do nothing } else { _SetPaint_Fill(); SkPath path; path.moveTo(SkIntToScalar(pts[0].x),SkIntToScalar(pts[0].y)); for(int i=1;i<count;i++) { //path.moveTo(SkIntToScalar(pts[i].x),SkIntToScalar(pts[i].y)); path.lineTo(SkIntToScalar(pts[i].x),SkIntToScalar(pts[i].y)); } path.close(); m_pCanvas->drawPath(path,m_Paint); } }
void FatBits::drawTriangle(SkCanvas* canvas, SkPoint pts[3]) { SkPaint paint; fInverse.mapPoints(pts, 3); if (fGrid) { apply_grid(pts, 3); } SkPath path; path.moveTo(pts[0]); path.lineTo(pts[1]); path.lineTo(pts[2]); path.close(); erase(fMinSurface.get()); this->setupPaint(&paint); paint.setColor(FAT_PIXEL_COLOR); fMinSurface->getCanvas()->drawPath(path, paint); this->copyMinToMax(); SkCanvas* max = fMaxSurface->getCanvas(); fMatrix.mapPoints(pts, 3); this->drawTriangleSkeleton(max, pts); fMaxSurface->draw(canvas, 0, 0, nullptr); }
void PlatformGraphicsContextSkia::drawConvexPolygon(size_t numPoints, const FloatPoint* points, bool shouldAntialias) { if (numPoints <= 1) return; SkPaint paint; SkPath path; path.incReserve(numPoints); path.moveTo(SkFloatToScalar(points[0].x()), SkFloatToScalar(points[0].y())); for (size_t i = 1; i < numPoints; i++) path.lineTo(SkFloatToScalar(points[i].x()), SkFloatToScalar(points[i].y())); if (mCanvas->quickReject(path, shouldAntialias ? SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType)) { return; } if (m_state->fillColor & 0xFF000000) { setupPaintFill(&paint); paint.setAntiAlias(shouldAntialias); mCanvas->drawPath(path, paint); } if (m_state->strokeStyle != NoStroke) { paint.reset(); setupPaintStroke(&paint, 0); paint.setAntiAlias(shouldAntialias); mCanvas->drawPath(path, paint); } }
static void failOne(skiatest::Reporter* reporter, int index) { SkPath path; int i = (int) (index % nonFinitePtsCount); int f = (int) (index % finitePtsCount); int g = (int) ((f + 1) % finitePtsCount); switch (index % 13) { case 0: path.lineTo(nonFinitePts[i]); break; case 1: path.quadTo(nonFinitePts[i], nonFinitePts[i]); break; case 2: path.quadTo(nonFinitePts[i], finitePts[f]); break; case 3: path.quadTo(finitePts[f], nonFinitePts[i]); break; case 4: path.cubicTo(nonFinitePts[i], finitePts[f], finitePts[f]); break; case 5: path.cubicTo(finitePts[f], nonFinitePts[i], finitePts[f]); break; case 6: path.cubicTo(finitePts[f], finitePts[f], nonFinitePts[i]); break; case 7: path.cubicTo(nonFinitePts[i], nonFinitePts[i], finitePts[f]); break; case 8: path.cubicTo(nonFinitePts[i], finitePts[f], nonFinitePts[i]); break; case 9: path.cubicTo(finitePts[f], nonFinitePts[i], nonFinitePts[i]); break; case 10: path.cubicTo(nonFinitePts[i], nonFinitePts[i], nonFinitePts[i]); break; case 11: path.cubicTo(nonFinitePts[i], finitePts[f], finitePts[g]); break; case 12: path.moveTo(nonFinitePts[i]); break; } SkPath result; result.setFillType(SkPath::kWinding_FillType); bool success = Simplify(path, &result); REPORTER_ASSERT(reporter, !success); REPORTER_ASSERT(reporter, result.isEmpty()); REPORTER_ASSERT(reporter, result.getFillType() == SkPath::kWinding_FillType); reporter->bumpTestCount(); }
void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, bool shouldAntialias) { if (paintingDisabled()) return; if (numPoints <= 1) return; platformContext()->prepareForSoftwareDraw(); SkPath path; path.incReserve(numPoints); path.moveTo(WebCoreFloatToSkScalar(points[0].x()), WebCoreFloatToSkScalar(points[0].y())); for (size_t i = 1; i < numPoints; i++) { path.lineTo(WebCoreFloatToSkScalar(points[i].x()), WebCoreFloatToSkScalar(points[i].y())); } if (!isPathSkiaSafe(getCTM(), path)) return; SkPaint paint; platformContext()->setupPaintForFilling(&paint); platformContext()->canvas()->drawPath(path, paint); if (strokeStyle() != NoStroke) { paint.reset(); platformContext()->setupPaintForStroking(&paint, 0, 0); platformContext()->canvas()->drawPath(path, paint); } }
static SkPath make_path() { SkPath path; int numOps = R(30); for (int i = 0; i < numOps; ++i) { switch (R(6)) { case 0: path.moveTo(make_scalar(), make_scalar()); break; case 1: path.lineTo(make_scalar(), make_scalar()); break; case 2: path.quadTo(make_scalar(), make_scalar(), make_scalar(), make_scalar()); break; case 3: path.conicTo(make_scalar(), make_scalar(), make_scalar(), make_scalar(), make_scalar()); break; case 4: path.cubicTo(make_scalar(), make_scalar(), make_scalar(), make_scalar(), make_scalar(), make_scalar()); break; case 5: default: path.arcTo(make_scalar(), make_scalar(), make_scalar(), make_scalar(), make_scalar()); break; } } path.close(); return path; }
EffectsView() { size_t i; const float pts[] = { 0, 0, 10, 0, 10, 5, 20, -5, 10, -15, 10, -10, 0, -10 }; fPath.moveTo(pts[0], pts[1]); for (i = 2; i < SK_ARRAY_COUNT(pts); i += 2) { fPath.lineTo(pts[i], pts[i+1]); } for (i = 0; i < SK_ARRAY_COUNT(gPaintProcs); i++) { fPaint[i].setAntiAlias(true); fPaint[i].setColor(COLOR); gPaintProcs[i](&fPaint[i]); } SkColorMatrix cm; cm.setRotate(SkColorMatrix::kG_Axis, 180); cm.setIdentity(); this->setBGColor(0xFFDDDDDD); }
virtual void onDraw(SkCanvas* canvas) { 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); SkPaint paint; paint.setTextSize(SkIntToScalar(100)); SkTypeface* hira = SkTypeface::CreateFromName("Hiragino Maru Gothic Pro", SkTypeface::kNormal); SkSafeUnref(paint.setTypeface(hira)); path.reset(); paint.getTextPath("e", 1, 50, 50, &path); canvas->translate(0, 100); test_rev(canvas, path); }
PathTexture* PathCache::getArc(float width, float height, float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) { PathDescription entry(kShapeArc, paint); entry.shape.arc.mWidth = width; entry.shape.arc.mHeight = height; entry.shape.arc.mStartAngle = startAngle; entry.shape.arc.mSweepAngle = sweepAngle; entry.shape.arc.mUseCenter = useCenter; PathTexture* texture = get(entry); if (!texture) { SkPath path; SkRect r; r.set(0.0f, 0.0f, width, height); if (useCenter) { path.moveTo(r.centerX(), r.centerY()); } path.arcTo(r, startAngle, sweepAngle, !useCenter); if (useCenter) { path.close(); } texture = addTexture(entry, &path, paint); } return texture; }
static void patheffect_slide(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); } }
// Regression test for b/26425223 DEF_TEST(PathMeasure_nextctr, reporter) { SkPath path; path.moveTo(0, 0); path.lineTo(100, 0); SkPathMeasure meas(path, false); // only expect 1 contour, even if we didn't explicitly call getLength() ourselves REPORTER_ASSERT(reporter, !meas.nextContour()); }
// A simple concave path. Test this with a non-invertible matrix. static SkPath create_path_17() { SkPath path; path.moveTo(20, 20); path.lineTo(80, 20); path.lineTo(30, 30); path.lineTo(20, 80); return path; }
static SkPoint AddMoveQuad(SkPath& path, SkPoint& startPt) { SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1); SkPoint midPt = moveToPt + SkPoint::Make(20*SK_Scalar1, 5*SK_Scalar1); SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0); path.moveTo(moveToPt); path.quadTo(midPt, endPt); return endPt; }
static void testLine1() { SkPath path; path.moveTo(2,0); path.lineTo(1,1); path.lineTo(0,0); path.close(); test(path); }
// Make an equilateral triangle path with its top corner at (originX, originY) static SkPath make_tri_path(SkScalar originX, SkScalar originY) { SkPath tri; tri.moveTo(originX, originY); tri.rLineTo(SkScalarHalf(kTriSide), 1.5f * kTriSide / kRoot3); tri.rLineTo(-kTriSide, 0); tri.close(); return tri; }
static SkPoint AddMoveLineClose(SkPath& path, SkPoint& startPt) { SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1); SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0); path.moveTo(moveToPt); path.lineTo(endPt); path.close(); return endPt; }
// Test out the asPoint culling behavior. DEF_TEST(DashPathEffectTest_asPoints, r) { const SkScalar intervals[] = { 1.0f, 1.0f }; const int count = 2; SkAutoTUnref<SkDashPathEffect> dash(SkDashPathEffect::Create(intervals, count, 0.0f)); SkRect cull = SkRect::MakeWH(1.0f, 1.0f); const struct { SkPoint fPts[2]; bool fExpectedResult; } testCases[] = { { { { -5.0f, 0.5f }, { -4.0f, 0.5f } }, false }, // off to the left { { { 4.0f, 0.5f }, { 5.0f, 0.5f } }, false }, // off to the right { { { 0.5f, 4.0f }, { 0.5f, 5.0f } }, false }, // off the bottom { { { 0.5f, -5.0f }, { 0.5f, -4.0f } }, false }, // off the top { { { 0.5f, 0.2f }, { 0.5f, 0.8f } }, true }, // entirely inside vertical { { { 0.2f, 0.5f }, { 0.8f, 0.5f } }, true }, // entirely inside horizontal { { { 0.5f, -5.0f }, { 0.5f, 5.0f } }, true }, // straddles both sides vertically { { { -5.0f, 0.5f }, { 5.0f, 0.5f } }, true }, // straddles both sides horizontally { { { 0.5f, -5.0f }, { 0.5f, 0.5f } }, true }, // straddles top { { { 0.5f, 5.0f }, { 0.5f, 0.5f } }, true }, // straddles bottom { { { -5.0f, 0.5f }, { 0.5f, 0.5f } }, true }, // straddles left { { { 5.0f, 0.5f }, { 0.5f, 0.5f } }, true }, // straddles right { { { 0.5f, 0.5f }, { 0.5f, 0.5f } }, false }, // zero length }; SkPaint paint; paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(1.0f); SkStrokeRec rec(paint); static const int kNumMats = 3; SkMatrix mats[kNumMats]; mats[0].reset(); mats[1].setRotate(90, 0.5f, 0.5f); mats[2].setTranslate(10.0f, 10.0f); for (int i = 0; i < kNumMats; ++i) { for (int j = 0; j < (int)SK_ARRAY_COUNT(testCases); ++j) { for (int k = 0; k < 2; ++k) { // exercise alternating endpoints SkPathEffect::PointData results; SkPath src; src.moveTo(testCases[j].fPts[k]); src.lineTo(testCases[j].fPts[(k+1)%2]); bool actualResult = dash->asPoints(&results, src, rec, mats[i], &cull); if (i < 2) { REPORTER_ASSERT(r, actualResult == testCases[j].fExpectedResult); } else { // On the third pass all the lines should be outside the translated cull rect REPORTER_ASSERT(r, !actualResult); } } } } }
void drawLabel(SkCanvas* canvas, const char *text, int startX, int startY, int endX, int endY) { SkPaint paint; paint.setColor(0xFF000000); SkPath path; path.moveTo(SkIntToScalar(startX), SkIntToScalar(startY)); path.lineTo(SkIntToScalar(endX), SkIntToScalar(endY)); canvas->drawTextOnPath(text, strlen(text), path, NULL, paint); }
static SkPath create_path_15() { SkPath path; path.moveTo( 0.0f, 0.0f); path.lineTo(10000.0f, 0.0f); path.lineTo( 0.0f, -1.0f); path.lineTo(10000.0f, 0.000001f); path.lineTo( 0.0f, -30.0f); return path; }
// AA stroking this path produces intersection failures on bevelling. // This should skip the point, but not assert. static SkPath create_path_28() { SkPath path; path.moveTo(-7.5952312625177475154e+21, -2.6819185100266674911e+24); path.lineTo( 1260.3787841796875, 1727.7947998046875); path.lineTo( 1260.5567626953125, 1728.0386962890625); path.lineTo(1.1482511310557754163e+21, 4.054538502765980051e+23); path.lineTo(-7.5952312625177475154e+21, -2.6819185100266674911e+24); return path; }
// A path which results in non-finite points when stroked and bevelled for AA. static SkPath create_path_27() { SkPath path; path.moveTo(8.5027233009104409507e+37, 1.7503381025241130639e+37); path.lineTo(7.0923661737711584874e+37, 1.4600074517285415699e+37); path.lineTo(7.0848733446033294691e+37, 1.4584649744781838604e+37); path.lineTo(-2.0473916115129349496e+37, -4.2146796450364162012e+36); path.lineTo(2.0473912312177548811e+37, 4.2146815465123165435e+36); return path; }
// A path which results in infs and nans when conics are converted to quads. static SkPath create_path_24() { SkPath path; path.moveTo(-2.20883e+37f, -1.02892e+37f); path.conicTo(-2.00958e+38f, -9.36107e+37f, -1.7887e+38f, -8.33215e+37f, 0.707107f); path.conicTo(-1.56782e+38f, -7.30323e+37f, 2.20883e+37f, 1.02892e+37f, 0.707107f); path.conicTo(2.00958e+38f, 9.36107e+37f, 1.7887e+38f, 8.33215e+37f, 0.707107f); path.conicTo(1.56782e+38f, 7.30323e+37f, -2.20883e+37f, -1.02892e+37f, 0.707107f); return path; }
// An intersection above the first vertex in the mesh. // Reduction from http://crbug.com/730687 static SkPath create_path_20() { SkPath path; path.moveTo( 2822128.5, 235.026336669921875); path.lineTo( 2819349.25, 235.3623504638671875); path.lineTo( -340558688, 23.83478546142578125); path.lineTo( -340558752, 25.510419845581054688); path.lineTo( -340558720, 27.18605804443359375); return path; }
SkPath SubsetContours::getSubsetPath() const { SkPath result; result.setFillType(fPath.getFillType()); if (!fSelected.count()) { return result; } SkPath::RawIter iter(fPath); uint8_t verb; SkPoint pts[4]; int contourCount = 0; bool enabled = fSelected[0]; bool addMoveTo = true; while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { if (enabled && addMoveTo) { result.moveTo(pts[0]); addMoveTo = false; } switch (verb) { case SkPath::kMove_Verb: break; case SkPath::kLine_Verb: if (enabled) { result.lineTo(pts[1]); } break; case SkPath::kQuad_Verb: if (enabled) { result.quadTo(pts[1], pts[2]); } break; case SkPath::kConic_Verb: if (enabled) { result.conicTo(pts[1], pts[2], iter.conicWeight()); } break; case SkPath::kCubic_Verb: if (enabled) { result.cubicTo(pts[1], pts[2], pts[3]); } break; case SkPath::kClose_Verb: if (enabled) { result.close(); } if (++contourCount >= fSelected.count()) { break; } enabled = fSelected[contourCount]; addMoveTo = true; continue; default: SkDEBUGFAIL("bad verb"); return result; } } return result; }
SkPath create_convex_path(const SkPoint& offset) { SkPath convexPath; convexPath.moveTo(kMin, kMin); convexPath.lineTo(kMax, kMax); convexPath.lineTo(kMin, kMax); convexPath.close(); convexPath.offset(offset.fX, offset.fY); return convexPath; }
static void textonpath_slide(SkCanvas* canvas) { const char* text = "Displacement"; size_t len =strlen(text); SkPath path; path.moveTo(100, 300); path.quadTo(300, 100, 500, 300); path.offset(0, -100); SkPaint paint; paint.setAntiAlias(true); paint.setTextSize(40); paint.setStyle(SkPaint::kStroke_Style); canvas->drawPath(path, paint); paint.setStyle(SkPaint::kFill_Style); SkScalar x = 50; paint.setColor(0xFF008800); canvas->drawTextOnPathHV(text, len, path, x, paint.getTextSize()*2/3, paint); paint.setColor(SK_ColorRED); canvas->drawTextOnPathHV(text, len, path, x + 60, 0, paint); paint.setColor(SK_ColorBLUE); canvas->drawTextOnPathHV(text, len, path, x + 120, -paint.getTextSize()*2/3, paint); path.offset(0, 200); paint.setTextAlign(SkPaint::kRight_Align); text = "Matrices"; len = strlen(text); SkScalar pathLen = getpathlen(path); SkMatrix matrix; paint.setColor(SK_ColorBLACK); paint.setStyle(SkPaint::kStroke_Style); canvas->drawPath(path, paint); paint.setStyle(SkPaint::kFill_Style); paint.setTextSize(50); canvas->drawTextOnPath(text, len, path, NULL, paint); paint.setColor(SK_ColorRED); matrix.setScale(-SK_Scalar1, SK_Scalar1); matrix.postTranslate(pathLen, 0); canvas->drawTextOnPath(text, len, path, &matrix, paint); paint.setColor(SK_ColorBLUE); matrix.setScale(SK_Scalar1, -SK_Scalar1); canvas->drawTextOnPath(text, len, path, &matrix, paint); paint.setColor(0xFF008800); matrix.setScale(-SK_Scalar1, -SK_Scalar1); matrix.postTranslate(pathLen, 0); canvas->drawTextOnPath(text, len, path, &matrix, paint); }
static SkPoint AddMoveCubic(SkPath& path, SkPoint& startPt) { SkPoint moveToPt = startPt + SkPoint::Make(0, 10*SK_Scalar1); SkPoint t1Pt = moveToPt + SkPoint::Make(15*SK_Scalar1, 5*SK_Scalar1); SkPoint t2Pt = moveToPt + SkPoint::Make(25*SK_Scalar1, 5*SK_Scalar1); SkPoint endPt = moveToPt + SkPoint::Make(40*SK_Scalar1, 0); path.moveTo(moveToPt); path.cubicTo(t1Pt, t2Pt, endPt); return endPt; }
static void writeFrames() { const int scale = 5; for (int index = 0; index < (int) SK_ARRAY_COUNT(frameSizes); ++index) { SkDRect bounds; bool boundsSet = false; int frameSize = frameSizes[index]; for (int fIndex = 0; fIndex < frameSize; ++fIndex) { const SkDConic& dC = frames[index][fIndex]; SkDConic dConic = {{{ {dC.fPts[0].fX * scale, dC.fPts[0].fY * scale }, {dC.fPts[1].fX * scale, dC.fPts[1].fY * scale }, {dC.fPts[2].fX * scale, dC.fPts[2].fY * scale }}}, dC.fWeight }; SkDRect dBounds; dBounds.setBounds(dConic); if (!boundsSet) { bounds = dBounds; boundsSet = true; } else { bounds.add((SkDPoint&) dBounds.fLeft); bounds.add((SkDPoint&) dBounds.fRight); } } bounds.fLeft -= 10; bounds.fTop -= 10; bounds.fRight += 10; bounds.fBottom += 10; SkBitmap bitmap; bitmap.tryAllocPixels(SkImageInfo::MakeN32Premul( SkScalarRoundToInt(SkDoubleToScalar(bounds.width())), SkScalarRoundToInt(SkDoubleToScalar(bounds.height())))); SkCanvas canvas(bitmap); SkPaint paint; paint.setAntiAlias(true); paint.setStyle(SkPaint::kStroke_Style); canvas.translate(SkDoubleToScalar(-bounds.fLeft), SkDoubleToScalar(-bounds.fTop)); canvas.drawColor(SK_ColorWHITE); for (int fIndex = 0; fIndex < frameSize; ++fIndex) { const SkDConic& dC = frames[index][fIndex]; SkDConic dConic = {{{ {dC.fPts[0].fX * scale, dC.fPts[0].fY * scale }, {dC.fPts[1].fX * scale, dC.fPts[1].fY * scale }, {dC.fPts[2].fX * scale, dC.fPts[2].fY * scale }}}, dC.fWeight }; SkPath path; path.moveTo(dConic.fPts[0].asSkPoint()); path.conicTo(dConic.fPts[1].asSkPoint(), dConic.fPts[2].asSkPoint(), dConic.fWeight); if (fIndex < 2) { paint.setARGB(0x80, 0xFF, 0, 0); } else { paint.setARGB(0x80, 0, 0, 0xFF); } canvas.drawPath(path, paint); } SkString filename("c:\\Users\\caryclark\\Documents\\"); filename.appendf("f%d.png", index); SkImageEncoder::EncodeFile(filename.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100); } }
void skiaDrawLine(caskbench_context_t *ctx, shapes_t *args) { path.reset(); path.moveTo(args->x, args->y); path.lineTo(args->x + args->width, args->y + args->height); ctx->skia_canvas->drawPath(path, *(ctx->skia_paint)); }