add arcto patheffect

BUG=skia:
TBR=

Review URL: https://codereview.chromium.org/813513003
This commit is contained in:
reed 2014-12-17 01:47:32 -08:00 committed by Commit bot
parent 287ccfece6
commit 8b5752443f
6 changed files with 159 additions and 20 deletions

View File

@ -10,6 +10,7 @@
'<(skia_src_path)/effects/Sk1DPathEffect.cpp',
'<(skia_src_path)/effects/Sk2DPathEffect.cpp',
'<(skia_src_path)/effects/SkAlphaThresholdFilter.cpp',
'<(skia_src_path)/effects/SkArcToPathEffect.cpp',
'<(skia_src_path)/effects/SkArithmeticMode.cpp',
'<(skia_src_path)/effects/SkAvoidXfermode.cpp',
'<(skia_src_path)/effects/SkBitmapSource.cpp',

View File

@ -0,0 +1,39 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkArcToPathEffect_DEFINED
#define SkArcToPathEffect_DEFINED
#include "SkPathEffect.h"
class SK_API SkArcToPathEffect : public SkPathEffect {
public:
/** radius must be > 0 to have an effect. It specifies the distance from each corner
that should be "rounded".
*/
static SkPathEffect* Create(SkScalar radius) {
if (radius <= 0) {
return NULL;
}
return SkNEW_ARGS(SkArcToPathEffect, (radius));
}
bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect*) const SK_OVERRIDE;
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkArcToPathEffect)
protected:
explicit SkArcToPathEffect(SkScalar radius);
virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
private:
SkScalar fRadius;
typedef SkPathEffect INHERITED;
};
#endif

View File

@ -214,45 +214,56 @@ DEF_SAMPLE( return new PathView; )
//////////////////////////////////////////////////////////////////////////////
#include "SkArcToPathEffect.h"
#include "SkCornerPathEffect.h"
#include "SkRandom.h"
class ArcToView : public SampleView {
SkPaint fPtsPaint, fArcPaint, fSkeletonPaint, fCornerPaint;
bool fDoFrame, fDoArcTo, fDoCorner, fDoConic;
SkPaint fPtsPaint, fArcToPaint, fSkeletonPaint, fCornerPaint;
public:
enum {
N = 4
};
SkPoint fPts[N];
SkScalar fRadius;
ArcToView() : fRadius(50) {
ArcToView()
: fDoFrame(false), fDoArcTo(false), fDoCorner(false), fDoConic(false)
{
SkRandom rand;
for (int i = 0; i < N; ++i) {
fPts[i].fX = 20 + rand.nextUScalar1() * 640;
fPts[i].fY = 20 + rand.nextUScalar1() * 480;
}
const SkScalar rad = 50;
fPtsPaint.setAntiAlias(true);
fPtsPaint.setStrokeWidth(15);
fPtsPaint.setStrokeCap(SkPaint::kRound_Cap);
fArcPaint.setAntiAlias(true);
fArcPaint.setStyle(SkPaint::kStroke_Style);
fArcPaint.setStrokeWidth(9);
fArcPaint.setColor(0x800000FF);
fArcToPaint.setAntiAlias(true);
fArcToPaint.setStyle(SkPaint::kStroke_Style);
fArcToPaint.setStrokeWidth(9);
fArcToPaint.setColor(0x800000FF);
fArcToPaint.setPathEffect(SkArcToPathEffect::Create(rad))->unref();
fCornerPaint.setAntiAlias(true);
fCornerPaint.setStyle(SkPaint::kStroke_Style);
fCornerPaint.setStrokeWidth(13);
fCornerPaint.setColor(SK_ColorGREEN);
fCornerPaint.setPathEffect(SkCornerPathEffect::Create(fRadius*2))->unref();
fCornerPaint.setPathEffect(SkCornerPathEffect::Create(rad*2))->unref();
fSkeletonPaint.setAntiAlias(true);
fSkeletonPaint.setStyle(SkPaint::kStroke_Style);
fSkeletonPaint.setColor(SK_ColorRED);
}
void toggle(bool& value) {
value = !value;
this->inval(NULL);
}
protected:
// overrides from SkEventSink
bool onQuery(SkEvent* evt) SK_OVERRIDE {
@ -260,29 +271,43 @@ protected:
SampleCode::TitleR(evt, "ArcTo");
return true;
}
SkUnichar uni;
if (SampleCode::CharQ(*evt, &uni)) {
switch (uni) {
case '1': this->toggle(fDoFrame); return true;
case '2': this->toggle(fDoArcTo); return true;
case '3': this->toggle(fDoCorner); return true;
case '4': this->toggle(fDoConic); return true;
default: break;
}
}
return this->INHERITED::onQuery(evt);
}
void makePath(SkPath* path) {
path->moveTo(fPts[0]);
for (int i = 1; i < N; ++i) {
path->lineTo(fPts[i]);
}
if (!fDoFrame) {
path->close();
}
}
void onDrawContent(SkCanvas* canvas) SK_OVERRIDE {
canvas->drawPoints(SkCanvas::kPoints_PointMode, N, fPts, fPtsPaint);
SkPath path;
this->makePath(&path);
path.moveTo(fPts[0]);
for (int i = 1; i < N; ++i) {
path.lineTo(fPts[i].fX, fPts[i].fY);
if (fDoCorner) {
canvas->drawPath(path, fCornerPaint);
}
canvas->drawPath(path, fCornerPaint);
path.reset();
path.moveTo(fPts[0]);
for (int i = 1; i < N - 1; ++i) {
path.arcTo(fPts[i].fX, fPts[i].fY, fPts[i+1].fX, fPts[i+1].fY, fRadius);
if (fDoArcTo) {
canvas->drawPath(path, fArcToPaint);
}
path.lineTo(fPts[N - 1]);
canvas->drawPath(path, fArcPaint);
canvas->drawPoints(SkCanvas::kPolygon_PointMode, N, fPts, fSkeletonPaint);
canvas->drawPath(path, fSkeletonPaint);
}
bool onClick(Click* click) SK_OVERRIDE {

View File

@ -0,0 +1,70 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkArcToPathEffect.h"
#include "SkPath.h"
#include "SkPoint.h"
#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"
SkArcToPathEffect::SkArcToPathEffect(SkScalar radius) : fRadius(radius) {}
bool SkArcToPathEffect::filterPath(SkPath* dst, const SkPath& src,
SkStrokeRec*, const SkRect*) const {
SkPath::Iter iter(src, false);
SkPath::Verb verb;
SkPoint pts[4];
SkPoint lastCorner = { 0, 0 }; // avoid warning
SkPath::Verb prevVerb = SkPath::kMove_Verb;
for (;;) {
switch (verb = iter.next(pts, false)) {
case SkPath::kMove_Verb:
if (SkPath::kLine_Verb == prevVerb) {
dst->lineTo(lastCorner);
}
dst->moveTo(pts[0]);
break;
case SkPath::kLine_Verb:
if (prevVerb == SkPath::kLine_Verb) {
dst->arcTo(pts[0], pts[1], fRadius);
}
lastCorner = pts[1];
break;
case SkPath::kQuad_Verb:
dst->quadTo(pts[1], pts[2]);
lastCorner = pts[2];
break;
case SkPath::kConic_Verb:
dst->conicTo(pts[1], pts[2], iter.conicWeight());
lastCorner = pts[2];
break;
case SkPath::kCubic_Verb:
dst->cubicTo(pts[1], pts[2], pts[3]);
lastCorner = pts[3];
break;
case SkPath::kClose_Verb:
dst->lineTo(lastCorner);
break;
case SkPath::kDone_Verb:
dst->lineTo(lastCorner);
goto DONE;
}
prevVerb = verb;
}
DONE:
return true;
}
SkFlattenable* SkArcToPathEffect::CreateProc(SkReadBuffer& buffer) {
return SkArcToPathEffect::Create(buffer.readScalar());
}
void SkArcToPathEffect::flatten(SkWriteBuffer& buffer) const {
buffer.writeScalar(fRadius);
}

View File

@ -16,6 +16,7 @@
#include "Sk1DPathEffect.h"
#include "Sk2DPathEffect.h"
#include "SkArithmeticMode.h"
#include "SkArcToPathEffect.h"
#include "SkAvoidXfermode.h"
#include "SkBitmapSource.h"
#include "SkBlurDrawLooper.h"
@ -63,6 +64,7 @@
class SkPrivateEffectInitializer {
public:
static void Init() {
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkArcToPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkAvoidXfermode)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBitmapProcShader)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBitmapSource)

View File

@ -16,6 +16,7 @@
#include "Sk1DPathEffect.h"
#include "Sk2DPathEffect.h"
#include "SkArithmeticMode.h"
#include "SkArcToPathEffect.h"
#include "SkAvoidXfermode.h"
#include "SkBitmapSource.h"
#include "SkBlurDrawLooper.h"
@ -63,6 +64,7 @@
class SkPrivateEffectInitializer {
public:
static void Init() {
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkArcToPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkAvoidXfermode)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBitmapProcShader)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBitmapSource)