From 0ef539af4cfbcccf1ef23e9ef3d1fcdafd2a6b99 Mon Sep 17 00:00:00 2001 From: Mike Reed Date: Wed, 18 Jul 2018 13:28:42 -0400 Subject: add new patheffects Bug: skia: Change-Id: Icc94eafbb26a097d5032cdb4f6e2e0f52a4e1025 Reviewed-on: https://skia-review.googlesource.com/141961 Commit-Queue: Mike Reed Reviewed-by: Florin Malita --- gm/patheffects.cpp | 61 ++++++++++++- gn/effects.gni | 1 + include/effects/SkOpPathEffect.h | 38 ++++++++ src/effects/SkOpPE.h | 79 +++++++++++++++++ src/effects/SkOpPathEffect.cpp | 124 +++++++++++++++++++++++++++ src/ports/SkGlobalInitialization_default.cpp | 5 ++ 6 files changed, 306 insertions(+), 2 deletions(-) create mode 100644 include/effects/SkOpPathEffect.h create mode 100644 src/effects/SkOpPE.h create mode 100644 src/effects/SkOpPathEffect.cpp diff --git a/gm/patheffects.cpp b/gm/patheffects.cpp index 744817a489..0f600c4fb5 100644 --- a/gm/patheffects.cpp +++ b/gm/patheffects.cpp @@ -161,9 +161,66 @@ private: typedef GM INHERITED; }; -////////////////////////////////////////////////////////////////////////////// - static GM* PathEffectFactory(void*) { return new PathEffectGM; } static GMRegistry regPathEffect(PathEffectFactory); } + +////////////////////////////////////////////////////////////////////////////// +#include "SkOpPathEffect.h" + +class ComboPathEfectsGM : public skiagm::GM { +public: + ComboPathEfectsGM() {} + +protected: + + SkString onShortName() override { + return SkString("combo-patheffects"); + } + + SkISize onISize() override { return SkISize::Make(360, 630); } + + void onDraw(SkCanvas* canvas) override { + SkPath path0, path1, path2; + path0.addCircle(100, 100, 60); + path1.moveTo(20, 20); path1.cubicTo(20, 180, 140, 0, 140, 140); + + sk_sp effects[] = { + nullptr, + SkStrokePathEffect::Make(20, SkPaint::kRound_Join, SkPaint::kRound_Cap, 0), + SkOpPathEffect::Make(nullptr, + SkStrokePathEffect::Make(20, SkPaint::kRound_Join, SkPaint::kRound_Cap, 0), + kDifference_SkPathOp), + SkOpPathEffect::Make(SkMatrixPathEffect::MakeTranslate(50, 30), + SkStrokePathEffect::Make(20, SkPaint::kRound_Join, SkPaint::kRound_Cap, 0), + kReverseDifference_SkPathOp), + }; + + SkPaint wireframe; + wireframe.setStyle(SkPaint::kStroke_Style); + wireframe.setAntiAlias(true); + + SkPaint paint; + paint.setColor(0xFF8888FF); + paint.setAntiAlias(true); + + for (auto& path : { path0, path1 }) { + canvas->save(); + for (auto pe : effects) { + paint.setPathEffect(pe); + canvas->drawPath(path, paint); + canvas->drawPath(path, wireframe); + + canvas->translate(0, 150); + } + canvas->restore(); + canvas->translate(180, 0); + } + } + +private: + typedef GM INHERITED; +}; +DEF_GM(return new ComboPathEfectsGM;) + diff --git a/gn/effects.gni b/gn/effects.gni index 9d14a53184..b8064213c2 100644 --- a/gn/effects.gni +++ b/gn/effects.gni @@ -23,6 +23,7 @@ skia_effects_sources = [ "$_src/effects/SkHighContrastFilter.cpp", "$_src/effects/SkLayerDrawLooper.cpp", "$_src/effects/SkLumaColorFilter.cpp", + "$_src/effects/SkOpPathEffect.cpp", "$_src/effects/SkOverdrawColorFilter.cpp", "$_src/effects/SkPackBits.cpp", "$_src/effects/SkPackBits.h", diff --git a/include/effects/SkOpPathEffect.h b/include/effects/SkOpPathEffect.h new file mode 100644 index 0000000000..54b177ea17 --- /dev/null +++ b/include/effects/SkOpPathEffect.h @@ -0,0 +1,38 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkOpPathEffect_DEFINED +#define SkOpPathEffect_DEFINED + +#include "SkPathEffect.h" +#include "SkPaint.h" +#include "SkPathOps.h" + +class SkOpPathEffect { +public: + /* Defers to two other patheffects, and then combines their outputs using the specified op. + * e.g. + * result = output_one op output_two + * + * If either one or two is nullptr, then the original path is passed through to the op. + */ + static sk_sp Make(sk_sp one, sk_sp two, SkPathOp op); +}; + +class SkMatrixPathEffect { +public: + static sk_sp MakeTranslate(SkScalar dx, SkScalar dy); + static sk_sp Make(const SkMatrix&); +}; + +class SkStrokePathEffect { +public: + static sk_sp Make(SkScalar width, SkPaint::Join, SkPaint::Cap, + SkScalar miter = 4); +}; + +#endif diff --git a/src/effects/SkOpPE.h b/src/effects/SkOpPE.h new file mode 100644 index 0000000000..d6883d0ff3 --- /dev/null +++ b/src/effects/SkOpPE.h @@ -0,0 +1,79 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkOpPE_DEFINED +#define SkOpPE_DEFINED + +#include "SkOpPathEffect.h" + +class SkOpPE : public SkPathEffect { +public: + SkOpPE(sk_sp one, sk_sp two, SkPathOp op); + + bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect*) const override; + + Factory getFactory() const override { return CreateProc; } + +protected: + void flatten(SkWriteBuffer&) const override; + +private: + static sk_sp CreateProc(SkReadBuffer&); + friend class SkFlattenable::PrivateInitializer; + + sk_sp fOne; + sk_sp fTwo; + SkPathOp fOp; + + typedef SkPathEffect INHERITED; +}; + +class SkMatrixPE : public SkPathEffect { +public: + SkMatrixPE(const SkMatrix&); + + bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect*) const override; + + Factory getFactory() const override { return CreateProc; } + +protected: + void flatten(SkWriteBuffer&) const override; + +private: + static sk_sp CreateProc(SkReadBuffer&); + friend class SkFlattenable::PrivateInitializer; + + SkMatrix fMatrix; + + typedef SkPathEffect INHERITED; +}; + +class SkStrokePE : public SkPathEffect { +public: + SkStrokePE(SkScalar width, SkPaint::Join, SkPaint::Cap, SkScalar miter); + + bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect*) const override; + + Factory getFactory() const override { return CreateProc; } + +protected: + void flatten(SkWriteBuffer&) const override; + +private: + static sk_sp CreateProc(SkReadBuffer&); + friend class SkFlattenable::PrivateInitializer; + + SkScalar fWidth, + fMiter; + SkPaint::Join fJoin; + SkPaint::Cap fCap; + + typedef SkPathEffect INHERITED; +}; + +#endif + diff --git a/src/effects/SkOpPathEffect.cpp b/src/effects/SkOpPathEffect.cpp new file mode 100644 index 0000000000..4f23ab8583 --- /dev/null +++ b/src/effects/SkOpPathEffect.cpp @@ -0,0 +1,124 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkOpPE.h" +#include "SkStrokeRec.h" +#include "SkReadBuffer.h" +#include "SkWriteBuffer.h" + +sk_sp SkOpPathEffect::Make(sk_sp one, sk_sp two, + SkPathOp op) { + return sk_sp(new SkOpPE(std::move(one), std::move(two), op)); +} + +SkOpPE::SkOpPE(sk_sp one, sk_sp two, SkPathOp op) + : fOne(std::move(one)), fTwo(std::move(two)), fOp(op) {} + +bool SkOpPE::filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec, + const SkRect* cull) const { + SkPath one, two; + if (fOne) { + if (!fOne->filterPath(&one, src, rec, cull)) { + return false; + } + } else { + one = src; + } + if (fTwo) { + if (!fTwo->filterPath(&two, src, rec, cull)) { + return false; + } + } else { + two = src; + } + return Op(one, two, fOp, dst); +} + +void SkOpPE::flatten(SkWriteBuffer& buffer) const { + buffer.writeFlattenable(fOne.get()); + buffer.writeFlattenable(fTwo.get()); + buffer.write32(fOp); +} + +sk_sp SkOpPE::CreateProc(SkReadBuffer& buffer) { + auto one = buffer.readPathEffect(); + auto two = buffer.readPathEffect(); + SkPathOp op = buffer.read32LE(kReverseDifference_SkPathOp); + return buffer.isValid() ? SkOpPathEffect::Make(std::move(one), std::move(two), op) : nullptr; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + +sk_sp SkMatrixPathEffect::MakeTranslate(SkScalar dx, SkScalar dy) { + if (!SkScalarsAreFinite(dx, dy)) { + return nullptr; + } + return sk_sp(new SkMatrixPE(SkMatrix::MakeTrans(dx, dy))); +} + +sk_sp SkMatrixPathEffect::Make(const SkMatrix& matrix) { + if (!matrix.isFinite()) { + return nullptr; + } + return sk_sp(new SkMatrixPE(matrix)); +} + +SkMatrixPE::SkMatrixPE(const SkMatrix& matrix) : fMatrix(matrix) { + SkASSERT(matrix.isFinite()); +} + +bool SkMatrixPE::filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect*) const { + src.transform(fMatrix, dst); + return true; +} + +void SkMatrixPE::flatten(SkWriteBuffer& buffer) const { + buffer.writeMatrix(fMatrix); +} + +sk_sp SkMatrixPE::CreateProc(SkReadBuffer& buffer) { + SkMatrix mx; + buffer.readMatrix(&mx); + return buffer.isValid() ? SkMatrixPathEffect::Make(mx) : nullptr; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + +sk_sp SkStrokePathEffect::Make(SkScalar width, SkPaint::Join join, SkPaint::Cap cap, + SkScalar miter) { + if (!SkScalarsAreFinite(width, miter) || width < 0 || miter < 0) { + return nullptr; + } + return sk_sp(new SkStrokePE(width, join, cap, miter)); +} + +SkStrokePE::SkStrokePE(SkScalar width, SkPaint::Join join, SkPaint::Cap cap, SkScalar miter) + : fWidth(width), fMiter(miter), fJoin(join), fCap(cap) {} + +bool SkStrokePE::filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect*) const { + SkStrokeRec rec(SkStrokeRec::kFill_InitStyle); + rec.setStrokeStyle(fWidth); + rec.setStrokeParams(fCap, fJoin, fMiter); + return rec.applyToPath(dst, src); +} + +void SkStrokePE::flatten(SkWriteBuffer& buffer) const { + buffer.writeScalar(fWidth); + buffer.writeScalar(fMiter); + buffer.write32(fJoin); + buffer.write32(fCap); +} + +sk_sp SkStrokePE::CreateProc(SkReadBuffer& buffer) { + SkScalar width = buffer.readScalar(); + SkScalar miter = buffer.readScalar(); + SkPaint::Join join = buffer.read32LE(SkPaint::kLast_Join); + SkPaint::Cap cap = buffer.read32LE(SkPaint::kLast_Cap); + return buffer.isValid() ? SkStrokePathEffect::Make(width, join, cap, miter) : nullptr; +} + + diff --git a/src/ports/SkGlobalInitialization_default.cpp b/src/ports/SkGlobalInitialization_default.cpp index ecb9ccb1ca..8ab32a6b55 100644 --- a/src/ports/SkGlobalInitialization_default.cpp +++ b/src/ports/SkGlobalInitialization_default.cpp @@ -23,6 +23,7 @@ #include "SkShaderMaskFilter.h" #include "SkTableColorFilter.h" #include "SkToSRGBColorFilter.h" +#include "../../src/effects/SkOpPE.h" #include "../../src/effects/SkTrimPE.h" /* @@ -64,4 +65,8 @@ void SkFlattenable::PrivateInitializer::InitEffects() { SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLine2DPathEffect) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath2DPathEffect) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTrimPE) + + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkOpPE) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMatrixPE) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkStrokePE) } -- cgit v1.2.3