1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2012 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h" 9cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 10cb93a386Sopenharmony_ci#include "include/core/SkColor.h" 11cb93a386Sopenharmony_ci#include "include/core/SkImageInfo.h" 12cb93a386Sopenharmony_ci#include "include/core/SkMatrix.h" 13cb93a386Sopenharmony_ci#include "include/core/SkPaint.h" 14cb93a386Sopenharmony_ci#include "include/core/SkPath.h" 15cb93a386Sopenharmony_ci#include "include/core/SkPathEffect.h" 16cb93a386Sopenharmony_ci#include "include/core/SkPoint.h" 17cb93a386Sopenharmony_ci#include "include/core/SkRRect.h" 18cb93a386Sopenharmony_ci#include "include/core/SkRect.h" 19cb93a386Sopenharmony_ci#include "include/core/SkRefCnt.h" 20cb93a386Sopenharmony_ci#include "include/core/SkScalar.h" 21cb93a386Sopenharmony_ci#include "include/core/SkStrokeRec.h" 22cb93a386Sopenharmony_ci#include "include/core/SkSurface.h" 23cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 24cb93a386Sopenharmony_ci#include "include/effects/SkDashPathEffect.h" 25cb93a386Sopenharmony_ci#include "tests/Test.h" 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ci// test that we can draw an aa-rect at coordinates > 32K (bigger than fixedpoint) 28cb93a386Sopenharmony_cistatic void test_big_aa_rect(skiatest::Reporter* reporter) { 29cb93a386Sopenharmony_ci SkBitmap output; 30cb93a386Sopenharmony_ci SkPMColor pixel[1]; 31cb93a386Sopenharmony_ci output.installPixels(SkImageInfo::MakeN32Premul(1, 1), pixel, 4); 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_ci auto surf = SkSurface::MakeRasterN32Premul(300, 33300); 34cb93a386Sopenharmony_ci SkCanvas* canvas = surf->getCanvas(); 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ci SkRect r = { 0, 33000, 300, 33300 }; 37cb93a386Sopenharmony_ci int x = SkScalarRoundToInt(r.left()); 38cb93a386Sopenharmony_ci int y = SkScalarRoundToInt(r.top()); 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_ci // check that the pixel in question starts as transparent (by the surface) 41cb93a386Sopenharmony_ci if (surf->readPixels(output, x, y)) { 42cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0 == pixel[0]); 43cb93a386Sopenharmony_ci } else { 44cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, false, "readPixels failed"); 45cb93a386Sopenharmony_ci } 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_ci SkPaint paint; 48cb93a386Sopenharmony_ci paint.setAntiAlias(true); 49cb93a386Sopenharmony_ci paint.setColor(SK_ColorWHITE); 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_ci canvas->drawRect(r, paint); 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_ci // Now check that it is BLACK 54cb93a386Sopenharmony_ci if (surf->readPixels(output, x, y)) { 55cb93a386Sopenharmony_ci // don't know what swizzling PMColor did, but white should always 56cb93a386Sopenharmony_ci // appear the same. 57cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0xFFFFFFFF == pixel[0]); 58cb93a386Sopenharmony_ci } else { 59cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, false, "readPixels failed"); 60cb93a386Sopenharmony_ci } 61cb93a386Sopenharmony_ci} 62cb93a386Sopenharmony_ci 63cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_cistatic void moveToH(SkPath* path, const uint32_t raw[]) { 66cb93a386Sopenharmony_ci const float* fptr = (const float*)raw; 67cb93a386Sopenharmony_ci path->moveTo(fptr[0], fptr[1]); 68cb93a386Sopenharmony_ci} 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_cistatic void cubicToH(SkPath* path, const uint32_t raw[]) { 71cb93a386Sopenharmony_ci const float* fptr = (const float*)raw; 72cb93a386Sopenharmony_ci path->cubicTo(fptr[0], fptr[1], fptr[2], fptr[3], fptr[4], fptr[5]); 73cb93a386Sopenharmony_ci} 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ci// This used to assert, because we performed a cast (int)(pt[0].fX * scale) to 76cb93a386Sopenharmony_ci// arrive at an int (SkFDot6) rather than calling sk_float_round2int. The assert 77cb93a386Sopenharmony_ci// was that the initial line-segment produced by the cubic was not monotonically 78cb93a386Sopenharmony_ci// going down (i.e. the initial DY was negative). By rounding the floats, we get 79cb93a386Sopenharmony_ci// the more proper result. 80cb93a386Sopenharmony_ci// 81cb93a386Sopenharmony_ci// http://code.google.com/p/chromium/issues/detail?id=131181 82cb93a386Sopenharmony_ci// 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci// we're not calling this test anymore; is that for a reason? 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_cistatic void test_crbug131181() { 87cb93a386Sopenharmony_ci /* 88cb93a386Sopenharmony_ci fX = 18.8943768, 89cb93a386Sopenharmony_ci fY = 129.121277 90cb93a386Sopenharmony_ci }, { 91cb93a386Sopenharmony_ci fX = 18.8937435, 92cb93a386Sopenharmony_ci fY = 129.121689 93cb93a386Sopenharmony_ci }, { 94cb93a386Sopenharmony_ci fX = 18.8950119, 95cb93a386Sopenharmony_ci fY = 129.120422 96cb93a386Sopenharmony_ci }, { 97cb93a386Sopenharmony_ci fX = 18.5030727, 98cb93a386Sopenharmony_ci fY = 129.13121 99cb93a386Sopenharmony_ci */ 100cb93a386Sopenharmony_ci uint32_t data[] = { 101cb93a386Sopenharmony_ci 0x419727af, 0x43011f0c, 0x41972663, 0x43011f27, 102cb93a386Sopenharmony_ci 0x419728fc, 0x43011ed4, 0x4194064b, 0x43012197 103cb93a386Sopenharmony_ci }; 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_ci SkPath path; 106cb93a386Sopenharmony_ci moveToH(&path, &data[0]); 107cb93a386Sopenharmony_ci cubicToH(&path, &data[2]); 108cb93a386Sopenharmony_ci 109cb93a386Sopenharmony_ci auto surface(SkSurface::MakeRasterN32Premul(640, 480)); 110cb93a386Sopenharmony_ci 111cb93a386Sopenharmony_ci SkPaint paint; 112cb93a386Sopenharmony_ci paint.setAntiAlias(true); 113cb93a386Sopenharmony_ci surface->getCanvas()->drawPath(path, paint); 114cb93a386Sopenharmony_ci} 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_ci// This used to assert in debug builds (and crash writing bad memory in release) 117cb93a386Sopenharmony_ci// because we overflowed an intermediate value (B coefficient) setting up our 118cb93a386Sopenharmony_ci// stepper for the quadratic. Now we bias that value by 1/2 so we don't overflow 119cb93a386Sopenharmony_cistatic void test_crbug_140803() { 120cb93a386Sopenharmony_ci SkBitmap bm; 121cb93a386Sopenharmony_ci bm.allocN32Pixels(2700, 30*1024); 122cb93a386Sopenharmony_ci SkCanvas canvas(bm); 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_ci SkPaint paint; 125cb93a386Sopenharmony_ci paint.setAntiAlias(true); 126cb93a386Sopenharmony_ci canvas.drawPath(SkPath().moveTo(2762, 20).quadTo(11, 21702, 10, 21706), paint); 127cb93a386Sopenharmony_ci} 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_cistatic void test_crbug_1239558(skiatest::Reporter* reporter) { 130cb93a386Sopenharmony_ci SkBitmap bm; 131cb93a386Sopenharmony_ci bm.allocN32Pixels(256, 256); 132cb93a386Sopenharmony_ci 133cb93a386Sopenharmony_ci SkCanvas canvas(bm); 134cb93a386Sopenharmony_ci canvas.clear(SK_ColorWHITE); 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_ci // This creates a single cubic where the control points form an extremely skinny, vertical 137cb93a386Sopenharmony_ci // triangle contained within the x=0 column of pixels. Since it is convex (ignoring the leading 138cb93a386Sopenharmony_ci // moveTo's) it uses the convex aaa optimized edge walking algorithm after clipping the path to 139cb93a386Sopenharmony_ci // the device bounds. However, due to fixed-point math while walking these edges, the edge 140cb93a386Sopenharmony_ci // walking evaluates to coords that are very slightly less than 0 (i.e. 0.0012). Both the left 141cb93a386Sopenharmony_ci // and right edges would be out of bounds, but the edge walking is optimized to only clamp the 142cb93a386Sopenharmony_ci // left edge to the left bounds, and the right edge to the right bounds. After this clamping, 143cb93a386Sopenharmony_ci // the left and right edges are no longer sorted. This then led to incorrect behavior in various 144cb93a386Sopenharmony_ci // forms (described below). 145cb93a386Sopenharmony_ci SkPath path; 146cb93a386Sopenharmony_ci path.setFillType(SkPathFillType::kWinding); 147cb93a386Sopenharmony_ci path.moveTo(7.00649e-45f, 2.f); 148cb93a386Sopenharmony_ci path.moveTo(0.0160219f, 7.45063e-09f); 149cb93a386Sopenharmony_ci path.moveTo(192.263f, 8.40779e-44f); 150cb93a386Sopenharmony_ci path.moveTo(7.34684e-40f, 194.25f); 151cb93a386Sopenharmony_ci path.moveTo(2.3449e-38f, 6.01858e-36f); 152cb93a386Sopenharmony_ci path.moveTo(7.34684e-40f, 194.25f); 153cb93a386Sopenharmony_ci path.cubicTo(5.07266e-39f, 56.0488f, 154cb93a386Sopenharmony_ci 0.0119172f, 0.f, 155cb93a386Sopenharmony_ci 7.34684e-40f, 194.25f); 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_ci SkPaint paint; 158cb93a386Sopenharmony_ci paint.setColor(SK_ColorRED); 159cb93a386Sopenharmony_ci paint.setAntiAlias(true); 160cb93a386Sopenharmony_ci // On debug builds, the inverted left/right edges led to a negative coverage that triggered an 161cb93a386Sopenharmony_ci // assert while converting to a uint8 alpha value. On release builds with UBSAN, it would 162cb93a386Sopenharmony_ci // detect a negative left shift when computing the pixel address and crash. On regular release 163cb93a386Sopenharmony_ci // builds it would write a saturate coverage value to pixels that wrapped around to the far edge 164cb93a386Sopenharmony_ci canvas.drawPath(path, paint); 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci // UBSAN and debug builds would fail inside the drawPath() call above, but detect the incorrect 167cb93a386Sopenharmony_ci // memory access on release builds so that the test would fail. Given the path, it should only 168cb93a386Sopenharmony_ci // touch pixels with x=0 but the incorrect addressing would wrap to the right edge. 169cb93a386Sopenharmony_ci for (int y = 0; y < 256; ++y) { 170cb93a386Sopenharmony_ci if (bm.getColor(255, y) != SK_ColorWHITE) { 171cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, false, "drawPath modified incorrect pixels"); 172cb93a386Sopenharmony_ci break; 173cb93a386Sopenharmony_ci } 174cb93a386Sopenharmony_ci } 175cb93a386Sopenharmony_ci} 176cb93a386Sopenharmony_ci 177cb93a386Sopenharmony_ci// Need to exercise drawing an inverse-path whose bounds intersect the clip, 178cb93a386Sopenharmony_ci// but whose edges do not (since its a quad which draws only in the bottom half 179cb93a386Sopenharmony_ci// of its bounds). 180cb93a386Sopenharmony_ci// In the debug build, we used to assert in this case, until it was fixed. 181cb93a386Sopenharmony_ci// 182cb93a386Sopenharmony_cistatic void test_inversepathwithclip() { 183cb93a386Sopenharmony_ci SkPath path; 184cb93a386Sopenharmony_ci 185cb93a386Sopenharmony_ci path.moveTo(0, 20); 186cb93a386Sopenharmony_ci path.quadTo(10, 10, 20, 20); 187cb93a386Sopenharmony_ci path.toggleInverseFillType(); 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_ci SkPaint paint; 190cb93a386Sopenharmony_ci 191cb93a386Sopenharmony_ci auto surface(SkSurface::MakeRasterN32Premul(640, 480)); 192cb93a386Sopenharmony_ci SkCanvas* canvas = surface->getCanvas(); 193cb93a386Sopenharmony_ci canvas->save(); 194cb93a386Sopenharmony_ci canvas->clipRect(SkRect::MakeWH(19, 11)); 195cb93a386Sopenharmony_ci 196cb93a386Sopenharmony_ci paint.setAntiAlias(false); 197cb93a386Sopenharmony_ci canvas->drawPath(path, paint); 198cb93a386Sopenharmony_ci paint.setAntiAlias(true); 199cb93a386Sopenharmony_ci canvas->drawPath(path, paint); 200cb93a386Sopenharmony_ci 201cb93a386Sopenharmony_ci canvas->restore(); 202cb93a386Sopenharmony_ci 203cb93a386Sopenharmony_ci // Now do the test again, with the path flipped, so we only draw in the 204cb93a386Sopenharmony_ci // top half of our bounds, and have the clip intersect our bounds at the 205cb93a386Sopenharmony_ci // bottom. 206cb93a386Sopenharmony_ci path.reset(); // preserves our filltype 207cb93a386Sopenharmony_ci path.moveTo(0, 10); 208cb93a386Sopenharmony_ci path.quadTo(10, 20, 20, 10); 209cb93a386Sopenharmony_ci canvas->clipRect(SkRect::MakeXYWH(0, 19, 19, 11)); 210cb93a386Sopenharmony_ci 211cb93a386Sopenharmony_ci paint.setAntiAlias(false); 212cb93a386Sopenharmony_ci canvas->drawPath(path, paint); 213cb93a386Sopenharmony_ci paint.setAntiAlias(true); 214cb93a386Sopenharmony_ci canvas->drawPath(path, paint); 215cb93a386Sopenharmony_ci} 216cb93a386Sopenharmony_ci 217cb93a386Sopenharmony_cistatic void test_bug533() { 218cb93a386Sopenharmony_ci /* 219cb93a386Sopenharmony_ci http://code.google.com/p/skia/issues/detail?id=533 220cb93a386Sopenharmony_ci This particular test/bug only applies to the float case, where the 221cb93a386Sopenharmony_ci coordinates are very large. 222cb93a386Sopenharmony_ci */ 223cb93a386Sopenharmony_ci SkPath path; 224cb93a386Sopenharmony_ci path.moveTo(64, 3); 225cb93a386Sopenharmony_ci path.quadTo(-329936, -100000000, 1153, 330003); 226cb93a386Sopenharmony_ci 227cb93a386Sopenharmony_ci SkPaint paint; 228cb93a386Sopenharmony_ci paint.setAntiAlias(true); 229cb93a386Sopenharmony_ci 230cb93a386Sopenharmony_ci auto surface(SkSurface::MakeRasterN32Premul(640, 480)); 231cb93a386Sopenharmony_ci surface->getCanvas()->drawPath(path, paint); 232cb93a386Sopenharmony_ci} 233cb93a386Sopenharmony_ci 234cb93a386Sopenharmony_cistatic void test_crbug_140642() { 235cb93a386Sopenharmony_ci /* 236cb93a386Sopenharmony_ci * We used to see this construct, and due to rounding as we accumulated 237cb93a386Sopenharmony_ci * our length, the loop where we apply the phase would run off the end of 238cb93a386Sopenharmony_ci * the array, since it relied on just -= each interval value, which did not 239cb93a386Sopenharmony_ci * behave as "expected". Now the code explicitly checks for walking off the 240cb93a386Sopenharmony_ci * end of that array. 241cb93a386Sopenharmony_ci 242cb93a386Sopenharmony_ci * A different (better) fix might be to rewrite dashing to do all of its 243cb93a386Sopenharmony_ci * length/phase/measure math using double, but this may need to be 244cb93a386Sopenharmony_ci * coordinated with SkPathMeasure, to be consistent between the two. 245cb93a386Sopenharmony_ci 246cb93a386Sopenharmony_ci <path stroke="mintcream" stroke-dasharray="27734 35660 2157846850 247" 247cb93a386Sopenharmony_ci stroke-dashoffset="-248.135982067"> 248cb93a386Sopenharmony_ci */ 249cb93a386Sopenharmony_ci 250cb93a386Sopenharmony_ci const SkScalar vals[] = { 27734, 35660, 2157846850.0f, 247 }; 251cb93a386Sopenharmony_ci auto dontAssert = SkDashPathEffect::Make(vals, 4, -248.135982067f); 252cb93a386Sopenharmony_ci} 253cb93a386Sopenharmony_ci 254cb93a386Sopenharmony_cistatic void test_crbug_124652() { 255cb93a386Sopenharmony_ci /* 256cb93a386Sopenharmony_ci http://code.google.com/p/chromium/issues/detail?id=124652 257cb93a386Sopenharmony_ci This particular test/bug only applies to the float case, where 258cb93a386Sopenharmony_ci large values can "swamp" small ones. 259cb93a386Sopenharmony_ci */ 260cb93a386Sopenharmony_ci SkScalar intervals[2] = {837099584, 33450}; 261cb93a386Sopenharmony_ci auto dontAssert = SkDashPathEffect::Make(intervals, 2, -10); 262cb93a386Sopenharmony_ci} 263cb93a386Sopenharmony_ci 264cb93a386Sopenharmony_cistatic void test_bigcubic() { 265cb93a386Sopenharmony_ci SkPath path; 266cb93a386Sopenharmony_ci path.moveTo(64, 3); 267cb93a386Sopenharmony_ci path.cubicTo(-329936, -100000000, -329936, 100000000, 1153, 330003); 268cb93a386Sopenharmony_ci 269cb93a386Sopenharmony_ci SkPaint paint; 270cb93a386Sopenharmony_ci paint.setAntiAlias(true); 271cb93a386Sopenharmony_ci 272cb93a386Sopenharmony_ci auto surface(SkSurface::MakeRasterN32Premul(640, 480)); 273cb93a386Sopenharmony_ci surface->getCanvas()->drawPath(path, paint); 274cb93a386Sopenharmony_ci} 275cb93a386Sopenharmony_ci 276cb93a386Sopenharmony_ci// asserts if halfway case is not handled 277cb93a386Sopenharmony_cistatic void test_halfway() { 278cb93a386Sopenharmony_ci SkPaint paint; 279cb93a386Sopenharmony_ci SkPath path; 280cb93a386Sopenharmony_ci path.moveTo(16365.5f, 1394); 281cb93a386Sopenharmony_ci path.lineTo(16365.5f, 1387.5f); 282cb93a386Sopenharmony_ci path.quadTo(16365.5f, 1385.43f, 16367, 1383.96f); 283cb93a386Sopenharmony_ci path.quadTo(16368.4f, 1382.5f, 16370.5f, 1382.5f); 284cb93a386Sopenharmony_ci path.lineTo(16465.5f, 1382.5f); 285cb93a386Sopenharmony_ci path.quadTo(16467.6f, 1382.5f, 16469, 1383.96f); 286cb93a386Sopenharmony_ci path.quadTo(16470.5f, 1385.43f, 16470.5f, 1387.5f); 287cb93a386Sopenharmony_ci path.lineTo(16470.5f, 1394); 288cb93a386Sopenharmony_ci path.quadTo(16470.5f, 1396.07f, 16469, 1397.54f); 289cb93a386Sopenharmony_ci path.quadTo(16467.6f, 1399, 16465.5f, 1399); 290cb93a386Sopenharmony_ci path.lineTo(16370.5f, 1399); 291cb93a386Sopenharmony_ci path.quadTo(16368.4f, 1399, 16367, 1397.54f); 292cb93a386Sopenharmony_ci path.quadTo(16365.5f, 1396.07f, 16365.5f, 1394); 293cb93a386Sopenharmony_ci path.close(); 294cb93a386Sopenharmony_ci SkPath p2; 295cb93a386Sopenharmony_ci SkMatrix m; 296cb93a386Sopenharmony_ci m.reset(); 297cb93a386Sopenharmony_ci m.postTranslate(0.001f, 0.001f); 298cb93a386Sopenharmony_ci path.transform(m, &p2); 299cb93a386Sopenharmony_ci 300cb93a386Sopenharmony_ci auto surface(SkSurface::MakeRasterN32Premul(640, 480)); 301cb93a386Sopenharmony_ci SkCanvas* canvas = surface->getCanvas(); 302cb93a386Sopenharmony_ci canvas->translate(-16366, -1383); 303cb93a386Sopenharmony_ci canvas->drawPath(p2, paint); 304cb93a386Sopenharmony_ci 305cb93a386Sopenharmony_ci m.reset(); 306cb93a386Sopenharmony_ci m.postTranslate(-0.001f, -0.001f); 307cb93a386Sopenharmony_ci path.transform(m, &p2); 308cb93a386Sopenharmony_ci canvas->drawPath(p2, paint); 309cb93a386Sopenharmony_ci 310cb93a386Sopenharmony_ci m.reset(); 311cb93a386Sopenharmony_ci path.transform(m, &p2); 312cb93a386Sopenharmony_ci canvas->drawPath(p2, paint); 313cb93a386Sopenharmony_ci} 314cb93a386Sopenharmony_ci 315cb93a386Sopenharmony_ci// we used to assert if the bounds of the device (clip) was larger than 32K 316cb93a386Sopenharmony_ci// even when the path itself was smaller. We just draw and hope in the debug 317cb93a386Sopenharmony_ci// version to not assert. 318cb93a386Sopenharmony_cistatic void test_giantaa() { 319cb93a386Sopenharmony_ci const int W = 400; 320cb93a386Sopenharmony_ci const int H = 400; 321cb93a386Sopenharmony_ci auto surface(SkSurface::MakeRasterN32Premul(33000, 10)); 322cb93a386Sopenharmony_ci 323cb93a386Sopenharmony_ci SkPaint paint; 324cb93a386Sopenharmony_ci paint.setAntiAlias(true); 325cb93a386Sopenharmony_ci SkPath path; 326cb93a386Sopenharmony_ci path.addOval(SkRect::MakeXYWH(-10, -10, 20 + W, 20 + H)); 327cb93a386Sopenharmony_ci surface->getCanvas()->drawPath(path, paint); 328cb93a386Sopenharmony_ci} 329cb93a386Sopenharmony_ci 330cb93a386Sopenharmony_ci// Extremely large path_length/dash_length ratios may cause infinite looping 331cb93a386Sopenharmony_ci// in SkDashPathEffect::filterPath() due to single precision rounding. 332cb93a386Sopenharmony_ci// The test is quite expensive, but it should get much faster after the fix 333cb93a386Sopenharmony_ci// for http://crbug.com/165432 goes in. 334cb93a386Sopenharmony_cistatic void test_infinite_dash(skiatest::Reporter* reporter) { 335cb93a386Sopenharmony_ci SkPath path; 336cb93a386Sopenharmony_ci path.moveTo(0, 0); 337cb93a386Sopenharmony_ci path.lineTo(5000000, 0); 338cb93a386Sopenharmony_ci 339cb93a386Sopenharmony_ci SkScalar intervals[] = { 0.2f, 0.2f }; 340cb93a386Sopenharmony_ci sk_sp<SkPathEffect> dash(SkDashPathEffect::Make(intervals, 2, 0)); 341cb93a386Sopenharmony_ci 342cb93a386Sopenharmony_ci SkPath filteredPath; 343cb93a386Sopenharmony_ci SkPaint paint; 344cb93a386Sopenharmony_ci paint.setStyle(SkPaint::kStroke_Style); 345cb93a386Sopenharmony_ci paint.setPathEffect(dash); 346cb93a386Sopenharmony_ci 347cb93a386Sopenharmony_ci paint.getFillPath(path, &filteredPath); 348cb93a386Sopenharmony_ci // If we reach this, we passed. 349cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, true); 350cb93a386Sopenharmony_ci} 351cb93a386Sopenharmony_ci 352cb93a386Sopenharmony_ci// http://crbug.com/165432 353cb93a386Sopenharmony_ci// Limit extreme dash path effects to avoid exhausting the system memory. 354cb93a386Sopenharmony_cistatic void test_crbug_165432(skiatest::Reporter* reporter) { 355cb93a386Sopenharmony_ci SkPath path; 356cb93a386Sopenharmony_ci path.moveTo(0, 0); 357cb93a386Sopenharmony_ci path.lineTo(10000000, 0); 358cb93a386Sopenharmony_ci 359cb93a386Sopenharmony_ci SkScalar intervals[] = { 0.5f, 0.5f }; 360cb93a386Sopenharmony_ci sk_sp<SkPathEffect> dash(SkDashPathEffect::Make(intervals, 2, 0)); 361cb93a386Sopenharmony_ci 362cb93a386Sopenharmony_ci SkPaint paint; 363cb93a386Sopenharmony_ci paint.setStyle(SkPaint::kStroke_Style); 364cb93a386Sopenharmony_ci paint.setPathEffect(dash); 365cb93a386Sopenharmony_ci 366cb93a386Sopenharmony_ci SkPath filteredPath; 367cb93a386Sopenharmony_ci SkStrokeRec rec(paint); 368cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !dash->filterPath(&filteredPath, path, &rec, nullptr)); 369cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, filteredPath.isEmpty()); 370cb93a386Sopenharmony_ci} 371cb93a386Sopenharmony_ci 372cb93a386Sopenharmony_ci// http://crbug.com/472147 373cb93a386Sopenharmony_ci// This is a simplified version from the bug. RRect radii not properly scaled. 374cb93a386Sopenharmony_cistatic void test_crbug_472147_simple(skiatest::Reporter* reporter) { 375cb93a386Sopenharmony_ci auto surface(SkSurface::MakeRasterN32Premul(1000, 1000)); 376cb93a386Sopenharmony_ci SkCanvas* canvas = surface->getCanvas(); 377cb93a386Sopenharmony_ci SkPaint p; 378cb93a386Sopenharmony_ci SkRect r = SkRect::MakeLTRB(-246.0f, 33.0f, 848.0f, 33554464.0f); 379cb93a386Sopenharmony_ci SkVector radii[4] = { 380cb93a386Sopenharmony_ci { 13.0f, 8.0f }, { 170.0f, 2.0 }, { 256.0f, 33554430.0f }, { 120.0f, 5.0f } 381cb93a386Sopenharmony_ci }; 382cb93a386Sopenharmony_ci SkRRect rr; 383cb93a386Sopenharmony_ci rr.setRectRadii(r, radii); 384cb93a386Sopenharmony_ci canvas->drawRRect(rr, p); 385cb93a386Sopenharmony_ci} 386cb93a386Sopenharmony_ci 387cb93a386Sopenharmony_ci// http://crbug.com/472147 388cb93a386Sopenharmony_ci// RRect radii not properly scaled. 389cb93a386Sopenharmony_cistatic void test_crbug_472147_actual(skiatest::Reporter* reporter) { 390cb93a386Sopenharmony_ci auto surface(SkSurface::MakeRasterN32Premul(1000, 1000)); 391cb93a386Sopenharmony_ci SkCanvas* canvas = surface->getCanvas(); 392cb93a386Sopenharmony_ci SkPaint p; 393cb93a386Sopenharmony_ci SkRect r = SkRect::MakeLTRB(-246.0f, 33.0f, 848.0f, 33554464.0f); 394cb93a386Sopenharmony_ci SkVector radii[4] = { 395cb93a386Sopenharmony_ci { 13.0f, 8.0f }, { 170.0f, 2.0 }, { 256.0f, 33554430.0f }, { 120.0f, 5.0f } 396cb93a386Sopenharmony_ci }; 397cb93a386Sopenharmony_ci SkRRect rr; 398cb93a386Sopenharmony_ci rr.setRectRadii(r, radii); 399cb93a386Sopenharmony_ci canvas->clipRRect(rr); 400cb93a386Sopenharmony_ci 401cb93a386Sopenharmony_ci SkRect r2 = SkRect::MakeLTRB(0, 33, 1102, 33554464); 402cb93a386Sopenharmony_ci canvas->drawRect(r2, p); 403cb93a386Sopenharmony_ci} 404cb93a386Sopenharmony_ci 405cb93a386Sopenharmony_ciDEF_TEST(DrawPath, reporter) { 406cb93a386Sopenharmony_ci test_giantaa(); 407cb93a386Sopenharmony_ci test_bug533(); 408cb93a386Sopenharmony_ci test_bigcubic(); 409cb93a386Sopenharmony_ci test_crbug_124652(); 410cb93a386Sopenharmony_ci test_crbug_140642(); 411cb93a386Sopenharmony_ci test_crbug_140803(); 412cb93a386Sopenharmony_ci test_inversepathwithclip(); 413cb93a386Sopenharmony_ci // why? 414cb93a386Sopenharmony_ci if (false) test_crbug131181(); 415cb93a386Sopenharmony_ci test_infinite_dash(reporter); 416cb93a386Sopenharmony_ci test_crbug_165432(reporter); 417cb93a386Sopenharmony_ci test_crbug_472147_simple(reporter); 418cb93a386Sopenharmony_ci test_crbug_472147_actual(reporter); 419cb93a386Sopenharmony_ci test_crbug_1239558(reporter); 420cb93a386Sopenharmony_ci test_big_aa_rect(reporter); 421cb93a386Sopenharmony_ci test_halfway(); 422cb93a386Sopenharmony_ci} 423