aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/patheffects.cpp61
-rw-r--r--gn/effects.gni1
-rw-r--r--include/effects/SkOpPathEffect.h38
-rw-r--r--src/effects/SkOpPE.h79
-rw-r--r--src/effects/SkOpPathEffect.cpp124
-rw-r--r--src/ports/SkGlobalInitialization_default.cpp5
6 files changed, 306 insertions, 2 deletions
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<SkPathEffect> 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<SkPathEffect> Make(sk_sp<SkPathEffect> one, sk_sp<SkPathEffect> two, SkPathOp op);
+};
+
+class SkMatrixPathEffect {
+public:
+ static sk_sp<SkPathEffect> MakeTranslate(SkScalar dx, SkScalar dy);
+ static sk_sp<SkPathEffect> Make(const SkMatrix&);
+};
+
+class SkStrokePathEffect {
+public:
+ static sk_sp<SkPathEffect> 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<SkPathEffect> one, sk_sp<SkPathEffect> 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<SkFlattenable> CreateProc(SkReadBuffer&);
+ friend class SkFlattenable::PrivateInitializer;
+
+ sk_sp<SkPathEffect> fOne;
+ sk_sp<SkPathEffect> 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<SkFlattenable> 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<SkFlattenable> 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<SkPathEffect> SkOpPathEffect::Make(sk_sp<SkPathEffect> one, sk_sp<SkPathEffect> two,
+ SkPathOp op) {
+ return sk_sp<SkPathEffect>(new SkOpPE(std::move(one), std::move(two), op));
+}
+
+SkOpPE::SkOpPE(sk_sp<SkPathEffect> one, sk_sp<SkPathEffect> 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<SkFlattenable> 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<SkPathEffect> SkMatrixPathEffect::MakeTranslate(SkScalar dx, SkScalar dy) {
+ if (!SkScalarsAreFinite(dx, dy)) {
+ return nullptr;
+ }
+ return sk_sp<SkPathEffect>(new SkMatrixPE(SkMatrix::MakeTrans(dx, dy)));
+}
+
+sk_sp<SkPathEffect> SkMatrixPathEffect::Make(const SkMatrix& matrix) {
+ if (!matrix.isFinite()) {
+ return nullptr;
+ }
+ return sk_sp<SkPathEffect>(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<SkFlattenable> SkMatrixPE::CreateProc(SkReadBuffer& buffer) {
+ SkMatrix mx;
+ buffer.readMatrix(&mx);
+ return buffer.isValid() ? SkMatrixPathEffect::Make(mx) : nullptr;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+sk_sp<SkPathEffect> 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<SkPathEffect>(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<SkFlattenable> 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)
}