43#include <initializer_list>
51 if (
const auto* lp = this->originalPathForListeners()) {
52 return lp->getGenerationID();
90 static constexpr int kRes = 2000;
92 static constexpr int kTol = 2;
93 static_assert(kRes % 4 == 0);
96 surface->getCanvas()->clear(0x0);
106 surface->getCanvas()->peekPixels(&pixmap);
107#if defined(SK_BUILD_FOR_WIN)
109 const uint8_t* kZeros =
reinterpret_cast<uint8_t*
>(
calloc(kRes, 1));
111 static constexpr uint8_t kZeros[kRes] = {0};
113 for (
int y = 0;
y < kRes; ++
y) {
114 const uint8_t* row = pixmap.
addr8(0,
y);
115 if (0 != memcmp(kZeros, row, kRes)) {
119#ifdef SK_BUILD_FOR_WIN
120 free(
const_cast<uint8_t*
>(kZeros));
138 const Key& keyA,
const Key& keyB) {
149 bool invertedA =
true, invertedB =
true;
151 bool aIsRRect =
a.asRRect(&rrectA, &invertedA);
152 bool bIsRRect =
b.asRRect(&rrectB, &invertedB);
153 bool aHasPE =
a.style().hasPathEffect();
154 bool bHasPE =
b.style().hasPathEffect();
155 bool allowSameRRectButDiffStartAndDir = (aIsRRect && bIsRRect) && (aHasPE != bHasPE);
157 bool allowedClosednessDiff = (
a.style().isSimpleFill() !=
b.style().isSimpleFill());
164 bool ignoreInversenessDifference =
false;
170 ignoreInversenessDifference = (canDropInverse1 != canDropInverse2);
172 bool ignoreWindingVsEvenOdd =
false;
177 if (aCanChange != bCanChange) {
178 ignoreWindingVsEvenOdd =
true;
181 if (allowSameRRectButDiffStartAndDir) {
184 REPORTER_ASSERT(r, ignoreInversenessDifference || invertedA == invertedB);
190 if (ignoreInversenessDifference) {
194 if (ignoreWindingVsEvenOdd) {
200 if (!ignoreInversenessDifference && !ignoreWindingVsEvenOdd) {
205 if (allowedClosednessDiff) {
216 REPORTER_ASSERT(r, ignoreInversenessDifference || invertedA == invertedB);
220 REPORTER_ASSERT(r, allowedClosednessDiff ||
a.knownToBeClosed() ==
b.knownToBeClosed());
222 REPORTER_ASSERT(r, allowedClosednessDiff ||
a.knownToBeConvex() ==
b.knownToBeConvex());
223 if (
a.knownToBeConvex()) {
226 if (
b.knownToBeConvex()) {
232 SkPoint pts[4] {{0, 0,}, {0, 0}, {0, 0}, {0, 0}} ;
233 bool invertedLine[2] {
true,
true};
234 REPORTER_ASSERT(r,
a.asLine(pts, &invertedLine[0]) ==
b.asLine(pts + 2, &invertedLine[1]));
239 if (
a.style().hasNonDashPathEffect() ==
b.style().hasNonDashPathEffect() &&
240 a.style().isDashed() ==
b.style().isDashed()) {
242 b.mayBeInverseFilledAfterStyling());
244 if (
a.asLine(
nullptr,
nullptr)) {
246 REPORTER_ASSERT(r, ignoreInversenessDifference || invertedLine[0] == invertedLine[1]);
250 REPORTER_ASSERT(r, ignoreInversenessDifference ||
a.inverseFilled() ==
b.inverseFilled());
256 bool baseIsNonVolatilePath =
base.testingOnly_isNonVolatilePath();
259 bool fullIsPath =
full.testingOnly_isPath();
263 uint32_t baseID =
base.testingOnly_getOriginalGenerationID();
266 uint32_t fullID =
full.testingOnly_getOriginalGenerationID();
288 if (baseIsNonVolatilePath) {
292 if (peStrokeIsPath) {
297 if (baseIsNonVolatilePath && peStrokeIsPath) {
321 make_key(&noninvertedKey, noninverted);
323 if (invertedKey.
size() || noninvertedKey.
size()) {
339 make_key(&doubleFlipKey, doubleFlip);
342 if (preserveKey.
size() && !doubleFlipKey.
size()) {
363 virtual bool fillChangesGeom()
const {
return false; }
364 virtual bool strokeIsConvertedToFill()
const {
return false; }
365 virtual bool strokeAndFillIsConvertedToFill(
const SkPaint&)
const {
return false; }
367 virtual bool isNonPath(
const SkPaint&
paint)
const {
return true; }
370class RectGeo :
public Geo {
384 bool strokeAndFillIsConvertedToFill(
const SkPaint&
paint)
const override {
396class RRectGeo :
public Geo {
410 bool strokeAndFillIsConvertedToFill(
const SkPaint&
paint)
const override {
422class ArcGeo :
public Geo {
424 ArcGeo(
const SkArc& arc) : fArc(arc) {}
438 bool isNonPath(
const SkPaint&
paint)
const override {
return false; }
444class PathGeo :
public Geo {
446 enum class Invert {
kNo,
kYes };
450 if (Invert::kYes ==
invert) {
466 bool fillChangesGeom()
const override {
468 return this->isUnclosedRect() ||
fPath.
isLine(
nullptr);
471 bool strokeIsConvertedToFill()
const override {
472 return this->isAxisAlignedLine();
475 bool strokeAndFillIsConvertedToFill(
const SkPaint&
paint)
const override {
477 if (this->isAxisAlignedLine()) {
485 return RectGeo(
rect).strokeAndFillIsConvertedToFill(
paint);
495 bool isAxisAlignedLine()
const {
500 return pts[0].
fX == pts[1].
fX || pts[0].
fY == pts[1].
fY;
503 bool isUnclosedRect()
const {
505 return fPath.
isRect(
nullptr, &closed,
nullptr) && !closed;
511class RRectPathGeo :
public PathGeo {
513 enum class RRectForStroke {
kNo,
kYes };
515 RRectPathGeo(
const SkPath&
path,
const SkRRect& equivalentRRect, RRectForStroke rrectForStroke,
519 , fRRectForStroke(rrectForStroke) {}
521 RRectPathGeo(
const SkPath&
path,
const SkRect& equivalentRect, RRectForStroke rrectForStroke,
536 RRectForStroke fRRectForStroke;
547 template <
typename... ShapeArgs>
558 struct SelfExpectations {
566 enum ComparisonExpecation {
567 kAllDifferent_ComparisonExpecation,
568 kSameUpToPE_ComparisonExpecation,
569 kSameUpToStroke_ComparisonExpecation,
570 kAllSame_ComparisonExpecation,
576 const GrStyledShape& appliedPathEffectShape()
const {
return *fAppliedPE; }
577 const GrStyledShape& appliedFullStyleShape()
const {
return *fAppliedFull; }
580 const Key& baseKey()
const {
return fBaseKey; }
581 const Key& appliedPathEffectKey()
const {
return fAppliedPEKey; }
582 const Key& appliedFullStyleKey()
const {
return fAppliedFullKey; }
583 const Key& appliedPathEffectThenStrokeKey()
const {
return fAppliedPEThenStrokeKey; }
595 if (
path.isEmpty()) {
605 fAppliedPE = std::make_unique<GrStyledShape>();
606 fAppliedPEThenStroke = std::make_unique<GrStyledShape>();
607 fAppliedFull = std::make_unique<GrStyledShape>();
610 *fAppliedPEThenStroke =
615 make_key(&fAppliedPEKey, *fAppliedPE);
616 make_key(&fAppliedPEThenStrokeKey, *fAppliedPEThenStroke);
617 make_key(&fAppliedFullKey, *fAppliedFull);
627 fAppliedPEThenStroke->asPath(&
a);
628 fAppliedFull->asPath(&
b);
635 if (fAppliedPE->asRRect(
nullptr,
nullptr)) {
640 REPORTER_ASSERT(r, fAppliedFull->isEmpty() == fAppliedPEThenStroke->isEmpty());
643 fBase->asPath(&
path);
646 fAppliedPE->asPath(&
path);
649 fAppliedFull->asPath(&
path);
653 CheckBounds(r, *fBase, fBase->bounds());
654 CheckBounds(r, *fAppliedPE, fAppliedPE->bounds());
655 CheckBounds(r, *fAppliedPEThenStroke, fAppliedPEThenStroke->bounds());
656 CheckBounds(r, *fAppliedFull, fAppliedFull->bounds());
657 SkRect styledBounds = fBase->styledBounds();
658 CheckBounds(r, *fAppliedFull, styledBounds);
659 styledBounds = fAppliedPE->styledBounds();
660 CheckBounds(r, *fAppliedFull, styledBounds);
667 fBase->asPath(&preStyle);
669 if (fBase->style().applyPathEffectToPath(&postPathEffect, &postPEStrokeRec, preStyle,
677 fAppliedPE->asPath(&testPath);
679 REPORTER_ASSERT(r, postPEStrokeRec.hasEqualEffect(fAppliedPE->style().strokeRec()));
682 if (fBase->style().applyToPath(&postAllStyle, &fillOrHairline, preStyle,
scale)) {
684 fAppliedFull->asPath(&testPath);
685 if (fBase->style().hasPathEffect()) {
709 std::unique_ptr<GrStyledShape> fBase;
710 std::unique_ptr<GrStyledShape> fAppliedPE;
711 std::unique_ptr<GrStyledShape> fAppliedPEThenStroke;
712 std::unique_ptr<GrStyledShape> fAppliedFull;
716 Key fAppliedPEThenStrokeKey;
723 if (expectations.fPEHasEffect) {
728 if (expectations.fStrokeApplies && expectations.fPEHasValidKey) {
736 fAppliedPE->asPath(&
b);
738 if (expectations.fStrokeApplies) {
750 case kAllDifferent_ComparisonExpecation:
755 case kSameUpToPE_ComparisonExpecation:
760 case kSameUpToStroke_ComparisonExpecation:
762 check_equivalence(r, *fAppliedPE, *that.fAppliedPE, fAppliedPEKey, that.fAppliedPEKey);
765 case kAllSame_ComparisonExpecation:
767 check_equivalence(r, *fAppliedPE, *that.fAppliedPE, fAppliedPEKey, that.fAppliedPEKey);
769 that.fAppliedFullKey);
776 static const SkScalar kIntervals[] = { 0.25, 3.f, 0.5, 2.f };
777 static const SkScalar kPhase = 0.75;
782 static const SkScalar kNullIntervals[] = {0, 0, 0, 0, 0, 0};
788template <
typename... Args>
790 return std::make_unique<TestCase>( std::forward<Args>(
args)... );
796 TestCase::SelfExpectations expectations;
799 TestCase fillCase(geo, fill,
reporter);
800 expectations.fPEHasEffect =
false;
801 expectations.fPEHasValidKey =
false;
802 expectations.fStrokeApplies =
false;
803 fillCase.testExpectations(
reporter, expectations);
806 ->compare(
reporter, fillCase, TestCase::kAllSame_ComparisonExpecation);
813 TestCase stroke2RoundBevelCase(geo, stroke2RoundBevel,
reporter);
814 expectations.fPEHasValidKey =
true;
815 expectations.fPEHasEffect =
false;
816 expectations.fStrokeApplies = !geo.strokeIsConvertedToFill();
817 stroke2RoundBevelCase.testExpectations(
reporter, expectations);
819 ->compare(
reporter, stroke2RoundBevelCase, TestCase::kAllSame_ComparisonExpecation);
821 SkPaint stroke2RoundBevelDash = stroke2RoundBevel;
823 TestCase stroke2RoundBevelDashCase(geo, stroke2RoundBevelDash,
reporter);
824 expectations.fPEHasValidKey =
true;
825 expectations.fPEHasEffect =
true;
826 expectations.fStrokeApplies =
true;
827 stroke2RoundBevelDashCase.testExpectations(
reporter, expectations);
829 ->compare(
reporter, stroke2RoundBevelDashCase, TestCase::kAllSame_ComparisonExpecation);
831 if (geo.fillChangesGeom() || geo.strokeIsConvertedToFill()) {
832 fillCase.compare(
reporter, stroke2RoundBevelCase,
833 TestCase::kAllDifferent_ComparisonExpecation);
834 fillCase.compare(
reporter, stroke2RoundBevelDashCase,
835 TestCase::kAllDifferent_ComparisonExpecation);
837 fillCase.compare(
reporter, stroke2RoundBevelCase,
838 TestCase::kSameUpToStroke_ComparisonExpecation);
839 fillCase.compare(
reporter, stroke2RoundBevelDashCase,
840 TestCase::kSameUpToPE_ComparisonExpecation);
842 if (geo.strokeIsConvertedToFill()) {
843 stroke2RoundBevelCase.compare(
reporter, stroke2RoundBevelDashCase,
844 TestCase::kAllDifferent_ComparisonExpecation);
846 stroke2RoundBevelCase.compare(
reporter, stroke2RoundBevelDashCase,
847 TestCase::kSameUpToPE_ComparisonExpecation);
851 SkPaint stroke2RoundBevelAndFill = stroke2RoundBevel;
853 TestCase stroke2RoundBevelAndFillCase(geo, stroke2RoundBevelAndFill,
reporter);
854 expectations.fPEHasValidKey =
true;
855 expectations.fPEHasEffect =
false;
856 expectations.fStrokeApplies = !geo.strokeIsConvertedToFill();
857 stroke2RoundBevelAndFillCase.testExpectations(
reporter, expectations);
859 reporter, stroke2RoundBevelAndFillCase, TestCase::kAllSame_ComparisonExpecation);
861 SkPaint stroke2RoundBevelAndFillDash = stroke2RoundBevelDash;
863 TestCase stroke2RoundBevelAndFillDashCase(geo, stroke2RoundBevelAndFillDash,
reporter);
864 expectations.fPEHasValidKey =
true;
865 expectations.fPEHasEffect =
false;
866 expectations.fStrokeApplies = !geo.strokeIsConvertedToFill();
867 stroke2RoundBevelAndFillDashCase.testExpectations(
reporter, expectations);
869 reporter, stroke2RoundBevelAndFillDashCase, TestCase::kAllSame_ComparisonExpecation);
870 stroke2RoundBevelAndFillDashCase.compare(
reporter, stroke2RoundBevelAndFillCase,
871 TestCase::kAllSame_ComparisonExpecation);
876 TestCase hairlineCase(geo, hairline,
reporter);
879 if (geo.fillChangesGeom()) {
880 hairlineCase.compare(
reporter, fillCase, TestCase::kAllDifferent_ComparisonExpecation);
882 hairlineCase.compare(
reporter, fillCase, TestCase::kAllSame_ComparisonExpecation);
897 TestCase fillCase1(geo, fill,
reporter, kS1);
898 TestCase fillCase2(geo, fill,
reporter, kS2);
900 fillCase1.compare(
reporter, fillCase2, TestCase::kAllSame_ComparisonExpecation);
905 TestCase hairlineCase1(geo, hairline,
reporter, kS1);
906 TestCase hairlineCase2(geo, hairline,
reporter, kS2);
908 hairlineCase1.compare(
reporter, hairlineCase2, TestCase::kAllSame_ComparisonExpecation);
912 stroke.setStrokeWidth(2.f);
916 if (geo.strokeIsConvertedToFill()) {
918 strokeCase1.compare(
reporter, strokeCase2, TestCase::kAllSame_ComparisonExpecation);
920 strokeCase1.compare(
reporter, strokeCase2, TestCase::kSameUpToStroke_ComparisonExpecation);
925 TestCase strokeDashCase1(geo, strokeDash,
reporter, kS1);
926 TestCase strokeDashCase2(geo, strokeDash,
reporter, kS2);
928 strokeDashCase1.compare(
reporter, strokeDashCase2,
929 TestCase::kSameUpToPE_ComparisonExpecation);
934 TestCase strokeAndFillCase1(geo, strokeAndFill,
reporter, kS1);
935 TestCase strokeAndFillCase2(geo, strokeAndFill,
reporter, kS2);
936 SkPaint strokeAndFillDash = strokeDash;
939 TestCase strokeAndFillDashCase1(geo, strokeAndFillDash,
reporter, kS1);
940 TestCase strokeAndFillDashCase2(geo, strokeAndFillDash,
reporter, kS2);
944 if (geo.strokeAndFillIsConvertedToFill(strokeAndFillDash)) {
946 strokeAndFillCase1.compare(
reporter, strokeAndFillCase2,
947 TestCase::kAllSame_ComparisonExpecation);
948 strokeAndFillDashCase1.compare(
reporter, strokeAndFillDashCase2,
949 TestCase::kAllSame_ComparisonExpecation);
951 strokeAndFillCase1.compare(
reporter, strokeAndFillCase2,
952 TestCase::kSameUpToStroke_ComparisonExpecation);
954 strokeAndFillDashCase1.compare(
reporter, strokeAndFillCase1,
955 TestCase::kAllSame_ComparisonExpecation);
956 strokeAndFillDashCase2.compare(
reporter, strokeAndFillCase2,
957 TestCase::kAllSame_ComparisonExpecation);
963 bool paramAffectsStroke,
964 bool paramAffectsDashAndStroke) {
976 TestCase strokeACase(geo, strokeA,
reporter);
977 TestCase strokeBCase(geo, strokeB,
reporter);
978 if (paramAffectsStroke) {
981 if (geo.strokeIsConvertedToFill()) {
982 strokeACase.compare(
reporter, strokeBCase,
983 TestCase::kAllDifferent_ComparisonExpecation);
985 strokeACase.compare(
reporter, strokeBCase,
986 TestCase::kSameUpToStroke_ComparisonExpecation);
989 strokeACase.compare(
reporter, strokeBCase, TestCase::kAllSame_ComparisonExpecation);
992 SkPaint strokeAndFillA = strokeA;
993 SkPaint strokeAndFillB = strokeB;
996 TestCase strokeAndFillACase(geo, strokeAndFillA,
reporter);
997 TestCase strokeAndFillBCase(geo, strokeAndFillB,
reporter);
998 if (paramAffectsStroke) {
1001 if (geo.strokeAndFillIsConvertedToFill(strokeAndFillA) ||
1002 geo.strokeAndFillIsConvertedToFill(strokeAndFillB)) {
1003 strokeAndFillACase.compare(
reporter, strokeAndFillBCase,
1004 TestCase::kAllDifferent_ComparisonExpecation);
1006 strokeAndFillACase.compare(
reporter, strokeAndFillBCase,
1007 TestCase::kSameUpToStroke_ComparisonExpecation);
1010 strokeAndFillACase.compare(
reporter, strokeAndFillBCase,
1011 TestCase::kAllSame_ComparisonExpecation);
1015 SkPaint fillA = strokeA, fillB = strokeB;
1018 TestCase fillACase(geo, fillA,
reporter);
1019 TestCase fillBCase(geo, fillB,
reporter);
1020 fillACase.compare(
reporter, fillBCase, TestCase::kAllSame_ComparisonExpecation);
1024 SkPaint dashA = strokeA, dashB = strokeB;
1027 TestCase dashACase(geo, dashA,
reporter);
1028 TestCase dashBCase(geo, dashB,
reporter);
1029 if (paramAffectsDashAndStroke) {
1030 dashACase.compare(
reporter, dashBCase, TestCase::kSameUpToStroke_ComparisonExpecation);
1032 dashACase.compare(
reporter, dashBCase, TestCase::kAllSame_ComparisonExpecation);
1036template <
typename T>
1050 bool affectsDashAndStroke =
true;
1051 test_stroke_param_impl<SkPaint::Cap>(
1057 affectsDashAndStroke);
1074 test_stroke_param_impl<SkPaint::Join>(
1079 affectsStroke,
true);
1085 p->setStrokeMiter(miter);
1090 p->setStrokeMiter(miter);
1101 test_stroke_param_impl<SkScalar>(
1104 setMiterJoinAndLimit,
1111 test_stroke_param_impl<SkScalar>(
1114 setOtherJoinAndLimit,
1126 TestCase dashFillCase(geo, dashFill,
reporter);
1129 dashFillCase.compare(
reporter, fillCase, TestCase::kAllSame_ComparisonExpecation);
1137 stroke.setStrokeWidth(1.f);
1147 TestCase fillCase(geo, fill,
reporter);
1149 TestCase dashCase(geo, dash,
reporter);
1150 TestCase nullDashCase(geo, nullDash,
reporter);
1153 nullDashCase.compare(
reporter, strokeCase, TestCase::kAllSame_ComparisonExpecation);
1156 if (geo.fillChangesGeom() || geo.strokeIsConvertedToFill()) {
1157 nullDashCase.compare(
reporter, fillCase, TestCase::kAllDifferent_ComparisonExpecation);
1159 nullDashCase.compare(
reporter, fillCase, TestCase::kSameUpToStroke_ComparisonExpecation);
1162 if (geo.strokeIsConvertedToFill()) {
1163 nullDashCase.compare(
reporter, dashCase, TestCase::kAllDifferent_ComparisonExpecation);
1165 nullDashCase.compare(
reporter, dashCase, TestCase::kSameUpToPE_ComparisonExpecation);
1176 static const SkRRect& RRect() {
1183 const char*
getTypeName()
const override {
return nullptr; }
1189 dst->addRRect(RRect());
1195 *
bounds = RRect().getBounds();
1201 RRectPathEffect() {}
1205 TestCase fillGeoCase(geo, fill,
reporter);
1209 TestCase geoPECase(geo, pe,
reporter);
1215 TestCase geoPEStrokeCase(geo, peStroke,
reporter);
1219 if (geo.fillChangesGeom()) {
1220 fillGeoCase.compare(
reporter, geoPECase, TestCase::kAllDifferent_ComparisonExpecation);
1221 fillGeoCase.compare(
reporter, geoPEStrokeCase,
1222 TestCase::kAllDifferent_ComparisonExpecation);
1224 fillGeoCase.compare(
reporter, geoPECase, TestCase::kSameUpToPE_ComparisonExpecation);
1225 fillGeoCase.compare(
reporter, geoPEStrokeCase, TestCase::kSameUpToPE_ComparisonExpecation);
1227 geoPECase.compare(
reporter, geoPEStrokeCase,
1228 TestCase::kSameUpToStroke_ComparisonExpecation);
1230 TestCase rrectFillCase(
reporter, RRectPathEffect::RRect(), fill);
1232 stroke.setPathEffect(
nullptr);
1233 TestCase rrectStrokeCase(
reporter, RRectPathEffect::RRect(),
stroke);
1253 rrectStrokeCase.appliedFullStyleKey());
1264 const char*
getTypeName()
const override {
return nullptr; }
1271 for (
int i = 0;
i < 100; ++
i) {
1284 AddLineTosPathEffect() {}
1294 TestCase geoPEStrokeCase(geo, peStroke,
reporter);
1295 TestCase::SelfExpectations expectations;
1296 expectations.fPEHasEffect =
true;
1297 expectations.fPEHasValidKey =
false;
1298 expectations.fStrokeApplies =
true;
1299 geoPEStrokeCase.testExpectations(
reporter, expectations);
1312 const char*
getTypeName()
const override {
return nullptr; }
1324 MakeHairlinePathEffect() {}
1331 TestCase peCase(geo, pe,
reporter);
1334 peCase.baseShape().asPath(&
a);
1335 peCase.appliedPathEffectShape().asPath(&
b);
1336 peCase.appliedFullStyleShape().asPath(&c);
1337 if (geo.isNonPath(pe)) {
1349 a.setFillType(
b.getFillType());
1363 SkPath vPath = geo.path();
1370 TestCase volatileCase(
reporter, vPath, dashAndStroke);
1373 if (geo.isNonPath(dashAndStroke)) {
1376 TestCase nonVolatileCase(
reporter, geo.path(), dashAndStroke);
1377 volatileCase.compare(
reporter, nonVolatileCase, TestCase::kAllSame_ComparisonExpecation);
1397 const char*
getTypeName()
const override {
return nullptr; }
1403 dst->toggleInverseFillType();
1409 *
bounds = { 0, 0, 0, 0 };
1426 Key invertedEmptyKey;
1427 make_key(&invertedEmptyKey, invertedEmptyShape);
1434 TestCase geoPECase(geo, pe,
reporter);
1447 TestCase geoPEStrokeCase(geo, peStroke,
reporter);
1457 TestCase geoPEInvertCase(geo, pe,
reporter);
1467 TestCase geoPEInvertStrokeCase(geo, peStroke,
reporter);
1471 geoPEInvertStrokeCase.appliedPathEffectThenStrokeKey() == invertedEmptyKey);
1486 const char*
getTypeName()
const override {
return nullptr; }
1495 FailurePathEffect() {}
1499 TestCase fillCase(geo, fill,
reporter);
1503 TestCase peCase(geo, pe,
reporter);
1506 stroke.setStrokeWidth(2.f);
1512 TestCase peStrokeCase(geo, peStroke,
reporter);
1523 fillCase.appliedPathEffectShape().asPath(&
a);
1524 peCase.appliedPathEffectShape().asPath(&
b);
1527 fillCase.appliedFullStyleShape().asPath(&
a);
1528 peCase.appliedFullStyleShape().asPath(&
b);
1531 strokeCase.appliedPathEffectShape().asPath(&
a);
1532 peStrokeCase.appliedPathEffectShape().asPath(&
b);
1535 strokeCase.appliedFullStyleShape().asPath(&
a);
1536 peStrokeCase.appliedFullStyleShape().asPath(&
b);
1542 SkPath invertedEmptyPath;
1545 TestCase fillEmptyCase(
reporter, emptyPath, fill);
1552 TestCase fillInvertedEmptyCase(
reporter, invertedEmptyPath, fill);
1560 const Key& emptyKey = fillEmptyCase.baseKey();
1562 const Key& inverseEmptyKey = fillInvertedEmptyCase.baseKey();
1564 TestCase::SelfExpectations expectations;
1565 expectations.fStrokeApplies =
false;
1566 expectations.fPEHasEffect =
false;
1568 fillEmptyCase.testExpectations(
reporter, expectations);
1569 fillInvertedEmptyCase.testExpectations(
reporter, expectations);
1573 stroke.setStrokeWidth(2.f);
1578 strokeEmptyCase.compare(
reporter, fillEmptyCase, TestCase::kAllSame_ComparisonExpecation);
1579 TestCase strokeInvertedEmptyCase(
reporter, invertedEmptyPath,
stroke);
1580 strokeInvertedEmptyCase.compare(
reporter, fillInvertedEmptyCase,
1581 TestCase::kAllSame_ComparisonExpecation);
1588 TestCase dashAndStrokeEmptyCase(
reporter, emptyPath, dashAndStroke);
1589 dashAndStrokeEmptyCase.compare(
reporter, fillEmptyCase,
1590 TestCase::kAllSame_ComparisonExpecation);
1591 TestCase dashAndStrokeInvertexEmptyCase(
reporter, invertedEmptyPath, dashAndStroke);
1593 dashAndStrokeInvertexEmptyCase.compare(
reporter, fillEmptyCase,
1594 TestCase::kAllSame_ComparisonExpecation);
1602 TestCase fillEmptyRRectCase(
reporter, emptyRRect, fill);
1603 fillEmptyRRectCase.compare(
reporter, fillEmptyCase, TestCase::kAllSame_ComparisonExpecation);
1606 strokeEmptyRRectCase.compare(
reporter, strokeEmptyCase,
1607 TestCase::kAllSame_ComparisonExpecation);
1609 TestCase dashAndStrokeEmptyRRectCase(
reporter, emptyRRect, dashAndStroke);
1610 dashAndStrokeEmptyRRectCase.compare(
reporter, fillEmptyCase,
1611 TestCase::kAllSame_ComparisonExpecation);
1614 static constexpr int kStart = 0;
1616 TestCase fillInvertedEmptyRRectCase(
reporter, emptyRRect, kDir, kStart,
true,
GrStyle(fill));
1617 fillInvertedEmptyRRectCase.compare(
reporter, fillInvertedEmptyCase,
1618 TestCase::kAllSame_ComparisonExpecation);
1620 TestCase strokeInvertedEmptyRRectCase(
reporter, emptyRRect, kDir, kStart,
true,
1622 strokeInvertedEmptyRRectCase.compare(
reporter, strokeInvertedEmptyCase,
1623 TestCase::kAllSame_ComparisonExpecation);
1625 TestCase dashAndStrokeEmptyInvertedRRectCase(
reporter, emptyRRect, kDir, kStart,
true,
1627 dashAndStrokeEmptyInvertedRRectCase.compare(
reporter, fillEmptyCase,
1628 TestCase::kAllSame_ComparisonExpecation);
1632 TestCase fillEmptyRectCase(
reporter, emptyRect, fill);
1633 fillEmptyRectCase.compare(
reporter, fillEmptyCase, TestCase::kAllSame_ComparisonExpecation);
1635 TestCase dashAndStrokeEmptyRectCase(
reporter, emptyRect, dashAndStroke);
1636 dashAndStrokeEmptyRectCase.compare(
reporter, fillEmptyCase,
1637 TestCase::kAllSame_ComparisonExpecation);
1640 kStart,
true,
GrStyle(dashAndStroke));
1642 dashAndStrokeEmptyInvertedRectCase.compare(
reporter, fillEmptyCase,
1643 TestCase::kAllSame_ComparisonExpecation);
1651 return (
s + 1) & 0b110;
1670 strokeRecs[kFill].setFillStyle();
1671 strokeRecs[kStroke].setStrokeStyle(2.f);
1672 strokeRecs[
kHairline].setHairlineStyle();
1673 strokeRecs[kStrokeAndFill].setStrokeStyle(3.f,
true);
1679 static constexpr size_t kStyleCnt =
std::size(strokeRecs);
1681 auto index = [](
bool inverted,
1686 return inverted * (2 * 8 * kStyleCnt * 2) +
1687 (
int)
dir * ( 8 * kStyleCnt * 2) +
1688 start * ( kStyleCnt * 2) +
1693 const int cnt = index(
true, kSecondDirection, 7,
static_cast<Style
>(kStyleCnt - 1),
true) + 1;
1695 for (
bool inverted : {
false,
true}) {
1698 for (Style style : {kFill, kStroke,
kHairline, kStrokeAndFill}) {
1699 for (
bool dash : {
false,
true}) {
1701 shapes[index(inverted,
dir,
start, style, dash)] =
1703 GrStyle(strokeRecs[style], std::move(pe)));
1713 static constexpr unsigned kExamplesStart = 0;
1714 const GrStyledShape& exampleFillCase = shapes[index(
false, kExamplesDir, kExamplesStart, kFill,
1716 Key exampleFillCaseKey;
1717 make_key(&exampleFillCaseKey, exampleFillCase);
1719 const GrStyledShape& exampleStrokeAndFillCase = shapes[index(
false, kExamplesDir,
1720 kExamplesStart, kStrokeAndFill,
false)];
1721 Key exampleStrokeAndFillCaseKey;
1722 make_key(&exampleStrokeAndFillCaseKey, exampleStrokeAndFillCase);
1724 const GrStyledShape& exampleInvFillCase = shapes[index(
true, kExamplesDir,
1725 kExamplesStart, kFill,
false)];
1726 Key exampleInvFillCaseKey;
1727 make_key(&exampleInvFillCaseKey, exampleInvFillCase);
1729 const GrStyledShape& exampleInvStrokeAndFillCase = shapes[index(
true, kExamplesDir,
1730 kExamplesStart, kStrokeAndFill,
1732 Key exampleInvStrokeAndFillCaseKey;
1733 make_key(&exampleInvStrokeAndFillCaseKey, exampleInvStrokeAndFillCase);
1735 const GrStyledShape& exampleStrokeCase = shapes[index(
false, kExamplesDir, kExamplesStart,
1737 Key exampleStrokeCaseKey;
1738 make_key(&exampleStrokeCaseKey, exampleStrokeCase);
1740 const GrStyledShape& exampleInvStrokeCase = shapes[index(
true, kExamplesDir, kExamplesStart,
1742 Key exampleInvStrokeCaseKey;
1743 make_key(&exampleInvStrokeCaseKey, exampleInvStrokeCase);
1745 const GrStyledShape& exampleHairlineCase = shapes[index(
false, kExamplesDir, kExamplesStart,
1747 Key exampleHairlineCaseKey;
1748 make_key(&exampleHairlineCaseKey, exampleHairlineCase);
1750 const GrStyledShape& exampleInvHairlineCase = shapes[index(
true, kExamplesDir, kExamplesStart,
1752 Key exampleInvHairlineCaseKey;
1753 make_key(&exampleInvHairlineCaseKey, exampleInvHairlineCase);
1757 bool queryInverted =
true;
1793 REPORTER_ASSERT(r, exampleFillCaseKey == exampleStrokeAndFillCaseKey);
1794 REPORTER_ASSERT(r, exampleFillCaseKey != exampleInvStrokeAndFillCaseKey);
1799 REPORTER_ASSERT(r, exampleInvStrokeAndFillCaseKey == exampleInvFillCaseKey);
1800 REPORTER_ASSERT(r, exampleInvStrokeAndFillCaseKey == exampleInvStrokeCaseKey);
1801 REPORTER_ASSERT(r, exampleInvStrokeAndFillCaseKey == exampleInvHairlineCaseKey);
1803 for (
bool inverted : {
false,
true}) {
1806 for (
bool dash : {
false,
true}) {
1813 kStrokeAndFill, dash)];
1814 Key strokeAndFillCaseKey;
1815 make_key(&strokeAndFillCaseKey, strokeAndFillCase);
1821 TestCase
a(fillCase, r);
1822 TestCase
b(inverted ? exampleInvFillCase : exampleFillCase, r);
1823 TestCase c(strokeAndFillCase, r);
1824 TestCase
d(inverted ? exampleInvStrokeAndFillCase
1825 : exampleStrokeAndFillCase, r);
1826 a.compare(r,
b, TestCase::kAllSame_ComparisonExpecation);
1827 c.compare(r,
d, TestCase::kAllSame_ComparisonExpecation);
1834 TestCase
e(strokeCase, r);
1835 TestCase g(hairlineCase, r);
1840 TestCase
f(exampleStrokeCase, r);
1841 TestCase
h(exampleHairlineCase, r);
1856 e.compare(r,
f, TestCase::kSameUpToPE_ComparisonExpecation);
1857 g.compare(r,
h, TestCase::kSameUpToPE_ComparisonExpecation);
1859 e.compare(r,
f, TestCase::kAllDifferent_ComparisonExpecation);
1860 g.compare(r,
h, TestCase::kAllDifferent_ComparisonExpecation);
1863 TestCase
f(inverted ? exampleInvStrokeCase : exampleStrokeCase, r);
1864 TestCase
h(inverted ? exampleInvHairlineCase : exampleHairlineCase, r);
1867 e.compare(r,
f, TestCase::kAllSame_ComparisonExpecation);
1868 g.compare(r,
h, TestCase::kAllSame_ComparisonExpecation);
1884 SkPath invLineAB = lineAB;
1891 stroke.setStrokeWidth(2.f);
1898 TestCase fillAB(r, lineAB, fill);
1899 TestCase fillEmpty(r,
SkPath(), fill);
1900 fillAB.compare(r, fillEmpty, TestCase::kAllSame_ComparisonExpecation);
1904 path.toggleInverseFillType();
1905 TestCase fillEmptyInverted(r,
path, fill);
1906 TestCase fillABInverted(r, invLineAB, fill);
1907 fillABInverted.compare(r, fillEmptyInverted, TestCase::kAllSame_ComparisonExpecation);
1908 REPORTER_ASSERT(r, !fillABInverted.baseShape().asLine(
nullptr,
nullptr));
1910 TestCase strokeAB(r, lineAB,
stroke);
1911 TestCase strokeBA(r, lineBA,
stroke);
1912 TestCase strokeAC(r, lineAC,
stroke);
1914 TestCase hairlineAB(r, lineAB, hairline);
1915 TestCase hairlineBA(r, lineBA, hairline);
1916 TestCase hairlineAC(r, lineAC, hairline);
1918 TestCase dashAB(r, lineAB, dash);
1919 TestCase dashBA(r, lineBA, dash);
1920 TestCase dashAC(r, lineAC, dash);
1922 strokeAB.compare(r, fillAB, TestCase::kAllDifferent_ComparisonExpecation);
1924 strokeAB.compare(r, strokeBA, TestCase::kAllSame_ComparisonExpecation);
1925 strokeAB.compare(r, strokeAC, TestCase::kAllDifferent_ComparisonExpecation);
1927 hairlineAB.compare(r, hairlineBA, TestCase::kAllSame_ComparisonExpecation);
1928 hairlineAB.compare(r, hairlineAC, TestCase::kAllDifferent_ComparisonExpecation);
1930 dashAB.compare(r, dashBA, TestCase::kAllDifferent_ComparisonExpecation);
1931 dashAB.compare(r, dashAC, TestCase::kAllDifferent_ComparisonExpecation);
1933 strokeAB.compare(r, hairlineAB, TestCase::kSameUpToStroke_ComparisonExpecation);
1937 bool canonicalizeAsAB;
1940 bool inverted =
true;
1941 SkPoint pts[2] {{0, 0}, {0, 0}};
1942 REPORTER_ASSERT(r, strokeAB.baseShape().asLine(pts, &inverted) && !inverted);
1943 if (pts[0] ==
kA && pts[1] ==
kB) {
1944 canonicalizeAsAB =
true;
1945 }
else if (pts[1] ==
kA && pts[0] ==
kB) {
1946 canonicalizeAsAB =
false;
1948 swap(canonicalPts[0], canonicalPts[1]);
1950 ERRORF(r,
"Should return pts (a,b) or (b, a)");
1954 strokeAB.compare(r, canonicalizeAsAB ? dashAB : dashBA,
1955 TestCase::kSameUpToPE_ComparisonExpecation);
1956 REPORTER_ASSERT(r, strokeAB.baseShape().asLine(pts, &inverted) && !inverted &&
1957 pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]);
1958 REPORTER_ASSERT(r, hairlineAB.baseShape().asLine(pts, &inverted) && !inverted &&
1959 pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]);
1960 REPORTER_ASSERT(r, dashAB.baseShape().asLine(pts, &inverted) && !inverted &&
1961 pts[0] ==
kA && pts[1] ==
kB);
1962 REPORTER_ASSERT(r, dashBA.baseShape().asLine(pts, &inverted) && !inverted &&
1963 pts[0] ==
kB && pts[1] ==
kA);
1966 TestCase strokeInvAB(r, invLineAB,
stroke);
1967 TestCase hairlineInvAB(r, invLineAB, hairline);
1968 TestCase dashInvAB(r, invLineAB, dash);
1969 strokeInvAB.compare(r, strokeAB, TestCase::kAllDifferent_ComparisonExpecation);
1970 hairlineInvAB.compare(r, hairlineAB, TestCase::kAllDifferent_ComparisonExpecation);
1972 dashInvAB.compare(r, dashAB, TestCase::kAllSame_ComparisonExpecation);
1974 REPORTER_ASSERT(r, strokeInvAB.baseShape().asLine(pts, &inverted) && inverted &&
1975 pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]);
1976 REPORTER_ASSERT(r, hairlineInvAB.baseShape().asLine(pts, &inverted) && inverted &&
1977 pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]);
1979 REPORTER_ASSERT(r, dashInvAB.baseShape().asLine(pts, &inverted) && !inverted &&
1980 pts[0] ==
kA && pts[1] ==
kB);
1985 static constexpr SkScalar kIntervals1[] = {1.f, 0.f};
1988 static constexpr SkScalar kIntervals2[] = {10.f, 0.f, 5.f, 0.f};
1994 for (
const auto& pe : pathEffects) {
2019 TestCase::kAllSame_ComparisonExpecation);
2023 TestCase::kAllSame_ComparisonExpecation);
2027 TestCase::kAllSame_ComparisonExpecation);
2036 TestCase::kAllSame_ComparisonExpecation);
2039 TestCase::kAllSame_ComparisonExpecation);
2042 TestCase::kAllSame_ComparisonExpecation);
2051 TestCase::kAllSame_ComparisonExpecation);
2054 TestCase::kAllSame_ComparisonExpecation);
2057 TestCase::kAllSame_ComparisonExpecation);
2072 SkPath volatileA = pathA;
2073 SkPath volatileB = pathB;
2079 for (PathGeo::Invert
invert : {PathGeo::Invert::kNo, PathGeo::Invert::kYes}) {
2091 pathA.
lineTo(10.f, 10.f);
2092 pathA.
conicTo(20.f, 20.f, 20.f, 30.f, 0.7f);
2094 pathB.
lineTo(10.f, 10.f);
2095 pathB.
conicTo(20.f, 20.f, 20.f, 30.f, 0.7f);
2096 compare(pathA, pathB, TestCase::kAllSame_ComparisonExpecation);
2100 pathB.lineTo(10.f, 10.f);
2101 pathB.conicTo(21.f, 20.f, 20.f, 30.f, 0.7f);
2102 compare(pathA, pathB, TestCase::kAllDifferent_ComparisonExpecation);
2106 pathB.lineTo(10.f, 10.f);
2107 pathB.conicTo(20.f, 20.f, 20.f, 30.f, 0.6f);
2108 compare(pathA, pathB, TestCase::kAllDifferent_ComparisonExpecation);
2112 pathB.lineTo(10.f, 10.f);
2113 pathB.conicTo(20.f, 20.f, 20.f, 30.f, 0.6f);
2114 pathB.lineTo(50.f, 50.f);
2115 compare(pathA, pathB, TestCase::kAllDifferent_ComparisonExpecation);
2119 pathB.lineTo(10.f, 10.f);
2120 pathB.conicTo(20.f, 20.f, 20.f, 30.f, 0.7f);
2122 compare(pathA, pathB, TestCase::kAllDifferent_ComparisonExpecation);
2136 geos.
emplace_back(
new RRectPathGeo(rectPath, r, RRectPathGeo::RRectForStroke::kYes,
2137 PathGeo::Invert::kNo));
2138 geos.
emplace_back(
new RRectPathGeo(rectPath, r, RRectPathGeo::RRectForStroke::kYes,
2139 PathGeo::Invert::kYes));
2140 rrectPathGeos.
emplace_back(
new RRectPathGeo(rectPath, r, RRectPathGeo::RRectForStroke::kYes,
2141 PathGeo::Invert::kNo));
2150 geos.
emplace_back(
new RRectPathGeo(rectPath, rr, RRectPathGeo::RRectForStroke::kYes,
2151 PathGeo::Invert::kNo));
2152 geos.
emplace_back(
new RRectPathGeo(rectPath, rr, RRectPathGeo::RRectForStroke::kYes,
2153 PathGeo::Invert::kYes));
2154 rrectPathGeos.
emplace_back(
new RRectPathGeo(rectPath, rr,
2155 RRectPathGeo::RRectForStroke::kYes,
2156 PathGeo::Invert::kNo));
2167 openRectPath.
moveTo(0, 0);
2168 openRectPath.
lineTo(10, 0);
2169 openRectPath.
lineTo(10, 10);
2170 openRectPath.
lineTo(0, 10);
2173 RRectPathGeo::RRectForStroke::kNo, PathGeo::Invert::kNo));
2176 RRectPathGeo::RRectForStroke::kNo, PathGeo::Invert::kYes));
2179 RRectPathGeo::RRectForStroke::kNo, PathGeo::Invert::kNo));
2184 quadPath.
quadTo(10, 10, 5, 8);
2185 geos.
emplace_back(
new PathGeo(quadPath, PathGeo::Invert::kNo));
2186 geos.
emplace_back(
new PathGeo(quadPath, PathGeo::Invert::kYes));
2192 geos.
emplace_back(
new PathGeo(linePath, PathGeo::Invert::kNo));
2193 geos.
emplace_back(
new PathGeo(linePath, PathGeo::Invert::kYes));
2200 geos.
emplace_back(
new PathGeo(vLinePath, PathGeo::Invert::kNo));
2201 geos.
emplace_back(
new PathGeo(vLinePath, PathGeo::Invert::kYes));
2207 geos.
emplace_back(
new PathGeo(hLinePath, PathGeo::Invert::kNo));
2208 geos.
emplace_back(
new PathGeo(hLinePath, PathGeo::Invert::kYes));
2211 for (
int i = 0;
i < geos.
size(); ++
i) {
2217 test_stroke_param<SkScalar>(
2232 for (
int i = 0;
i < rrectPathGeos.
size(); ++
i) {
2233 const RRectPathGeo& rrgeo = *rrectPathGeos[
i];
2235 TestCase fillPathCase(
reporter, rrgeo.path(), fillPaint);
2238 fillPathCase.baseShape().asRRect(&
rrect,
nullptr));
2239 if (rrgeo.isNonPath(fillPaint)) {
2240 TestCase fillPathCase2(
reporter, rrgeo.path(), fillPaint);
2243 fillPathCase2.compare(
reporter, fillRRectCase,
2244 TestCase::kAllSame_ComparisonExpecation);
2249 TestCase strokePathCase(
reporter, rrgeo.path(), strokePaint);
2250 if (rrgeo.isNonPath(strokePaint)) {
2254 strokePathCase.compare(
reporter, strokeRRectCase,
2255 TestCase::kAllSame_ComparisonExpecation);
2274 static constexpr SkScalar kIntervals[] = {1, 2};
2285 for (
const auto& style : styles) {
2292 emptyArc.compare(
reporter, emptyPath, TestCase::kAllSame_ComparisonExpecation);
2294 static constexpr SkRect kOval1{0, 0, 50, 50};
2295 static constexpr SkRect kOval2{50, 0, 100, 50};
2305 TestCase arc1CWWithCenter(
2308 TestCase arc1CCWWithCenter(
2316 TestCase arc2CWWithCenter(
2320 auto reversedExepectations = style.hasPathEffect()
2321 ? TestCase::kAllDifferent_ComparisonExpecation
2322 : TestCase::kAllSame_ComparisonExpecation;
2323 arc1CW.compare(
reporter, arc1CCW, reversedExepectations);
2324 arc1CWWithCenter.compare(
reporter, arc1CCWWithCenter, reversedExepectations);
2325 arc1CW.compare(
reporter, arc2CW, TestCase::kAllDifferent_ComparisonExpecation);
2326 arc1CW.compare(
reporter, arc1CWWithCenter, TestCase::kAllDifferent_ComparisonExpecation);
2327 arc1CWWithCenter.compare(
reporter, arc2CWWithCenter,
2328 TestCase::kAllDifferent_ComparisonExpecation);
2337 arc3A.compare(
reporter, arc3B, TestCase::kAllDifferent_ComparisonExpecation);
2345 auto ovalExpectations = style.hasPathEffect() ? TestCase::kAllDifferent_ComparisonExpecation
2346 : TestCase::kAllSame_ComparisonExpecation;
2347 if (style.strokeRec().getWidth() >= 0 && style.strokeRec().getCap() !=
SkPaint::kButt_Cap) {
2348 ovalExpectations = TestCase::kAllDifferent_ComparisonExpecation;
2354 TestCase ovalArcWithCenter(
2358 ovalExpectations = style.isSimpleFill() ? TestCase::kAllSame_ComparisonExpecation
2359 : TestCase::kAllDifferent_ComparisonExpecation;
2360 ovalArcWithCenter.compare(
reporter,
oval, ovalExpectations);
2366 SkScalar radii[] = {10.f, 10.f, 10.f, 10.f,
2367 10.f, 10.f, 10.f, 10.f};
2369 path.toggleInverseFillType();
2373 rrect.setInverted(
false);
2386 inverseRRect.
reset();
2389 inverseRRect.
reset();
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static bool paths_fill_same(const SkPath &a, const SkPath &b)
static void test_stroke_cap(skiatest::Reporter *reporter, const Geo &geo)
DEF_TEST(GrStyledShape_empty_shape, reporter)
static void test_stroke_join(skiatest::Reporter *reporter, const Geo &geo)
void test_path_effect_makes_empty_shape(skiatest::Reporter *reporter, const Geo &geo)
unsigned canonicalize_rrect_start(int s, const SkRRect &rrect)
static void test_scale(skiatest::Reporter *reporter, const Geo &geo)
void test_make_hairline_path_effect(skiatest::Reporter *reporter, const Geo &geo)
void test_path_effect_makes_rrect(skiatest::Reporter *reporter, const Geo &geo)
static void test_basic(skiatest::Reporter *reporter, const Geo &geo)
void test_rrect(skiatest::Reporter *r, const SkRRect &rrect)
static void test_stroke_param(skiatest::Reporter *reporter, const Geo &geo, std::function< void(SkPaint *, T)> setter, T a, T b)
void test_inversions(skiatest::Reporter *r, const GrStyledShape &shape, const Key &shapeKey)
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)
static sk_sp< SkPathEffect > make_null_dash()
static void check_original_path_ids(skiatest::Reporter *r, const GrStyledShape &base, const GrStyledShape &pe, const GrStyledShape &peStroke, const GrStyledShape &full)
static bool shape_known_not_to_have_joins(const GrStyledShape &shape)
static std::unique_ptr< TestCase > make_TestCase(Args &&... args)
static void check_equivalence(skiatest::Reporter *r, const GrStyledShape &a, const GrStyledShape &b, const Key &keyA, const Key &keyB)
static bool make_key(Key *key, const GrStyledShape &shape)
void test_volatile_path(skiatest::Reporter *reporter, const Geo &geo)
void test_unknown_path_effect(skiatest::Reporter *reporter, const Geo &geo)
static bool can_interchange_winding_and_even_odd_fill(const GrStyledShape &shape)
static void test_dash_fill(skiatest::Reporter *reporter, const Geo &geo)
static bool test_bounds_by_rasterizing(const SkPath &path, const SkRect &bounds)
void test_null_dash(skiatest::Reporter *reporter, const Geo &geo)
static sk_sp< SkPathEffect > make_dash()
static void test_miter_limit(skiatest::Reporter *reporter, const Geo &geo)
void test_path_effect_fails(skiatest::Reporter *reporter, const Geo &geo)
constexpr SkColor SK_ColorWHITE
@ kYes
Do pre-clip the geometry before applying the (perspective) matrix.
@ kNo
Don't pre-clip the geometry before applying the (perspective) matrix.
@ kXOR_SkPathOp
exclusive-or the two paths
static SkPathFillType SkPathFillType_ConvertToNonInverse(SkPathFillType ft)
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
void swap(sk_sp< T > &a, sk_sp< T > &b)
static constexpr bool SkToBool(const T &x)
#define REPORTER_ASSERT(r, cond,...)
void setPath(const SkPath &path)
bool simplify(unsigned flags=kAll_Flags)
static const GrStyle & SimpleHairline()
@ kPathEffectAndStrokeRec
SkPathEffect * pathEffect() const
static const GrStyle & SimpleFill()
bool hasNonDashPathEffect() const
bool isSimpleFill() const
const SkStrokeRec & strokeRec() const
bool knownToBeClosed() const
void asPath(SkPath *out) const
void writeUnstyledKey(uint32_t *key) const
int unstyledKeySize() const
static GrStyledShape MakeArc(const SkArc &arc, const GrStyle &style, DoSimplify=DoSimplify::kYes)
bool asLine(SkPoint pts[2], bool *inverted) const
bool asRRect(SkRRect *rrect, bool *inverted) const
bool inverseFilled() const
const GrStyle & style() const
bool testingOnly_isPath() const
bool testingOnly_isNonVolatilePath() const
uint32_t testingOnly_getOriginalGenerationID() const
static GrStyledShape MakeFilled(const GrStyledShape &original, FillInversion=FillInversion::kPreserve)
static sk_sp< SkPathEffect > Make(const SkScalar intervals[], int count, SkScalar phase)
virtual const char * getTypeName() const =0
virtual Factory getFactory() const =0
static SkMatrix RectToRect(const SkRect &src, const SkRect &dst, ScaleToFit mode=kFill_ScaleToFit)
@ kButt_Cap
no stroke extension
void setStyle(Style style)
void setColor(SkColor color)
void setStrokeCap(Cap cap)
@ kStroke_Style
set to stroke geometry
@ kFill_Style
set to fill geometry
@ kStrokeAndFill_Style
sets to stroke and fill geometry
void setStrokeJoin(Join join)
void setPathEffect(sk_sp< SkPathEffect > pathEffect)
@ kMiter_Join
extends to miter limit
@ kBevel_Join
connects outside edges
void setStrokeWidth(SkScalar width)
virtual bool computeFastBounds(SkRect *bounds) const =0
virtual bool onFilterPath(SkPath *, const SkPath &, SkStrokeRec *, const SkRect *, const SkMatrix &) const =0
static bool IsSimpleRect(const SkPath &path, bool isSimpleFill, SkRect *rect, SkPathDirection *direction, unsigned *start)
static void CreateDrawArcPath(SkPath *path, const SkArc &arc, bool isFillNoPathEffect)
bool isInverseFillType() const
uint32_t getGenerationID() const
SkPath & moveTo(SkScalar x, SkScalar y)
bool isLine(SkPoint line[2]) const
SkPathFillType getFillType() const
void setFillType(SkPathFillType ft)
SkPath & lineTo(SkScalar x, SkScalar y)
SkPath & addRRect(const SkRRect &rrect, SkPathDirection dir=SkPathDirection::kCW)
void toggleInverseFillType()
SkPath & setIsVolatile(bool isVolatile)
SkPath & quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
SkPath & conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w)
bool isRect(SkRect *rect, bool *isClosed=nullptr, SkPathDirection *direction=nullptr) const
static SkPath Line(const SkPoint a, const SkPoint b)
SkPath & addRect(const SkRect &rect, SkPathDirection dir, unsigned start)
const uint8_t * addr8() const
const SkRect & rect() const
@ kOval_Type
non-zero width and height filled with radii
@ kEmpty_Type
zero width or height
@ kRect_Type
non-zero width and height, and zeroed radii
static SkRRect MakeOval(const SkRect &oval)
static SkRRect MakeRect(const SkRect &r)
static SkRRect MakeRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
static SkRRect MakeEmpty()
static void GrowToInclude(SkRect *r, const SkPoint &pt)
void setStrokeStyle(SkScalar width, bool strokeAndFill=false)
void setStrokeParams(SkPaint::Cap cap, SkPaint::Join join, SkScalar miterLimit)
T & emplace_back(Args &&... args)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
Dart_NativeFunction function
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
unsigned useCenter Optional< SkMatrix > matrix
Optional< SkRect > bounds
sk_sp< SkBlender > blender SkRect rect
SKSHAPER_API sk_sp< Factory > Factory()
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
void * calloc(size_t n, size_t size)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets dir
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
GrOp::Owner MakeRect(GrRecordingContext *context, GrPaint &&paint, const SkRect &drawRect, const SkRect &localRect, const SkMatrix &localM)
int compare(const void *untyped_lhs, const void *untyped_rhs)
static SkArc Make(const SkRect &oval, SkScalar startAngleDegrees, SkScalar sweepAngleDegrees, Type type)
static SkImageInfo MakeA8(int width, int height)
static constexpr SkRect MakeEmpty()
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
static constexpr SkRect MakeWH(float w, float h)
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)