Make cap only affect the keys of GrShapes that are possibly-open
BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1949193002 Review-Url: https://codereview.chromium.org/1949193002
This commit is contained in:
parent
3452426715
commit
06077565b1
@ -103,7 +103,11 @@ void GrShape::setInheritedKey(const GrShape &parent, GrStyle::Apply apply) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
int styleCnt = GrStyle::KeySize(parent.fStyle, apply);
|
||||
uint32_t styleKeyFlags = 0;
|
||||
if (parent.knownToBeClosed()) {
|
||||
styleKeyFlags |= GrStyle::kClosed_KeyFlag;
|
||||
}
|
||||
int styleCnt = GrStyle::KeySize(parent.fStyle, apply, styleKeyFlags);
|
||||
if (styleCnt < 0) {
|
||||
// The style doesn't allow a key, set the path to volatile so that we fail when
|
||||
// we try to get a key for the shape.
|
||||
@ -120,7 +124,7 @@ void GrShape::setInheritedKey(const GrShape &parent, GrStyle::Apply apply) {
|
||||
parentCnt * sizeof(uint32_t));
|
||||
}
|
||||
// Now turn (geo,path_effect) or (geo) into (geo,path_effect,stroke)
|
||||
GrStyle::WriteKey(fInheritedKey.get() + parentCnt, parent.fStyle, apply);
|
||||
GrStyle::WriteKey(fInheritedKey.get() + parentCnt, parent.fStyle, apply, styleKeyFlags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,6 +120,9 @@ public:
|
||||
|
||||
void asPath(SkPath* out) const {
|
||||
switch (fType) {
|
||||
case Type::kEmpty:
|
||||
out->reset();
|
||||
break;
|
||||
case Type::kRRect:
|
||||
out->reset();
|
||||
out->addRRect(fRRect);
|
||||
@ -127,12 +130,25 @@ public:
|
||||
case Type::kPath:
|
||||
*out = *fPath.get();
|
||||
break;
|
||||
case Type::kEmpty:
|
||||
out->reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is it known that the shape has no unclosed contours. This means that it will not have
|
||||
* any caps if stroked (modulo the effect of any path effect).
|
||||
*/
|
||||
bool knownToBeClosed() const {
|
||||
switch (fType) {
|
||||
case Type::kEmpty:
|
||||
return true;
|
||||
case Type::kRRect:
|
||||
return true;
|
||||
case Type::kPath:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of the key for the shape represented by this GrShape (ignoring its styling).
|
||||
* A negative value is returned if the shape has no key (shouldn't be cached).
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include "GrStyle.h"
|
||||
|
||||
int GrStyle::KeySize(const GrStyle &style, Apply apply) {
|
||||
int GrStyle::KeySize(const GrStyle &style, Apply apply, uint32_t flags) {
|
||||
GR_STATIC_ASSERT(sizeof(uint32_t) == sizeof(SkScalar));
|
||||
int size = 0;
|
||||
if (style.isDashed()) {
|
||||
@ -29,7 +29,7 @@ int GrStyle::KeySize(const GrStyle &style, Apply apply) {
|
||||
return size;
|
||||
}
|
||||
|
||||
void GrStyle::WriteKey(uint32_t *key, const GrStyle &style, Apply apply) {
|
||||
void GrStyle::WriteKey(uint32_t *key, const GrStyle &style, Apply apply, uint32_t flags) {
|
||||
SkASSERT(key);
|
||||
SkASSERT(KeySize(style, apply) >= 0);
|
||||
GR_STATIC_ASSERT(sizeof(uint32_t) == sizeof(SkScalar));
|
||||
@ -63,9 +63,17 @@ void GrStyle::WriteKey(uint32_t *key, const GrStyle &style, Apply apply) {
|
||||
GR_STATIC_ASSERT(SkStrokeRec::kStyleCount <= (1 << kStyleBits));
|
||||
GR_STATIC_ASSERT(SkPaint::kJoinCount <= (1 << kJoinBits));
|
||||
GR_STATIC_ASSERT(SkPaint::kCapCount <= (1 << kCapBits));
|
||||
// The cap type only matters for unclosed shapes. However, a path effect could unclose
|
||||
// the shape before it is stroked.
|
||||
SkPaint::Cap cap;
|
||||
if ((flags & kClosed_KeyFlag) && !style.pathEffect()) {
|
||||
cap = SkPaint::kButt_Cap;
|
||||
} else {
|
||||
cap = style.strokeRec().getCap();
|
||||
}
|
||||
key[i++] = style.strokeRec().getStyle() |
|
||||
style.strokeRec().getJoin() << kJoinShift |
|
||||
style.strokeRec().getCap() << kCapShift;
|
||||
cap << kCapShift;
|
||||
|
||||
SkScalar scalar;
|
||||
// Miter limit only affects miter joins
|
||||
|
@ -48,22 +48,31 @@ public:
|
||||
kPathEffectAndStrokeRec
|
||||
};
|
||||
|
||||
/**
|
||||
* Optional flags for computing keys that may remove unnecessary variation in the key due to
|
||||
* style settings that don't affect particular classes of geometry.
|
||||
*/
|
||||
enum KeyFlags {
|
||||
// The shape being styled has no open contours.
|
||||
kClosed_KeyFlag = 0x1
|
||||
};
|
||||
|
||||
/**
|
||||
* Computes the key length for a GrStyle. The return will be negative if it cannot be turned
|
||||
* into a key. This occurs when there is a path effect that is not a dash. The key can
|
||||
* either reflect just the path effect (if one) or the path effect and the strokerec. Note
|
||||
* that a simple fill has a zero sized key.
|
||||
*/
|
||||
static int KeySize(const GrStyle& , Apply);
|
||||
static int KeySize(const GrStyle& , Apply, uint32_t flags = 0);
|
||||
|
||||
/**
|
||||
* Writes a unique key for the style into the provided buffer. This function assumes the buffer
|
||||
* has room for at least KeySize() values. It assumes that KeySize() returns a non-negative
|
||||
* value for the style and Apply param. This is written so that the key for just dash
|
||||
* application followed by the key for the remaining SkStrokeRec is the same as the key for
|
||||
* applying dashing and SkStrokeRec all at once.
|
||||
* value for the combination of GrStyle, Apply and flags params. This is written so that the key
|
||||
* for just dash application followed by the key for the remaining SkStrokeRec is the same as
|
||||
* the key for applying dashing and SkStrokeRec all at once.
|
||||
*/
|
||||
static void WriteKey(uint32_t*, const GrStyle&, Apply);
|
||||
static void WriteKey(uint32_t*, const GrStyle&, Apply, uint32_t flags = 0);
|
||||
|
||||
GrStyle() : GrStyle(SkStrokeRec::kFill_InitStyle) {}
|
||||
|
||||
|
@ -263,10 +263,12 @@ static void test_basic(skiatest::Reporter* reporter, const GEO& geo) {
|
||||
}
|
||||
|
||||
template <typename GEO, typename T>
|
||||
static void test_stroke_param(skiatest::Reporter* reporter, const GEO& geo,
|
||||
std::function<void(SkPaint*, T)> setter, T a, T b) {
|
||||
// Set the stroke width so that we don't get hairline. However, call the function second so that
|
||||
// it can override.
|
||||
static void test_stroke_param_impl(skiatest::Reporter* reporter, const GEO& geo,
|
||||
std::function<void(SkPaint*, T)> setter, T a, T b,
|
||||
bool paramAffectsStroke,
|
||||
bool paramAffectsDashAndStroke) {
|
||||
// Set the stroke width so that we don't get hairline. However, call the setter afterward so
|
||||
// that it can override the stroke width.
|
||||
SkPaint strokeA;
|
||||
strokeA.setStyle(SkPaint::kStroke_Style);
|
||||
strokeA.setStrokeWidth(2.f);
|
||||
@ -278,7 +280,11 @@ static void test_stroke_param(skiatest::Reporter* reporter, const GEO& geo,
|
||||
|
||||
TestCase strokeACase(geo, strokeA, reporter);
|
||||
TestCase strokeBCase(geo, strokeB, reporter);
|
||||
if (paramAffectsStroke) {
|
||||
strokeACase.compare(reporter, strokeBCase, TestCase::kSameUpToStroke_ComparisonExpecation);
|
||||
} else {
|
||||
strokeACase.compare(reporter, strokeBCase, TestCase::kAllSame_ComparisonExpecation);
|
||||
}
|
||||
|
||||
// Make sure stroking params don't affect fill style.
|
||||
SkPaint fillA = strokeA, fillB = strokeB;
|
||||
@ -295,38 +301,66 @@ static void test_stroke_param(skiatest::Reporter* reporter, const GEO& geo,
|
||||
dashB.setPathEffect(make_dash());
|
||||
TestCase dashACase(geo, dashA, reporter);
|
||||
TestCase dashBCase(geo, dashB, reporter);
|
||||
if (paramAffectsDashAndStroke) {
|
||||
dashACase.compare(reporter, dashBCase, TestCase::kSameUpToStroke_ComparisonExpecation);
|
||||
} else {
|
||||
dashACase.compare(reporter, dashBCase, TestCase::kAllSame_ComparisonExpecation);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename GEO, typename T>
|
||||
static void test_stroke_param(skiatest::Reporter* reporter, const GEO& geo,
|
||||
std::function<void(SkPaint*, T)> setter, T a, T b) {
|
||||
test_stroke_param_impl(reporter, geo, setter, a, b, true, true);
|
||||
};
|
||||
|
||||
template <typename GEO>
|
||||
static void test_stroke_cap(skiatest::Reporter* reporter, const GEO& geo) {
|
||||
GrShape shape(geo, GrStyle(SkStrokeRec::kHairline_InitStyle));
|
||||
// The cap should only affect shapes that may be open.
|
||||
bool affectsStroke = !shape.knownToBeClosed();
|
||||
// Dashing adds ends that need caps.
|
||||
bool affectsDashAndStroke = true;
|
||||
test_stroke_param_impl<GEO, SkPaint::Cap>(
|
||||
reporter,
|
||||
geo,
|
||||
[](SkPaint* p, SkPaint::Cap c) { p->setStrokeCap(c);},
|
||||
SkPaint::kButt_Cap, SkPaint::kRound_Cap,
|
||||
affectsStroke,
|
||||
affectsDashAndStroke);
|
||||
};
|
||||
|
||||
template <typename GEO>
|
||||
static void test_miter_limit(skiatest::Reporter* reporter, const GEO& geo) {
|
||||
// Miter limit should only matter when stroking with miter joins. It shouldn't affect other
|
||||
// joins or fills.
|
||||
SkPaint miterA;
|
||||
miterA.setStyle(SkPaint::kStroke_Style);
|
||||
miterA.setStrokeWidth(2.f);
|
||||
miterA.setStrokeJoin(SkPaint::kMiter_Join);
|
||||
miterA.setStrokeMiter(0.5f);
|
||||
SkPaint miterB = miterA;
|
||||
miterA.setStrokeMiter(0.6f);
|
||||
auto setMiterJoinAndLimit = [](SkPaint* p, SkScalar miter) {
|
||||
p->setStrokeJoin(SkPaint::kMiter_Join);
|
||||
p->setStrokeMiter(miter);
|
||||
};
|
||||
|
||||
TestCase miterACase(geo, miterA, reporter);
|
||||
TestCase miterBCase(geo, miterB, reporter);
|
||||
miterACase.compare(reporter, miterBCase, TestCase::kSameUpToStroke_ComparisonExpecation);
|
||||
auto setOtherJoinAndLimit = [](SkPaint* p, SkScalar miter) {
|
||||
p->setStrokeJoin(SkPaint::kRound_Join);
|
||||
p->setStrokeMiter(miter);
|
||||
};
|
||||
|
||||
SkPaint noMiterA = miterA, noMiterB = miterB;
|
||||
noMiterA.setStrokeJoin(SkPaint::kRound_Join);
|
||||
noMiterB.setStrokeJoin(SkPaint::kRound_Join);
|
||||
TestCase noMiterACase(geo, noMiterA, reporter);
|
||||
TestCase noMiterBCase(geo, noMiterB, reporter);
|
||||
noMiterACase.compare(reporter, noMiterBCase, TestCase::kAllSame_ComparisonExpecation);
|
||||
// The miter limit should affect stroked and dashed-stroked cases when the join type is
|
||||
// miter.
|
||||
test_stroke_param_impl<GEO, SkScalar>(
|
||||
reporter,
|
||||
geo,
|
||||
setMiterJoinAndLimit,
|
||||
0.5f, 0.75f,
|
||||
true,
|
||||
true);
|
||||
|
||||
SkPaint fillA = miterA, fillB = miterB;
|
||||
fillA.setStyle(SkPaint::kFill_Style);
|
||||
fillB.setStyle(SkPaint::kFill_Style);
|
||||
TestCase fillACase(geo, fillA, reporter);
|
||||
TestCase fillBCase(geo, fillB, reporter);
|
||||
fillACase.compare(reporter, fillBCase, TestCase::kAllSame_ComparisonExpecation);
|
||||
// The miter limit should not affect stroked and dashed-stroked cases when the join type is
|
||||
// not miter.
|
||||
test_stroke_param_impl<GEO, SkScalar>(
|
||||
reporter,
|
||||
geo,
|
||||
setOtherJoinAndLimit,
|
||||
0.5f, 0.75f,
|
||||
false,
|
||||
false);
|
||||
}
|
||||
|
||||
template<typename GEO>
|
||||
@ -660,14 +694,11 @@ DEF_TEST(GrShape, reporter) {
|
||||
reporter, rr,
|
||||
[](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);},
|
||||
SkIntToScalar(2), SkIntToScalar(4));
|
||||
test_stroke_param<SkRRect, SkPaint::Cap>(
|
||||
reporter, rr,
|
||||
[](SkPaint* p, SkPaint::Cap c) { p->setStrokeCap(c);},
|
||||
SkPaint::kButt_Cap, SkPaint::kRound_Cap);
|
||||
test_stroke_param<SkRRect, SkPaint::Join>(
|
||||
reporter, rr,
|
||||
[](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);},
|
||||
SkPaint::kMiter_Join, SkPaint::kRound_Join);
|
||||
test_stroke_cap(reporter, rr);
|
||||
test_miter_limit(reporter, rr);
|
||||
test_path_effect_makes_rrect(reporter, rr);
|
||||
test_unknown_path_effect(reporter, rr);
|
||||
@ -725,14 +756,11 @@ DEF_TEST(GrShape, reporter) {
|
||||
reporter, path,
|
||||
[](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);},
|
||||
SkIntToScalar(2), SkIntToScalar(4));
|
||||
test_stroke_param<SkPath, SkPaint::Cap>(
|
||||
reporter, path,
|
||||
[](SkPaint* p, SkPaint::Cap c) { p->setStrokeCap(c);},
|
||||
SkPaint::kButt_Cap, SkPaint::kRound_Cap);
|
||||
test_stroke_param<SkPath, SkPaint::Join>(
|
||||
reporter, path,
|
||||
[](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);},
|
||||
SkPaint::kMiter_Join, SkPaint::kRound_Join);
|
||||
test_stroke_cap(reporter, path);
|
||||
test_miter_limit(reporter, path);
|
||||
test_unknown_path_effect(reporter, path);
|
||||
test_path_effect_makes_empty_shape(reporter, path);
|
||||
|
Loading…
Reference in New Issue
Block a user