Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 3e84312

Browse files
reed-at-googleSkia Commit-Bot
authored andcommitted
add new patheffect for stroke-and-fill
Change-Id: I2212e547d3d15c65c20f2f8e10fda5f2ef832187 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/291041 Reviewed-by: Florin Malita <[email protected]> Commit-Queue: Mike Reed <[email protected]>
1 parent 1ac5474 commit 3e84312

File tree

5 files changed

+138
-0
lines changed

5 files changed

+138
-0
lines changed

gm/patheffects.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,3 +237,58 @@ class ComboPathEfectsGM : public skiagm::GM {
237237
};
238238
DEF_GM(return new ComboPathEfectsGM;)
239239

240+
#include "include/effects/SkStrokeAndFillPathEffect.h"
241+
242+
// Test that we can replicate SkPaint::kStrokeAndFill_Style
243+
// with a patheffect. We expect the 2nd and 3rd columns to draw the same.
244+
DEF_SIMPLE_GM(stroke_and_fill_patheffect, canvas, 900, 450) {
245+
const float kStrokeWidth = 20;
246+
247+
typedef void (*Maker)(SkPath*);
248+
const Maker makers[] = {
249+
[](SkPath* path) {
250+
path->addOval({0, 0, 100, 100}, SkPathDirection::kCW);
251+
},
252+
[](SkPath* path) {
253+
path->addOval({0, 0, 100, 100}, SkPathDirection::kCCW);
254+
},
255+
[](SkPath* path) {
256+
path->moveTo(0, 0).lineTo(100, 100).lineTo(0, 100).lineTo(100, 0).close();
257+
},
258+
};
259+
260+
const struct {
261+
SkPaint::Style fStyle;
262+
float fWidth;
263+
bool fUsePE;
264+
bool fExpectStrokeAndFill;
265+
} rec[] = {
266+
{ SkPaint::kStroke_Style, 0, false, false },
267+
{ SkPaint::kFill_Style, 0, true, false },
268+
{ SkPaint::kStroke_Style, 0, true, false },
269+
{ SkPaint::kStrokeAndFill_Style, kStrokeWidth, false, true },
270+
{ SkPaint::kStroke_Style, kStrokeWidth, true, true },
271+
{ SkPaint::kStrokeAndFill_Style, kStrokeWidth, true, true },
272+
};
273+
274+
SkPaint paint;
275+
canvas->translate(20, 20);
276+
for (auto maker : makers) {
277+
SkPath path;
278+
maker(&path);
279+
280+
canvas->save();
281+
for (const auto& r : rec) {
282+
paint.setStyle(r.fStyle);
283+
paint.setStrokeWidth(r.fWidth);
284+
paint.setPathEffect(r.fUsePE ? SkStrokeAndFillPathEffect::Make() : nullptr);
285+
paint.setColor(r.fExpectStrokeAndFill ? SK_ColorGRAY : SK_ColorBLACK);
286+
287+
canvas->drawPath(path, paint);
288+
canvas->translate(150, 0);
289+
}
290+
canvas->restore();
291+
292+
canvas->translate(0, 150);
293+
}
294+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2020 Google Inc.
3+
*
4+
* Use of this source code is governed by a BSD-style license that can be
5+
* found in the LICENSE file.
6+
*/
7+
8+
#ifndef SkStrokeAndFillPathEffect_DEFINED
9+
#define SkStrokeAndFillPathEffect_DEFINED
10+
11+
#include "include/core/SkPaint.h"
12+
#include "include/core/SkPathEffect.h"
13+
#include "include/pathops/SkPathOps.h"
14+
15+
class SK_API SkStrokeAndFillPathEffect {
16+
public:
17+
/* If the paint is set to stroke, this will add the stroke and fill geometries
18+
* together (hoping that the winding-direction works out).
19+
*
20+
* If the paint is set to fill, this effect is ignored.
21+
*
22+
* Note that if the paint is set to stroke and the stroke-width is 0, then
23+
* this will turn the geometry into just a fill.
24+
*/
25+
static sk_sp<SkPathEffect> Make();
26+
};
27+
28+
#endif

src/effects/SkOpPE.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,20 @@ class SkStrokePE : public SkPathEffect {
6565
typedef SkPathEffect INHERITED;
6666
};
6767

68+
class SkStrokeAndFillPE : public SkPathEffect {
69+
public:
70+
SkStrokeAndFillPE() {}
71+
72+
protected:
73+
void flatten(SkWriteBuffer&) const override;
74+
bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect*) const override;
75+
// TODO: override onComputeFastBounds (I think)
76+
77+
private:
78+
SK_FLATTENABLE_HOOKS(SkStrokeAndFillPE)
79+
80+
typedef SkPathEffect INHERITED;
81+
};
82+
6883
#endif
6984

src/effects/SkOpPathEffect.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,43 @@ sk_sp<SkFlattenable> SkStrokePE::CreateProc(SkReadBuffer& buffer) {
121121
return buffer.isValid() ? SkStrokePathEffect::Make(width, join, cap, miter) : nullptr;
122122
}
123123

124+
//////////////////////////////////////////////////////////////////////////////////////////////////
125+
126+
#include "include/effects/SkStrokeAndFillPathEffect.h"
127+
#include "src/core/SkPathPriv.h"
128+
129+
sk_sp<SkPathEffect> SkStrokeAndFillPathEffect::Make() {
130+
return sk_sp<SkPathEffect>(new SkStrokeAndFillPE);
131+
}
132+
133+
void SkStrokeAndFillPE::flatten(SkWriteBuffer&) const {}
134+
135+
bool SkStrokeAndFillPE::onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
136+
const SkRect*) const {
137+
// This one is weird, since we exist to allow this paint-style to go away. If we see it,
138+
// just let the normal machine run its course.
139+
if (rec->getStyle() == SkStrokeRec::kStrokeAndFill_Style) {
140+
*dst = src;
141+
return true;
142+
}
143+
144+
if (rec->getStyle() == SkStrokeRec::kStroke_Style) {
145+
if (!rec->applyToPath(dst, src)) {
146+
return false;
147+
}
148+
// lifted from SkStroke.cpp as an attempt to handle winding directions
149+
if (SkPathPriv::CheapIsFirstDirection(src, SkPathPriv::kCCW_FirstDirection)) {
150+
dst->reverseAddPath(src);
151+
} else {
152+
dst->addPath(src);
153+
}
154+
} else {
155+
*dst = src;
156+
}
157+
rec->setFillStyle();
158+
return true;
159+
}
124160

161+
sk_sp<SkFlattenable> SkStrokeAndFillPE::CreateProc(SkReadBuffer& buffer) {
162+
return SkStrokeAndFillPathEffect::Make();
163+
}

src/ports/SkGlobalInitialization_default.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
SK_REGISTER_FLATTENABLE(SkPath1DPathEffect);
9797
SK_REGISTER_FLATTENABLE(SkPath2DPathEffect);
9898
SK_REGISTER_FLATTENABLE(SkStrokePE);
99+
SK_REGISTER_FLATTENABLE(SkStrokeAndFillPE);
99100
SK_REGISTER_FLATTENABLE(SkTrimPE);
100101
SkPathEffect::RegisterFlattenables();
101102

0 commit comments

Comments
 (0)