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); }
// Draw the match specified by region to the canvas. void FindOnPage::drawMatch(const SkRegion& region, SkCanvas* canvas, bool focused) { // For the match which has focus, use a filled paint. For the others, use // a stroked paint. if (focused) { m_findPaint.setStyle(SkPaint::kFill_Style); m_findBlurPaint.setStyle(SkPaint::kFill_Style); } else { m_findPaint.setStyle(SkPaint::kStroke_Style); m_findPaint.setStrokeWidth(SK_Scalar1); m_findBlurPaint.setStyle(SkPaint::kStroke_Style); m_findBlurPaint.setStrokeWidth(SkIntToScalar(2)); } // Find the path for the current match SkPath matchPath; region.getBoundaryPath(&matchPath); // Offset the path for a blurred shadow SkPath blurPath; matchPath.offset(SK_Scalar1, SkIntToScalar(2), &blurPath); int saveCount = 0; if (!focused) { saveCount = canvas->save(); canvas->clipPath(matchPath, SkRegion::kDifference_Op); } // Draw the blurred background canvas->drawPath(blurPath, m_findBlurPaint); if (!focused) canvas->restoreToCount(saveCount); // Draw the foreground canvas->drawPath(matchPath, m_findPaint); }
void onDrawContent(SkCanvas* canvas) override { test_huge_stroke(canvas); return; canvas->translate(SkIntToScalar(10), SkIntToScalar(10)); SkPaint paint; paint.setAntiAlias(true); if (true) { canvas->drawColor(SK_ColorBLACK); paint.setTextSize(24); paint.setColor(SK_ColorWHITE); canvas->translate(10, 30); static const SkBlurStyle gStyle[] = { kNormal_SkBlurStyle, kInner_SkBlurStyle, kOuter_SkBlurStyle, kSolid_SkBlurStyle, }; for (int x = 0; x < 5; x++) { SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(4)); for (int y = 0; y < 10; y++) { if (x) { paint.setMaskFilter(SkBlurMaskFilter::Make(gStyle[x - 1], sigma)); } canvas->drawString("Title Bar", x*SkIntToScalar(100), y*SkIntToScalar(30), paint); sigma *= 0.75f; } } return; } paint.setColor(SK_ColorBLUE); #if 1 SkPath p; float r = rand.nextUScalar1() + 0.5f; SkScalar x = 0, y = 0; p.moveTo(x, y); #if 0 p.cubicTo(x-75*r, y+75*r, x-40*r, y+125*r, x, y+85*r); p.cubicTo(x+40*r, y+125*r, x+75*r, y+75*r, x, y); #else p.cubicTo(x+75*r, y+75*r, x+40*r, y+125*r, x, y+85*r); p.cubicTo(x-40*r, y+125*r, x-75*r, y+75*r, x, y); #endif p.close(); fPath = p; fPath.offset(100, 0); #endif fPath.setFillType(SkPath::kWinding_FillType); drawSet(canvas, &paint); canvas->translate(0, fPath.getBounds().height() * 5 / 4); fPath.setFillType(SkPath::kEvenOdd_FillType); drawSet(canvas, &paint); }
static void lettersToBitmap2(SkBitmap* dst, const char chars[], const SkPaint& original, SkBitmap::Config config) { SkPath path; SkScalar x = 0; SkScalar width; SkPath p; for (size_t i = 0; i < strlen(chars); i++) { original.getTextPath(&chars[i], 1, x, 0, &p); path.addPath(p); original.getTextWidths(&chars[i], 1, &width); x += width; } SkRect bounds = path.getBounds(); SkScalar sw = -original.getStrokeWidth(); bounds.inset(sw, sw); path.offset(-bounds.fLeft, -bounds.fTop); bounds.offset(-bounds.fLeft, -bounds.fTop); int w = SkScalarRound(bounds.width()); int h = SkScalarRound(bounds.height()); SkPaint paint(original); paint.setAntiAlias(true); paint.setXfermodeMode(SkXfermode::kDstATop_Mode); paint.setColor(original.getColor()); paint.setStyle(SkPaint::kStroke_Style); dst->setConfig(config, w, h); dst->allocPixels(); dst->eraseColor(SK_ColorWHITE); SkCanvas canvas(*dst); canvas.drawPath(path, paint); }
virtual void onDraw(SkCanvas* canvas) { if (false) test_rev(canvas); // avoid bit rot, suppress warning 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); }
void onDraw(SkCanvas* canvas) override { SkPath path; SkRandom rand; int scale = 300; for (int i = 0; i < 4; ++i) { // get the random values deterministically SkScalar randoms[12]; for (int index = 0; index < (int) SK_ARRAY_COUNT(randoms); ++index) { randoms[index] = rand.nextUScalar1(); } path.lineTo(randoms[0] * scale, randoms[1] * scale); path.quadTo(randoms[2] * scale, randoms[3] * scale, randoms[4] * scale, randoms[5] * scale); path.cubicTo(randoms[6] * scale, randoms[7] * scale, randoms[8] * scale, randoms[9] * scale, randoms[10] * scale, randoms[11] * scale); } path.setFillType(SkPath::kEvenOdd_FillType); path.offset(SkIntToScalar(20), SkIntToScalar(20)); test_hittest(canvas, path); canvas->translate(SkIntToScalar(scale), 0); path.setFillType(SkPath::kWinding_FillType); test_hittest(canvas, path); }
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; }
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); }
static void one_d_pe(SkPaint* paint) { SkPath path; path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1])); for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2) path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1])); path.close(); path.offset(SkIntToScalar(-6), 0); scale(&path, 1.5f); paint->setPathEffect(SkPath1DPathEffect::Create(path, SkIntToScalar(21), 0, SkPath1DPathEffect::kRotate_Style))->unref(); compose_pe(paint); }
static sk_sp<SkPathEffect> make_warp_pe(SkScalar phase) { SkPath path; path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1])); for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2) { path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1])); } path.close(); path.offset(SkIntToScalar(-6), 0); auto outer = SkPath1DPathEffect::Make( path, 12, phase, SkPath1DPathEffect::kMorph_Style); auto inner = SkCornerPathEffect::Make(SkIntToScalar(CORNER_RADIUS)); return SkComposePathEffect::Make(outer, inner); }
SkPath create_concave_path(const SkPoint& offset) { SkPath concavePath; concavePath.moveTo(kMin, kMin); concavePath.lineTo(kMid, 105.0f); concavePath.lineTo(kMax, kMin); concavePath.lineTo(295.0f, kMid); concavePath.lineTo(kMax, kMax); concavePath.lineTo(kMid, 295.0f); concavePath.lineTo(kMin, kMax); concavePath.lineTo(105.0f, kMid); concavePath.close(); concavePath.offset(offset.fX, offset.fY); return concavePath; }
void draw(SkCanvas* canvas) { SkPaint paint; paint.setAntiAlias(true); paint.setStyle(SkPaint::kStroke_Style); SkPath path; path.moveTo(0, -10); for (int i = 0; i < 128; i += 16) { SkScalar c = i * 0.5f; path.cubicTo( 10 + c, -10 - i, 10 + i, -10 - c, 10 + i, 0); path.cubicTo( 14 + i, 14 + c, 14 + c, 14 + i, 0, 14 + i); path.cubicTo(-18 - c, 18 + i, -18 - i, 18 + c, -18 - i, 0); path.cubicTo(-22 - i, -22 - c, -22 - c, -22 - i, 0, -22 - i); } path.offset(128, 128); canvas->drawPath(path, paint); }
static SkPathEffect* make_warp_pe() { SkPath path; path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1])); for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2) path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1])); path.close(); path.offset(SkIntToScalar(-6), 0); SkPathEffect* outer = new SkPath1DPathEffect(path, SkIntToScalar(12), gPhase, SkPath1DPathEffect::kMorph_Style); SkPathEffect* inner = new SkCornerPathEffect(SkIntToScalar(CORNER_RADIUS)); SkPathEffect* pe = new SkComposePathEffect(outer, inner); outer->unref(); inner->unref(); return pe; }
void onDraw(SkCanvas* canvas) override { canvas->translate(8.5f, 8.5f); const SkRect rect = { 0, 0, 80, 80 }; const SkScalar RAD = rect.width()/8; int i = 0; for (int insetFirst = 0; insetFirst <= 1; ++insetFirst) { for (int doEvenOdd = 0; doEvenOdd <= 1; ++doEvenOdd) { for (int outerRR = 0; outerRR <= 1; ++outerRR) { for (int innerRR = 0; innerRR <= 1; ++innerRR) { for (int outerCW = 0; outerCW <= 1; ++outerCW) { for (int innerCW = 0; innerCW <= 1; ++innerCW) { SkPath path; path.setFillType(doEvenOdd ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType); SkPath::Direction outerDir = outerCW ? SkPath::kCW_Direction : SkPath::kCCW_Direction; SkPath::Direction innerDir = innerCW ? SkPath::kCW_Direction : SkPath::kCCW_Direction; SkRect r = insetFirst ? inset(rect) : rect; if (outerRR) { path.addRoundRect(r, RAD, RAD, outerDir); } else { path.addRect(r, outerDir); } r = insetFirst ? rect : inset(rect); if (innerRR) { path.addRoundRect(r, RAD, RAD, innerDir); } else { path.addRect(r, innerDir); } SkScalar dx = (i / 8) * rect.width() * 6 / 5; SkScalar dy = (i % 8) * rect.height() * 6 / 5; i++; path.offset(dx, dy); this->show(canvas, path); } } } } } } }
virtual void onDrawContent(SkCanvas* canvas) { #if 1 SkAAClip aaclip; SkPath path; SkRect bounds; bounds.set(0, 0, 20, 20); bounds.inset(SK_ScalarHalf, SK_ScalarHalf); // path.addRect(bounds); // path.addOval(bounds); path.addRoundRect(bounds, 4, 4); aaclip.setPath(path); canvas->translate(30, 30); drawClip(canvas, aaclip); SkAAClip aaclip2; path.offset(10, 10); aaclip2.setPath(path); canvas->translate(30, 0); drawClip(canvas, aaclip2); SkAAClip aaclip3; aaclip3.op(aaclip, aaclip2, SkRegion::kIntersect_Op); canvas->translate(30, 0); drawClip(canvas, aaclip3); #endif #if 0 SkRect r; r.set(0, 0, this->width(), this->height()); r.inset(20, 20); canvas->clipRect(r); SkPath path; path.addRect(r); SkPaint paint; paint.setAntiAlias(true); paint.setColor(SK_ColorRED); canvas->drawPath(path, paint); #endif }
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 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); }
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) { SkPath path; SkRandom rand; int scale = 300; for (int i = 0; i < 4; ++i) { path.lineTo(rand.nextUScalar1() * scale, rand.nextUScalar1() * scale); path.quadTo(rand.nextUScalar1() * scale, rand.nextUScalar1() * scale, rand.nextUScalar1() * scale, rand.nextUScalar1() * scale); path.cubicTo(rand.nextUScalar1() * scale, rand.nextUScalar1() * scale, rand.nextUScalar1() * scale, rand.nextUScalar1() * scale, rand.nextUScalar1() * scale, rand.nextUScalar1() * scale); } path.setFillType(SkPath::kEvenOdd_FillType); path.offset(SkIntToScalar(20), SkIntToScalar(20)); test_hittest(canvas, path); canvas->translate(SkIntToScalar(scale), 0); path.setFillType(SkPath::kWinding_FillType); test_hittest(canvas, path); }
virtual void onDraw(SkCanvas* canvas) { drawBG(canvas); //return; canvas->translate(SkIntToScalar(10), SkIntToScalar(10)); SkPaint paint; paint.setAntiAlias(true); if (true) { canvas->drawColor(SK_ColorBLACK); paint.setTextSize(24); paint.setColor(SK_ColorWHITE); canvas->translate(10, 30); static const SkBlurMaskFilter::BlurStyle gStyle[] = { SkBlurMaskFilter::kNormal_BlurStyle, SkBlurMaskFilter::kInner_BlurStyle, SkBlurMaskFilter::kOuter_BlurStyle, SkBlurMaskFilter::kSolid_BlurStyle, }; for (int x = 0; x < 5; x++) { SkMaskFilter* mf; SkScalar radius = 4; for (int y = 0; y < 10; y++) { if (x) { mf = SkBlurMaskFilter::Create(radius, gStyle[x - 1]); paint.setMaskFilter(mf)->unref(); } canvas->drawText("Title Bar", 9, x*100, y*30, paint); radius *= 0.75f; } } return; } paint.setColor(SK_ColorBLUE); #if 1 SkPath p; float r = rand.nextUScalar1() + 0.5f; SkScalar x = 0, y = 0; p.moveTo(x, y); #if 0 p.cubicTo(x-75*r, y+75*r, x-40*r, y+125*r, x, y+85*r); p.cubicTo(x+40*r, y+125*r, x+75*r, y+75*r, x, y); #else p.cubicTo(x+75*r, y+75*r, x+40*r, y+125*r, x, y+85*r); p.cubicTo(x-40*r, y+125*r, x-75*r, y+75*r, x, y); #endif p.close(); fPath = p; fPath.offset(100, 0); #endif fPath.setFillType(SkPath::kWinding_FillType); drawSet(canvas, &paint); canvas->translate(0, fPath.getBounds().height() * 5 / 4); fPath.setFillType(SkPath::kEvenOdd_FillType); drawSet(canvas, &paint); }
void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath, SkPath* devPath, SkMatrix* fillToDevMatrix) { SkPath path; this->getGlyphContext(glyph)->generatePath(glyph, &path); if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { SkFixed dx = glyph.getSubXFixed(); SkFixed dy = glyph.getSubYFixed(); if (dx | dy) { path.offset(SkFixedToScalar(dx), SkFixedToScalar(dy)); } } if (fRec.fFrameWidth > 0 || fPathEffect != NULL) { // need the path in user-space, with only the point-size applied // so that our stroking and effects will operate the same way they // would if the user had extracted the path themself, and then // called drawPath SkPath localPath; SkMatrix matrix, inverse; fRec.getMatrixFrom2x2(&matrix); matrix.invert(&inverse); path.transform(inverse, &localPath); // now localPath is only affected by the paint settings, and not the canvas matrix SkScalar width = fRec.fFrameWidth; if (fPathEffect) { SkPath effectPath; if (fPathEffect->filterPath(&effectPath, localPath, &width)) { localPath.swap(effectPath); } } if (width > 0) { SkStroke stroker; SkPath outline; stroker.setWidth(width); stroker.setMiterLimit(fRec.fMiterLimit); stroker.setJoin((SkPaint::Join)fRec.fStrokeJoin); stroker.setDoFill(SkToBool(fRec.fFlags & kFrameAndFill_Flag)); stroker.strokePath(localPath, &outline); localPath.swap(outline); } // now return stuff to the caller if (fillToDevMatrix) { *fillToDevMatrix = matrix; } if (devPath) { localPath.transform(matrix, devPath); } if (fillPath) { fillPath->swap(localPath); } } else { // nothing tricky to do if (fillToDevMatrix) { fillToDevMatrix->reset(); } if (devPath) { if (fillPath == NULL) { devPath->swap(path); } else { *devPath = path; } } if (fillPath) { fillPath->swap(path); } } if (devPath) { devPath->updateBoundsCache(); } if (fillPath) { fillPath->updateBoundsCache(); } }
void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath, SkPath* devPath, SkMatrix* fillToDevMatrix) { SkPath path; generatePath(glyph, &path); if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { SkFixed dx = glyph.getSubXFixed(); SkFixed dy = glyph.getSubYFixed(); if (dx | dy) { path.offset(SkFixedToScalar(dx), SkFixedToScalar(dy)); } } if (fRec.fFrameWidth > 0 || fPathEffect != nullptr) { // need the path in user-space, with only the point-size applied // so that our stroking and effects will operate the same way they // would if the user had extracted the path themself, and then // called drawPath SkPath localPath; SkMatrix matrix, inverse; fRec.getMatrixFrom2x2(&matrix); if (!matrix.invert(&inverse)) { // assume fillPath and devPath are already empty. return; } path.transform(inverse, &localPath); // now localPath is only affected by the paint settings, and not the canvas matrix SkStrokeRec rec(SkStrokeRec::kFill_InitStyle); if (fRec.fFrameWidth > 0) { rec.setStrokeStyle(fRec.fFrameWidth, SkToBool(fRec.fFlags & kFrameAndFill_Flag)); // glyphs are always closed contours, so cap type is ignored, // so we just pass something. rec.setStrokeParams((SkPaint::Cap)fRec.fStrokeCap, (SkPaint::Join)fRec.fStrokeJoin, fRec.fMiterLimit); } if (fPathEffect) { SkPath effectPath; if (fPathEffect->filterPath(&effectPath, localPath, &rec, nullptr)) { localPath.swap(effectPath); } } if (rec.needToApply()) { SkPath strokePath; if (rec.applyToPath(&strokePath, localPath)) { localPath.swap(strokePath); } } // now return stuff to the caller if (fillToDevMatrix) { *fillToDevMatrix = matrix; } if (devPath) { localPath.transform(matrix, devPath); } if (fillPath) { fillPath->swap(localPath); } } else { // nothing tricky to do if (fillToDevMatrix) { fillToDevMatrix->reset(); } if (devPath) { if (fillPath == nullptr) { devPath->swap(path); } else { *devPath = path; } } if (fillPath) { fillPath->swap(path); } } if (devPath) { devPath->updateBoundsCache(); } if (fillPath) { fillPath->updateBoundsCache(); } }