blob: 6f4976a0d938c49869eddc3bd1df7a77364a2a53 [file] [log] [blame]
commit-bot@chromium.org19dd0172013-08-05 13:28:55 +00001/*
2 * Copyright 2013 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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkTypes.h"
halcanary96fcdcc2015-08-27 07:41:13 -07009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkBitmap.h"
11#include "include/core/SkCanvas.h"
12#include "include/core/SkColor.h"
13#include "include/core/SkPaint.h"
14#include "include/core/SkPath.h"
15#include "include/core/SkRRect.h"
16#include "include/core/SkRect.h"
17#include "include/core/SkSurface.h"
18#include "include/effects/SkDashPathEffect.h"
Robert Phillips6d344c32020-07-06 10:56:46 -040019#include "include/gpu/GrDirectContext.h"
Michael Ludwig2686d692020-04-17 20:21:37 +000020#include "src/gpu/geometry/GrStyledShape.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050021#include "tests/Test.h"
commit-bot@chromium.org19dd0172013-08-05 13:28:55 +000022
kkinnunen15302832015-12-01 04:35:26 -080023#include <initializer_list>
24
tfarina@chromium.org4ee16bf2014-01-10 22:08:27 +000025static void test_drawPathEmpty(skiatest::Reporter*, SkCanvas* canvas) {
commit-bot@chromium.org19dd0172013-08-05 13:28:55 +000026 // Filling an empty path should not crash.
27 SkPaint paint;
fmalitafbe1c112015-11-18 20:12:56 -080028 SkRect emptyRect = SkRect::MakeEmpty();
29 canvas->drawRect(emptyRect, paint);
commit-bot@chromium.org19dd0172013-08-05 13:28:55 +000030 canvas->drawPath(SkPath(), paint);
fmalitafbe1c112015-11-18 20:12:56 -080031 canvas->drawOval(emptyRect, paint);
32 canvas->drawRect(emptyRect, paint);
33 canvas->drawRRect(SkRRect::MakeRect(emptyRect), paint);
commit-bot@chromium.org19dd0172013-08-05 13:28:55 +000034
35 // Stroking an empty path should not crash.
36 paint.setAntiAlias(true);
37 paint.setStyle(SkPaint::kStroke_Style);
38 paint.setColor(SK_ColorGRAY);
39 paint.setStrokeWidth(SkIntToScalar(20));
40 paint.setStrokeJoin(SkPaint::kRound_Join);
fmalitafbe1c112015-11-18 20:12:56 -080041 canvas->drawRect(emptyRect, paint);
commit-bot@chromium.org19dd0172013-08-05 13:28:55 +000042 canvas->drawPath(SkPath(), paint);
fmalitafbe1c112015-11-18 20:12:56 -080043 canvas->drawOval(emptyRect, paint);
44 canvas->drawRect(emptyRect, paint);
45 canvas->drawRRect(SkRRect::MakeRect(emptyRect), paint);
commit-bot@chromium.org19dd0172013-08-05 13:28:55 +000046}
47
fmalitafbe1c112015-11-18 20:12:56 -080048static void fill_and_stroke(SkCanvas* canvas, const SkPath& p1, const SkPath& p2,
reeda4393342016-03-18 11:22:57 -070049 sk_sp<SkPathEffect> effect) {
fmalitafbe1c112015-11-18 20:12:56 -080050 SkPaint paint;
51 paint.setAntiAlias(true);
52 paint.setPathEffect(effect);
53
54 canvas->drawPath(p1, paint);
55 canvas->drawPath(p2, paint);
56
57 paint.setStyle(SkPaint::kStroke_Style);
58 canvas->drawPath(p1, paint);
59 canvas->drawPath(p2, paint);
60}
61
62static void test_drawSameRectOvals(skiatest::Reporter*, SkCanvas* canvas) {
63 // Drawing ovals with similar bounds but different points order should not crash.
64
65 SkPath oval1, oval2;
66 const SkRect rect = SkRect::MakeWH(100, 50);
Mike Reed30bc5272019-11-22 18:34:02 +000067 oval1.addOval(rect, SkPathDirection::kCW);
68 oval2.addOval(rect, SkPathDirection::kCCW);
fmalitafbe1c112015-11-18 20:12:56 -080069
70 fill_and_stroke(canvas, oval1, oval2, nullptr);
71
72 const SkScalar intervals[] = { 1, 1 };
reeda4393342016-03-18 11:22:57 -070073 fill_and_stroke(canvas, oval1, oval2, SkDashPathEffect::Make(intervals, 2, 0));
fmalitafbe1c112015-11-18 20:12:56 -080074}
commit-bot@chromium.org19dd0172013-08-05 13:28:55 +000075
bsalomon758586c2016-04-06 14:02:39 -070076DEF_GPUTEST_FOR_ALL_GL_CONTEXTS(GpuDrawPath, reporter, ctxInfo) {
kkinnunen15302832015-12-01 04:35:26 -080077 for (auto& test_func : { &test_drawPathEmpty, &test_drawSameRectOvals }) {
Brian Salomonbdecacf2018-02-02 20:32:49 -050078 for (auto& sampleCount : {1, 4, 16}) {
reed69f6f002014-09-18 06:09:44 -070079 SkImageInfo info = SkImageInfo::MakeN32Premul(255, 255);
reede8f30622016-03-23 18:59:25 -070080 auto surface(
Robert Phillips6d344c32020-07-06 10:56:46 -040081 SkSurface::MakeRenderTarget(ctxInfo.directContext(), SkBudgeted::kNo, info,
bsalomon8b7451a2016-05-11 06:33:06 -070082 sampleCount, nullptr));
kkinnunenc11a5272015-11-19 09:37:02 -080083 if (!surface) {
84 continue;
85 }
kkinnunen15302832015-12-01 04:35:26 -080086 test_func(reporter, surface->getCanvas());
commit-bot@chromium.org19dd0172013-08-05 13:28:55 +000087 }
88 }
89}
90
Brian Osman2caecd22019-09-25 14:02:26 -040091DEF_GPUTEST_FOR_ALL_CONTEXTS(GrDrawCollapsedPath, reporter, ctxInfo) {
92 // From https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=37330, it's possible for a convex
93 // path to be accepted by AAConvexPathRenderer, then be transformed to something without a
94 // computable first direction by a perspective matrix.
95 SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
Robert Phillips6d344c32020-07-06 10:56:46 -040096 auto surface(SkSurface::MakeRenderTarget(ctxInfo.directContext(), SkBudgeted::kNo, info));
Brian Osman2caecd22019-09-25 14:02:26 -040097
98 SkPaint paint;
99 paint.setAntiAlias(true);
100
101 SkPath path;
102 path.moveTo(0, 0);
103 path.lineTo(50, 0);
104 path.lineTo(0, 50);
105 path.close();
106
107 SkMatrix m;
108 m.setAll( 0.966006875f , -0.125156224f , 72.0899811f,
109 -0.00885376986f , -0.112347461f , 64.7121124f,
110 -8.94321693e-06f, -0.00173384184f, 0.998692870f);
111 surface->getCanvas()->setMatrix(m);
112 surface->getCanvas()->drawPath(path, paint);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400113 surface->flushAndSubmit();
Brian Osman2caecd22019-09-25 14:02:26 -0400114}
Brian Osmanae8e0632021-07-26 16:07:35 -0400115
116DEF_GPUTEST_FOR_ALL_CONTEXTS(PathTest_CrBug1232834, reporter, ctxInfo) {
Robert Phillips461c5392021-08-17 16:42:51 -0400117 // AAHairlinePathRenderer chops this path to quads that include infinities (and then NaNs).
Brian Osmanae8e0632021-07-26 16:07:35 -0400118 // It used to trigger asserts, now the degenerate quad segments should cause it to be rejected.
119 SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256);
120 auto surface(SkSurface::MakeRenderTarget(ctxInfo.directContext(), SkBudgeted::kNo, info));
121
122 SkPaint paint;
123 paint.setAntiAlias(true);
124 paint.setStyle(SkPaint::kStroke_Style);
125
126 SkPath path;
127 path.moveTo(9.0072E15f, 60);
128 path.cubicTo(0, 3.40282e+38f, 0, 3.40282e+38f, 0, 0);
129
130 surface->getCanvas()->drawPath(path, paint);
131 surface->flushAndSubmit();
132}