1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2011 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/SkCanvas.h" 9cb93a386Sopenharmony_ci#include "include/core/SkFont.h" 10cb93a386Sopenharmony_ci#include "include/core/SkPaint.h" 11cb93a386Sopenharmony_ci#include "include/core/SkRRect.h" 12cb93a386Sopenharmony_ci#include "include/core/SkSize.h" 13cb93a386Sopenharmony_ci#include "include/core/SkStream.h" 14cb93a386Sopenharmony_ci#include "include/core/SkStrokeRec.h" 15cb93a386Sopenharmony_ci#include "include/core/SkSurface.h" 16cb93a386Sopenharmony_ci#include "include/private/SkIDChangeListener.h" 17cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 18cb93a386Sopenharmony_ci#include "include/utils/SkNullCanvas.h" 19cb93a386Sopenharmony_ci#include "include/utils/SkParse.h" 20cb93a386Sopenharmony_ci#include "include/utils/SkParsePath.h" 21cb93a386Sopenharmony_ci#include "include/utils/SkRandom.h" 22cb93a386Sopenharmony_ci#include "src/core/SkAutoMalloc.h" 23cb93a386Sopenharmony_ci#include "src/core/SkGeometry.h" 24cb93a386Sopenharmony_ci#include "src/core/SkPathPriv.h" 25cb93a386Sopenharmony_ci#include "src/core/SkReadBuffer.h" 26cb93a386Sopenharmony_ci#include "src/core/SkWriteBuffer.h" 27cb93a386Sopenharmony_ci#include "tests/Test.h" 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_ci#include <cmath> 30cb93a386Sopenharmony_ci#include <utility> 31cb93a386Sopenharmony_ci#include <vector> 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_cistatic void set_radii(SkVector radii[4], int index, float rad) { 34cb93a386Sopenharmony_ci sk_bzero(radii, sizeof(SkVector) * 4); 35cb93a386Sopenharmony_ci radii[index].set(rad, rad); 36cb93a386Sopenharmony_ci} 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_cistatic void test_add_rrect(skiatest::Reporter* reporter, const SkRect& bounds, 39cb93a386Sopenharmony_ci const SkVector radii[4]) { 40cb93a386Sopenharmony_ci SkRRect rrect; 41cb93a386Sopenharmony_ci rrect.setRectRadii(bounds, radii); 42cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, bounds == rrect.rect()); 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_ci SkPath path; 45cb93a386Sopenharmony_ci // this line should not assert in the debug build (from validate) 46cb93a386Sopenharmony_ci path.addRRect(rrect); 47cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, bounds == path.getBounds()); 48cb93a386Sopenharmony_ci} 49cb93a386Sopenharmony_ci 50cb93a386Sopenharmony_cistatic void test_skbug_3469(skiatest::Reporter* reporter) { 51cb93a386Sopenharmony_ci SkPath path; 52cb93a386Sopenharmony_ci path.moveTo(20, 20); 53cb93a386Sopenharmony_ci path.quadTo(20, 50, 80, 50); 54cb93a386Sopenharmony_ci path.quadTo(20, 50, 20, 80); 55cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isConvex()); 56cb93a386Sopenharmony_ci} 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_cistatic void test_skbug_3239(skiatest::Reporter* reporter) { 59cb93a386Sopenharmony_ci const float min = SkBits2Float(0xcb7f16c8); /* -16717512.000000 */ 60cb93a386Sopenharmony_ci const float max = SkBits2Float(0x4b7f1c1d); /* 16718877.000000 */ 61cb93a386Sopenharmony_ci const float big = SkBits2Float(0x4b7f1bd7); /* 16718807.000000 */ 62cb93a386Sopenharmony_ci 63cb93a386Sopenharmony_ci const float rad = 33436320; 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_ci const SkRect rectx = SkRect::MakeLTRB(min, min, max, big); 66cb93a386Sopenharmony_ci const SkRect recty = SkRect::MakeLTRB(min, min, big, max); 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ci SkVector radii[4]; 69cb93a386Sopenharmony_ci for (int i = 0; i < 4; ++i) { 70cb93a386Sopenharmony_ci set_radii(radii, i, rad); 71cb93a386Sopenharmony_ci test_add_rrect(reporter, rectx, radii); 72cb93a386Sopenharmony_ci test_add_rrect(reporter, recty, radii); 73cb93a386Sopenharmony_ci } 74cb93a386Sopenharmony_ci} 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_cistatic void make_path_crbug364224(SkPath* path) { 77cb93a386Sopenharmony_ci path->reset(); 78cb93a386Sopenharmony_ci path->moveTo(3.747501373f, 2.724499941f); 79cb93a386Sopenharmony_ci path->lineTo(3.747501373f, 3.75f); 80cb93a386Sopenharmony_ci path->cubicTo(3.747501373f, 3.88774991f, 3.635501385f, 4.0f, 3.497501373f, 4.0f); 81cb93a386Sopenharmony_ci path->lineTo(0.7475013733f, 4.0f); 82cb93a386Sopenharmony_ci path->cubicTo(0.6095013618f, 4.0f, 0.4975013733f, 3.88774991f, 0.4975013733f, 3.75f); 83cb93a386Sopenharmony_ci path->lineTo(0.4975013733f, 1.0f); 84cb93a386Sopenharmony_ci path->cubicTo(0.4975013733f, 0.8622499704f, 0.6095013618f, 0.75f, 0.7475013733f,0.75f); 85cb93a386Sopenharmony_ci path->lineTo(3.497501373f, 0.75f); 86cb93a386Sopenharmony_ci path->cubicTo(3.50275135f, 0.75f, 3.5070014f, 0.7527500391f, 3.513001442f, 0.753000021f); 87cb93a386Sopenharmony_ci path->lineTo(3.715001345f, 0.5512499809f); 88cb93a386Sopenharmony_ci path->cubicTo(3.648251295f, 0.5194999576f, 3.575501442f, 0.4999999702f, 3.497501373f, 0.4999999702f); 89cb93a386Sopenharmony_ci path->lineTo(0.7475013733f, 0.4999999702f); 90cb93a386Sopenharmony_ci path->cubicTo(0.4715013802f, 0.4999999702f, 0.2475013733f, 0.7239999771f, 0.2475013733f, 1.0f); 91cb93a386Sopenharmony_ci path->lineTo(0.2475013733f, 3.75f); 92cb93a386Sopenharmony_ci path->cubicTo(0.2475013733f, 4.026000023f, 0.4715013504f, 4.25f, 0.7475013733f, 4.25f); 93cb93a386Sopenharmony_ci path->lineTo(3.497501373f, 4.25f); 94cb93a386Sopenharmony_ci path->cubicTo(3.773501396f, 4.25f, 3.997501373f, 4.026000023f, 3.997501373f, 3.75f); 95cb93a386Sopenharmony_ci path->lineTo(3.997501373f, 2.474750042f); 96cb93a386Sopenharmony_ci path->lineTo(3.747501373f, 2.724499941f); 97cb93a386Sopenharmony_ci path->close(); 98cb93a386Sopenharmony_ci} 99cb93a386Sopenharmony_ci 100cb93a386Sopenharmony_cistatic void make_path_crbug364224_simplified(SkPath* path) { 101cb93a386Sopenharmony_ci path->moveTo(3.747501373f, 2.724499941f); 102cb93a386Sopenharmony_ci path->cubicTo(3.648251295f, 0.5194999576f, 3.575501442f, 0.4999999702f, 3.497501373f, 0.4999999702f); 103cb93a386Sopenharmony_ci path->close(); 104cb93a386Sopenharmony_ci} 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_cistatic void test_sect_with_horizontal_needs_pinning() { 107cb93a386Sopenharmony_ci // Test that sect_with_horizontal in SkLineClipper.cpp needs to pin after computing the 108cb93a386Sopenharmony_ci // intersection. 109cb93a386Sopenharmony_ci SkPath path; 110cb93a386Sopenharmony_ci path.reset(); 111cb93a386Sopenharmony_ci path.moveTo(-540000, -720000); 112cb93a386Sopenharmony_ci path.lineTo(-9.10000017e-05f, 9.99999996e-13f); 113cb93a386Sopenharmony_ci path.lineTo(1, 1); 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_ci // Without the pinning code in sect_with_horizontal(), this would assert in the lineclipper 116cb93a386Sopenharmony_ci SkPaint paint; 117cb93a386Sopenharmony_ci SkSurface::MakeRasterN32Premul(10, 10)->getCanvas()->drawPath(path, paint); 118cb93a386Sopenharmony_ci} 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_cistatic void test_path_crbug364224() { 121cb93a386Sopenharmony_ci SkPath path; 122cb93a386Sopenharmony_ci SkPaint paint; 123cb93a386Sopenharmony_ci auto surface(SkSurface::MakeRasterN32Premul(84, 88)); 124cb93a386Sopenharmony_ci SkCanvas* canvas = surface->getCanvas(); 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_ci make_path_crbug364224_simplified(&path); 127cb93a386Sopenharmony_ci canvas->drawPath(path, paint); 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ci make_path_crbug364224(&path); 130cb93a386Sopenharmony_ci canvas->drawPath(path, paint); 131cb93a386Sopenharmony_ci} 132cb93a386Sopenharmony_ci 133cb93a386Sopenharmony_cistatic void test_draw_AA_path(int width, int height, const SkPath& path) { 134cb93a386Sopenharmony_ci auto surface(SkSurface::MakeRasterN32Premul(width, height)); 135cb93a386Sopenharmony_ci SkCanvas* canvas = surface->getCanvas(); 136cb93a386Sopenharmony_ci SkPaint paint; 137cb93a386Sopenharmony_ci paint.setAntiAlias(true); 138cb93a386Sopenharmony_ci canvas->drawPath(path, paint); 139cb93a386Sopenharmony_ci} 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci// this is a unit test instead of a GM because it doesn't draw anything 142cb93a386Sopenharmony_cistatic void test_fuzz_crbug_638223() { 143cb93a386Sopenharmony_ci SkPath path; 144cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0x47452a00), SkBits2Float(0x43211d01)); // 50474, 161.113f 145cb93a386Sopenharmony_ci path.conicTo(SkBits2Float(0x401c0000), SkBits2Float(0x40680000), 146cb93a386Sopenharmony_ci SkBits2Float(0x02c25a81), SkBits2Float(0x981a1fa0), 147cb93a386Sopenharmony_ci SkBits2Float(0x6bf9abea)); // 2.4375f, 3.625f, 2.85577e-37f, -1.992e-24f, 6.03669e+26f 148cb93a386Sopenharmony_ci test_draw_AA_path(250, 250, path); 149cb93a386Sopenharmony_ci} 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_cistatic void test_fuzz_crbug_643933() { 152cb93a386Sopenharmony_ci SkPath path; 153cb93a386Sopenharmony_ci path.moveTo(0, 0); 154cb93a386Sopenharmony_ci path.conicTo(SkBits2Float(0x002001f2), SkBits2Float(0x4161ffff), // 2.93943e-39f, 14.125f 155cb93a386Sopenharmony_ci SkBits2Float(0x49f7224d), SkBits2Float(0x45eec8df), // 2.02452e+06f, 7641.11f 156cb93a386Sopenharmony_ci SkBits2Float(0x721aee0c)); // 3.0687e+30f 157cb93a386Sopenharmony_ci test_draw_AA_path(250, 250, path); 158cb93a386Sopenharmony_ci path.reset(); 159cb93a386Sopenharmony_ci path.moveTo(0, 0); 160cb93a386Sopenharmony_ci path.conicTo(SkBits2Float(0x00007ff2), SkBits2Float(0x4169ffff), // 4.58981e-41f, 14.625f 161cb93a386Sopenharmony_ci SkBits2Float(0x43ff2261), SkBits2Float(0x41eeea04), // 510.269f, 29.8643f 162cb93a386Sopenharmony_ci SkBits2Float(0x5d06eff8)); // 6.07704e+17f 163cb93a386Sopenharmony_ci test_draw_AA_path(250, 250, path); 164cb93a386Sopenharmony_ci} 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_cistatic void test_fuzz_crbug_647922() { 167cb93a386Sopenharmony_ci SkPath path; 168cb93a386Sopenharmony_ci path.moveTo(0, 0); 169cb93a386Sopenharmony_ci path.conicTo(SkBits2Float(0x00003939), SkBits2Float(0x42487fff), // 2.05276e-41f, 50.125f 170cb93a386Sopenharmony_ci SkBits2Float(0x48082361), SkBits2Float(0x4408e8e9), // 139406, 547.639f 171cb93a386Sopenharmony_ci SkBits2Float(0x4d1ade0f)); // 1.6239e+08f 172cb93a386Sopenharmony_ci test_draw_AA_path(250, 250, path); 173cb93a386Sopenharmony_ci} 174cb93a386Sopenharmony_ci 175cb93a386Sopenharmony_cistatic void test_fuzz_crbug_662780() { 176cb93a386Sopenharmony_ci auto surface(SkSurface::MakeRasterN32Premul(250, 250)); 177cb93a386Sopenharmony_ci SkCanvas* canvas = surface->getCanvas(); 178cb93a386Sopenharmony_ci SkPaint paint; 179cb93a386Sopenharmony_ci paint.setAntiAlias(true); 180cb93a386Sopenharmony_ci SkPath path; 181cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0x41000000), SkBits2Float(0x431e0000)); // 8, 158 182cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x41000000), SkBits2Float(0x42f00000)); // 8, 120 183cb93a386Sopenharmony_ci // 8, 8, 8.00002f, 8, 0.707107f 184cb93a386Sopenharmony_ci path.conicTo(SkBits2Float(0x41000000), SkBits2Float(0x41000000), 185cb93a386Sopenharmony_ci SkBits2Float(0x41000010), SkBits2Float(0x41000000), SkBits2Float(0x3f3504f3)); 186cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x439a0000), SkBits2Float(0x41000000)); // 308, 8 187cb93a386Sopenharmony_ci // 308, 8, 308, 8, 0.707107f 188cb93a386Sopenharmony_ci path.conicTo(SkBits2Float(0x439a0000), SkBits2Float(0x41000000), 189cb93a386Sopenharmony_ci SkBits2Float(0x439a0000), SkBits2Float(0x41000000), SkBits2Float(0x3f3504f3)); 190cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x439a0000), SkBits2Float(0x431e0000)); // 308, 158 191cb93a386Sopenharmony_ci // 308, 158, 308, 158, 0.707107f 192cb93a386Sopenharmony_ci path.conicTo(SkBits2Float(0x439a0000), SkBits2Float(0x431e0000), 193cb93a386Sopenharmony_ci SkBits2Float(0x439a0000), SkBits2Float(0x431e0000), SkBits2Float(0x3f3504f3)); 194cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x41000000), SkBits2Float(0x431e0000)); // 8, 158 195cb93a386Sopenharmony_ci // 8, 158, 8, 158, 0.707107f 196cb93a386Sopenharmony_ci path.conicTo(SkBits2Float(0x41000000), SkBits2Float(0x431e0000), 197cb93a386Sopenharmony_ci SkBits2Float(0x41000000), SkBits2Float(0x431e0000), SkBits2Float(0x3f3504f3)); 198cb93a386Sopenharmony_ci path.close(); 199cb93a386Sopenharmony_ci canvas->clipPath(path, true); 200cb93a386Sopenharmony_ci canvas->drawRect(SkRect::MakeWH(250, 250), paint); 201cb93a386Sopenharmony_ci} 202cb93a386Sopenharmony_ci 203cb93a386Sopenharmony_cistatic void test_mask_overflow() { 204cb93a386Sopenharmony_ci SkPath path; 205cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0x43e28000), SkBits2Float(0x43aa8000)); // 453, 341 206cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x43de6000), SkBits2Float(0x43aa8000)); // 444.75f, 341 207cb93a386Sopenharmony_ci // 440.47f, 341, 437, 344.47f, 437, 348.75f 208cb93a386Sopenharmony_ci path.cubicTo(SkBits2Float(0x43dc3c29), SkBits2Float(0x43aa8000), 209cb93a386Sopenharmony_ci SkBits2Float(0x43da8000), SkBits2Float(0x43ac3c29), 210cb93a386Sopenharmony_ci SkBits2Float(0x43da8000), SkBits2Float(0x43ae6000)); 211cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x43da8000), SkBits2Float(0x43b18000)); // 437, 355 212cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x43e28000), SkBits2Float(0x43b18000)); // 453, 355 213cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x43e28000), SkBits2Float(0x43aa8000)); // 453, 341 214cb93a386Sopenharmony_ci test_draw_AA_path(500, 500, path); 215cb93a386Sopenharmony_ci} 216cb93a386Sopenharmony_ci 217cb93a386Sopenharmony_cistatic void test_fuzz_crbug_668907() { 218cb93a386Sopenharmony_ci SkPath path; 219cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0x46313741), SkBits2Float(0x3b00e540)); // 11341.8f, 0.00196679f 220cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0x41410041), SkBits2Float(0xc1414141), SkBits2Float(0x41414141), 221cb93a386Sopenharmony_ci SkBits2Float(0x414100ff)); // 12.0626f, -12.0784f, 12.0784f, 12.0627f 222cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x46313741), SkBits2Float(0x3b00e540)); // 11341.8f, 0.00196679f 223cb93a386Sopenharmony_ci path.close(); 224cb93a386Sopenharmony_ci test_draw_AA_path(400, 500, path); 225cb93a386Sopenharmony_ci} 226cb93a386Sopenharmony_ci 227cb93a386Sopenharmony_ci/** 228cb93a386Sopenharmony_ci * In debug mode, this path was causing an assertion to fail in 229cb93a386Sopenharmony_ci * SkPathStroker::preJoinTo() and, in Release, the use of an unitialized value. 230cb93a386Sopenharmony_ci */ 231cb93a386Sopenharmony_cistatic void make_path_crbugskia2820(SkPath* path, skiatest::Reporter* reporter) { 232cb93a386Sopenharmony_ci SkPoint orig, p1, p2, p3; 233cb93a386Sopenharmony_ci orig = SkPoint::Make(1.f, 1.f); 234cb93a386Sopenharmony_ci p1 = SkPoint::Make(1.f - SK_ScalarNearlyZero, 1.f); 235cb93a386Sopenharmony_ci p2 = SkPoint::Make(1.f, 1.f + SK_ScalarNearlyZero); 236cb93a386Sopenharmony_ci p3 = SkPoint::Make(2.f, 2.f); 237cb93a386Sopenharmony_ci 238cb93a386Sopenharmony_ci path->reset(); 239cb93a386Sopenharmony_ci path->moveTo(orig); 240cb93a386Sopenharmony_ci path->cubicTo(p1, p2, p3); 241cb93a386Sopenharmony_ci path->close(); 242cb93a386Sopenharmony_ci} 243cb93a386Sopenharmony_ci 244cb93a386Sopenharmony_cistatic void test_path_crbugskia2820(skiatest::Reporter* reporter) { 245cb93a386Sopenharmony_ci SkPath path; 246cb93a386Sopenharmony_ci make_path_crbugskia2820(&path, reporter); 247cb93a386Sopenharmony_ci 248cb93a386Sopenharmony_ci SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 249cb93a386Sopenharmony_ci stroke.setStrokeStyle(2 * SK_Scalar1); 250cb93a386Sopenharmony_ci stroke.applyToPath(&path, path); 251cb93a386Sopenharmony_ci} 252cb93a386Sopenharmony_ci 253cb93a386Sopenharmony_cistatic void test_path_crbugskia5995() { 254cb93a386Sopenharmony_ci SkPath path; 255cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0x40303030), SkBits2Float(0x3e303030)); // 2.75294f, 0.172059f 256cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0x41d63030), SkBits2Float(0x30303030), SkBits2Float(0x41013030), 257cb93a386Sopenharmony_ci SkBits2Float(0x00000000)); // 26.7735f, 6.40969e-10f, 8.07426f, 0 258cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0 259cb93a386Sopenharmony_ci test_draw_AA_path(500, 500, path); 260cb93a386Sopenharmony_ci} 261cb93a386Sopenharmony_ci 262cb93a386Sopenharmony_cistatic void make_path0(SkPath* path) { 263cb93a386Sopenharmony_ci // from * https://code.google.com/p/skia/issues/detail?id=1706 264cb93a386Sopenharmony_ci 265cb93a386Sopenharmony_ci path->moveTo(146.939f, 1012.84f); 266cb93a386Sopenharmony_ci path->lineTo(181.747f, 1009.18f); 267cb93a386Sopenharmony_ci path->lineTo(182.165f, 1013.16f); 268cb93a386Sopenharmony_ci path->lineTo(147.357f, 1016.82f); 269cb93a386Sopenharmony_ci path->lineTo(146.939f, 1012.84f); 270cb93a386Sopenharmony_ci path->close(); 271cb93a386Sopenharmony_ci} 272cb93a386Sopenharmony_ci 273cb93a386Sopenharmony_cistatic void make_path1(SkPath* path) { 274cb93a386Sopenharmony_ci path->addRect(SkRect::MakeXYWH(10, 10, 10, 1)); 275cb93a386Sopenharmony_ci} 276cb93a386Sopenharmony_ci 277cb93a386Sopenharmony_citypedef void (*PathProc)(SkPath*); 278cb93a386Sopenharmony_ci 279cb93a386Sopenharmony_ci/* 280cb93a386Sopenharmony_ci * Regression test: we used to crash (overwrite internal storage) during 281cb93a386Sopenharmony_ci * construction of the region when the path was INVERSE. That is now fixed, 282cb93a386Sopenharmony_ci * so test these regions (which used to assert/crash). 283cb93a386Sopenharmony_ci * 284cb93a386Sopenharmony_ci * https://code.google.com/p/skia/issues/detail?id=1706 285cb93a386Sopenharmony_ci */ 286cb93a386Sopenharmony_cistatic void test_path_to_region(skiatest::Reporter* reporter) { 287cb93a386Sopenharmony_ci PathProc procs[] = { 288cb93a386Sopenharmony_ci make_path0, 289cb93a386Sopenharmony_ci make_path1, 290cb93a386Sopenharmony_ci }; 291cb93a386Sopenharmony_ci 292cb93a386Sopenharmony_ci SkRegion clip; 293cb93a386Sopenharmony_ci clip.setRect({0, 0, 1255, 1925}); 294cb93a386Sopenharmony_ci 295cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(procs); ++i) { 296cb93a386Sopenharmony_ci SkPath path; 297cb93a386Sopenharmony_ci procs[i](&path); 298cb93a386Sopenharmony_ci 299cb93a386Sopenharmony_ci SkRegion rgn; 300cb93a386Sopenharmony_ci rgn.setPath(path, clip); 301cb93a386Sopenharmony_ci path.toggleInverseFillType(); 302cb93a386Sopenharmony_ci rgn.setPath(path, clip); 303cb93a386Sopenharmony_ci } 304cb93a386Sopenharmony_ci} 305cb93a386Sopenharmony_ci 306cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_WIN 307cb93a386Sopenharmony_ci #define SUPPRESS_VISIBILITY_WARNING 308cb93a386Sopenharmony_ci#else 309cb93a386Sopenharmony_ci #define SUPPRESS_VISIBILITY_WARNING __attribute__((visibility("hidden"))) 310cb93a386Sopenharmony_ci#endif 311cb93a386Sopenharmony_ci 312cb93a386Sopenharmony_cistatic void test_path_close_issue1474(skiatest::Reporter* reporter) { 313cb93a386Sopenharmony_ci // This test checks that r{Line,Quad,Conic,Cubic}To following a close() 314cb93a386Sopenharmony_ci // are relative to the point we close to, not relative to the point we close from. 315cb93a386Sopenharmony_ci SkPath path; 316cb93a386Sopenharmony_ci SkPoint last; 317cb93a386Sopenharmony_ci 318cb93a386Sopenharmony_ci // Test rLineTo(). 319cb93a386Sopenharmony_ci path.rLineTo(0, 100); 320cb93a386Sopenharmony_ci path.rLineTo(100, 0); 321cb93a386Sopenharmony_ci path.close(); // Returns us back to 0,0. 322cb93a386Sopenharmony_ci path.rLineTo(50, 50); // This should go to 50,50. 323cb93a386Sopenharmony_ci 324cb93a386Sopenharmony_ci path.getLastPt(&last); 325cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 50 == last.fX); 326cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 50 == last.fY); 327cb93a386Sopenharmony_ci 328cb93a386Sopenharmony_ci // Test rQuadTo(). 329cb93a386Sopenharmony_ci path.rewind(); 330cb93a386Sopenharmony_ci path.rLineTo(0, 100); 331cb93a386Sopenharmony_ci path.rLineTo(100, 0); 332cb93a386Sopenharmony_ci path.close(); 333cb93a386Sopenharmony_ci path.rQuadTo(50, 50, 75, 75); 334cb93a386Sopenharmony_ci 335cb93a386Sopenharmony_ci path.getLastPt(&last); 336cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 75 == last.fX); 337cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 75 == last.fY); 338cb93a386Sopenharmony_ci 339cb93a386Sopenharmony_ci // Test rConicTo(). 340cb93a386Sopenharmony_ci path.rewind(); 341cb93a386Sopenharmony_ci path.rLineTo(0, 100); 342cb93a386Sopenharmony_ci path.rLineTo(100, 0); 343cb93a386Sopenharmony_ci path.close(); 344cb93a386Sopenharmony_ci path.rConicTo(50, 50, 85, 85, 2); 345cb93a386Sopenharmony_ci 346cb93a386Sopenharmony_ci path.getLastPt(&last); 347cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 85 == last.fX); 348cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 85 == last.fY); 349cb93a386Sopenharmony_ci 350cb93a386Sopenharmony_ci // Test rCubicTo(). 351cb93a386Sopenharmony_ci path.rewind(); 352cb93a386Sopenharmony_ci path.rLineTo(0, 100); 353cb93a386Sopenharmony_ci path.rLineTo(100, 0); 354cb93a386Sopenharmony_ci path.close(); 355cb93a386Sopenharmony_ci path.rCubicTo(50, 50, 85, 85, 95, 95); 356cb93a386Sopenharmony_ci 357cb93a386Sopenharmony_ci path.getLastPt(&last); 358cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 95 == last.fX); 359cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 95 == last.fY); 360cb93a386Sopenharmony_ci} 361cb93a386Sopenharmony_ci 362cb93a386Sopenharmony_cistatic void test_gen_id(skiatest::Reporter* reporter) { 363cb93a386Sopenharmony_ci SkPath a, b; 364cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, a.getGenerationID() == b.getGenerationID()); 365cb93a386Sopenharmony_ci 366cb93a386Sopenharmony_ci a.moveTo(0, 0); 367cb93a386Sopenharmony_ci const uint32_t z = a.getGenerationID(); 368cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, z != b.getGenerationID()); 369cb93a386Sopenharmony_ci 370cb93a386Sopenharmony_ci a.reset(); 371cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, a.getGenerationID() == b.getGenerationID()); 372cb93a386Sopenharmony_ci 373cb93a386Sopenharmony_ci a.moveTo(1, 1); 374cb93a386Sopenharmony_ci const uint32_t y = a.getGenerationID(); 375cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, z != y); 376cb93a386Sopenharmony_ci 377cb93a386Sopenharmony_ci b.moveTo(2, 2); 378cb93a386Sopenharmony_ci const uint32_t x = b.getGenerationID(); 379cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, x != y && x != z); 380cb93a386Sopenharmony_ci 381cb93a386Sopenharmony_ci a.swap(b); 382cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, b.getGenerationID() == y && a.getGenerationID() == x); 383cb93a386Sopenharmony_ci 384cb93a386Sopenharmony_ci b = a; 385cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, b.getGenerationID() == x); 386cb93a386Sopenharmony_ci 387cb93a386Sopenharmony_ci SkPath c(a); 388cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, c.getGenerationID() == x); 389cb93a386Sopenharmony_ci 390cb93a386Sopenharmony_ci c.lineTo(3, 3); 391cb93a386Sopenharmony_ci const uint32_t w = c.getGenerationID(); 392cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, b.getGenerationID() == x); 393cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, a.getGenerationID() == x); 394cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, w != x); 395cb93a386Sopenharmony_ci 396cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 397cb93a386Sopenharmony_ci static bool kExpectGenIDToIgnoreFill = false; 398cb93a386Sopenharmony_ci#else 399cb93a386Sopenharmony_ci static bool kExpectGenIDToIgnoreFill = true; 400cb93a386Sopenharmony_ci#endif 401cb93a386Sopenharmony_ci 402cb93a386Sopenharmony_ci c.toggleInverseFillType(); 403cb93a386Sopenharmony_ci const uint32_t v = c.getGenerationID(); 404cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, (v == w) == kExpectGenIDToIgnoreFill); 405cb93a386Sopenharmony_ci 406cb93a386Sopenharmony_ci c.rewind(); 407cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, v != c.getGenerationID()); 408cb93a386Sopenharmony_ci} 409cb93a386Sopenharmony_ci 410cb93a386Sopenharmony_ci// This used to assert in the debug build, as the edges did not all line-up. 411cb93a386Sopenharmony_cistatic void test_bad_cubic_crbug234190() { 412cb93a386Sopenharmony_ci SkPath path; 413cb93a386Sopenharmony_ci path.moveTo(13.8509f, 3.16858f); 414cb93a386Sopenharmony_ci path.cubicTo(-2.35893e+08f, -4.21044e+08f, 415cb93a386Sopenharmony_ci -2.38991e+08f, -4.26573e+08f, 416cb93a386Sopenharmony_ci -2.41016e+08f, -4.30188e+08f); 417cb93a386Sopenharmony_ci test_draw_AA_path(84, 88, path); 418cb93a386Sopenharmony_ci} 419cb93a386Sopenharmony_ci 420cb93a386Sopenharmony_cistatic void test_bad_cubic_crbug229478() { 421cb93a386Sopenharmony_ci const SkPoint pts[] = { 422cb93a386Sopenharmony_ci { 4595.91064f, -11596.9873f }, 423cb93a386Sopenharmony_ci { 4597.2168f, -11595.9414f }, 424cb93a386Sopenharmony_ci { 4598.52344f, -11594.8955f }, 425cb93a386Sopenharmony_ci { 4599.83008f, -11593.8496f }, 426cb93a386Sopenharmony_ci }; 427cb93a386Sopenharmony_ci 428cb93a386Sopenharmony_ci SkPath path; 429cb93a386Sopenharmony_ci path.moveTo(pts[0]); 430cb93a386Sopenharmony_ci path.cubicTo(pts[1], pts[2], pts[3]); 431cb93a386Sopenharmony_ci 432cb93a386Sopenharmony_ci SkPaint paint; 433cb93a386Sopenharmony_ci paint.setStyle(SkPaint::kStroke_Style); 434cb93a386Sopenharmony_ci paint.setStrokeWidth(20); 435cb93a386Sopenharmony_ci 436cb93a386Sopenharmony_ci SkPath dst; 437cb93a386Sopenharmony_ci // Before the fix, this would infinite-recurse, and run out of stack 438cb93a386Sopenharmony_ci // because we would keep trying to subdivide a degenerate cubic segment. 439cb93a386Sopenharmony_ci paint.getFillPath(path, &dst, nullptr); 440cb93a386Sopenharmony_ci} 441cb93a386Sopenharmony_ci 442cb93a386Sopenharmony_cistatic void build_path_170666(SkPath& path) { 443cb93a386Sopenharmony_ci path.moveTo(17.9459f, 21.6344f); 444cb93a386Sopenharmony_ci path.lineTo(139.545f, -47.8105f); 445cb93a386Sopenharmony_ci path.lineTo(139.545f, -47.8105f); 446cb93a386Sopenharmony_ci path.lineTo(131.07f, -47.3888f); 447cb93a386Sopenharmony_ci path.lineTo(131.07f, -47.3888f); 448cb93a386Sopenharmony_ci path.lineTo(122.586f, -46.9532f); 449cb93a386Sopenharmony_ci path.lineTo(122.586f, -46.9532f); 450cb93a386Sopenharmony_ci path.lineTo(18076.6f, 31390.9f); 451cb93a386Sopenharmony_ci path.lineTo(18076.6f, 31390.9f); 452cb93a386Sopenharmony_ci path.lineTo(18085.1f, 31390.5f); 453cb93a386Sopenharmony_ci path.lineTo(18085.1f, 31390.5f); 454cb93a386Sopenharmony_ci path.lineTo(18076.6f, 31390.9f); 455cb93a386Sopenharmony_ci path.lineTo(18076.6f, 31390.9f); 456cb93a386Sopenharmony_ci path.lineTo(17955, 31460.3f); 457cb93a386Sopenharmony_ci path.lineTo(17955, 31460.3f); 458cb93a386Sopenharmony_ci path.lineTo(17963.5f, 31459.9f); 459cb93a386Sopenharmony_ci path.lineTo(17963.5f, 31459.9f); 460cb93a386Sopenharmony_ci path.lineTo(17971.9f, 31459.5f); 461cb93a386Sopenharmony_ci path.lineTo(17971.9f, 31459.5f); 462cb93a386Sopenharmony_ci path.lineTo(17.9551f, 21.6205f); 463cb93a386Sopenharmony_ci path.lineTo(17.9551f, 21.6205f); 464cb93a386Sopenharmony_ci path.lineTo(9.47091f, 22.0561f); 465cb93a386Sopenharmony_ci path.lineTo(9.47091f, 22.0561f); 466cb93a386Sopenharmony_ci path.lineTo(17.9459f, 21.6344f); 467cb93a386Sopenharmony_ci path.lineTo(17.9459f, 21.6344f); 468cb93a386Sopenharmony_ci path.close();path.moveTo(0.995934f, 22.4779f); 469cb93a386Sopenharmony_ci path.lineTo(0.986725f, 22.4918f); 470cb93a386Sopenharmony_ci path.lineTo(0.986725f, 22.4918f); 471cb93a386Sopenharmony_ci path.lineTo(17955, 31460.4f); 472cb93a386Sopenharmony_ci path.lineTo(17955, 31460.4f); 473cb93a386Sopenharmony_ci path.lineTo(17971.9f, 31459.5f); 474cb93a386Sopenharmony_ci path.lineTo(17971.9f, 31459.5f); 475cb93a386Sopenharmony_ci path.lineTo(18093.6f, 31390.1f); 476cb93a386Sopenharmony_ci path.lineTo(18093.6f, 31390.1f); 477cb93a386Sopenharmony_ci path.lineTo(18093.6f, 31390); 478cb93a386Sopenharmony_ci path.lineTo(18093.6f, 31390); 479cb93a386Sopenharmony_ci path.lineTo(139.555f, -47.8244f); 480cb93a386Sopenharmony_ci path.lineTo(139.555f, -47.8244f); 481cb93a386Sopenharmony_ci path.lineTo(122.595f, -46.9671f); 482cb93a386Sopenharmony_ci path.lineTo(122.595f, -46.9671f); 483cb93a386Sopenharmony_ci path.lineTo(0.995934f, 22.4779f); 484cb93a386Sopenharmony_ci path.lineTo(0.995934f, 22.4779f); 485cb93a386Sopenharmony_ci path.close(); 486cb93a386Sopenharmony_ci path.moveTo(5.43941f, 25.5223f); 487cb93a386Sopenharmony_ci path.lineTo(798267, -28871.1f); 488cb93a386Sopenharmony_ci path.lineTo(798267, -28871.1f); 489cb93a386Sopenharmony_ci path.lineTo(3.12512e+06f, -113102); 490cb93a386Sopenharmony_ci path.lineTo(3.12512e+06f, -113102); 491cb93a386Sopenharmony_ci path.cubicTo(5.16324e+06f, -186882, 8.15247e+06f, -295092, 1.1957e+07f, -432813); 492cb93a386Sopenharmony_ci path.cubicTo(1.95659e+07f, -708257, 3.04359e+07f, -1.10175e+06f, 4.34798e+07f, -1.57394e+06f); 493cb93a386Sopenharmony_ci path.cubicTo(6.95677e+07f, -2.51831e+06f, 1.04352e+08f, -3.77748e+06f, 1.39135e+08f, -5.03666e+06f); 494cb93a386Sopenharmony_ci path.cubicTo(1.73919e+08f, -6.29583e+06f, 2.08703e+08f, -7.555e+06f, 2.34791e+08f, -8.49938e+06f); 495cb93a386Sopenharmony_ci path.cubicTo(2.47835e+08f, -8.97157e+06f, 2.58705e+08f, -9.36506e+06f, 2.66314e+08f, -9.6405e+06f); 496cb93a386Sopenharmony_ci path.cubicTo(2.70118e+08f, -9.77823e+06f, 2.73108e+08f, -9.88644e+06f, 2.75146e+08f, -9.96022e+06f); 497cb93a386Sopenharmony_ci path.cubicTo(2.76165e+08f, -9.99711e+06f, 2.76946e+08f, -1.00254e+07f, 2.77473e+08f, -1.00444e+07f); 498cb93a386Sopenharmony_ci path.lineTo(2.78271e+08f, -1.00733e+07f); 499cb93a386Sopenharmony_ci path.lineTo(2.78271e+08f, -1.00733e+07f); 500cb93a386Sopenharmony_ci path.cubicTo(2.78271e+08f, -1.00733e+07f, 2.08703e+08f, -7.555e+06f, 135.238f, 23.3517f); 501cb93a386Sopenharmony_ci path.cubicTo(131.191f, 23.4981f, 125.995f, 23.7976f, 123.631f, 24.0206f); 502cb93a386Sopenharmony_ci path.cubicTo(121.267f, 24.2436f, 122.631f, 24.3056f, 126.677f, 24.1591f); 503cb93a386Sopenharmony_ci path.cubicTo(2.08703e+08f, -7.555e+06f, 2.78271e+08f, -1.00733e+07f, 2.78271e+08f, -1.00733e+07f); 504cb93a386Sopenharmony_ci path.lineTo(2.77473e+08f, -1.00444e+07f); 505cb93a386Sopenharmony_ci path.lineTo(2.77473e+08f, -1.00444e+07f); 506cb93a386Sopenharmony_ci path.cubicTo(2.76946e+08f, -1.00254e+07f, 2.76165e+08f, -9.99711e+06f, 2.75146e+08f, -9.96022e+06f); 507cb93a386Sopenharmony_ci path.cubicTo(2.73108e+08f, -9.88644e+06f, 2.70118e+08f, -9.77823e+06f, 2.66314e+08f, -9.6405e+06f); 508cb93a386Sopenharmony_ci path.cubicTo(2.58705e+08f, -9.36506e+06f, 2.47835e+08f, -8.97157e+06f, 2.34791e+08f, -8.49938e+06f); 509cb93a386Sopenharmony_ci path.cubicTo(2.08703e+08f, -7.555e+06f, 1.73919e+08f, -6.29583e+06f, 1.39135e+08f, -5.03666e+06f); 510cb93a386Sopenharmony_ci path.cubicTo(1.04352e+08f, -3.77749e+06f, 6.95677e+07f, -2.51831e+06f, 4.34798e+07f, -1.57394e+06f); 511cb93a386Sopenharmony_ci path.cubicTo(3.04359e+07f, -1.10175e+06f, 1.95659e+07f, -708258, 1.1957e+07f, -432814); 512cb93a386Sopenharmony_ci path.cubicTo(8.15248e+06f, -295092, 5.16324e+06f, -186883, 3.12513e+06f, -113103); 513cb93a386Sopenharmony_ci path.lineTo(798284, -28872); 514cb93a386Sopenharmony_ci path.lineTo(798284, -28872); 515cb93a386Sopenharmony_ci path.lineTo(22.4044f, 24.6677f); 516cb93a386Sopenharmony_ci path.lineTo(22.4044f, 24.6677f); 517cb93a386Sopenharmony_ci path.cubicTo(22.5186f, 24.5432f, 18.8134f, 24.6337f, 14.1287f, 24.8697f); 518cb93a386Sopenharmony_ci path.cubicTo(9.4439f, 25.1057f, 5.55359f, 25.3978f, 5.43941f, 25.5223f); 519cb93a386Sopenharmony_ci path.close(); 520cb93a386Sopenharmony_ci} 521cb93a386Sopenharmony_ci 522cb93a386Sopenharmony_cistatic void build_path_simple_170666(SkPath& path) { 523cb93a386Sopenharmony_ci path.moveTo(126.677f, 24.1591f); 524cb93a386Sopenharmony_ci path.cubicTo(2.08703e+08f, -7.555e+06f, 2.78271e+08f, -1.00733e+07f, 2.78271e+08f, -1.00733e+07f); 525cb93a386Sopenharmony_ci} 526cb93a386Sopenharmony_ci 527cb93a386Sopenharmony_ci// This used to assert in the SK_DEBUG build, as the clip step would fail with 528cb93a386Sopenharmony_ci// too-few interations in our cubic-line intersection code. That code now runs 529cb93a386Sopenharmony_ci// 24 interations (instead of 16). 530cb93a386Sopenharmony_cistatic void test_crbug_170666() { 531cb93a386Sopenharmony_ci SkPath path; 532cb93a386Sopenharmony_ci build_path_simple_170666(path); 533cb93a386Sopenharmony_ci test_draw_AA_path(1000, 1000, path); 534cb93a386Sopenharmony_ci 535cb93a386Sopenharmony_ci build_path_170666(path); 536cb93a386Sopenharmony_ci test_draw_AA_path(1000, 1000, path); 537cb93a386Sopenharmony_ci} 538cb93a386Sopenharmony_ci 539cb93a386Sopenharmony_ci 540cb93a386Sopenharmony_cistatic void test_tiny_path_convexity(skiatest::Reporter* reporter, const char* pathBug, 541cb93a386Sopenharmony_ci SkScalar tx, SkScalar ty, SkScalar scale) { 542cb93a386Sopenharmony_ci SkPath smallPath; 543cb93a386Sopenharmony_ci SkAssertResult(SkParsePath::FromSVGString(pathBug, &smallPath)); 544cb93a386Sopenharmony_ci bool smallConvex = smallPath.isConvex(); 545cb93a386Sopenharmony_ci SkPath largePath; 546cb93a386Sopenharmony_ci SkAssertResult(SkParsePath::FromSVGString(pathBug, &largePath)); 547cb93a386Sopenharmony_ci SkMatrix matrix; 548cb93a386Sopenharmony_ci matrix.reset(); 549cb93a386Sopenharmony_ci matrix.preTranslate(100, 100); 550cb93a386Sopenharmony_ci matrix.preScale(scale, scale); 551cb93a386Sopenharmony_ci largePath.transform(matrix); 552cb93a386Sopenharmony_ci bool largeConvex = largePath.isConvex(); 553cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, smallConvex == largeConvex); 554cb93a386Sopenharmony_ci} 555cb93a386Sopenharmony_ci 556cb93a386Sopenharmony_cistatic void test_crbug_493450(skiatest::Reporter* reporter) { 557cb93a386Sopenharmony_ci const char reducedCase[] = 558cb93a386Sopenharmony_ci "M0,0" 559cb93a386Sopenharmony_ci "L0.0002, 0" 560cb93a386Sopenharmony_ci "L0.0002, 0.0002" 561cb93a386Sopenharmony_ci "L0.0001, 0.0001" 562cb93a386Sopenharmony_ci "L0,0.0002" 563cb93a386Sopenharmony_ci "Z"; 564cb93a386Sopenharmony_ci test_tiny_path_convexity(reporter, reducedCase, 100, 100, 100000); 565cb93a386Sopenharmony_ci const char originalFiddleData[] = 566cb93a386Sopenharmony_ci "M-0.3383152268862998,-0.11217565719203619L-0.33846085183212765,-0.11212264406895281" 567cb93a386Sopenharmony_ci "L-0.338509393480737,-0.11210607966681395L-0.33857792286700894,-0.1121889121487573" 568cb93a386Sopenharmony_ci "L-0.3383866116636664,-0.11228834570924921L-0.33842087635680235,-0.11246078673250548" 569cb93a386Sopenharmony_ci "L-0.33809536177201055,-0.11245415228342878L-0.33797257995493996,-0.11216571641452182" 570cb93a386Sopenharmony_ci "L-0.33802112160354925,-0.11201996164188659L-0.33819815585141844,-0.11218559834671019Z"; 571cb93a386Sopenharmony_ci test_tiny_path_convexity(reporter, originalFiddleData, 280081.4116670522f, 93268.04618493588f, 572cb93a386Sopenharmony_ci 826357.3384828606f); 573cb93a386Sopenharmony_ci} 574cb93a386Sopenharmony_ci 575cb93a386Sopenharmony_cistatic void test_crbug_495894(skiatest::Reporter* reporter) { 576cb93a386Sopenharmony_ci const char originalFiddleData[] = 577cb93a386Sopenharmony_ci "M-0.34004273849857214,-0.11332803232216355L-0.34008271397389744,-0.11324483772714951" 578cb93a386Sopenharmony_ci "L-0.3401940742265893,-0.11324483772714951L-0.34017694188002134,-0.11329807920275889" 579cb93a386Sopenharmony_ci "L-0.3402026403998733,-0.11333468903941245L-0.34029972369709194,-0.11334134592705701" 580cb93a386Sopenharmony_ci "L-0.3403054344792813,-0.11344121970007795L-0.3403140006525653,-0.11351115418399343" 581cb93a386Sopenharmony_ci "L-0.34024261587519866,-0.11353446986281181L-0.3402197727464413,-0.11360442946144192" 582cb93a386Sopenharmony_ci "L-0.34013696640469604,-0.11359110237029302L-0.34009128014718143,-0.1135877707043939" 583cb93a386Sopenharmony_ci "L-0.3400598708451401,-0.11360776134112742L-0.34004273849857214,-0.11355112520064405" 584cb93a386Sopenharmony_ci "L-0.3400113291965308,-0.11355112520064405L-0.3399970522410575,-0.11359110237029302" 585cb93a386Sopenharmony_ci "L-0.33997135372120546,-0.11355112520064405L-0.3399627875479215,-0.11353780084493197" 586cb93a386Sopenharmony_ci "L-0.3399485105924481,-0.11350782354357004L-0.3400027630232468,-0.11346452910331437" 587cb93a386Sopenharmony_ci "L-0.3399485105924481,-0.11340126558629839L-0.33993994441916414,-0.11340126558629839" 588cb93a386Sopenharmony_ci "L-0.33988283659727087,-0.11331804756574679L-0.33989140277055485,-0.11324483772714951" 589cb93a386Sopenharmony_ci "L-0.33997991989448945,-0.11324483772714951L-0.3399856306766788,-0.11324483772714951" 590cb93a386Sopenharmony_ci "L-0.34002560615200417,-0.11334467443478255ZM-0.3400684370184241,-0.11338461985124307" 591cb93a386Sopenharmony_ci "L-0.340154098751264,-0.11341791238732665L-0.340162664924548,-0.1134378899559977" 592cb93a386Sopenharmony_ci "L-0.34017979727111597,-0.11340126558629839L-0.3401655203156427,-0.11338129083212668" 593cb93a386Sopenharmony_ci "L-0.34012268944922275,-0.11332137577529414L-0.34007414780061346,-0.11334467443478255Z" 594cb93a386Sopenharmony_ci "M-0.3400027630232468,-0.11290567901106024L-0.3400113291965308,-0.11298876531245433" 595cb93a386Sopenharmony_ci "L-0.33997991989448945,-0.11301535852306784L-0.33990282433493346,-0.11296217481488612" 596cb93a386Sopenharmony_ci "L-0.33993994441916414,-0.11288906492739594Z"; 597cb93a386Sopenharmony_ci test_tiny_path_convexity(reporter, originalFiddleData, 22682.240000000005f,7819.72220766405f, 598cb93a386Sopenharmony_ci 65536); 599cb93a386Sopenharmony_ci} 600cb93a386Sopenharmony_ci 601cb93a386Sopenharmony_cistatic void test_crbug_613918() { 602cb93a386Sopenharmony_ci SkPath path; 603cb93a386Sopenharmony_ci path.conicTo(-6.62478e-08f, 4.13885e-08f, -6.36935e-08f, 3.97927e-08f, 0.729058f); 604cb93a386Sopenharmony_ci path.quadTo(2.28206e-09f, -1.42572e-09f, 3.91919e-09f, -2.44852e-09f); 605cb93a386Sopenharmony_ci path.cubicTo(-16752.2f, -26792.9f, -21.4673f, 10.9347f, -8.57322f, -7.22739f); 606cb93a386Sopenharmony_ci 607cb93a386Sopenharmony_ci // This call could lead to an assert or uninitialized read due to a failure 608cb93a386Sopenharmony_ci // to check the return value from SkCubicClipper::ChopMonoAtY. 609cb93a386Sopenharmony_ci path.contains(-1.84817e-08f, 1.15465e-08f); 610cb93a386Sopenharmony_ci} 611cb93a386Sopenharmony_ci 612cb93a386Sopenharmony_cistatic void test_addrect(skiatest::Reporter* reporter) { 613cb93a386Sopenharmony_ci SkPath path; 614cb93a386Sopenharmony_ci path.lineTo(0, 0); 615cb93a386Sopenharmony_ci path.addRect(SkRect::MakeWH(50, 100)); 616cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isRect(nullptr)); 617cb93a386Sopenharmony_ci 618cb93a386Sopenharmony_ci path.reset(); 619cb93a386Sopenharmony_ci path.lineTo(FLT_EPSILON, FLT_EPSILON); 620cb93a386Sopenharmony_ci path.addRect(SkRect::MakeWH(50, 100)); 621cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isRect(nullptr)); 622cb93a386Sopenharmony_ci 623cb93a386Sopenharmony_ci path.reset(); 624cb93a386Sopenharmony_ci path.quadTo(0, 0, 0, 0); 625cb93a386Sopenharmony_ci path.addRect(SkRect::MakeWH(50, 100)); 626cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isRect(nullptr)); 627cb93a386Sopenharmony_ci 628cb93a386Sopenharmony_ci path.reset(); 629cb93a386Sopenharmony_ci path.conicTo(0, 0, 0, 0, 0.5f); 630cb93a386Sopenharmony_ci path.addRect(SkRect::MakeWH(50, 100)); 631cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isRect(nullptr)); 632cb93a386Sopenharmony_ci 633cb93a386Sopenharmony_ci path.reset(); 634cb93a386Sopenharmony_ci path.cubicTo(0, 0, 0, 0, 0, 0); 635cb93a386Sopenharmony_ci path.addRect(SkRect::MakeWH(50, 100)); 636cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isRect(nullptr)); 637cb93a386Sopenharmony_ci} 638cb93a386Sopenharmony_ci 639cb93a386Sopenharmony_ci// Make sure we stay non-finite once we get there (unless we reset or rewind). 640cb93a386Sopenharmony_cistatic void test_addrect_isfinite(skiatest::Reporter* reporter) { 641cb93a386Sopenharmony_ci SkPath path; 642cb93a386Sopenharmony_ci 643cb93a386Sopenharmony_ci path.addRect(SkRect::MakeWH(50, 100)); 644cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isFinite()); 645cb93a386Sopenharmony_ci 646cb93a386Sopenharmony_ci path.moveTo(0, 0); 647cb93a386Sopenharmony_ci path.lineTo(SK_ScalarInfinity, 42); 648cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isFinite()); 649cb93a386Sopenharmony_ci 650cb93a386Sopenharmony_ci path.addRect(SkRect::MakeWH(50, 100)); 651cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isFinite()); 652cb93a386Sopenharmony_ci 653cb93a386Sopenharmony_ci path.reset(); 654cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isFinite()); 655cb93a386Sopenharmony_ci 656cb93a386Sopenharmony_ci path.addRect(SkRect::MakeWH(50, 100)); 657cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isFinite()); 658cb93a386Sopenharmony_ci} 659cb93a386Sopenharmony_ci 660cb93a386Sopenharmony_cistatic void build_big_path(SkPath* path, bool reducedCase) { 661cb93a386Sopenharmony_ci if (reducedCase) { 662cb93a386Sopenharmony_ci path->moveTo(577330, 1971.72f); 663cb93a386Sopenharmony_ci path->cubicTo(10.7082f, -116.596f, 262.057f, 45.6468f, 294.694f, 1.96237f); 664cb93a386Sopenharmony_ci } else { 665cb93a386Sopenharmony_ci path->moveTo(60.1631f, 7.70567f); 666cb93a386Sopenharmony_ci path->quadTo(60.1631f, 7.70567f, 0.99474f, 0.901199f); 667cb93a386Sopenharmony_ci path->lineTo(577379, 1977.77f); 668cb93a386Sopenharmony_ci path->quadTo(577364, 1979.57f, 577325, 1980.26f); 669cb93a386Sopenharmony_ci path->quadTo(577286, 1980.95f, 577245, 1980.13f); 670cb93a386Sopenharmony_ci path->quadTo(577205, 1979.3f, 577187, 1977.45f); 671cb93a386Sopenharmony_ci path->quadTo(577168, 1975.6f, 577183, 1973.8f); 672cb93a386Sopenharmony_ci path->quadTo(577198, 1972, 577238, 1971.31f); 673cb93a386Sopenharmony_ci path->quadTo(577277, 1970.62f, 577317, 1971.45f); 674cb93a386Sopenharmony_ci path->quadTo(577330, 1971.72f, 577341, 1972.11f); 675cb93a386Sopenharmony_ci path->cubicTo(10.7082f, -116.596f, 262.057f, 45.6468f, 294.694f, 1.96237f); 676cb93a386Sopenharmony_ci path->moveTo(306.718f, -32.912f); 677cb93a386Sopenharmony_ci path->cubicTo(30.531f, 10.0005f, 1502.47f, 13.2804f, 84.3088f, 9.99601f); 678cb93a386Sopenharmony_ci } 679cb93a386Sopenharmony_ci} 680cb93a386Sopenharmony_ci 681cb93a386Sopenharmony_cistatic void test_clipped_cubic() { 682cb93a386Sopenharmony_ci auto surface(SkSurface::MakeRasterN32Premul(640, 480)); 683cb93a386Sopenharmony_ci 684cb93a386Sopenharmony_ci // This path used to assert, because our cubic-chopping code incorrectly 685cb93a386Sopenharmony_ci // moved control points after the chop. This test should be run in SK_DEBUG 686cb93a386Sopenharmony_ci // mode to ensure that we no long assert. 687cb93a386Sopenharmony_ci SkPath path; 688cb93a386Sopenharmony_ci for (int doReducedCase = 0; doReducedCase <= 1; ++doReducedCase) { 689cb93a386Sopenharmony_ci build_big_path(&path, SkToBool(doReducedCase)); 690cb93a386Sopenharmony_ci 691cb93a386Sopenharmony_ci SkPaint paint; 692cb93a386Sopenharmony_ci for (int doAA = 0; doAA <= 1; ++doAA) { 693cb93a386Sopenharmony_ci paint.setAntiAlias(SkToBool(doAA)); 694cb93a386Sopenharmony_ci surface->getCanvas()->drawPath(path, paint); 695cb93a386Sopenharmony_ci } 696cb93a386Sopenharmony_ci } 697cb93a386Sopenharmony_ci} 698cb93a386Sopenharmony_ci 699cb93a386Sopenharmony_cistatic void dump_if_ne(skiatest::Reporter* reporter, const SkRect& expected, const SkRect& bounds) { 700cb93a386Sopenharmony_ci if (expected != bounds) { 701cb93a386Sopenharmony_ci ERRORF(reporter, "path.getBounds() returned [%g %g %g %g], but expected [%g %g %g %g]", 702cb93a386Sopenharmony_ci bounds.left(), bounds.top(), bounds.right(), bounds.bottom(), 703cb93a386Sopenharmony_ci expected.left(), expected.top(), expected.right(), expected.bottom()); 704cb93a386Sopenharmony_ci } 705cb93a386Sopenharmony_ci} 706cb93a386Sopenharmony_ci 707cb93a386Sopenharmony_cistatic void test_bounds_crbug_513799(skiatest::Reporter* reporter) { 708cb93a386Sopenharmony_ci SkPath path; 709cb93a386Sopenharmony_ci#if 0 710cb93a386Sopenharmony_ci // As written these tests were failing on LLVM 4.2 MacMini Release mysteriously, so we've 711cb93a386Sopenharmony_ci // rewritten them to avoid this (compiler-bug?). 712cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkRect::MakeLTRB(0, 0, 0, 0) == path.getBounds()); 713cb93a386Sopenharmony_ci 714cb93a386Sopenharmony_ci path.moveTo(-5, -8); 715cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkRect::MakeLTRB(-5, -8, -5, -8) == path.getBounds()); 716cb93a386Sopenharmony_ci 717cb93a386Sopenharmony_ci path.addRect(SkRect::MakeLTRB(1, 2, 3, 4)); 718cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkRect::MakeLTRB(-5, -8, 3, 4) == path.getBounds()); 719cb93a386Sopenharmony_ci 720cb93a386Sopenharmony_ci path.moveTo(1, 2); 721cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkRect::MakeLTRB(-5, -8, 3, 4) == path.getBounds()); 722cb93a386Sopenharmony_ci#else 723cb93a386Sopenharmony_ci dump_if_ne(reporter, SkRect::MakeLTRB(0, 0, 0, 0), path.getBounds()); 724cb93a386Sopenharmony_ci 725cb93a386Sopenharmony_ci path.moveTo(-5, -8); // should set the bounds 726cb93a386Sopenharmony_ci dump_if_ne(reporter, SkRect::MakeLTRB(-5, -8, -5, -8), path.getBounds()); 727cb93a386Sopenharmony_ci 728cb93a386Sopenharmony_ci path.addRect(SkRect::MakeLTRB(1, 2, 3, 4)); // should extend the bounds 729cb93a386Sopenharmony_ci dump_if_ne(reporter, SkRect::MakeLTRB(-5, -8, 3, 4), path.getBounds()); 730cb93a386Sopenharmony_ci 731cb93a386Sopenharmony_ci path.moveTo(1, 2); // don't expect this to have changed the bounds 732cb93a386Sopenharmony_ci dump_if_ne(reporter, SkRect::MakeLTRB(-5, -8, 3, 4), path.getBounds()); 733cb93a386Sopenharmony_ci#endif 734cb93a386Sopenharmony_ci} 735cb93a386Sopenharmony_ci 736cb93a386Sopenharmony_ci#include "include/core/SkSurface.h" 737cb93a386Sopenharmony_cistatic void test_fuzz_crbug_627414(skiatest::Reporter* reporter) { 738cb93a386Sopenharmony_ci SkPath path; 739cb93a386Sopenharmony_ci path.moveTo(0, 0); 740cb93a386Sopenharmony_ci path.conicTo(3.58732e-43f, 2.72084f, 3.00392f, 3.00392f, 8.46e+37f); 741cb93a386Sopenharmony_ci test_draw_AA_path(100, 100, path); 742cb93a386Sopenharmony_ci} 743cb93a386Sopenharmony_ci 744cb93a386Sopenharmony_ci// Inspired by http://ie.microsoft.com/testdrive/Performance/Chalkboard/ 745cb93a386Sopenharmony_ci// which triggered an assert, from a tricky cubic. This test replicates that 746cb93a386Sopenharmony_ci// example, so we can ensure that we handle it (in SkEdge.cpp), and don't 747cb93a386Sopenharmony_ci// assert in the SK_DEBUG build. 748cb93a386Sopenharmony_cistatic void test_tricky_cubic() { 749cb93a386Sopenharmony_ci const SkPoint pts[] = { 750cb93a386Sopenharmony_ci { SkDoubleToScalar(18.8943768), SkDoubleToScalar(129.121277) }, 751cb93a386Sopenharmony_ci { SkDoubleToScalar(18.8937435), SkDoubleToScalar(129.121689) }, 752cb93a386Sopenharmony_ci { SkDoubleToScalar(18.8950119), SkDoubleToScalar(129.120422) }, 753cb93a386Sopenharmony_ci { SkDoubleToScalar(18.5030727), SkDoubleToScalar(129.13121) }, 754cb93a386Sopenharmony_ci }; 755cb93a386Sopenharmony_ci 756cb93a386Sopenharmony_ci SkPath path; 757cb93a386Sopenharmony_ci path.moveTo(pts[0]); 758cb93a386Sopenharmony_ci path.cubicTo(pts[1], pts[2], pts[3]); 759cb93a386Sopenharmony_ci test_draw_AA_path(19, 130, path); 760cb93a386Sopenharmony_ci} 761cb93a386Sopenharmony_ci 762cb93a386Sopenharmony_ci// Inspired by http://code.google.com/p/chromium/issues/detail?id=141651 763cb93a386Sopenharmony_ci// 764cb93a386Sopenharmony_cistatic void test_isfinite_after_transform(skiatest::Reporter* reporter) { 765cb93a386Sopenharmony_ci SkPath path; 766cb93a386Sopenharmony_ci path.quadTo(157, 366, 286, 208); 767cb93a386Sopenharmony_ci path.arcTo(37, 442, 315, 163, 957494590897113.0f); 768cb93a386Sopenharmony_ci 769cb93a386Sopenharmony_ci SkMatrix matrix; 770cb93a386Sopenharmony_ci matrix.setScale(1000*1000, 1000*1000); 771cb93a386Sopenharmony_ci 772cb93a386Sopenharmony_ci // Be sure that path::transform correctly updates isFinite and the bounds 773cb93a386Sopenharmony_ci // if the transformation overflows. The previous bug was that isFinite was 774cb93a386Sopenharmony_ci // set to true in this case, but the bounds were not set to empty (which 775cb93a386Sopenharmony_ci // they should be). 776cb93a386Sopenharmony_ci while (path.isFinite()) { 777cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.getBounds().isFinite()); 778cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.getBounds().isEmpty()); 779cb93a386Sopenharmony_ci path.transform(matrix); 780cb93a386Sopenharmony_ci } 781cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.getBounds().isEmpty()); 782cb93a386Sopenharmony_ci 783cb93a386Sopenharmony_ci matrix.setTranslate(SK_Scalar1, SK_Scalar1); 784cb93a386Sopenharmony_ci path.transform(matrix); 785cb93a386Sopenharmony_ci // we need to still be non-finite 786cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isFinite()); 787cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.getBounds().isEmpty()); 788cb93a386Sopenharmony_ci} 789cb93a386Sopenharmony_ci 790cb93a386Sopenharmony_cistatic void add_corner_arc(SkPath* path, const SkRect& rect, 791cb93a386Sopenharmony_ci SkScalar xIn, SkScalar yIn, 792cb93a386Sopenharmony_ci int startAngle) 793cb93a386Sopenharmony_ci{ 794cb93a386Sopenharmony_ci 795cb93a386Sopenharmony_ci SkScalar rx = std::min(rect.width(), xIn); 796cb93a386Sopenharmony_ci SkScalar ry = std::min(rect.height(), yIn); 797cb93a386Sopenharmony_ci 798cb93a386Sopenharmony_ci SkRect arcRect; 799cb93a386Sopenharmony_ci arcRect.setLTRB(-rx, -ry, rx, ry); 800cb93a386Sopenharmony_ci switch (startAngle) { 801cb93a386Sopenharmony_ci case 0: 802cb93a386Sopenharmony_ci arcRect.offset(rect.fRight - arcRect.fRight, rect.fBottom - arcRect.fBottom); 803cb93a386Sopenharmony_ci break; 804cb93a386Sopenharmony_ci case 90: 805cb93a386Sopenharmony_ci arcRect.offset(rect.fLeft - arcRect.fLeft, rect.fBottom - arcRect.fBottom); 806cb93a386Sopenharmony_ci break; 807cb93a386Sopenharmony_ci case 180: 808cb93a386Sopenharmony_ci arcRect.offset(rect.fLeft - arcRect.fLeft, rect.fTop - arcRect.fTop); 809cb93a386Sopenharmony_ci break; 810cb93a386Sopenharmony_ci case 270: 811cb93a386Sopenharmony_ci arcRect.offset(rect.fRight - arcRect.fRight, rect.fTop - arcRect.fTop); 812cb93a386Sopenharmony_ci break; 813cb93a386Sopenharmony_ci default: 814cb93a386Sopenharmony_ci break; 815cb93a386Sopenharmony_ci } 816cb93a386Sopenharmony_ci 817cb93a386Sopenharmony_ci path->arcTo(arcRect, SkIntToScalar(startAngle), SkIntToScalar(90), false); 818cb93a386Sopenharmony_ci} 819cb93a386Sopenharmony_ci 820cb93a386Sopenharmony_cistatic void make_arb_round_rect(SkPath* path, const SkRect& r, 821cb93a386Sopenharmony_ci SkScalar xCorner, SkScalar yCorner) { 822cb93a386Sopenharmony_ci // we are lazy here and use the same x & y for each corner 823cb93a386Sopenharmony_ci add_corner_arc(path, r, xCorner, yCorner, 270); 824cb93a386Sopenharmony_ci add_corner_arc(path, r, xCorner, yCorner, 0); 825cb93a386Sopenharmony_ci add_corner_arc(path, r, xCorner, yCorner, 90); 826cb93a386Sopenharmony_ci add_corner_arc(path, r, xCorner, yCorner, 180); 827cb93a386Sopenharmony_ci path->close(); 828cb93a386Sopenharmony_ci} 829cb93a386Sopenharmony_ci 830cb93a386Sopenharmony_ci// Chrome creates its own round rects with each corner possibly being different. 831cb93a386Sopenharmony_ci// Performance will suffer if they are not convex. 832cb93a386Sopenharmony_ci// Note: PathBench::ArbRoundRectBench performs almost exactly 833cb93a386Sopenharmony_ci// the same test (but with drawing) 834cb93a386Sopenharmony_cistatic void test_arb_round_rect_is_convex(skiatest::Reporter* reporter) { 835cb93a386Sopenharmony_ci SkRandom rand; 836cb93a386Sopenharmony_ci SkRect r; 837cb93a386Sopenharmony_ci 838cb93a386Sopenharmony_ci for (int i = 0; i < 5000; ++i) { 839cb93a386Sopenharmony_ci 840cb93a386Sopenharmony_ci SkScalar size = rand.nextUScalar1() * 30; 841cb93a386Sopenharmony_ci if (size < SK_Scalar1) { 842cb93a386Sopenharmony_ci continue; 843cb93a386Sopenharmony_ci } 844cb93a386Sopenharmony_ci r.fLeft = rand.nextUScalar1() * 300; 845cb93a386Sopenharmony_ci r.fTop = rand.nextUScalar1() * 300; 846cb93a386Sopenharmony_ci r.fRight = r.fLeft + 2 * size; 847cb93a386Sopenharmony_ci r.fBottom = r.fTop + 2 * size; 848cb93a386Sopenharmony_ci 849cb93a386Sopenharmony_ci SkPath temp; 850cb93a386Sopenharmony_ci 851cb93a386Sopenharmony_ci make_arb_round_rect(&temp, r, r.width() / 10, r.height() / 15); 852cb93a386Sopenharmony_ci 853cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, temp.isConvex()); 854cb93a386Sopenharmony_ci } 855cb93a386Sopenharmony_ci} 856cb93a386Sopenharmony_ci 857cb93a386Sopenharmony_ci// Chrome will sometimes create a 0 radius round rect. The degenerate 858cb93a386Sopenharmony_ci// quads prevent the path from being converted to a rect 859cb93a386Sopenharmony_ci// Note: PathBench::ArbRoundRectBench performs almost exactly 860cb93a386Sopenharmony_ci// the same test (but with drawing) 861cb93a386Sopenharmony_cistatic void test_arb_zero_rad_round_rect_is_rect(skiatest::Reporter* reporter) { 862cb93a386Sopenharmony_ci SkRandom rand; 863cb93a386Sopenharmony_ci SkRect r; 864cb93a386Sopenharmony_ci 865cb93a386Sopenharmony_ci for (int i = 0; i < 5000; ++i) { 866cb93a386Sopenharmony_ci 867cb93a386Sopenharmony_ci SkScalar size = rand.nextUScalar1() * 30; 868cb93a386Sopenharmony_ci if (size < SK_Scalar1) { 869cb93a386Sopenharmony_ci continue; 870cb93a386Sopenharmony_ci } 871cb93a386Sopenharmony_ci r.fLeft = rand.nextUScalar1() * 300; 872cb93a386Sopenharmony_ci r.fTop = rand.nextUScalar1() * 300; 873cb93a386Sopenharmony_ci r.fRight = r.fLeft + 2 * size; 874cb93a386Sopenharmony_ci r.fBottom = r.fTop + 2 * size; 875cb93a386Sopenharmony_ci 876cb93a386Sopenharmony_ci SkPath temp; 877cb93a386Sopenharmony_ci 878cb93a386Sopenharmony_ci make_arb_round_rect(&temp, r, 0, 0); 879cb93a386Sopenharmony_ci 880cb93a386Sopenharmony_ci SkRect result; 881cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, temp.isRect(&result)); 882cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, r == result); 883cb93a386Sopenharmony_ci } 884cb93a386Sopenharmony_ci} 885cb93a386Sopenharmony_ci 886cb93a386Sopenharmony_cistatic void test_rect_isfinite(skiatest::Reporter* reporter) { 887cb93a386Sopenharmony_ci const SkScalar inf = SK_ScalarInfinity; 888cb93a386Sopenharmony_ci const SkScalar negInf = SK_ScalarNegativeInfinity; 889cb93a386Sopenharmony_ci const SkScalar nan = SK_ScalarNaN; 890cb93a386Sopenharmony_ci 891cb93a386Sopenharmony_ci SkRect r; 892cb93a386Sopenharmony_ci r.setEmpty(); 893cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, r.isFinite()); 894cb93a386Sopenharmony_ci r.setLTRB(0, 0, inf, negInf); 895cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !r.isFinite()); 896cb93a386Sopenharmony_ci r.setLTRB(0, 0, nan, 0); 897cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !r.isFinite()); 898cb93a386Sopenharmony_ci 899cb93a386Sopenharmony_ci SkPoint pts[] = { 900cb93a386Sopenharmony_ci { 0, 0 }, 901cb93a386Sopenharmony_ci { SK_Scalar1, 0 }, 902cb93a386Sopenharmony_ci { 0, SK_Scalar1 }, 903cb93a386Sopenharmony_ci }; 904cb93a386Sopenharmony_ci 905cb93a386Sopenharmony_ci bool isFine = r.setBoundsCheck(pts, 3); 906cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, isFine); 907cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !r.isEmpty()); 908cb93a386Sopenharmony_ci 909cb93a386Sopenharmony_ci pts[1].set(inf, 0); 910cb93a386Sopenharmony_ci isFine = r.setBoundsCheck(pts, 3); 911cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !isFine); 912cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, r.isEmpty()); 913cb93a386Sopenharmony_ci 914cb93a386Sopenharmony_ci pts[1].set(nan, 0); 915cb93a386Sopenharmony_ci isFine = r.setBoundsCheck(pts, 3); 916cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !isFine); 917cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, r.isEmpty()); 918cb93a386Sopenharmony_ci} 919cb93a386Sopenharmony_ci 920cb93a386Sopenharmony_cistatic void test_path_isfinite(skiatest::Reporter* reporter) { 921cb93a386Sopenharmony_ci const SkScalar inf = SK_ScalarInfinity; 922cb93a386Sopenharmony_ci const SkScalar negInf = SK_ScalarNegativeInfinity; 923cb93a386Sopenharmony_ci const SkScalar nan = SK_ScalarNaN; 924cb93a386Sopenharmony_ci 925cb93a386Sopenharmony_ci SkPath path; 926cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isFinite()); 927cb93a386Sopenharmony_ci 928cb93a386Sopenharmony_ci path.reset(); 929cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isFinite()); 930cb93a386Sopenharmony_ci 931cb93a386Sopenharmony_ci path.reset(); 932cb93a386Sopenharmony_ci path.moveTo(SK_Scalar1, 0); 933cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isFinite()); 934cb93a386Sopenharmony_ci 935cb93a386Sopenharmony_ci path.reset(); 936cb93a386Sopenharmony_ci path.moveTo(inf, negInf); 937cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isFinite()); 938cb93a386Sopenharmony_ci 939cb93a386Sopenharmony_ci path.reset(); 940cb93a386Sopenharmony_ci path.moveTo(nan, 0); 941cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isFinite()); 942cb93a386Sopenharmony_ci} 943cb93a386Sopenharmony_ci 944cb93a386Sopenharmony_cistatic void test_isfinite(skiatest::Reporter* reporter) { 945cb93a386Sopenharmony_ci test_rect_isfinite(reporter); 946cb93a386Sopenharmony_ci test_path_isfinite(reporter); 947cb93a386Sopenharmony_ci} 948cb93a386Sopenharmony_ci 949cb93a386Sopenharmony_cistatic void test_islastcontourclosed(skiatest::Reporter* reporter) { 950cb93a386Sopenharmony_ci SkPath path; 951cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isLastContourClosed()); 952cb93a386Sopenharmony_ci path.moveTo(0, 0); 953cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isLastContourClosed()); 954cb93a386Sopenharmony_ci path.close(); 955cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isLastContourClosed()); 956cb93a386Sopenharmony_ci path.lineTo(100, 100); 957cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isLastContourClosed()); 958cb93a386Sopenharmony_ci path.moveTo(200, 200); 959cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isLastContourClosed()); 960cb93a386Sopenharmony_ci path.close(); 961cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isLastContourClosed()); 962cb93a386Sopenharmony_ci path.moveTo(0, 0); 963cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isLastContourClosed()); 964cb93a386Sopenharmony_ci} 965cb93a386Sopenharmony_ci 966cb93a386Sopenharmony_ci// assert that we always 967cb93a386Sopenharmony_ci// start with a moveTo 968cb93a386Sopenharmony_ci// only have 1 moveTo 969cb93a386Sopenharmony_ci// only have Lines after that 970cb93a386Sopenharmony_ci// end with a single close 971cb93a386Sopenharmony_ci// only have (at most) 1 close 972cb93a386Sopenharmony_ci// 973cb93a386Sopenharmony_cistatic void test_poly(skiatest::Reporter* reporter, const SkPath& path, 974cb93a386Sopenharmony_ci const SkPoint srcPts[], bool expectClose) { 975cb93a386Sopenharmony_ci bool firstTime = true; 976cb93a386Sopenharmony_ci bool foundClose = false; 977cb93a386Sopenharmony_ci for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) { 978cb93a386Sopenharmony_ci switch (verb) { 979cb93a386Sopenharmony_ci case SkPathVerb::kMove: 980cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, firstTime); 981cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0] == srcPts[0]); 982cb93a386Sopenharmony_ci srcPts++; 983cb93a386Sopenharmony_ci firstTime = false; 984cb93a386Sopenharmony_ci break; 985cb93a386Sopenharmony_ci case SkPathVerb::kLine: 986cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !firstTime); 987cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[1] == srcPts[0]); 988cb93a386Sopenharmony_ci srcPts++; 989cb93a386Sopenharmony_ci break; 990cb93a386Sopenharmony_ci case SkPathVerb::kQuad: 991cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, false, "unexpected quad verb"); 992cb93a386Sopenharmony_ci break; 993cb93a386Sopenharmony_ci case SkPathVerb::kConic: 994cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, false, "unexpected conic verb"); 995cb93a386Sopenharmony_ci break; 996cb93a386Sopenharmony_ci case SkPathVerb::kCubic: 997cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, false, "unexpected cubic verb"); 998cb93a386Sopenharmony_ci break; 999cb93a386Sopenharmony_ci case SkPathVerb::kClose: 1000cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !firstTime); 1001cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !foundClose); 1002cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, expectClose); 1003cb93a386Sopenharmony_ci foundClose = true; 1004cb93a386Sopenharmony_ci break; 1005cb93a386Sopenharmony_ci } 1006cb93a386Sopenharmony_ci } 1007cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, foundClose == expectClose); 1008cb93a386Sopenharmony_ci} 1009cb93a386Sopenharmony_ci 1010cb93a386Sopenharmony_cistatic void test_addPoly(skiatest::Reporter* reporter) { 1011cb93a386Sopenharmony_ci SkPoint pts[32]; 1012cb93a386Sopenharmony_ci SkRandom rand; 1013cb93a386Sopenharmony_ci 1014cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(pts); ++i) { 1015cb93a386Sopenharmony_ci pts[i].fX = rand.nextSScalar1(); 1016cb93a386Sopenharmony_ci pts[i].fY = rand.nextSScalar1(); 1017cb93a386Sopenharmony_ci } 1018cb93a386Sopenharmony_ci 1019cb93a386Sopenharmony_ci for (int doClose = 0; doClose <= 1; ++doClose) { 1020cb93a386Sopenharmony_ci for (size_t count = 1; count <= SK_ARRAY_COUNT(pts); ++count) { 1021cb93a386Sopenharmony_ci SkPath path; 1022cb93a386Sopenharmony_ci path.addPoly(pts, SkToInt(count), SkToBool(doClose)); 1023cb93a386Sopenharmony_ci test_poly(reporter, path, pts, SkToBool(doClose)); 1024cb93a386Sopenharmony_ci } 1025cb93a386Sopenharmony_ci } 1026cb93a386Sopenharmony_ci} 1027cb93a386Sopenharmony_ci 1028cb93a386Sopenharmony_cistatic void test_strokerec(skiatest::Reporter* reporter) { 1029cb93a386Sopenharmony_ci SkStrokeRec rec(SkStrokeRec::kFill_InitStyle); 1030cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, rec.isFillStyle()); 1031cb93a386Sopenharmony_ci 1032cb93a386Sopenharmony_ci rec.setHairlineStyle(); 1033cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, rec.isHairlineStyle()); 1034cb93a386Sopenharmony_ci 1035cb93a386Sopenharmony_ci rec.setStrokeStyle(SK_Scalar1, false); 1036cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkStrokeRec::kStroke_Style == rec.getStyle()); 1037cb93a386Sopenharmony_ci 1038cb93a386Sopenharmony_ci rec.setStrokeStyle(SK_Scalar1, true); 1039cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkStrokeRec::kStrokeAndFill_Style == rec.getStyle()); 1040cb93a386Sopenharmony_ci 1041cb93a386Sopenharmony_ci rec.setStrokeStyle(0, false); 1042cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkStrokeRec::kHairline_Style == rec.getStyle()); 1043cb93a386Sopenharmony_ci 1044cb93a386Sopenharmony_ci rec.setStrokeStyle(0, true); 1045cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkStrokeRec::kFill_Style == rec.getStyle()); 1046cb93a386Sopenharmony_ci} 1047cb93a386Sopenharmony_ci 1048cb93a386Sopenharmony_ci// Set this for paths that don't have a consistent direction such as a bowtie. 1049cb93a386Sopenharmony_ci// (cheapComputeDirection is not expected to catch these.) 1050cb93a386Sopenharmony_ci// Legal values are CW (0), CCW (1) and Unknown (2), leaving 3 as a convenient sentinel. 1051cb93a386Sopenharmony_ciconst SkPathFirstDirection kDontCheckDir = static_cast<SkPathFirstDirection>(3); 1052cb93a386Sopenharmony_ci 1053cb93a386Sopenharmony_cistatic void check_direction(skiatest::Reporter* reporter, const SkPath& path, 1054cb93a386Sopenharmony_ci SkPathFirstDirection expected) { 1055cb93a386Sopenharmony_ci if (expected == kDontCheckDir) { 1056cb93a386Sopenharmony_ci return; 1057cb93a386Sopenharmony_ci } 1058cb93a386Sopenharmony_ci // We make a copy so that we don't cache the result on the passed in path. 1059cb93a386Sopenharmony_ci SkPath copy(path); // NOLINT(performance-unnecessary-copy-initialization) 1060cb93a386Sopenharmony_ci 1061cb93a386Sopenharmony_ci SkPathFirstDirection dir = SkPathPriv::ComputeFirstDirection(copy); 1062cb93a386Sopenharmony_ci if (dir != SkPathFirstDirection::kUnknown) { 1063cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, dir == expected); 1064cb93a386Sopenharmony_ci } 1065cb93a386Sopenharmony_ci} 1066cb93a386Sopenharmony_ci 1067cb93a386Sopenharmony_cistatic void test_direction(skiatest::Reporter* reporter) { 1068cb93a386Sopenharmony_ci size_t i; 1069cb93a386Sopenharmony_ci SkPath path; 1070cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 1071cb93a386Sopenharmony_ci SkPathPriv::ComputeFirstDirection(path) == SkPathFirstDirection::kUnknown); 1072cb93a386Sopenharmony_ci 1073cb93a386Sopenharmony_ci static const char* gDegen[] = { 1074cb93a386Sopenharmony_ci "M 10 10", 1075cb93a386Sopenharmony_ci "M 10 10 M 20 20", 1076cb93a386Sopenharmony_ci "M 10 10 L 20 20", 1077cb93a386Sopenharmony_ci "M 10 10 L 10 10 L 10 10", 1078cb93a386Sopenharmony_ci "M 10 10 Q 10 10 10 10", 1079cb93a386Sopenharmony_ci "M 10 10 C 10 10 10 10 10 10", 1080cb93a386Sopenharmony_ci }; 1081cb93a386Sopenharmony_ci for (i = 0; i < SK_ARRAY_COUNT(gDegen); ++i) { 1082cb93a386Sopenharmony_ci path.reset(); 1083cb93a386Sopenharmony_ci bool valid = SkParsePath::FromSVGString(gDegen[i], &path); 1084cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, valid); 1085cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 1086cb93a386Sopenharmony_ci SkPathPriv::ComputeFirstDirection(path) == SkPathFirstDirection::kUnknown); 1087cb93a386Sopenharmony_ci } 1088cb93a386Sopenharmony_ci 1089cb93a386Sopenharmony_ci static const char* gCW[] = { 1090cb93a386Sopenharmony_ci "M 10 10 L 10 10 Q 20 10 20 20", 1091cb93a386Sopenharmony_ci "M 10 10 C 20 10 20 20 20 20", 1092cb93a386Sopenharmony_ci "M 20 10 Q 20 20 30 20 L 10 20", // test double-back at y-max 1093cb93a386Sopenharmony_ci // rect with top two corners replaced by cubics with identical middle 1094cb93a386Sopenharmony_ci // control points 1095cb93a386Sopenharmony_ci "M 10 10 C 10 0 10 0 20 0 L 40 0 C 50 0 50 0 50 10", 1096cb93a386Sopenharmony_ci "M 20 10 L 0 10 Q 10 10 20 0", // left, degenerate serif 1097cb93a386Sopenharmony_ci }; 1098cb93a386Sopenharmony_ci for (i = 0; i < SK_ARRAY_COUNT(gCW); ++i) { 1099cb93a386Sopenharmony_ci path.reset(); 1100cb93a386Sopenharmony_ci bool valid = SkParsePath::FromSVGString(gCW[i], &path); 1101cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, valid); 1102cb93a386Sopenharmony_ci check_direction(reporter, path, SkPathFirstDirection::kCW); 1103cb93a386Sopenharmony_ci } 1104cb93a386Sopenharmony_ci 1105cb93a386Sopenharmony_ci static const char* gCCW[] = { 1106cb93a386Sopenharmony_ci "M 10 10 L 10 10 Q 20 10 20 -20", 1107cb93a386Sopenharmony_ci "M 10 10 C 20 10 20 -20 20 -20", 1108cb93a386Sopenharmony_ci "M 20 10 Q 20 20 10 20 L 30 20", // test double-back at y-max 1109cb93a386Sopenharmony_ci // rect with top two corners replaced by cubics with identical middle 1110cb93a386Sopenharmony_ci // control points 1111cb93a386Sopenharmony_ci "M 50 10 C 50 0 50 0 40 0 L 20 0 C 10 0 10 0 10 10", 1112cb93a386Sopenharmony_ci "M 10 10 L 30 10 Q 20 10 10 0", // right, degenerate serif 1113cb93a386Sopenharmony_ci }; 1114cb93a386Sopenharmony_ci for (i = 0; i < SK_ARRAY_COUNT(gCCW); ++i) { 1115cb93a386Sopenharmony_ci path.reset(); 1116cb93a386Sopenharmony_ci bool valid = SkParsePath::FromSVGString(gCCW[i], &path); 1117cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, valid); 1118cb93a386Sopenharmony_ci check_direction(reporter, path, SkPathFirstDirection::kCCW); 1119cb93a386Sopenharmony_ci } 1120cb93a386Sopenharmony_ci 1121cb93a386Sopenharmony_ci // Test two donuts, each wound a different direction. Only the outer contour 1122cb93a386Sopenharmony_ci // determines the cheap direction 1123cb93a386Sopenharmony_ci path.reset(); 1124cb93a386Sopenharmony_ci path.addCircle(0, 0, SkIntToScalar(2), SkPathDirection::kCW); 1125cb93a386Sopenharmony_ci path.addCircle(0, 0, SkIntToScalar(1), SkPathDirection::kCCW); 1126cb93a386Sopenharmony_ci check_direction(reporter, path, SkPathFirstDirection::kCW); 1127cb93a386Sopenharmony_ci 1128cb93a386Sopenharmony_ci path.reset(); 1129cb93a386Sopenharmony_ci path.addCircle(0, 0, SkIntToScalar(1), SkPathDirection::kCW); 1130cb93a386Sopenharmony_ci path.addCircle(0, 0, SkIntToScalar(2), SkPathDirection::kCCW); 1131cb93a386Sopenharmony_ci check_direction(reporter, path, SkPathFirstDirection::kCCW); 1132cb93a386Sopenharmony_ci 1133cb93a386Sopenharmony_ci // triangle with one point really far from the origin. 1134cb93a386Sopenharmony_ci path.reset(); 1135cb93a386Sopenharmony_ci // the first point is roughly 1.05e10, 1.05e10 1136cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0x501c7652), SkBits2Float(0x501c7652)); 1137cb93a386Sopenharmony_ci path.lineTo(110 * SK_Scalar1, -10 * SK_Scalar1); 1138cb93a386Sopenharmony_ci path.lineTo(-10 * SK_Scalar1, 60 * SK_Scalar1); 1139cb93a386Sopenharmony_ci check_direction(reporter, path, SkPathFirstDirection::kCCW); 1140cb93a386Sopenharmony_ci 1141cb93a386Sopenharmony_ci path.reset(); 1142cb93a386Sopenharmony_ci path.conicTo(20, 0, 20, 20, 0.5f); 1143cb93a386Sopenharmony_ci path.close(); 1144cb93a386Sopenharmony_ci check_direction(reporter, path, SkPathFirstDirection::kCW); 1145cb93a386Sopenharmony_ci 1146cb93a386Sopenharmony_ci path.reset(); 1147cb93a386Sopenharmony_ci path.lineTo(1, 1e7f); 1148cb93a386Sopenharmony_ci path.lineTo(1e7f, 2e7f); 1149cb93a386Sopenharmony_ci path.close(); 1150cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isConvex()); 1151cb93a386Sopenharmony_ci check_direction(reporter, path, SkPathFirstDirection::kCCW); 1152cb93a386Sopenharmony_ci} 1153cb93a386Sopenharmony_ci 1154cb93a386Sopenharmony_cistatic void add_rect(SkPath* path, const SkRect& r) { 1155cb93a386Sopenharmony_ci path->moveTo(r.fLeft, r.fTop); 1156cb93a386Sopenharmony_ci path->lineTo(r.fRight, r.fTop); 1157cb93a386Sopenharmony_ci path->lineTo(r.fRight, r.fBottom); 1158cb93a386Sopenharmony_ci path->lineTo(r.fLeft, r.fBottom); 1159cb93a386Sopenharmony_ci path->close(); 1160cb93a386Sopenharmony_ci} 1161cb93a386Sopenharmony_ci 1162cb93a386Sopenharmony_cistatic void test_bounds(skiatest::Reporter* reporter) { 1163cb93a386Sopenharmony_ci static const SkRect rects[] = { 1164cb93a386Sopenharmony_ci { SkIntToScalar(10), SkIntToScalar(160), SkIntToScalar(610), SkIntToScalar(160) }, 1165cb93a386Sopenharmony_ci { SkIntToScalar(610), SkIntToScalar(160), SkIntToScalar(610), SkIntToScalar(199) }, 1166cb93a386Sopenharmony_ci { SkIntToScalar(10), SkIntToScalar(198), SkIntToScalar(610), SkIntToScalar(199) }, 1167cb93a386Sopenharmony_ci { SkIntToScalar(10), SkIntToScalar(160), SkIntToScalar(10), SkIntToScalar(199) }, 1168cb93a386Sopenharmony_ci }; 1169cb93a386Sopenharmony_ci 1170cb93a386Sopenharmony_ci SkPath path0, path1; 1171cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(rects); ++i) { 1172cb93a386Sopenharmony_ci path0.addRect(rects[i]); 1173cb93a386Sopenharmony_ci add_rect(&path1, rects[i]); 1174cb93a386Sopenharmony_ci } 1175cb93a386Sopenharmony_ci 1176cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path0.getBounds() == path1.getBounds()); 1177cb93a386Sopenharmony_ci} 1178cb93a386Sopenharmony_ci 1179cb93a386Sopenharmony_cistatic void stroke_cubic(const SkPoint pts[4]) { 1180cb93a386Sopenharmony_ci SkPath path; 1181cb93a386Sopenharmony_ci path.moveTo(pts[0]); 1182cb93a386Sopenharmony_ci path.cubicTo(pts[1], pts[2], pts[3]); 1183cb93a386Sopenharmony_ci 1184cb93a386Sopenharmony_ci SkPaint paint; 1185cb93a386Sopenharmony_ci paint.setStyle(SkPaint::kStroke_Style); 1186cb93a386Sopenharmony_ci paint.setStrokeWidth(SK_Scalar1 * 2); 1187cb93a386Sopenharmony_ci 1188cb93a386Sopenharmony_ci SkPath fill; 1189cb93a386Sopenharmony_ci paint.getFillPath(path, &fill); 1190cb93a386Sopenharmony_ci} 1191cb93a386Sopenharmony_ci 1192cb93a386Sopenharmony_ci// just ensure this can run w/o any SkASSERTS firing in the debug build 1193cb93a386Sopenharmony_ci// we used to assert due to differences in how we determine a degenerate vector 1194cb93a386Sopenharmony_ci// but that was fixed with the introduction of SkPoint::CanNormalize 1195cb93a386Sopenharmony_cistatic void stroke_tiny_cubic() { 1196cb93a386Sopenharmony_ci SkPoint p0[] = { 1197cb93a386Sopenharmony_ci { 372.0f, 92.0f }, 1198cb93a386Sopenharmony_ci { 372.0f, 92.0f }, 1199cb93a386Sopenharmony_ci { 372.0f, 92.0f }, 1200cb93a386Sopenharmony_ci { 372.0f, 92.0f }, 1201cb93a386Sopenharmony_ci }; 1202cb93a386Sopenharmony_ci 1203cb93a386Sopenharmony_ci stroke_cubic(p0); 1204cb93a386Sopenharmony_ci 1205cb93a386Sopenharmony_ci SkPoint p1[] = { 1206cb93a386Sopenharmony_ci { 372.0f, 92.0f }, 1207cb93a386Sopenharmony_ci { 372.0007f, 92.000755f }, 1208cb93a386Sopenharmony_ci { 371.99927f, 92.003922f }, 1209cb93a386Sopenharmony_ci { 371.99826f, 92.003899f }, 1210cb93a386Sopenharmony_ci }; 1211cb93a386Sopenharmony_ci 1212cb93a386Sopenharmony_ci stroke_cubic(p1); 1213cb93a386Sopenharmony_ci} 1214cb93a386Sopenharmony_ci 1215cb93a386Sopenharmony_cistatic void check_close(skiatest::Reporter* reporter, const SkPath& path) { 1216cb93a386Sopenharmony_ci for (int i = 0; i < 2; ++i) { 1217cb93a386Sopenharmony_ci SkPath::Iter iter(path, SkToBool(i)); 1218cb93a386Sopenharmony_ci SkPoint mv; 1219cb93a386Sopenharmony_ci SkPoint pts[4]; 1220cb93a386Sopenharmony_ci SkPath::Verb v; 1221cb93a386Sopenharmony_ci int nMT = 0; 1222cb93a386Sopenharmony_ci int nCL = 0; 1223cb93a386Sopenharmony_ci mv.set(0, 0); 1224cb93a386Sopenharmony_ci while (SkPath::kDone_Verb != (v = iter.next(pts))) { 1225cb93a386Sopenharmony_ci switch (v) { 1226cb93a386Sopenharmony_ci case SkPath::kMove_Verb: 1227cb93a386Sopenharmony_ci mv = pts[0]; 1228cb93a386Sopenharmony_ci ++nMT; 1229cb93a386Sopenharmony_ci break; 1230cb93a386Sopenharmony_ci case SkPath::kClose_Verb: 1231cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, mv == pts[0]); 1232cb93a386Sopenharmony_ci ++nCL; 1233cb93a386Sopenharmony_ci break; 1234cb93a386Sopenharmony_ci default: 1235cb93a386Sopenharmony_ci break; 1236cb93a386Sopenharmony_ci } 1237cb93a386Sopenharmony_ci } 1238cb93a386Sopenharmony_ci // if we force a close on the interator we should have a close 1239cb93a386Sopenharmony_ci // for every moveTo 1240cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !i || nMT == nCL); 1241cb93a386Sopenharmony_ci } 1242cb93a386Sopenharmony_ci} 1243cb93a386Sopenharmony_ci 1244cb93a386Sopenharmony_cistatic void test_close(skiatest::Reporter* reporter) { 1245cb93a386Sopenharmony_ci SkPath closePt; 1246cb93a386Sopenharmony_ci closePt.moveTo(0, 0); 1247cb93a386Sopenharmony_ci closePt.close(); 1248cb93a386Sopenharmony_ci check_close(reporter, closePt); 1249cb93a386Sopenharmony_ci 1250cb93a386Sopenharmony_ci SkPath openPt; 1251cb93a386Sopenharmony_ci openPt.moveTo(0, 0); 1252cb93a386Sopenharmony_ci check_close(reporter, openPt); 1253cb93a386Sopenharmony_ci 1254cb93a386Sopenharmony_ci SkPath empty; 1255cb93a386Sopenharmony_ci check_close(reporter, empty); 1256cb93a386Sopenharmony_ci empty.close(); 1257cb93a386Sopenharmony_ci check_close(reporter, empty); 1258cb93a386Sopenharmony_ci 1259cb93a386Sopenharmony_ci SkPath rect; 1260cb93a386Sopenharmony_ci rect.addRect(SK_Scalar1, SK_Scalar1, 10 * SK_Scalar1, 10*SK_Scalar1); 1261cb93a386Sopenharmony_ci check_close(reporter, rect); 1262cb93a386Sopenharmony_ci rect.close(); 1263cb93a386Sopenharmony_ci check_close(reporter, rect); 1264cb93a386Sopenharmony_ci 1265cb93a386Sopenharmony_ci SkPath quad; 1266cb93a386Sopenharmony_ci quad.quadTo(SK_Scalar1, SK_Scalar1, 10 * SK_Scalar1, 10*SK_Scalar1); 1267cb93a386Sopenharmony_ci check_close(reporter, quad); 1268cb93a386Sopenharmony_ci quad.close(); 1269cb93a386Sopenharmony_ci check_close(reporter, quad); 1270cb93a386Sopenharmony_ci 1271cb93a386Sopenharmony_ci SkPath cubic; 1272cb93a386Sopenharmony_ci quad.cubicTo(SK_Scalar1, SK_Scalar1, 10 * SK_Scalar1, 1273cb93a386Sopenharmony_ci 10*SK_Scalar1, 20 * SK_Scalar1, 20*SK_Scalar1); 1274cb93a386Sopenharmony_ci check_close(reporter, cubic); 1275cb93a386Sopenharmony_ci cubic.close(); 1276cb93a386Sopenharmony_ci check_close(reporter, cubic); 1277cb93a386Sopenharmony_ci 1278cb93a386Sopenharmony_ci SkPath line; 1279cb93a386Sopenharmony_ci line.moveTo(SK_Scalar1, SK_Scalar1); 1280cb93a386Sopenharmony_ci line.lineTo(10 * SK_Scalar1, 10*SK_Scalar1); 1281cb93a386Sopenharmony_ci check_close(reporter, line); 1282cb93a386Sopenharmony_ci line.close(); 1283cb93a386Sopenharmony_ci check_close(reporter, line); 1284cb93a386Sopenharmony_ci 1285cb93a386Sopenharmony_ci SkPath rect2; 1286cb93a386Sopenharmony_ci rect2.addRect(SK_Scalar1, SK_Scalar1, 10 * SK_Scalar1, 10*SK_Scalar1); 1287cb93a386Sopenharmony_ci rect2.close(); 1288cb93a386Sopenharmony_ci rect2.addRect(SK_Scalar1, SK_Scalar1, 10 * SK_Scalar1, 10*SK_Scalar1); 1289cb93a386Sopenharmony_ci check_close(reporter, rect2); 1290cb93a386Sopenharmony_ci rect2.close(); 1291cb93a386Sopenharmony_ci check_close(reporter, rect2); 1292cb93a386Sopenharmony_ci 1293cb93a386Sopenharmony_ci SkPath oval3; 1294cb93a386Sopenharmony_ci oval3.addOval(SkRect::MakeWH(SK_Scalar1*100,SK_Scalar1*100)); 1295cb93a386Sopenharmony_ci oval3.close(); 1296cb93a386Sopenharmony_ci oval3.addOval(SkRect::MakeWH(SK_Scalar1*200,SK_Scalar1*200)); 1297cb93a386Sopenharmony_ci check_close(reporter, oval3); 1298cb93a386Sopenharmony_ci oval3.close(); 1299cb93a386Sopenharmony_ci check_close(reporter, oval3); 1300cb93a386Sopenharmony_ci 1301cb93a386Sopenharmony_ci SkPath moves; 1302cb93a386Sopenharmony_ci moves.moveTo(SK_Scalar1, SK_Scalar1); 1303cb93a386Sopenharmony_ci moves.moveTo(5 * SK_Scalar1, SK_Scalar1); 1304cb93a386Sopenharmony_ci moves.moveTo(SK_Scalar1, 10 * SK_Scalar1); 1305cb93a386Sopenharmony_ci moves.moveTo(10 *SK_Scalar1, SK_Scalar1); 1306cb93a386Sopenharmony_ci check_close(reporter, moves); 1307cb93a386Sopenharmony_ci 1308cb93a386Sopenharmony_ci stroke_tiny_cubic(); 1309cb93a386Sopenharmony_ci} 1310cb93a386Sopenharmony_ci 1311cb93a386Sopenharmony_cistatic void check_convexity(skiatest::Reporter* reporter, const SkPath& path, 1312cb93a386Sopenharmony_ci bool expectedConvexity) { 1313cb93a386Sopenharmony_ci // We make a copy so that we don't cache the result on the passed in path. 1314cb93a386Sopenharmony_ci SkPath copy(path); // NOLINT(performance-unnecessary-copy-initialization) 1315cb93a386Sopenharmony_ci bool convexity = copy.isConvex(); 1316cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, convexity == expectedConvexity); 1317cb93a386Sopenharmony_ci} 1318cb93a386Sopenharmony_ci 1319cb93a386Sopenharmony_cistatic void test_path_crbug389050(skiatest::Reporter* reporter) { 1320cb93a386Sopenharmony_ci SkPath tinyConvexPolygon; 1321cb93a386Sopenharmony_ci tinyConvexPolygon.moveTo(600.131559f, 800.112512f); 1322cb93a386Sopenharmony_ci tinyConvexPolygon.lineTo(600.161735f, 800.118627f); 1323cb93a386Sopenharmony_ci tinyConvexPolygon.lineTo(600.148962f, 800.142338f); 1324cb93a386Sopenharmony_ci tinyConvexPolygon.lineTo(600.134891f, 800.137724f); 1325cb93a386Sopenharmony_ci tinyConvexPolygon.close(); 1326cb93a386Sopenharmony_ci tinyConvexPolygon.isConvex(); 1327cb93a386Sopenharmony_ci check_direction(reporter, tinyConvexPolygon, SkPathFirstDirection::kCW); 1328cb93a386Sopenharmony_ci 1329cb93a386Sopenharmony_ci SkPath platTriangle; 1330cb93a386Sopenharmony_ci platTriangle.moveTo(0, 0); 1331cb93a386Sopenharmony_ci platTriangle.lineTo(200, 0); 1332cb93a386Sopenharmony_ci platTriangle.lineTo(100, 0.04f); 1333cb93a386Sopenharmony_ci platTriangle.close(); 1334cb93a386Sopenharmony_ci platTriangle.isConvex(); 1335cb93a386Sopenharmony_ci check_direction(reporter, platTriangle, SkPathFirstDirection::kCW); 1336cb93a386Sopenharmony_ci 1337cb93a386Sopenharmony_ci platTriangle.reset(); 1338cb93a386Sopenharmony_ci platTriangle.moveTo(0, 0); 1339cb93a386Sopenharmony_ci platTriangle.lineTo(200, 0); 1340cb93a386Sopenharmony_ci platTriangle.lineTo(100, 0.03f); 1341cb93a386Sopenharmony_ci platTriangle.close(); 1342cb93a386Sopenharmony_ci platTriangle.isConvex(); 1343cb93a386Sopenharmony_ci check_direction(reporter, platTriangle, SkPathFirstDirection::kCW); 1344cb93a386Sopenharmony_ci} 1345cb93a386Sopenharmony_ci 1346cb93a386Sopenharmony_cistatic void test_convexity2(skiatest::Reporter* reporter) { 1347cb93a386Sopenharmony_ci SkPath pt; 1348cb93a386Sopenharmony_ci pt.moveTo(0, 0); 1349cb93a386Sopenharmony_ci pt.close(); 1350cb93a386Sopenharmony_ci check_convexity(reporter, pt, true); 1351cb93a386Sopenharmony_ci check_direction(reporter, pt, SkPathFirstDirection::kUnknown); 1352cb93a386Sopenharmony_ci 1353cb93a386Sopenharmony_ci SkPath line; 1354cb93a386Sopenharmony_ci line.moveTo(12*SK_Scalar1, 20*SK_Scalar1); 1355cb93a386Sopenharmony_ci line.lineTo(-12*SK_Scalar1, -20*SK_Scalar1); 1356cb93a386Sopenharmony_ci line.close(); 1357cb93a386Sopenharmony_ci check_convexity(reporter, line, true); 1358cb93a386Sopenharmony_ci check_direction(reporter, line, SkPathFirstDirection::kUnknown); 1359cb93a386Sopenharmony_ci 1360cb93a386Sopenharmony_ci SkPath triLeft; 1361cb93a386Sopenharmony_ci triLeft.moveTo(0, 0); 1362cb93a386Sopenharmony_ci triLeft.lineTo(SK_Scalar1, 0); 1363cb93a386Sopenharmony_ci triLeft.lineTo(SK_Scalar1, SK_Scalar1); 1364cb93a386Sopenharmony_ci triLeft.close(); 1365cb93a386Sopenharmony_ci check_convexity(reporter, triLeft, true); 1366cb93a386Sopenharmony_ci check_direction(reporter, triLeft, SkPathFirstDirection::kCW); 1367cb93a386Sopenharmony_ci 1368cb93a386Sopenharmony_ci SkPath triRight; 1369cb93a386Sopenharmony_ci triRight.moveTo(0, 0); 1370cb93a386Sopenharmony_ci triRight.lineTo(-SK_Scalar1, 0); 1371cb93a386Sopenharmony_ci triRight.lineTo(SK_Scalar1, SK_Scalar1); 1372cb93a386Sopenharmony_ci triRight.close(); 1373cb93a386Sopenharmony_ci check_convexity(reporter, triRight, true); 1374cb93a386Sopenharmony_ci check_direction(reporter, triRight, SkPathFirstDirection::kCCW); 1375cb93a386Sopenharmony_ci 1376cb93a386Sopenharmony_ci SkPath square; 1377cb93a386Sopenharmony_ci square.moveTo(0, 0); 1378cb93a386Sopenharmony_ci square.lineTo(SK_Scalar1, 0); 1379cb93a386Sopenharmony_ci square.lineTo(SK_Scalar1, SK_Scalar1); 1380cb93a386Sopenharmony_ci square.lineTo(0, SK_Scalar1); 1381cb93a386Sopenharmony_ci square.close(); 1382cb93a386Sopenharmony_ci check_convexity(reporter, square, true); 1383cb93a386Sopenharmony_ci check_direction(reporter, square, SkPathFirstDirection::kCW); 1384cb93a386Sopenharmony_ci 1385cb93a386Sopenharmony_ci SkPath redundantSquare; 1386cb93a386Sopenharmony_ci redundantSquare.moveTo(0, 0); 1387cb93a386Sopenharmony_ci redundantSquare.lineTo(0, 0); 1388cb93a386Sopenharmony_ci redundantSquare.lineTo(0, 0); 1389cb93a386Sopenharmony_ci redundantSquare.lineTo(SK_Scalar1, 0); 1390cb93a386Sopenharmony_ci redundantSquare.lineTo(SK_Scalar1, 0); 1391cb93a386Sopenharmony_ci redundantSquare.lineTo(SK_Scalar1, 0); 1392cb93a386Sopenharmony_ci redundantSquare.lineTo(SK_Scalar1, SK_Scalar1); 1393cb93a386Sopenharmony_ci redundantSquare.lineTo(SK_Scalar1, SK_Scalar1); 1394cb93a386Sopenharmony_ci redundantSquare.lineTo(SK_Scalar1, SK_Scalar1); 1395cb93a386Sopenharmony_ci redundantSquare.lineTo(0, SK_Scalar1); 1396cb93a386Sopenharmony_ci redundantSquare.lineTo(0, SK_Scalar1); 1397cb93a386Sopenharmony_ci redundantSquare.lineTo(0, SK_Scalar1); 1398cb93a386Sopenharmony_ci redundantSquare.close(); 1399cb93a386Sopenharmony_ci check_convexity(reporter, redundantSquare, true); 1400cb93a386Sopenharmony_ci check_direction(reporter, redundantSquare, SkPathFirstDirection::kCW); 1401cb93a386Sopenharmony_ci 1402cb93a386Sopenharmony_ci SkPath bowTie; 1403cb93a386Sopenharmony_ci bowTie.moveTo(0, 0); 1404cb93a386Sopenharmony_ci bowTie.lineTo(0, 0); 1405cb93a386Sopenharmony_ci bowTie.lineTo(0, 0); 1406cb93a386Sopenharmony_ci bowTie.lineTo(SK_Scalar1, SK_Scalar1); 1407cb93a386Sopenharmony_ci bowTie.lineTo(SK_Scalar1, SK_Scalar1); 1408cb93a386Sopenharmony_ci bowTie.lineTo(SK_Scalar1, SK_Scalar1); 1409cb93a386Sopenharmony_ci bowTie.lineTo(SK_Scalar1, 0); 1410cb93a386Sopenharmony_ci bowTie.lineTo(SK_Scalar1, 0); 1411cb93a386Sopenharmony_ci bowTie.lineTo(SK_Scalar1, 0); 1412cb93a386Sopenharmony_ci bowTie.lineTo(0, SK_Scalar1); 1413cb93a386Sopenharmony_ci bowTie.lineTo(0, SK_Scalar1); 1414cb93a386Sopenharmony_ci bowTie.lineTo(0, SK_Scalar1); 1415cb93a386Sopenharmony_ci bowTie.close(); 1416cb93a386Sopenharmony_ci check_convexity(reporter, bowTie, false); 1417cb93a386Sopenharmony_ci check_direction(reporter, bowTie, kDontCheckDir); 1418cb93a386Sopenharmony_ci 1419cb93a386Sopenharmony_ci SkPath spiral; 1420cb93a386Sopenharmony_ci spiral.moveTo(0, 0); 1421cb93a386Sopenharmony_ci spiral.lineTo(100*SK_Scalar1, 0); 1422cb93a386Sopenharmony_ci spiral.lineTo(100*SK_Scalar1, 100*SK_Scalar1); 1423cb93a386Sopenharmony_ci spiral.lineTo(0, 100*SK_Scalar1); 1424cb93a386Sopenharmony_ci spiral.lineTo(0, 50*SK_Scalar1); 1425cb93a386Sopenharmony_ci spiral.lineTo(50*SK_Scalar1, 50*SK_Scalar1); 1426cb93a386Sopenharmony_ci spiral.lineTo(50*SK_Scalar1, 75*SK_Scalar1); 1427cb93a386Sopenharmony_ci spiral.close(); 1428cb93a386Sopenharmony_ci check_convexity(reporter, spiral, false); 1429cb93a386Sopenharmony_ci check_direction(reporter, spiral, kDontCheckDir); 1430cb93a386Sopenharmony_ci 1431cb93a386Sopenharmony_ci SkPath dent; 1432cb93a386Sopenharmony_ci dent.moveTo(0, 0); 1433cb93a386Sopenharmony_ci dent.lineTo(100*SK_Scalar1, 100*SK_Scalar1); 1434cb93a386Sopenharmony_ci dent.lineTo(0, 100*SK_Scalar1); 1435cb93a386Sopenharmony_ci dent.lineTo(-50*SK_Scalar1, 200*SK_Scalar1); 1436cb93a386Sopenharmony_ci dent.lineTo(-200*SK_Scalar1, 100*SK_Scalar1); 1437cb93a386Sopenharmony_ci dent.close(); 1438cb93a386Sopenharmony_ci check_convexity(reporter, dent, false); 1439cb93a386Sopenharmony_ci check_direction(reporter, dent, SkPathFirstDirection::kCW); 1440cb93a386Sopenharmony_ci 1441cb93a386Sopenharmony_ci // https://bug.skia.org/2235 1442cb93a386Sopenharmony_ci SkPath strokedSin; 1443cb93a386Sopenharmony_ci for (int i = 0; i < 2000; i++) { 1444cb93a386Sopenharmony_ci SkScalar x = SkIntToScalar(i) / 2; 1445cb93a386Sopenharmony_ci SkScalar y = 500 - (x + SkScalarSin(x / 100) * 40) / 3; 1446cb93a386Sopenharmony_ci if (0 == i) { 1447cb93a386Sopenharmony_ci strokedSin.moveTo(x, y); 1448cb93a386Sopenharmony_ci } else { 1449cb93a386Sopenharmony_ci strokedSin.lineTo(x, y); 1450cb93a386Sopenharmony_ci } 1451cb93a386Sopenharmony_ci } 1452cb93a386Sopenharmony_ci SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 1453cb93a386Sopenharmony_ci stroke.setStrokeStyle(2 * SK_Scalar1); 1454cb93a386Sopenharmony_ci stroke.applyToPath(&strokedSin, strokedSin); 1455cb93a386Sopenharmony_ci check_convexity(reporter, strokedSin, false); 1456cb93a386Sopenharmony_ci check_direction(reporter, strokedSin, kDontCheckDir); 1457cb93a386Sopenharmony_ci 1458cb93a386Sopenharmony_ci // http://crbug.com/412640 1459cb93a386Sopenharmony_ci SkPath degenerateConcave; 1460cb93a386Sopenharmony_ci degenerateConcave.moveTo(148.67912f, 191.875f); 1461cb93a386Sopenharmony_ci degenerateConcave.lineTo(470.37695f, 7.5f); 1462cb93a386Sopenharmony_ci degenerateConcave.lineTo(148.67912f, 191.875f); 1463cb93a386Sopenharmony_ci degenerateConcave.lineTo(41.446522f, 376.25f); 1464cb93a386Sopenharmony_ci degenerateConcave.lineTo(-55.971577f, 460.0f); 1465cb93a386Sopenharmony_ci degenerateConcave.lineTo(41.446522f, 376.25f); 1466cb93a386Sopenharmony_ci check_convexity(reporter, degenerateConcave, false); 1467cb93a386Sopenharmony_ci check_direction(reporter, degenerateConcave, SkPathFirstDirection::kUnknown); 1468cb93a386Sopenharmony_ci 1469cb93a386Sopenharmony_ci // http://crbug.com/433683 1470cb93a386Sopenharmony_ci SkPath badFirstVector; 1471cb93a386Sopenharmony_ci badFirstVector.moveTo(501.087708f, 319.610352f); 1472cb93a386Sopenharmony_ci badFirstVector.lineTo(501.087708f, 319.610352f); 1473cb93a386Sopenharmony_ci badFirstVector.cubicTo(501.087677f, 319.610321f, 449.271606f, 258.078674f, 395.084564f, 198.711182f); 1474cb93a386Sopenharmony_ci badFirstVector.cubicTo(358.967072f, 159.140717f, 321.910553f, 120.650436f, 298.442322f, 101.955399f); 1475cb93a386Sopenharmony_ci badFirstVector.lineTo(301.557678f, 98.044601f); 1476cb93a386Sopenharmony_ci badFirstVector.cubicTo(325.283844f, 116.945084f, 362.615204f, 155.720825f, 398.777557f, 195.340454f); 1477cb93a386Sopenharmony_ci badFirstVector.cubicTo(453.031860f, 254.781662f, 504.912262f, 316.389618f, 504.912292f, 316.389648f); 1478cb93a386Sopenharmony_ci badFirstVector.lineTo(504.912292f, 316.389648f); 1479cb93a386Sopenharmony_ci badFirstVector.lineTo(501.087708f, 319.610352f); 1480cb93a386Sopenharmony_ci badFirstVector.close(); 1481cb93a386Sopenharmony_ci check_convexity(reporter, badFirstVector, false); 1482cb93a386Sopenharmony_ci 1483cb93a386Sopenharmony_ci // http://crbug.com/993330 1484cb93a386Sopenharmony_ci SkPath falseBackEdge; 1485cb93a386Sopenharmony_ci falseBackEdge.moveTo(-217.83430557928145f, -382.14948768484857f); 1486cb93a386Sopenharmony_ci falseBackEdge.lineTo(-227.73867866614847f, -399.52485512718323f); 1487cb93a386Sopenharmony_ci falseBackEdge.cubicTo(-158.3541047666846f, -439.0757140459542f, 1488cb93a386Sopenharmony_ci -79.8654464485281f, -459.875f, 1489cb93a386Sopenharmony_ci -1.1368683772161603e-13f, -459.875f); 1490cb93a386Sopenharmony_ci falseBackEdge.lineTo(-8.08037266162413e-14f, -439.875f); 1491cb93a386Sopenharmony_ci falseBackEdge.lineTo(-8.526512829121202e-14f, -439.87499999999994f); 1492cb93a386Sopenharmony_ci falseBackEdge.cubicTo(-76.39209188702645f, -439.87499999999994f, 1493cb93a386Sopenharmony_ci -151.46727226799754f, -419.98027663161537f, 1494cb93a386Sopenharmony_ci -217.83430557928145f, -382.14948768484857f); 1495cb93a386Sopenharmony_ci falseBackEdge.close(); 1496cb93a386Sopenharmony_ci check_convexity(reporter, falseBackEdge, false); 1497cb93a386Sopenharmony_ci} 1498cb93a386Sopenharmony_ci 1499cb93a386Sopenharmony_cistatic void test_convexity_doubleback(skiatest::Reporter* reporter) { 1500cb93a386Sopenharmony_ci SkPath doubleback; 1501cb93a386Sopenharmony_ci doubleback.lineTo(1, 1); 1502cb93a386Sopenharmony_ci check_convexity(reporter, doubleback, true); 1503cb93a386Sopenharmony_ci doubleback.lineTo(2, 2); 1504cb93a386Sopenharmony_ci check_convexity(reporter, doubleback, true); 1505cb93a386Sopenharmony_ci doubleback.reset(); 1506cb93a386Sopenharmony_ci doubleback.lineTo(1, 0); 1507cb93a386Sopenharmony_ci check_convexity(reporter, doubleback, true); 1508cb93a386Sopenharmony_ci doubleback.lineTo(2, 0); 1509cb93a386Sopenharmony_ci check_convexity(reporter, doubleback, true); 1510cb93a386Sopenharmony_ci doubleback.lineTo(1, 0); 1511cb93a386Sopenharmony_ci check_convexity(reporter, doubleback, true); 1512cb93a386Sopenharmony_ci doubleback.reset(); 1513cb93a386Sopenharmony_ci doubleback.quadTo(1, 1, 2, 2); 1514cb93a386Sopenharmony_ci check_convexity(reporter, doubleback, true); 1515cb93a386Sopenharmony_ci doubleback.reset(); 1516cb93a386Sopenharmony_ci doubleback.quadTo(1, 0, 2, 0); 1517cb93a386Sopenharmony_ci check_convexity(reporter, doubleback, true); 1518cb93a386Sopenharmony_ci doubleback.quadTo(1, 0, 0, 0); 1519cb93a386Sopenharmony_ci check_convexity(reporter, doubleback, true); 1520cb93a386Sopenharmony_ci} 1521cb93a386Sopenharmony_ci 1522cb93a386Sopenharmony_cistatic void check_convex_bounds(skiatest::Reporter* reporter, const SkPath& p, 1523cb93a386Sopenharmony_ci const SkRect& bounds) { 1524cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.isConvex()); 1525cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.getBounds() == bounds); 1526cb93a386Sopenharmony_ci 1527cb93a386Sopenharmony_ci SkPath p2(p); 1528cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p2.isConvex()); 1529cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p2.getBounds() == bounds); 1530cb93a386Sopenharmony_ci 1531cb93a386Sopenharmony_ci SkPath other; 1532cb93a386Sopenharmony_ci other.swap(p2); 1533cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, other.isConvex()); 1534cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, other.getBounds() == bounds); 1535cb93a386Sopenharmony_ci} 1536cb93a386Sopenharmony_ci 1537cb93a386Sopenharmony_cistatic void setFromString(SkPath* path, const char str[]) { 1538cb93a386Sopenharmony_ci bool first = true; 1539cb93a386Sopenharmony_ci while (str) { 1540cb93a386Sopenharmony_ci SkScalar x, y; 1541cb93a386Sopenharmony_ci str = SkParse::FindScalar(str, &x); 1542cb93a386Sopenharmony_ci if (nullptr == str) { 1543cb93a386Sopenharmony_ci break; 1544cb93a386Sopenharmony_ci } 1545cb93a386Sopenharmony_ci str = SkParse::FindScalar(str, &y); 1546cb93a386Sopenharmony_ci SkASSERT(str); 1547cb93a386Sopenharmony_ci if (first) { 1548cb93a386Sopenharmony_ci path->moveTo(x, y); 1549cb93a386Sopenharmony_ci first = false; 1550cb93a386Sopenharmony_ci } else { 1551cb93a386Sopenharmony_ci path->lineTo(x, y); 1552cb93a386Sopenharmony_ci } 1553cb93a386Sopenharmony_ci } 1554cb93a386Sopenharmony_ci} 1555cb93a386Sopenharmony_ci 1556cb93a386Sopenharmony_cistatic void test_convexity(skiatest::Reporter* reporter) { 1557cb93a386Sopenharmony_ci SkPath path; 1558cb93a386Sopenharmony_ci 1559cb93a386Sopenharmony_ci check_convexity(reporter, path, true); 1560cb93a386Sopenharmony_ci path.addCircle(0, 0, SkIntToScalar(10)); 1561cb93a386Sopenharmony_ci check_convexity(reporter, path, true); 1562cb93a386Sopenharmony_ci path.addCircle(0, 0, SkIntToScalar(10)); // 2nd circle 1563cb93a386Sopenharmony_ci check_convexity(reporter, path, false); 1564cb93a386Sopenharmony_ci 1565cb93a386Sopenharmony_ci path.reset(); 1566cb93a386Sopenharmony_ci path.addRect(0, 0, SkIntToScalar(10), SkIntToScalar(10), SkPathDirection::kCCW); 1567cb93a386Sopenharmony_ci check_convexity(reporter, path, true); 1568cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::ComputeFirstDirection(path) == SkPathFirstDirection::kCCW); 1569cb93a386Sopenharmony_ci 1570cb93a386Sopenharmony_ci path.reset(); 1571cb93a386Sopenharmony_ci path.addRect(0, 0, SkIntToScalar(10), SkIntToScalar(10), SkPathDirection::kCW); 1572cb93a386Sopenharmony_ci check_convexity(reporter, path, true); 1573cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::ComputeFirstDirection(path) == SkPathFirstDirection::kCW); 1574cb93a386Sopenharmony_ci 1575cb93a386Sopenharmony_ci path.reset(); 1576cb93a386Sopenharmony_ci path.quadTo(100, 100, 50, 50); // This from GM:convexpaths 1577cb93a386Sopenharmony_ci check_convexity(reporter, path, true); 1578cb93a386Sopenharmony_ci 1579cb93a386Sopenharmony_ci static const struct { 1580cb93a386Sopenharmony_ci const char* fPathStr; 1581cb93a386Sopenharmony_ci bool fExpectedIsConvex; 1582cb93a386Sopenharmony_ci SkPathFirstDirection fExpectedDirection; 1583cb93a386Sopenharmony_ci } gRec[] = { 1584cb93a386Sopenharmony_ci { "", true, SkPathFirstDirection::kUnknown }, 1585cb93a386Sopenharmony_ci { "0 0", true, SkPathFirstDirection::kUnknown }, 1586cb93a386Sopenharmony_ci { "0 0 10 10", true, SkPathFirstDirection::kUnknown }, 1587cb93a386Sopenharmony_ci { "0 0 10 10 20 20 0 0 10 10", false, SkPathFirstDirection::kUnknown }, 1588cb93a386Sopenharmony_ci { "0 0 10 10 10 20", true, SkPathFirstDirection::kCW }, 1589cb93a386Sopenharmony_ci { "0 0 10 10 10 0", true, SkPathFirstDirection::kCCW }, 1590cb93a386Sopenharmony_ci { "0 0 10 10 10 0 0 10", false, kDontCheckDir }, 1591cb93a386Sopenharmony_ci { "0 0 10 0 0 10 -10 -10", false, SkPathFirstDirection::kCW }, 1592cb93a386Sopenharmony_ci }; 1593cb93a386Sopenharmony_ci 1594cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { 1595cb93a386Sopenharmony_ci path.reset(); 1596cb93a386Sopenharmony_ci setFromString(&path, gRec[i].fPathStr); 1597cb93a386Sopenharmony_ci check_convexity(reporter, path, gRec[i].fExpectedIsConvex); 1598cb93a386Sopenharmony_ci check_direction(reporter, path, gRec[i].fExpectedDirection); 1599cb93a386Sopenharmony_ci // check after setting the initial convex and direction 1600cb93a386Sopenharmony_ci if (kDontCheckDir != gRec[i].fExpectedDirection) { 1601cb93a386Sopenharmony_ci // We make a copy so that we don't cache the result on the passed in path. 1602cb93a386Sopenharmony_ci SkPath copy(path); // NOLINT(performance-unnecessary-copy-initialization) 1603cb93a386Sopenharmony_ci SkPathFirstDirection dir = SkPathPriv::ComputeFirstDirection(copy); 1604cb93a386Sopenharmony_ci bool foundDir = dir != SkPathFirstDirection::kUnknown; 1605cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, (gRec[i].fExpectedDirection == SkPathFirstDirection::kUnknown) 1606cb93a386Sopenharmony_ci ^ foundDir); 1607cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !foundDir || gRec[i].fExpectedDirection == dir); 1608cb93a386Sopenharmony_ci check_convexity(reporter, copy, gRec[i].fExpectedIsConvex); 1609cb93a386Sopenharmony_ci } 1610cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, gRec[i].fExpectedIsConvex == path.isConvex()); 1611cb93a386Sopenharmony_ci check_direction(reporter, path, gRec[i].fExpectedDirection); 1612cb93a386Sopenharmony_ci } 1613cb93a386Sopenharmony_ci 1614cb93a386Sopenharmony_ci static const SkPoint nonFinitePts[] = { 1615cb93a386Sopenharmony_ci { SK_ScalarInfinity, 0 }, 1616cb93a386Sopenharmony_ci { 0, SK_ScalarInfinity }, 1617cb93a386Sopenharmony_ci { SK_ScalarInfinity, SK_ScalarInfinity }, 1618cb93a386Sopenharmony_ci { SK_ScalarNegativeInfinity, 0}, 1619cb93a386Sopenharmony_ci { 0, SK_ScalarNegativeInfinity }, 1620cb93a386Sopenharmony_ci { SK_ScalarNegativeInfinity, SK_ScalarNegativeInfinity }, 1621cb93a386Sopenharmony_ci { SK_ScalarNegativeInfinity, SK_ScalarInfinity }, 1622cb93a386Sopenharmony_ci { SK_ScalarInfinity, SK_ScalarNegativeInfinity }, 1623cb93a386Sopenharmony_ci { SK_ScalarNaN, 0 }, 1624cb93a386Sopenharmony_ci { 0, SK_ScalarNaN }, 1625cb93a386Sopenharmony_ci { SK_ScalarNaN, SK_ScalarNaN }, 1626cb93a386Sopenharmony_ci }; 1627cb93a386Sopenharmony_ci 1628cb93a386Sopenharmony_ci const size_t nonFinitePtsCount = sizeof(nonFinitePts) / sizeof(nonFinitePts[0]); 1629cb93a386Sopenharmony_ci 1630cb93a386Sopenharmony_ci static const SkPoint axisAlignedPts[] = { 1631cb93a386Sopenharmony_ci { SK_ScalarMax, 0 }, 1632cb93a386Sopenharmony_ci { 0, SK_ScalarMax }, 1633cb93a386Sopenharmony_ci { SK_ScalarMin, 0 }, 1634cb93a386Sopenharmony_ci { 0, SK_ScalarMin }, 1635cb93a386Sopenharmony_ci }; 1636cb93a386Sopenharmony_ci 1637cb93a386Sopenharmony_ci const size_t axisAlignedPtsCount = sizeof(axisAlignedPts) / sizeof(axisAlignedPts[0]); 1638cb93a386Sopenharmony_ci 1639cb93a386Sopenharmony_ci for (int index = 0; index < (int) (13 * nonFinitePtsCount * axisAlignedPtsCount); ++index) { 1640cb93a386Sopenharmony_ci int i = (int) (index % nonFinitePtsCount); 1641cb93a386Sopenharmony_ci int f = (int) (index % axisAlignedPtsCount); 1642cb93a386Sopenharmony_ci int g = (int) ((f + 1) % axisAlignedPtsCount); 1643cb93a386Sopenharmony_ci path.reset(); 1644cb93a386Sopenharmony_ci switch (index % 13) { 1645cb93a386Sopenharmony_ci case 0: path.lineTo(nonFinitePts[i]); break; 1646cb93a386Sopenharmony_ci case 1: path.quadTo(nonFinitePts[i], nonFinitePts[i]); break; 1647cb93a386Sopenharmony_ci case 2: path.quadTo(nonFinitePts[i], axisAlignedPts[f]); break; 1648cb93a386Sopenharmony_ci case 3: path.quadTo(axisAlignedPts[f], nonFinitePts[i]); break; 1649cb93a386Sopenharmony_ci case 4: path.cubicTo(nonFinitePts[i], axisAlignedPts[f], axisAlignedPts[f]); break; 1650cb93a386Sopenharmony_ci case 5: path.cubicTo(axisAlignedPts[f], nonFinitePts[i], axisAlignedPts[f]); break; 1651cb93a386Sopenharmony_ci case 6: path.cubicTo(axisAlignedPts[f], axisAlignedPts[f], nonFinitePts[i]); break; 1652cb93a386Sopenharmony_ci case 7: path.cubicTo(nonFinitePts[i], nonFinitePts[i], axisAlignedPts[f]); break; 1653cb93a386Sopenharmony_ci case 8: path.cubicTo(nonFinitePts[i], axisAlignedPts[f], nonFinitePts[i]); break; 1654cb93a386Sopenharmony_ci case 9: path.cubicTo(axisAlignedPts[f], nonFinitePts[i], nonFinitePts[i]); break; 1655cb93a386Sopenharmony_ci case 10: path.cubicTo(nonFinitePts[i], nonFinitePts[i], nonFinitePts[i]); break; 1656cb93a386Sopenharmony_ci case 11: path.cubicTo(nonFinitePts[i], axisAlignedPts[f], axisAlignedPts[g]); break; 1657cb93a386Sopenharmony_ci case 12: path.moveTo(nonFinitePts[i]); break; 1658cb93a386Sopenharmony_ci } 1659cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 1660cb93a386Sopenharmony_ci SkPathPriv::GetConvexityOrUnknown(path) == SkPathConvexity::kUnknown); 1661cb93a386Sopenharmony_ci } 1662cb93a386Sopenharmony_ci 1663cb93a386Sopenharmony_ci for (int index = 0; index < (int) (11 * axisAlignedPtsCount); ++index) { 1664cb93a386Sopenharmony_ci int f = (int) (index % axisAlignedPtsCount); 1665cb93a386Sopenharmony_ci int g = (int) ((f + 1) % axisAlignedPtsCount); 1666cb93a386Sopenharmony_ci path.reset(); 1667cb93a386Sopenharmony_ci int curveSelect = index % 11; 1668cb93a386Sopenharmony_ci switch (curveSelect) { 1669cb93a386Sopenharmony_ci case 0: path.moveTo(axisAlignedPts[f]); break; 1670cb93a386Sopenharmony_ci case 1: path.lineTo(axisAlignedPts[f]); break; 1671cb93a386Sopenharmony_ci case 2: path.quadTo(axisAlignedPts[f], axisAlignedPts[f]); break; 1672cb93a386Sopenharmony_ci case 3: path.quadTo(axisAlignedPts[f], axisAlignedPts[g]); break; 1673cb93a386Sopenharmony_ci case 4: path.quadTo(axisAlignedPts[g], axisAlignedPts[f]); break; 1674cb93a386Sopenharmony_ci case 5: path.cubicTo(axisAlignedPts[f], axisAlignedPts[f], axisAlignedPts[f]); break; 1675cb93a386Sopenharmony_ci case 6: path.cubicTo(axisAlignedPts[f], axisAlignedPts[f], axisAlignedPts[g]); break; 1676cb93a386Sopenharmony_ci case 7: path.cubicTo(axisAlignedPts[f], axisAlignedPts[g], axisAlignedPts[f]); break; 1677cb93a386Sopenharmony_ci case 8: path.cubicTo(axisAlignedPts[f], axisAlignedPts[g], axisAlignedPts[g]); break; 1678cb93a386Sopenharmony_ci case 9: path.cubicTo(axisAlignedPts[g], axisAlignedPts[f], axisAlignedPts[f]); break; 1679cb93a386Sopenharmony_ci case 10: path.cubicTo(axisAlignedPts[g], axisAlignedPts[f], axisAlignedPts[g]); break; 1680cb93a386Sopenharmony_ci } 1681cb93a386Sopenharmony_ci if (curveSelect == 0 || curveSelect == 1 || curveSelect == 2 || curveSelect == 5) { 1682cb93a386Sopenharmony_ci check_convexity(reporter, path, true); 1683cb93a386Sopenharmony_ci } else { 1684cb93a386Sopenharmony_ci // We make a copy so that we don't cache the result on the passed in path. 1685cb93a386Sopenharmony_ci SkPath copy(path); // NOLINT(performance-unnecessary-copy-initialization) 1686cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !copy.isConvex()); 1687cb93a386Sopenharmony_ci } 1688cb93a386Sopenharmony_ci } 1689cb93a386Sopenharmony_ci 1690cb93a386Sopenharmony_ci static const SkPoint diagonalPts[] = { 1691cb93a386Sopenharmony_ci { SK_ScalarMax, SK_ScalarMax }, 1692cb93a386Sopenharmony_ci { SK_ScalarMin, SK_ScalarMin }, 1693cb93a386Sopenharmony_ci }; 1694cb93a386Sopenharmony_ci 1695cb93a386Sopenharmony_ci const size_t diagonalPtsCount = sizeof(diagonalPts) / sizeof(diagonalPts[0]); 1696cb93a386Sopenharmony_ci 1697cb93a386Sopenharmony_ci for (int index = 0; index < (int) (7 * diagonalPtsCount); ++index) { 1698cb93a386Sopenharmony_ci int f = (int) (index % diagonalPtsCount); 1699cb93a386Sopenharmony_ci int g = (int) ((f + 1) % diagonalPtsCount); 1700cb93a386Sopenharmony_ci path.reset(); 1701cb93a386Sopenharmony_ci int curveSelect = index % 11; 1702cb93a386Sopenharmony_ci switch (curveSelect) { 1703cb93a386Sopenharmony_ci case 0: path.moveTo(diagonalPts[f]); break; 1704cb93a386Sopenharmony_ci case 1: path.lineTo(diagonalPts[f]); break; 1705cb93a386Sopenharmony_ci case 2: path.quadTo(diagonalPts[f], diagonalPts[f]); break; 1706cb93a386Sopenharmony_ci case 3: path.quadTo(axisAlignedPts[f], diagonalPts[g]); break; 1707cb93a386Sopenharmony_ci case 4: path.quadTo(diagonalPts[g], axisAlignedPts[f]); break; 1708cb93a386Sopenharmony_ci case 5: path.cubicTo(diagonalPts[f], diagonalPts[f], diagonalPts[f]); break; 1709cb93a386Sopenharmony_ci case 6: path.cubicTo(diagonalPts[f], diagonalPts[f], axisAlignedPts[g]); break; 1710cb93a386Sopenharmony_ci case 7: path.cubicTo(diagonalPts[f], axisAlignedPts[g], diagonalPts[f]); break; 1711cb93a386Sopenharmony_ci case 8: path.cubicTo(axisAlignedPts[f], diagonalPts[g], diagonalPts[g]); break; 1712cb93a386Sopenharmony_ci case 9: path.cubicTo(diagonalPts[g], diagonalPts[f], axisAlignedPts[f]); break; 1713cb93a386Sopenharmony_ci case 10: path.cubicTo(diagonalPts[g], axisAlignedPts[f], diagonalPts[g]); break; 1714cb93a386Sopenharmony_ci } 1715cb93a386Sopenharmony_ci if (curveSelect == 0) { 1716cb93a386Sopenharmony_ci check_convexity(reporter, path, true); 1717cb93a386Sopenharmony_ci } else { 1718cb93a386Sopenharmony_ci // We make a copy so that we don't cache the result on the passed in path. 1719cb93a386Sopenharmony_ci SkPath copy(path); // NOLINT(performance-unnecessary-copy-initialization) 1720cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !copy.isConvex()); 1721cb93a386Sopenharmony_ci } 1722cb93a386Sopenharmony_ci } 1723cb93a386Sopenharmony_ci 1724cb93a386Sopenharmony_ci 1725cb93a386Sopenharmony_ci path.reset(); 1726cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0xbe9171db), SkBits2Float(0xbd7eeb5d)); // -0.284072f, -0.0622362f 1727cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xbe9171db), SkBits2Float(0xbd7eea38)); // -0.284072f, -0.0622351f 1728cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xbe9171a0), SkBits2Float(0xbd7ee5a7)); // -0.28407f, -0.0622307f 1729cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xbe917147), SkBits2Float(0xbd7ed886)); // -0.284067f, -0.0622182f 1730cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xbe917378), SkBits2Float(0xbd7ee1a9)); // -0.284084f, -0.0622269f 1731cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xbe9171db), SkBits2Float(0xbd7eeb5d)); // -0.284072f, -0.0622362f 1732cb93a386Sopenharmony_ci path.close(); 1733cb93a386Sopenharmony_ci check_convexity(reporter, path, false); 1734cb93a386Sopenharmony_ci 1735cb93a386Sopenharmony_ci} 1736cb93a386Sopenharmony_ci 1737cb93a386Sopenharmony_cistatic void test_isLine(skiatest::Reporter* reporter) { 1738cb93a386Sopenharmony_ci SkPath path; 1739cb93a386Sopenharmony_ci SkPoint pts[2]; 1740cb93a386Sopenharmony_ci const SkScalar value = SkIntToScalar(5); 1741cb93a386Sopenharmony_ci 1742cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isLine(nullptr)); 1743cb93a386Sopenharmony_ci 1744cb93a386Sopenharmony_ci // set some non-zero values 1745cb93a386Sopenharmony_ci pts[0].set(value, value); 1746cb93a386Sopenharmony_ci pts[1].set(value, value); 1747cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isLine(pts)); 1748cb93a386Sopenharmony_ci // check that pts was untouched 1749cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].equals(value, value)); 1750cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[1].equals(value, value)); 1751cb93a386Sopenharmony_ci 1752cb93a386Sopenharmony_ci const SkScalar moveX = SkIntToScalar(1); 1753cb93a386Sopenharmony_ci const SkScalar moveY = SkIntToScalar(2); 1754cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, value != moveX && value != moveY); 1755cb93a386Sopenharmony_ci 1756cb93a386Sopenharmony_ci path.moveTo(moveX, moveY); 1757cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isLine(nullptr)); 1758cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isLine(pts)); 1759cb93a386Sopenharmony_ci // check that pts was untouched 1760cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].equals(value, value)); 1761cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[1].equals(value, value)); 1762cb93a386Sopenharmony_ci 1763cb93a386Sopenharmony_ci const SkScalar lineX = SkIntToScalar(2); 1764cb93a386Sopenharmony_ci const SkScalar lineY = SkIntToScalar(2); 1765cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, value != lineX && value != lineY); 1766cb93a386Sopenharmony_ci 1767cb93a386Sopenharmony_ci path.lineTo(lineX, lineY); 1768cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isLine(nullptr)); 1769cb93a386Sopenharmony_ci 1770cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !pts[0].equals(moveX, moveY)); 1771cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !pts[1].equals(lineX, lineY)); 1772cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isLine(pts)); 1773cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].equals(moveX, moveY)); 1774cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[1].equals(lineX, lineY)); 1775cb93a386Sopenharmony_ci 1776cb93a386Sopenharmony_ci path.lineTo(0, 0); // too many points/verbs 1777cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isLine(nullptr)); 1778cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isLine(pts)); 1779cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].equals(moveX, moveY)); 1780cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[1].equals(lineX, lineY)); 1781cb93a386Sopenharmony_ci 1782cb93a386Sopenharmony_ci path.reset(); 1783cb93a386Sopenharmony_ci path.quadTo(1, 1, 2, 2); 1784cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isLine(nullptr)); 1785cb93a386Sopenharmony_ci} 1786cb93a386Sopenharmony_ci 1787cb93a386Sopenharmony_cistatic void test_conservativelyContains(skiatest::Reporter* reporter) { 1788cb93a386Sopenharmony_ci SkPath path; 1789cb93a386Sopenharmony_ci 1790cb93a386Sopenharmony_ci // kBaseRect is used to construct most our test paths: a rect, a circle, and a round-rect. 1791cb93a386Sopenharmony_ci static const SkRect kBaseRect = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(100)); 1792cb93a386Sopenharmony_ci 1793cb93a386Sopenharmony_ci // A circle that bounds kBaseRect (with a significant amount of slop) 1794cb93a386Sopenharmony_ci SkScalar circleR = std::max(kBaseRect.width(), kBaseRect.height()); 1795cb93a386Sopenharmony_ci circleR *= 1.75f / 2; 1796cb93a386Sopenharmony_ci static const SkPoint kCircleC = {kBaseRect.centerX(), kBaseRect.centerY()}; 1797cb93a386Sopenharmony_ci 1798cb93a386Sopenharmony_ci // round-rect radii 1799cb93a386Sopenharmony_ci static const SkScalar kRRRadii[] = {SkIntToScalar(5), SkIntToScalar(3)}; 1800cb93a386Sopenharmony_ci 1801cb93a386Sopenharmony_ci static const struct SUPPRESS_VISIBILITY_WARNING { 1802cb93a386Sopenharmony_ci SkRect fQueryRect; 1803cb93a386Sopenharmony_ci bool fInRect; 1804cb93a386Sopenharmony_ci bool fInCircle; 1805cb93a386Sopenharmony_ci bool fInRR; 1806cb93a386Sopenharmony_ci bool fInCubicRR; 1807cb93a386Sopenharmony_ci } kQueries[] = { 1808cb93a386Sopenharmony_ci {kBaseRect, true, true, false, false}, 1809cb93a386Sopenharmony_ci 1810cb93a386Sopenharmony_ci // rect well inside of kBaseRect 1811cb93a386Sopenharmony_ci {SkRect::MakeLTRB(kBaseRect.fLeft + 0.25f*kBaseRect.width(), 1812cb93a386Sopenharmony_ci kBaseRect.fTop + 0.25f*kBaseRect.height(), 1813cb93a386Sopenharmony_ci kBaseRect.fRight - 0.25f*kBaseRect.width(), 1814cb93a386Sopenharmony_ci kBaseRect.fBottom - 0.25f*kBaseRect.height()), 1815cb93a386Sopenharmony_ci true, true, true, true}, 1816cb93a386Sopenharmony_ci 1817cb93a386Sopenharmony_ci // rects with edges off by one from kBaseRect's edges 1818cb93a386Sopenharmony_ci {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fTop, 1819cb93a386Sopenharmony_ci kBaseRect.width(), kBaseRect.height() + 1), 1820cb93a386Sopenharmony_ci false, true, false, false}, 1821cb93a386Sopenharmony_ci {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fTop, 1822cb93a386Sopenharmony_ci kBaseRect.width() + 1, kBaseRect.height()), 1823cb93a386Sopenharmony_ci false, true, false, false}, 1824cb93a386Sopenharmony_ci {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fTop, 1825cb93a386Sopenharmony_ci kBaseRect.width() + 1, kBaseRect.height() + 1), 1826cb93a386Sopenharmony_ci false, true, false, false}, 1827cb93a386Sopenharmony_ci {SkRect::MakeXYWH(kBaseRect.fLeft - 1, kBaseRect.fTop, 1828cb93a386Sopenharmony_ci kBaseRect.width(), kBaseRect.height()), 1829cb93a386Sopenharmony_ci false, true, false, false}, 1830cb93a386Sopenharmony_ci {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fTop - 1, 1831cb93a386Sopenharmony_ci kBaseRect.width(), kBaseRect.height()), 1832cb93a386Sopenharmony_ci false, true, false, false}, 1833cb93a386Sopenharmony_ci {SkRect::MakeXYWH(kBaseRect.fLeft - 1, kBaseRect.fTop, 1834cb93a386Sopenharmony_ci kBaseRect.width() + 2, kBaseRect.height()), 1835cb93a386Sopenharmony_ci false, true, false, false}, 1836cb93a386Sopenharmony_ci {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fTop - 1, 1837cb93a386Sopenharmony_ci kBaseRect.width() + 2, kBaseRect.height()), 1838cb93a386Sopenharmony_ci false, true, false, false}, 1839cb93a386Sopenharmony_ci 1840cb93a386Sopenharmony_ci // zero-w/h rects at each corner of kBaseRect 1841cb93a386Sopenharmony_ci {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fTop, 0, 0), true, true, false, false}, 1842cb93a386Sopenharmony_ci {SkRect::MakeXYWH(kBaseRect.fRight, kBaseRect.fTop, 0, 0), true, true, false, true}, 1843cb93a386Sopenharmony_ci {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fBottom, 0, 0), true, true, false, true}, 1844cb93a386Sopenharmony_ci {SkRect::MakeXYWH(kBaseRect.fRight, kBaseRect.fBottom, 0, 0), true, true, false, true}, 1845cb93a386Sopenharmony_ci 1846cb93a386Sopenharmony_ci // far away rect 1847cb93a386Sopenharmony_ci {SkRect::MakeXYWH(10 * kBaseRect.fRight, 10 * kBaseRect.fBottom, 1848cb93a386Sopenharmony_ci SkIntToScalar(10), SkIntToScalar(10)), 1849cb93a386Sopenharmony_ci false, false, false, false}, 1850cb93a386Sopenharmony_ci 1851cb93a386Sopenharmony_ci // very large rect containing kBaseRect 1852cb93a386Sopenharmony_ci {SkRect::MakeXYWH(kBaseRect.fLeft - 5 * kBaseRect.width(), 1853cb93a386Sopenharmony_ci kBaseRect.fTop - 5 * kBaseRect.height(), 1854cb93a386Sopenharmony_ci 11 * kBaseRect.width(), 11 * kBaseRect.height()), 1855cb93a386Sopenharmony_ci false, false, false, false}, 1856cb93a386Sopenharmony_ci 1857cb93a386Sopenharmony_ci // skinny rect that spans same y-range as kBaseRect 1858cb93a386Sopenharmony_ci {SkRect::MakeXYWH(kBaseRect.centerX(), kBaseRect.fTop, 1859cb93a386Sopenharmony_ci SkIntToScalar(1), kBaseRect.height()), 1860cb93a386Sopenharmony_ci true, true, true, true}, 1861cb93a386Sopenharmony_ci 1862cb93a386Sopenharmony_ci // short rect that spans same x-range as kBaseRect 1863cb93a386Sopenharmony_ci {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.centerY(), kBaseRect.width(), SkScalar(1)), 1864cb93a386Sopenharmony_ci true, true, true, true}, 1865cb93a386Sopenharmony_ci 1866cb93a386Sopenharmony_ci // skinny rect that spans slightly larger y-range than kBaseRect 1867cb93a386Sopenharmony_ci {SkRect::MakeXYWH(kBaseRect.centerX(), kBaseRect.fTop, 1868cb93a386Sopenharmony_ci SkIntToScalar(1), kBaseRect.height() + 1), 1869cb93a386Sopenharmony_ci false, true, false, false}, 1870cb93a386Sopenharmony_ci 1871cb93a386Sopenharmony_ci // short rect that spans slightly larger x-range than kBaseRect 1872cb93a386Sopenharmony_ci {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.centerY(), 1873cb93a386Sopenharmony_ci kBaseRect.width() + 1, SkScalar(1)), 1874cb93a386Sopenharmony_ci false, true, false, false}, 1875cb93a386Sopenharmony_ci }; 1876cb93a386Sopenharmony_ci 1877cb93a386Sopenharmony_ci for (int inv = 0; inv < 4; ++inv) { 1878cb93a386Sopenharmony_ci for (size_t q = 0; q < SK_ARRAY_COUNT(kQueries); ++q) { 1879cb93a386Sopenharmony_ci SkRect qRect = kQueries[q].fQueryRect; 1880cb93a386Sopenharmony_ci if (inv & 0x1) { 1881cb93a386Sopenharmony_ci using std::swap; 1882cb93a386Sopenharmony_ci swap(qRect.fLeft, qRect.fRight); 1883cb93a386Sopenharmony_ci } 1884cb93a386Sopenharmony_ci if (inv & 0x2) { 1885cb93a386Sopenharmony_ci using std::swap; 1886cb93a386Sopenharmony_ci swap(qRect.fTop, qRect.fBottom); 1887cb93a386Sopenharmony_ci } 1888cb93a386Sopenharmony_ci for (int d = 0; d < 2; ++d) { 1889cb93a386Sopenharmony_ci SkPathDirection dir = d ? SkPathDirection::kCCW : SkPathDirection::kCW; 1890cb93a386Sopenharmony_ci path.reset(); 1891cb93a386Sopenharmony_ci path.addRect(kBaseRect, dir); 1892cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, kQueries[q].fInRect == 1893cb93a386Sopenharmony_ci path.conservativelyContainsRect(qRect)); 1894cb93a386Sopenharmony_ci 1895cb93a386Sopenharmony_ci path.reset(); 1896cb93a386Sopenharmony_ci path.addCircle(kCircleC.fX, kCircleC.fY, circleR, dir); 1897cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, kQueries[q].fInCircle == 1898cb93a386Sopenharmony_ci path.conservativelyContainsRect(qRect)); 1899cb93a386Sopenharmony_ci 1900cb93a386Sopenharmony_ci path.reset(); 1901cb93a386Sopenharmony_ci path.addRoundRect(kBaseRect, kRRRadii[0], kRRRadii[1], dir); 1902cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, kQueries[q].fInRR == 1903cb93a386Sopenharmony_ci path.conservativelyContainsRect(qRect)); 1904cb93a386Sopenharmony_ci 1905cb93a386Sopenharmony_ci path.reset(); 1906cb93a386Sopenharmony_ci path.moveTo(kBaseRect.fLeft + kRRRadii[0], kBaseRect.fTop); 1907cb93a386Sopenharmony_ci path.cubicTo(kBaseRect.fLeft + kRRRadii[0] / 2, kBaseRect.fTop, 1908cb93a386Sopenharmony_ci kBaseRect.fLeft, kBaseRect.fTop + kRRRadii[1] / 2, 1909cb93a386Sopenharmony_ci kBaseRect.fLeft, kBaseRect.fTop + kRRRadii[1]); 1910cb93a386Sopenharmony_ci path.lineTo(kBaseRect.fLeft, kBaseRect.fBottom); 1911cb93a386Sopenharmony_ci path.lineTo(kBaseRect.fRight, kBaseRect.fBottom); 1912cb93a386Sopenharmony_ci path.lineTo(kBaseRect.fRight, kBaseRect.fTop); 1913cb93a386Sopenharmony_ci path.close(); 1914cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, kQueries[q].fInCubicRR == 1915cb93a386Sopenharmony_ci path.conservativelyContainsRect(qRect)); 1916cb93a386Sopenharmony_ci 1917cb93a386Sopenharmony_ci } 1918cb93a386Sopenharmony_ci // Slightly non-convex shape, shouldn't contain any rects. 1919cb93a386Sopenharmony_ci path.reset(); 1920cb93a386Sopenharmony_ci path.moveTo(0, 0); 1921cb93a386Sopenharmony_ci path.lineTo(SkIntToScalar(50), 0.05f); 1922cb93a386Sopenharmony_ci path.lineTo(SkIntToScalar(100), 0); 1923cb93a386Sopenharmony_ci path.lineTo(SkIntToScalar(100), SkIntToScalar(100)); 1924cb93a386Sopenharmony_ci path.lineTo(0, SkIntToScalar(100)); 1925cb93a386Sopenharmony_ci path.close(); 1926cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(qRect)); 1927cb93a386Sopenharmony_ci } 1928cb93a386Sopenharmony_ci } 1929cb93a386Sopenharmony_ci 1930cb93a386Sopenharmony_ci // make sure a minimal convex shape works, a right tri with edges along pos x and y axes. 1931cb93a386Sopenharmony_ci path.reset(); 1932cb93a386Sopenharmony_ci path.moveTo(0, 0); 1933cb93a386Sopenharmony_ci path.lineTo(SkIntToScalar(100), 0); 1934cb93a386Sopenharmony_ci path.lineTo(0, SkIntToScalar(100)); 1935cb93a386Sopenharmony_ci 1936cb93a386Sopenharmony_ci // inside, on along top edge 1937cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.conservativelyContainsRect(SkRect::MakeXYWH(SkIntToScalar(50), 0, 1938cb93a386Sopenharmony_ci SkIntToScalar(10), 1939cb93a386Sopenharmony_ci SkIntToScalar(10)))); 1940cb93a386Sopenharmony_ci // above 1941cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.conservativelyContainsRect( 1942cb93a386Sopenharmony_ci SkRect::MakeXYWH(SkIntToScalar(50), 1943cb93a386Sopenharmony_ci SkIntToScalar(-10), 1944cb93a386Sopenharmony_ci SkIntToScalar(10), 1945cb93a386Sopenharmony_ci SkIntToScalar(10)))); 1946cb93a386Sopenharmony_ci // to the left 1947cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeXYWH(SkIntToScalar(-10), 1948cb93a386Sopenharmony_ci SkIntToScalar(5), 1949cb93a386Sopenharmony_ci SkIntToScalar(5), 1950cb93a386Sopenharmony_ci SkIntToScalar(5)))); 1951cb93a386Sopenharmony_ci 1952cb93a386Sopenharmony_ci // outside the diagonal edge 1953cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeXYWH(SkIntToScalar(10), 1954cb93a386Sopenharmony_ci SkIntToScalar(200), 1955cb93a386Sopenharmony_ci SkIntToScalar(20), 1956cb93a386Sopenharmony_ci SkIntToScalar(5)))); 1957cb93a386Sopenharmony_ci 1958cb93a386Sopenharmony_ci 1959cb93a386Sopenharmony_ci // Test that multiple move commands do not cause asserts. 1960cb93a386Sopenharmony_ci path.moveTo(SkIntToScalar(100), SkIntToScalar(100)); 1961cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.conservativelyContainsRect(SkRect::MakeXYWH(SkIntToScalar(50), 0, 1962cb93a386Sopenharmony_ci SkIntToScalar(10), 1963cb93a386Sopenharmony_ci SkIntToScalar(10)))); 1964cb93a386Sopenharmony_ci 1965cb93a386Sopenharmony_ci // Same as above path and first test but with an extra moveTo. 1966cb93a386Sopenharmony_ci path.reset(); 1967cb93a386Sopenharmony_ci path.moveTo(100, 100); 1968cb93a386Sopenharmony_ci path.moveTo(0, 0); 1969cb93a386Sopenharmony_ci path.lineTo(SkIntToScalar(100), 0); 1970cb93a386Sopenharmony_ci path.lineTo(0, SkIntToScalar(100)); 1971cb93a386Sopenharmony_ci // Convexity logic treats a path as filled and closed, so that multiple (non-trailing) moveTos 1972cb93a386Sopenharmony_ci // have no effect on convexity 1973cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.conservativelyContainsRect( 1974cb93a386Sopenharmony_ci SkRect::MakeXYWH(SkIntToScalar(50), 0, 1975cb93a386Sopenharmony_ci SkIntToScalar(10), 1976cb93a386Sopenharmony_ci SkIntToScalar(10)))); 1977cb93a386Sopenharmony_ci 1978cb93a386Sopenharmony_ci // Same as above path and first test but with the extra moveTo making a degenerate sub-path 1979cb93a386Sopenharmony_ci // following the non-empty sub-path. Verifies that this does not trigger assertions. 1980cb93a386Sopenharmony_ci path.reset(); 1981cb93a386Sopenharmony_ci path.moveTo(0, 0); 1982cb93a386Sopenharmony_ci path.lineTo(SkIntToScalar(100), 0); 1983cb93a386Sopenharmony_ci path.lineTo(0, SkIntToScalar(100)); 1984cb93a386Sopenharmony_ci path.moveTo(100, 100); 1985cb93a386Sopenharmony_ci 1986cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.conservativelyContainsRect(SkRect::MakeXYWH(SkIntToScalar(50), 0, 1987cb93a386Sopenharmony_ci SkIntToScalar(10), 1988cb93a386Sopenharmony_ci SkIntToScalar(10)))); 1989cb93a386Sopenharmony_ci 1990cb93a386Sopenharmony_ci // Test that multiple move commands do not cause asserts and that the function 1991cb93a386Sopenharmony_ci // is not confused by the multiple moves. 1992cb93a386Sopenharmony_ci path.reset(); 1993cb93a386Sopenharmony_ci path.moveTo(0, 0); 1994cb93a386Sopenharmony_ci path.lineTo(SkIntToScalar(100), 0); 1995cb93a386Sopenharmony_ci path.lineTo(0, SkIntToScalar(100)); 1996cb93a386Sopenharmony_ci path.moveTo(0, SkIntToScalar(200)); 1997cb93a386Sopenharmony_ci path.lineTo(SkIntToScalar(100), SkIntToScalar(200)); 1998cb93a386Sopenharmony_ci path.lineTo(0, SkIntToScalar(300)); 1999cb93a386Sopenharmony_ci 2000cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.conservativelyContainsRect( 2001cb93a386Sopenharmony_ci SkRect::MakeXYWH(SkIntToScalar(50), 0, 2002cb93a386Sopenharmony_ci SkIntToScalar(10), 2003cb93a386Sopenharmony_ci SkIntToScalar(10)))); 2004cb93a386Sopenharmony_ci 2005cb93a386Sopenharmony_ci path.reset(); 2006cb93a386Sopenharmony_ci path.lineTo(100, 100); 2007cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeXYWH(0, 0, 1, 1))); 2008cb93a386Sopenharmony_ci 2009cb93a386Sopenharmony_ci // An empty path should not contain any rectangle. It's questionable whether an empty path 2010cb93a386Sopenharmony_ci // contains an empty rectangle. However, since it is a conservative test it is ok to 2011cb93a386Sopenharmony_ci // return false. 2012cb93a386Sopenharmony_ci path.reset(); 2013cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeWH(1,1))); 2014cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeWH(0,0))); 2015cb93a386Sopenharmony_ci} 2016cb93a386Sopenharmony_ci 2017cb93a386Sopenharmony_cistatic void test_isRect_open_close(skiatest::Reporter* reporter) { 2018cb93a386Sopenharmony_ci SkPath path; 2019cb93a386Sopenharmony_ci bool isClosed; 2020cb93a386Sopenharmony_ci 2021cb93a386Sopenharmony_ci path.moveTo(0, 0); path.lineTo(1, 0); path.lineTo(1, 1); path.lineTo(0, 1); 2022cb93a386Sopenharmony_ci path.close(); 2023cb93a386Sopenharmony_ci 2024cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isRect(nullptr, &isClosed, nullptr)); 2025cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, isClosed); 2026cb93a386Sopenharmony_ci} 2027cb93a386Sopenharmony_ci 2028cb93a386Sopenharmony_ci// Simple isRect test is inline TestPath, below. 2029cb93a386Sopenharmony_ci// test_isRect provides more extensive testing. 2030cb93a386Sopenharmony_cistatic void test_isRect(skiatest::Reporter* reporter) { 2031cb93a386Sopenharmony_ci test_isRect_open_close(reporter); 2032cb93a386Sopenharmony_ci 2033cb93a386Sopenharmony_ci // passing tests (all moveTo / lineTo... 2034cb93a386Sopenharmony_ci SkPoint r1[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; 2035cb93a386Sopenharmony_ci SkPoint r2[] = {{1, 0}, {1, 1}, {0, 1}, {0, 0}}; 2036cb93a386Sopenharmony_ci SkPoint r3[] = {{1, 1}, {0, 1}, {0, 0}, {1, 0}}; 2037cb93a386Sopenharmony_ci SkPoint r4[] = {{0, 1}, {0, 0}, {1, 0}, {1, 1}}; 2038cb93a386Sopenharmony_ci SkPoint r5[] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}}; 2039cb93a386Sopenharmony_ci SkPoint r6[] = {{0, 1}, {1, 1}, {1, 0}, {0, 0}}; 2040cb93a386Sopenharmony_ci SkPoint r7[] = {{1, 1}, {1, 0}, {0, 0}, {0, 1}}; 2041cb93a386Sopenharmony_ci SkPoint r8[] = {{1, 0}, {0, 0}, {0, 1}, {1, 1}}; 2042cb93a386Sopenharmony_ci SkPoint r9[] = {{0, 1}, {1, 1}, {1, 0}, {0, 0}}; 2043cb93a386Sopenharmony_ci SkPoint ra[] = {{0, 0}, {0, .5f}, {0, 1}, {.5f, 1}, {1, 1}, {1, .5f}, {1, 0}, {.5f, 0}}; 2044cb93a386Sopenharmony_ci SkPoint rb[] = {{0, 0}, {.5f, 0}, {1, 0}, {1, .5f}, {1, 1}, {.5f, 1}, {0, 1}, {0, .5f}}; 2045cb93a386Sopenharmony_ci SkPoint rc[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}}; 2046cb93a386Sopenharmony_ci SkPoint rd[] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}}; 2047cb93a386Sopenharmony_ci SkPoint re[] = {{0, 0}, {1, 0}, {1, 0}, {1, 1}, {0, 1}}; 2048cb93a386Sopenharmony_ci SkPoint rf[] = {{1, 0}, {8, 0}, {8, 8}, {0, 8}, {0, 0}}; 2049cb93a386Sopenharmony_ci 2050cb93a386Sopenharmony_ci // failing tests 2051cb93a386Sopenharmony_ci SkPoint f1[] = {{0, 0}, {1, 0}, {1, 1}}; // too few points 2052cb93a386Sopenharmony_ci SkPoint f2[] = {{0, 0}, {1, 1}, {0, 1}, {1, 0}}; // diagonal 2053cb93a386Sopenharmony_ci SkPoint f3[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}, {1, 0}}; // wraps 2054cb93a386Sopenharmony_ci SkPoint f4[] = {{0, 0}, {1, 0}, {0, 0}, {1, 0}, {1, 1}, {0, 1}}; // backs up 2055cb93a386Sopenharmony_ci SkPoint f5[] = {{0, 0}, {1, 0}, {1, 1}, {2, 0}}; // end overshoots 2056cb93a386Sopenharmony_ci SkPoint f6[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 2}}; // end overshoots 2057cb93a386Sopenharmony_ci SkPoint f7[] = {{0, 0}, {1, 0}, {1, 1}, {0, 2}}; // end overshoots 2058cb93a386Sopenharmony_ci SkPoint f8[] = {{0, 0}, {1, 0}, {1, 1}, {1, 0}}; // 'L' 2059cb93a386Sopenharmony_ci SkPoint f9[] = {{1, 0}, {8, 0}, {8, 8}, {0, 8}, {0, 0}, {2, 0}}; // overlaps 2060cb93a386Sopenharmony_ci SkPoint fa[] = {{1, 0}, {8, 0}, {8, 8}, {0, 8}, {0, -1}, {1, -1}}; // non colinear gap 2061cb93a386Sopenharmony_ci SkPoint fb[] = {{1, 0}, {8, 0}, {8, 8}, {0, 8}, {0, 1}}; // falls short 2062cb93a386Sopenharmony_ci 2063cb93a386Sopenharmony_ci // no close, but we should detect them as fillably the same as a rect 2064cb93a386Sopenharmony_ci SkPoint c1[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; 2065cb93a386Sopenharmony_ci SkPoint c2[] = {{0, 0}, {1, 0}, {1, 2}, {0, 2}, {0, 1}}; 2066cb93a386Sopenharmony_ci SkPoint c3[] = {{0, 0}, {1, 0}, {1, 2}, {0, 2}, {0, 1}, {0, 0}}; // hit the start 2067cb93a386Sopenharmony_ci 2068cb93a386Sopenharmony_ci // like c2, but we double-back on ourselves 2069cb93a386Sopenharmony_ci SkPoint d1[] = {{0, 0}, {1, 0}, {1, 2}, {0, 2}, {0, 1}, {0, 2}}; 2070cb93a386Sopenharmony_ci // like c2, but we overshoot the start point 2071cb93a386Sopenharmony_ci SkPoint d2[] = {{0, 0}, {1, 0}, {1, 2}, {0, 2}, {0, -1}}; 2072cb93a386Sopenharmony_ci SkPoint d3[] = {{0, 0}, {1, 0}, {1, 2}, {0, 2}, {0, -1}, {0, 0}}; 2073cb93a386Sopenharmony_ci 2074cb93a386Sopenharmony_ci struct IsRectTest { 2075cb93a386Sopenharmony_ci SkPoint *fPoints; 2076cb93a386Sopenharmony_ci int fPointCount; 2077cb93a386Sopenharmony_ci bool fClose; 2078cb93a386Sopenharmony_ci bool fIsRect; 2079cb93a386Sopenharmony_ci } tests[] = { 2080cb93a386Sopenharmony_ci { r1, SK_ARRAY_COUNT(r1), true, true }, 2081cb93a386Sopenharmony_ci { r2, SK_ARRAY_COUNT(r2), true, true }, 2082cb93a386Sopenharmony_ci { r3, SK_ARRAY_COUNT(r3), true, true }, 2083cb93a386Sopenharmony_ci { r4, SK_ARRAY_COUNT(r4), true, true }, 2084cb93a386Sopenharmony_ci { r5, SK_ARRAY_COUNT(r5), true, true }, 2085cb93a386Sopenharmony_ci { r6, SK_ARRAY_COUNT(r6), true, true }, 2086cb93a386Sopenharmony_ci { r7, SK_ARRAY_COUNT(r7), true, true }, 2087cb93a386Sopenharmony_ci { r8, SK_ARRAY_COUNT(r8), true, true }, 2088cb93a386Sopenharmony_ci { r9, SK_ARRAY_COUNT(r9), true, true }, 2089cb93a386Sopenharmony_ci { ra, SK_ARRAY_COUNT(ra), true, true }, 2090cb93a386Sopenharmony_ci { rb, SK_ARRAY_COUNT(rb), true, true }, 2091cb93a386Sopenharmony_ci { rc, SK_ARRAY_COUNT(rc), true, true }, 2092cb93a386Sopenharmony_ci { rd, SK_ARRAY_COUNT(rd), true, true }, 2093cb93a386Sopenharmony_ci { re, SK_ARRAY_COUNT(re), true, true }, 2094cb93a386Sopenharmony_ci { rf, SK_ARRAY_COUNT(rf), true, true }, 2095cb93a386Sopenharmony_ci 2096cb93a386Sopenharmony_ci { f1, SK_ARRAY_COUNT(f1), true, false }, 2097cb93a386Sopenharmony_ci { f2, SK_ARRAY_COUNT(f2), true, false }, 2098cb93a386Sopenharmony_ci { f3, SK_ARRAY_COUNT(f3), true, false }, 2099cb93a386Sopenharmony_ci { f4, SK_ARRAY_COUNT(f4), true, false }, 2100cb93a386Sopenharmony_ci { f5, SK_ARRAY_COUNT(f5), true, false }, 2101cb93a386Sopenharmony_ci { f6, SK_ARRAY_COUNT(f6), true, false }, 2102cb93a386Sopenharmony_ci { f7, SK_ARRAY_COUNT(f7), true, false }, 2103cb93a386Sopenharmony_ci { f8, SK_ARRAY_COUNT(f8), true, false }, 2104cb93a386Sopenharmony_ci { f9, SK_ARRAY_COUNT(f9), true, false }, 2105cb93a386Sopenharmony_ci { fa, SK_ARRAY_COUNT(fa), true, false }, 2106cb93a386Sopenharmony_ci { fb, SK_ARRAY_COUNT(fb), true, false }, 2107cb93a386Sopenharmony_ci 2108cb93a386Sopenharmony_ci { c1, SK_ARRAY_COUNT(c1), false, true }, 2109cb93a386Sopenharmony_ci { c2, SK_ARRAY_COUNT(c2), false, true }, 2110cb93a386Sopenharmony_ci { c3, SK_ARRAY_COUNT(c3), false, true }, 2111cb93a386Sopenharmony_ci 2112cb93a386Sopenharmony_ci { d1, SK_ARRAY_COUNT(d1), false, false }, 2113cb93a386Sopenharmony_ci { d2, SK_ARRAY_COUNT(d2), false, true }, 2114cb93a386Sopenharmony_ci { d3, SK_ARRAY_COUNT(d3), false, false }, 2115cb93a386Sopenharmony_ci }; 2116cb93a386Sopenharmony_ci 2117cb93a386Sopenharmony_ci const size_t testCount = SK_ARRAY_COUNT(tests); 2118cb93a386Sopenharmony_ci int index; 2119cb93a386Sopenharmony_ci for (size_t testIndex = 0; testIndex < testCount; ++testIndex) { 2120cb93a386Sopenharmony_ci SkPath path; 2121cb93a386Sopenharmony_ci path.moveTo(tests[testIndex].fPoints[0].fX, tests[testIndex].fPoints[0].fY); 2122cb93a386Sopenharmony_ci for (index = 1; index < tests[testIndex].fPointCount; ++index) { 2123cb93a386Sopenharmony_ci path.lineTo(tests[testIndex].fPoints[index].fX, tests[testIndex].fPoints[index].fY); 2124cb93a386Sopenharmony_ci } 2125cb93a386Sopenharmony_ci if (tests[testIndex].fClose) { 2126cb93a386Sopenharmony_ci path.close(); 2127cb93a386Sopenharmony_ci } 2128cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, tests[testIndex].fIsRect == path.isRect(nullptr)); 2129cb93a386Sopenharmony_ci 2130cb93a386Sopenharmony_ci if (tests[testIndex].fIsRect) { 2131cb93a386Sopenharmony_ci SkRect computed, expected; 2132cb93a386Sopenharmony_ci bool isClosed; 2133cb93a386Sopenharmony_ci SkPathDirection direction; 2134cb93a386Sopenharmony_ci int pointCount = tests[testIndex].fPointCount - (d2 == tests[testIndex].fPoints); 2135cb93a386Sopenharmony_ci expected.setBounds(tests[testIndex].fPoints, pointCount); 2136cb93a386Sopenharmony_ci SkPathFirstDirection cheapDirection = SkPathPriv::ComputeFirstDirection(path); 2137cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, cheapDirection != SkPathFirstDirection::kUnknown); 2138cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isRect(&computed, &isClosed, &direction)); 2139cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, expected == computed); 2140cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, isClosed == tests[testIndex].fClose); 2141cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::AsFirstDirection(direction) == cheapDirection); 2142cb93a386Sopenharmony_ci } else { 2143cb93a386Sopenharmony_ci SkRect computed; 2144cb93a386Sopenharmony_ci computed.setLTRB(123, 456, 789, 1011); 2145cb93a386Sopenharmony_ci for (auto c : {true, false}) 2146cb93a386Sopenharmony_ci for (auto d : {SkPathDirection::kCW, SkPathDirection::kCCW}) { 2147cb93a386Sopenharmony_ci bool isClosed = c; 2148cb93a386Sopenharmony_ci SkPathDirection direction = d; 2149cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isRect(&computed, &isClosed, &direction)); 2150cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, computed.fLeft == 123 && computed.fTop == 456); 2151cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, computed.fRight == 789 && computed.fBottom == 1011); 2152cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, isClosed == c); 2153cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, direction == d); 2154cb93a386Sopenharmony_ci } 2155cb93a386Sopenharmony_ci } 2156cb93a386Sopenharmony_ci } 2157cb93a386Sopenharmony_ci 2158cb93a386Sopenharmony_ci // fail, close then line 2159cb93a386Sopenharmony_ci SkPath path1; 2160cb93a386Sopenharmony_ci path1.moveTo(r1[0].fX, r1[0].fY); 2161cb93a386Sopenharmony_ci for (index = 1; index < SkToInt(SK_ARRAY_COUNT(r1)); ++index) { 2162cb93a386Sopenharmony_ci path1.lineTo(r1[index].fX, r1[index].fY); 2163cb93a386Sopenharmony_ci } 2164cb93a386Sopenharmony_ci path1.close(); 2165cb93a386Sopenharmony_ci path1.lineTo(1, 0); 2166cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path1.isRect(nullptr)); 2167cb93a386Sopenharmony_ci 2168cb93a386Sopenharmony_ci // fail, move in the middle 2169cb93a386Sopenharmony_ci path1.reset(); 2170cb93a386Sopenharmony_ci path1.moveTo(r1[0].fX, r1[0].fY); 2171cb93a386Sopenharmony_ci for (index = 1; index < SkToInt(SK_ARRAY_COUNT(r1)); ++index) { 2172cb93a386Sopenharmony_ci if (index == 2) { 2173cb93a386Sopenharmony_ci path1.moveTo(1, .5f); 2174cb93a386Sopenharmony_ci } 2175cb93a386Sopenharmony_ci path1.lineTo(r1[index].fX, r1[index].fY); 2176cb93a386Sopenharmony_ci } 2177cb93a386Sopenharmony_ci path1.close(); 2178cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path1.isRect(nullptr)); 2179cb93a386Sopenharmony_ci 2180cb93a386Sopenharmony_ci // fail, move on the edge 2181cb93a386Sopenharmony_ci path1.reset(); 2182cb93a386Sopenharmony_ci for (index = 1; index < SkToInt(SK_ARRAY_COUNT(r1)); ++index) { 2183cb93a386Sopenharmony_ci path1.moveTo(r1[index - 1].fX, r1[index - 1].fY); 2184cb93a386Sopenharmony_ci path1.lineTo(r1[index].fX, r1[index].fY); 2185cb93a386Sopenharmony_ci } 2186cb93a386Sopenharmony_ci path1.close(); 2187cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path1.isRect(nullptr)); 2188cb93a386Sopenharmony_ci 2189cb93a386Sopenharmony_ci // fail, quad 2190cb93a386Sopenharmony_ci path1.reset(); 2191cb93a386Sopenharmony_ci path1.moveTo(r1[0].fX, r1[0].fY); 2192cb93a386Sopenharmony_ci for (index = 1; index < SkToInt(SK_ARRAY_COUNT(r1)); ++index) { 2193cb93a386Sopenharmony_ci if (index == 2) { 2194cb93a386Sopenharmony_ci path1.quadTo(1, .5f, 1, .5f); 2195cb93a386Sopenharmony_ci } 2196cb93a386Sopenharmony_ci path1.lineTo(r1[index].fX, r1[index].fY); 2197cb93a386Sopenharmony_ci } 2198cb93a386Sopenharmony_ci path1.close(); 2199cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path1.isRect(nullptr)); 2200cb93a386Sopenharmony_ci 2201cb93a386Sopenharmony_ci // fail, cubic 2202cb93a386Sopenharmony_ci path1.reset(); 2203cb93a386Sopenharmony_ci path1.moveTo(r1[0].fX, r1[0].fY); 2204cb93a386Sopenharmony_ci for (index = 1; index < SkToInt(SK_ARRAY_COUNT(r1)); ++index) { 2205cb93a386Sopenharmony_ci if (index == 2) { 2206cb93a386Sopenharmony_ci path1.cubicTo(1, .5f, 1, .5f, 1, .5f); 2207cb93a386Sopenharmony_ci } 2208cb93a386Sopenharmony_ci path1.lineTo(r1[index].fX, r1[index].fY); 2209cb93a386Sopenharmony_ci } 2210cb93a386Sopenharmony_ci path1.close(); 2211cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path1.isRect(nullptr)); 2212cb93a386Sopenharmony_ci} 2213cb93a386Sopenharmony_ci 2214cb93a386Sopenharmony_cistatic void check_simple_rect(skiatest::Reporter* reporter, const SkPath& path, bool isClosed, 2215cb93a386Sopenharmony_ci const SkRect& rect, SkPathDirection dir, unsigned start) { 2216cb93a386Sopenharmony_ci SkRect r = SkRect::MakeEmpty(); 2217cb93a386Sopenharmony_ci SkPathDirection d = SkPathDirection::kCCW; 2218cb93a386Sopenharmony_ci unsigned s = ~0U; 2219cb93a386Sopenharmony_ci 2220cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::IsSimpleRect(path, false, &r, &d, &s) == isClosed); 2221cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::IsSimpleRect(path, true, &r, &d, &s)); 2222cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, r == rect); 2223cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, d == dir); 2224cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, s == start); 2225cb93a386Sopenharmony_ci} 2226cb93a386Sopenharmony_ci 2227cb93a386Sopenharmony_cistatic void test_is_closed_rect(skiatest::Reporter* reporter) { 2228cb93a386Sopenharmony_ci using std::swap; 2229cb93a386Sopenharmony_ci SkRect r = SkRect::MakeEmpty(); 2230cb93a386Sopenharmony_ci SkPathDirection d = SkPathDirection::kCCW; 2231cb93a386Sopenharmony_ci unsigned s = ~0U; 2232cb93a386Sopenharmony_ci 2233cb93a386Sopenharmony_ci const SkRect testRect = SkRect::MakeXYWH(10, 10, 50, 70); 2234cb93a386Sopenharmony_ci const SkRect emptyRect = SkRect::MakeEmpty(); 2235cb93a386Sopenharmony_ci for (int start = 0; start < 4; ++start) { 2236cb93a386Sopenharmony_ci for (auto dir : {SkPathDirection::kCCW, SkPathDirection::kCW}) { 2237cb93a386Sopenharmony_ci SkPath path; 2238cb93a386Sopenharmony_ci path.addRect(testRect, dir, start); 2239cb93a386Sopenharmony_ci check_simple_rect(reporter, path, true, testRect, dir, start); 2240cb93a386Sopenharmony_ci path.close(); 2241cb93a386Sopenharmony_ci check_simple_rect(reporter, path, true, testRect, dir, start); 2242cb93a386Sopenharmony_ci SkPath path2 = path; 2243cb93a386Sopenharmony_ci path2.lineTo(10, 10); 2244cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path2, false, &r, &d, &s)); 2245cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path2, true, &r, &d, &s)); 2246cb93a386Sopenharmony_ci path2 = path; 2247cb93a386Sopenharmony_ci path2.moveTo(10, 10); 2248cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path2, false, &r, &d, &s)); 2249cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path2, true, &r, &d, &s)); 2250cb93a386Sopenharmony_ci path2 = path; 2251cb93a386Sopenharmony_ci path2.addRect(testRect, dir, start); 2252cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path2, false, &r, &d, &s)); 2253cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path2, true, &r, &d, &s)); 2254cb93a386Sopenharmony_ci // Make the path by hand, manually closing it. 2255cb93a386Sopenharmony_ci path2.reset(); 2256cb93a386Sopenharmony_ci SkPoint firstPt = {0.f, 0.f}; 2257cb93a386Sopenharmony_ci for (auto [v, verbPts, w] : SkPathPriv::Iterate(path)) { 2258cb93a386Sopenharmony_ci switch(v) { 2259cb93a386Sopenharmony_ci case SkPathVerb::kMove: 2260cb93a386Sopenharmony_ci firstPt = verbPts[0]; 2261cb93a386Sopenharmony_ci path2.moveTo(verbPts[0]); 2262cb93a386Sopenharmony_ci break; 2263cb93a386Sopenharmony_ci case SkPathVerb::kLine: 2264cb93a386Sopenharmony_ci path2.lineTo(verbPts[1]); 2265cb93a386Sopenharmony_ci break; 2266cb93a386Sopenharmony_ci default: 2267cb93a386Sopenharmony_ci break; 2268cb93a386Sopenharmony_ci } 2269cb93a386Sopenharmony_ci } 2270cb93a386Sopenharmony_ci // We haven't closed it yet... 2271cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path2, false, &r, &d, &s)); 2272cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path2, true, &r, &d, &s)); 2273cb93a386Sopenharmony_ci // ... now we do and test again. 2274cb93a386Sopenharmony_ci path2.lineTo(firstPt); 2275cb93a386Sopenharmony_ci check_simple_rect(reporter, path2, false, testRect, dir, start); 2276cb93a386Sopenharmony_ci // A redundant close shouldn't cause a failure. 2277cb93a386Sopenharmony_ci path2.close(); 2278cb93a386Sopenharmony_ci check_simple_rect(reporter, path2, true, testRect, dir, start); 2279cb93a386Sopenharmony_ci // Degenerate point and line rects are not allowed 2280cb93a386Sopenharmony_ci path2.reset(); 2281cb93a386Sopenharmony_ci path2.addRect(emptyRect, dir, start); 2282cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path2, false, &r, &d, &s)); 2283cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path2, true, &r, &d, &s)); 2284cb93a386Sopenharmony_ci SkRect degenRect = testRect; 2285cb93a386Sopenharmony_ci degenRect.fLeft = degenRect.fRight; 2286cb93a386Sopenharmony_ci path2.reset(); 2287cb93a386Sopenharmony_ci path2.addRect(degenRect, dir, start); 2288cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path2, false, &r, &d, &s)); 2289cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path2, true, &r, &d, &s)); 2290cb93a386Sopenharmony_ci degenRect = testRect; 2291cb93a386Sopenharmony_ci degenRect.fTop = degenRect.fBottom; 2292cb93a386Sopenharmony_ci path2.reset(); 2293cb93a386Sopenharmony_ci path2.addRect(degenRect, dir, start); 2294cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path2, false, &r, &d, &s)); 2295cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path2, true, &r, &d, &s)); 2296cb93a386Sopenharmony_ci // An inverted rect makes a rect path, but changes the winding dir and start point. 2297cb93a386Sopenharmony_ci SkPathDirection swapDir = (dir == SkPathDirection::kCW) 2298cb93a386Sopenharmony_ci ? SkPathDirection::kCCW 2299cb93a386Sopenharmony_ci : SkPathDirection::kCW; 2300cb93a386Sopenharmony_ci static constexpr unsigned kXSwapStarts[] = { 1, 0, 3, 2 }; 2301cb93a386Sopenharmony_ci static constexpr unsigned kYSwapStarts[] = { 3, 2, 1, 0 }; 2302cb93a386Sopenharmony_ci SkRect swapRect = testRect; 2303cb93a386Sopenharmony_ci swap(swapRect.fLeft, swapRect.fRight); 2304cb93a386Sopenharmony_ci path2.reset(); 2305cb93a386Sopenharmony_ci path2.addRect(swapRect, dir, start); 2306cb93a386Sopenharmony_ci check_simple_rect(reporter, path2, true, testRect, swapDir, kXSwapStarts[start]); 2307cb93a386Sopenharmony_ci swapRect = testRect; 2308cb93a386Sopenharmony_ci swap(swapRect.fTop, swapRect.fBottom); 2309cb93a386Sopenharmony_ci path2.reset(); 2310cb93a386Sopenharmony_ci path2.addRect(swapRect, dir, start); 2311cb93a386Sopenharmony_ci check_simple_rect(reporter, path2, true, testRect, swapDir, kYSwapStarts[start]); 2312cb93a386Sopenharmony_ci } 2313cb93a386Sopenharmony_ci } 2314cb93a386Sopenharmony_ci // down, up, left, close 2315cb93a386Sopenharmony_ci SkPath path; 2316cb93a386Sopenharmony_ci path.moveTo(1, 1); 2317cb93a386Sopenharmony_ci path.lineTo(1, 2); 2318cb93a386Sopenharmony_ci path.lineTo(1, 1); 2319cb93a386Sopenharmony_ci path.lineTo(0, 1); 2320cb93a386Sopenharmony_ci SkRect rect; 2321cb93a386Sopenharmony_ci SkPathDirection dir; 2322cb93a386Sopenharmony_ci unsigned start; 2323cb93a386Sopenharmony_ci path.close(); 2324cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path, false, &rect, &dir, &start)); 2325cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path, true, &rect, &dir, &start)); 2326cb93a386Sopenharmony_ci // right, left, up, close 2327cb93a386Sopenharmony_ci path.reset(); 2328cb93a386Sopenharmony_ci path.moveTo(1, 1); 2329cb93a386Sopenharmony_ci path.lineTo(2, 1); 2330cb93a386Sopenharmony_ci path.lineTo(1, 1); 2331cb93a386Sopenharmony_ci path.lineTo(1, 0); 2332cb93a386Sopenharmony_ci path.close(); 2333cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path, false, &rect, &dir, &start)); 2334cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path, true, &rect, &dir, &start)); 2335cb93a386Sopenharmony_ci // parallelogram with horizontal edges 2336cb93a386Sopenharmony_ci path.reset(); 2337cb93a386Sopenharmony_ci path.moveTo(1, 0); 2338cb93a386Sopenharmony_ci path.lineTo(3, 0); 2339cb93a386Sopenharmony_ci path.lineTo(2, 1); 2340cb93a386Sopenharmony_ci path.lineTo(0, 1); 2341cb93a386Sopenharmony_ci path.close(); 2342cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path, false, &rect, &dir, &start)); 2343cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path, true, &rect, &dir, &start)); 2344cb93a386Sopenharmony_ci // parallelogram with vertical edges 2345cb93a386Sopenharmony_ci path.reset(); 2346cb93a386Sopenharmony_ci path.moveTo(0, 1); 2347cb93a386Sopenharmony_ci path.lineTo(0, 3); 2348cb93a386Sopenharmony_ci path.lineTo(1, 2); 2349cb93a386Sopenharmony_ci path.lineTo(1, 0); 2350cb93a386Sopenharmony_ci path.close(); 2351cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path, false, &rect, &dir, &start)); 2352cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path, true, &rect, &dir, &start)); 2353cb93a386Sopenharmony_ci 2354cb93a386Sopenharmony_ci} 2355cb93a386Sopenharmony_ci 2356cb93a386Sopenharmony_cistatic void test_isNestedFillRects(skiatest::Reporter* reporter) { 2357cb93a386Sopenharmony_ci // passing tests (all moveTo / lineTo... 2358cb93a386Sopenharmony_ci SkPoint r1[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; // CW 2359cb93a386Sopenharmony_ci SkPoint r2[] = {{1, 0}, {1, 1}, {0, 1}, {0, 0}}; 2360cb93a386Sopenharmony_ci SkPoint r3[] = {{1, 1}, {0, 1}, {0, 0}, {1, 0}}; 2361cb93a386Sopenharmony_ci SkPoint r4[] = {{0, 1}, {0, 0}, {1, 0}, {1, 1}}; 2362cb93a386Sopenharmony_ci SkPoint r5[] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}}; // CCW 2363cb93a386Sopenharmony_ci SkPoint r6[] = {{0, 1}, {1, 1}, {1, 0}, {0, 0}}; 2364cb93a386Sopenharmony_ci SkPoint r7[] = {{1, 1}, {1, 0}, {0, 0}, {0, 1}}; 2365cb93a386Sopenharmony_ci SkPoint r8[] = {{1, 0}, {0, 0}, {0, 1}, {1, 1}}; 2366cb93a386Sopenharmony_ci SkPoint r9[] = {{0, 1}, {1, 1}, {1, 0}, {0, 0}}; 2367cb93a386Sopenharmony_ci SkPoint ra[] = {{0, 0}, {0, .5f}, {0, 1}, {.5f, 1}, {1, 1}, {1, .5f}, {1, 0}, {.5f, 0}}; // CCW 2368cb93a386Sopenharmony_ci SkPoint rb[] = {{0, 0}, {.5f, 0}, {1, 0}, {1, .5f}, {1, 1}, {.5f, 1}, {0, 1}, {0, .5f}}; // CW 2369cb93a386Sopenharmony_ci SkPoint rc[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}}; // CW 2370cb93a386Sopenharmony_ci SkPoint rd[] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}}; // CCW 2371cb93a386Sopenharmony_ci SkPoint re[] = {{0, 0}, {1, 0}, {1, 0}, {1, 1}, {0, 1}}; // CW 2372cb93a386Sopenharmony_ci 2373cb93a386Sopenharmony_ci // failing tests 2374cb93a386Sopenharmony_ci SkPoint f1[] = {{0, 0}, {1, 0}, {1, 1}}; // too few points 2375cb93a386Sopenharmony_ci SkPoint f2[] = {{0, 0}, {1, 1}, {0, 1}, {1, 0}}; // diagonal 2376cb93a386Sopenharmony_ci SkPoint f3[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}, {1, 0}}; // wraps 2377cb93a386Sopenharmony_ci SkPoint f4[] = {{0, 0}, {1, 0}, {0, 0}, {1, 0}, {1, 1}, {0, 1}}; // backs up 2378cb93a386Sopenharmony_ci SkPoint f5[] = {{0, 0}, {1, 0}, {1, 1}, {2, 0}}; // end overshoots 2379cb93a386Sopenharmony_ci SkPoint f6[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 2}}; // end overshoots 2380cb93a386Sopenharmony_ci SkPoint f7[] = {{0, 0}, {1, 0}, {1, 1}, {0, 2}}; // end overshoots 2381cb93a386Sopenharmony_ci SkPoint f8[] = {{0, 0}, {1, 0}, {1, 1}, {1, 0}}; // 'L' 2382cb93a386Sopenharmony_ci 2383cb93a386Sopenharmony_ci // success, no close is OK 2384cb93a386Sopenharmony_ci SkPoint c1[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; // close doesn't match 2385cb93a386Sopenharmony_ci SkPoint c2[] = {{0, 0}, {1, 0}, {1, 2}, {0, 2}, {0, 1}}; // ditto 2386cb93a386Sopenharmony_ci 2387cb93a386Sopenharmony_ci struct IsNestedRectTest { 2388cb93a386Sopenharmony_ci SkPoint *fPoints; 2389cb93a386Sopenharmony_ci int fPointCount; 2390cb93a386Sopenharmony_ci SkPathFirstDirection fDirection; 2391cb93a386Sopenharmony_ci bool fClose; 2392cb93a386Sopenharmony_ci bool fIsNestedRect; // nests with path.addRect(-1, -1, 2, 2); 2393cb93a386Sopenharmony_ci } tests[] = { 2394cb93a386Sopenharmony_ci { r1, SK_ARRAY_COUNT(r1), SkPathFirstDirection::kCW , true, true }, 2395cb93a386Sopenharmony_ci { r2, SK_ARRAY_COUNT(r2), SkPathFirstDirection::kCW , true, true }, 2396cb93a386Sopenharmony_ci { r3, SK_ARRAY_COUNT(r3), SkPathFirstDirection::kCW , true, true }, 2397cb93a386Sopenharmony_ci { r4, SK_ARRAY_COUNT(r4), SkPathFirstDirection::kCW , true, true }, 2398cb93a386Sopenharmony_ci { r5, SK_ARRAY_COUNT(r5), SkPathFirstDirection::kCCW, true, true }, 2399cb93a386Sopenharmony_ci { r6, SK_ARRAY_COUNT(r6), SkPathFirstDirection::kCCW, true, true }, 2400cb93a386Sopenharmony_ci { r7, SK_ARRAY_COUNT(r7), SkPathFirstDirection::kCCW, true, true }, 2401cb93a386Sopenharmony_ci { r8, SK_ARRAY_COUNT(r8), SkPathFirstDirection::kCCW, true, true }, 2402cb93a386Sopenharmony_ci { r9, SK_ARRAY_COUNT(r9), SkPathFirstDirection::kCCW, true, true }, 2403cb93a386Sopenharmony_ci { ra, SK_ARRAY_COUNT(ra), SkPathFirstDirection::kCCW, true, true }, 2404cb93a386Sopenharmony_ci { rb, SK_ARRAY_COUNT(rb), SkPathFirstDirection::kCW, true, true }, 2405cb93a386Sopenharmony_ci { rc, SK_ARRAY_COUNT(rc), SkPathFirstDirection::kCW, true, true }, 2406cb93a386Sopenharmony_ci { rd, SK_ARRAY_COUNT(rd), SkPathFirstDirection::kCCW, true, true }, 2407cb93a386Sopenharmony_ci { re, SK_ARRAY_COUNT(re), SkPathFirstDirection::kCW, true, true }, 2408cb93a386Sopenharmony_ci 2409cb93a386Sopenharmony_ci { f1, SK_ARRAY_COUNT(f1), SkPathFirstDirection::kUnknown, true, false }, 2410cb93a386Sopenharmony_ci { f2, SK_ARRAY_COUNT(f2), SkPathFirstDirection::kUnknown, true, false }, 2411cb93a386Sopenharmony_ci { f3, SK_ARRAY_COUNT(f3), SkPathFirstDirection::kUnknown, true, false }, 2412cb93a386Sopenharmony_ci { f4, SK_ARRAY_COUNT(f4), SkPathFirstDirection::kUnknown, true, false }, 2413cb93a386Sopenharmony_ci { f5, SK_ARRAY_COUNT(f5), SkPathFirstDirection::kUnknown, true, false }, 2414cb93a386Sopenharmony_ci { f6, SK_ARRAY_COUNT(f6), SkPathFirstDirection::kUnknown, true, false }, 2415cb93a386Sopenharmony_ci { f7, SK_ARRAY_COUNT(f7), SkPathFirstDirection::kUnknown, true, false }, 2416cb93a386Sopenharmony_ci { f8, SK_ARRAY_COUNT(f8), SkPathFirstDirection::kUnknown, true, false }, 2417cb93a386Sopenharmony_ci 2418cb93a386Sopenharmony_ci { c1, SK_ARRAY_COUNT(c1), SkPathFirstDirection::kCW, false, true }, 2419cb93a386Sopenharmony_ci { c2, SK_ARRAY_COUNT(c2), SkPathFirstDirection::kCW, false, true }, 2420cb93a386Sopenharmony_ci }; 2421cb93a386Sopenharmony_ci 2422cb93a386Sopenharmony_ci const size_t testCount = SK_ARRAY_COUNT(tests); 2423cb93a386Sopenharmony_ci int index; 2424cb93a386Sopenharmony_ci for (int rectFirst = 0; rectFirst <= 1; ++rectFirst) { 2425cb93a386Sopenharmony_ci for (size_t testIndex = 0; testIndex < testCount; ++testIndex) { 2426cb93a386Sopenharmony_ci SkPath path; 2427cb93a386Sopenharmony_ci if (rectFirst) { 2428cb93a386Sopenharmony_ci path.addRect(-1, -1, 2, 2, SkPathDirection::kCW); 2429cb93a386Sopenharmony_ci } 2430cb93a386Sopenharmony_ci path.moveTo(tests[testIndex].fPoints[0].fX, tests[testIndex].fPoints[0].fY); 2431cb93a386Sopenharmony_ci for (index = 1; index < tests[testIndex].fPointCount; ++index) { 2432cb93a386Sopenharmony_ci path.lineTo(tests[testIndex].fPoints[index].fX, tests[testIndex].fPoints[index].fY); 2433cb93a386Sopenharmony_ci } 2434cb93a386Sopenharmony_ci if (tests[testIndex].fClose) { 2435cb93a386Sopenharmony_ci path.close(); 2436cb93a386Sopenharmony_ci } 2437cb93a386Sopenharmony_ci if (!rectFirst) { 2438cb93a386Sopenharmony_ci path.addRect(-1, -1, 2, 2, SkPathDirection::kCCW); 2439cb93a386Sopenharmony_ci } 2440cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 2441cb93a386Sopenharmony_ci tests[testIndex].fIsNestedRect == SkPathPriv::IsNestedFillRects(path, nullptr)); 2442cb93a386Sopenharmony_ci if (tests[testIndex].fIsNestedRect) { 2443cb93a386Sopenharmony_ci SkRect expected[2], computed[2]; 2444cb93a386Sopenharmony_ci SkPathFirstDirection expectedDirs[2]; 2445cb93a386Sopenharmony_ci SkPathDirection computedDirs[2]; 2446cb93a386Sopenharmony_ci SkRect testBounds; 2447cb93a386Sopenharmony_ci testBounds.setBounds(tests[testIndex].fPoints, tests[testIndex].fPointCount); 2448cb93a386Sopenharmony_ci expected[0] = SkRect::MakeLTRB(-1, -1, 2, 2); 2449cb93a386Sopenharmony_ci expected[1] = testBounds; 2450cb93a386Sopenharmony_ci if (rectFirst) { 2451cb93a386Sopenharmony_ci expectedDirs[0] = SkPathFirstDirection::kCW; 2452cb93a386Sopenharmony_ci } else { 2453cb93a386Sopenharmony_ci expectedDirs[0] = SkPathFirstDirection::kCCW; 2454cb93a386Sopenharmony_ci } 2455cb93a386Sopenharmony_ci expectedDirs[1] = tests[testIndex].fDirection; 2456cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::IsNestedFillRects(path, computed, computedDirs)); 2457cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, expected[0] == computed[0]); 2458cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, expected[1] == computed[1]); 2459cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, expectedDirs[0] == SkPathPriv::AsFirstDirection(computedDirs[0])); 2460cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, expectedDirs[1] == SkPathPriv::AsFirstDirection(computedDirs[1])); 2461cb93a386Sopenharmony_ci } 2462cb93a386Sopenharmony_ci } 2463cb93a386Sopenharmony_ci 2464cb93a386Sopenharmony_ci // fail, close then line 2465cb93a386Sopenharmony_ci SkPath path1; 2466cb93a386Sopenharmony_ci if (rectFirst) { 2467cb93a386Sopenharmony_ci path1.addRect(-1, -1, 2, 2, SkPathDirection::kCW); 2468cb93a386Sopenharmony_ci } 2469cb93a386Sopenharmony_ci path1.moveTo(r1[0].fX, r1[0].fY); 2470cb93a386Sopenharmony_ci for (index = 1; index < SkToInt(SK_ARRAY_COUNT(r1)); ++index) { 2471cb93a386Sopenharmony_ci path1.lineTo(r1[index].fX, r1[index].fY); 2472cb93a386Sopenharmony_ci } 2473cb93a386Sopenharmony_ci path1.close(); 2474cb93a386Sopenharmony_ci path1.lineTo(1, 0); 2475cb93a386Sopenharmony_ci if (!rectFirst) { 2476cb93a386Sopenharmony_ci path1.addRect(-1, -1, 2, 2, SkPathDirection::kCCW); 2477cb93a386Sopenharmony_ci } 2478cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsNestedFillRects(path1, nullptr)); 2479cb93a386Sopenharmony_ci 2480cb93a386Sopenharmony_ci // fail, move in the middle 2481cb93a386Sopenharmony_ci path1.reset(); 2482cb93a386Sopenharmony_ci if (rectFirst) { 2483cb93a386Sopenharmony_ci path1.addRect(-1, -1, 2, 2, SkPathDirection::kCW); 2484cb93a386Sopenharmony_ci } 2485cb93a386Sopenharmony_ci path1.moveTo(r1[0].fX, r1[0].fY); 2486cb93a386Sopenharmony_ci for (index = 1; index < SkToInt(SK_ARRAY_COUNT(r1)); ++index) { 2487cb93a386Sopenharmony_ci if (index == 2) { 2488cb93a386Sopenharmony_ci path1.moveTo(1, .5f); 2489cb93a386Sopenharmony_ci } 2490cb93a386Sopenharmony_ci path1.lineTo(r1[index].fX, r1[index].fY); 2491cb93a386Sopenharmony_ci } 2492cb93a386Sopenharmony_ci path1.close(); 2493cb93a386Sopenharmony_ci if (!rectFirst) { 2494cb93a386Sopenharmony_ci path1.addRect(-1, -1, 2, 2, SkPathDirection::kCCW); 2495cb93a386Sopenharmony_ci } 2496cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsNestedFillRects(path1, nullptr)); 2497cb93a386Sopenharmony_ci 2498cb93a386Sopenharmony_ci // fail, move on the edge 2499cb93a386Sopenharmony_ci path1.reset(); 2500cb93a386Sopenharmony_ci if (rectFirst) { 2501cb93a386Sopenharmony_ci path1.addRect(-1, -1, 2, 2, SkPathDirection::kCW); 2502cb93a386Sopenharmony_ci } 2503cb93a386Sopenharmony_ci for (index = 1; index < SkToInt(SK_ARRAY_COUNT(r1)); ++index) { 2504cb93a386Sopenharmony_ci path1.moveTo(r1[index - 1].fX, r1[index - 1].fY); 2505cb93a386Sopenharmony_ci path1.lineTo(r1[index].fX, r1[index].fY); 2506cb93a386Sopenharmony_ci } 2507cb93a386Sopenharmony_ci path1.close(); 2508cb93a386Sopenharmony_ci if (!rectFirst) { 2509cb93a386Sopenharmony_ci path1.addRect(-1, -1, 2, 2, SkPathDirection::kCCW); 2510cb93a386Sopenharmony_ci } 2511cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsNestedFillRects(path1, nullptr)); 2512cb93a386Sopenharmony_ci 2513cb93a386Sopenharmony_ci // fail, quad 2514cb93a386Sopenharmony_ci path1.reset(); 2515cb93a386Sopenharmony_ci if (rectFirst) { 2516cb93a386Sopenharmony_ci path1.addRect(-1, -1, 2, 2, SkPathDirection::kCW); 2517cb93a386Sopenharmony_ci } 2518cb93a386Sopenharmony_ci path1.moveTo(r1[0].fX, r1[0].fY); 2519cb93a386Sopenharmony_ci for (index = 1; index < SkToInt(SK_ARRAY_COUNT(r1)); ++index) { 2520cb93a386Sopenharmony_ci if (index == 2) { 2521cb93a386Sopenharmony_ci path1.quadTo(1, .5f, 1, .5f); 2522cb93a386Sopenharmony_ci } 2523cb93a386Sopenharmony_ci path1.lineTo(r1[index].fX, r1[index].fY); 2524cb93a386Sopenharmony_ci } 2525cb93a386Sopenharmony_ci path1.close(); 2526cb93a386Sopenharmony_ci if (!rectFirst) { 2527cb93a386Sopenharmony_ci path1.addRect(-1, -1, 2, 2, SkPathDirection::kCCW); 2528cb93a386Sopenharmony_ci } 2529cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsNestedFillRects(path1, nullptr)); 2530cb93a386Sopenharmony_ci 2531cb93a386Sopenharmony_ci // fail, cubic 2532cb93a386Sopenharmony_ci path1.reset(); 2533cb93a386Sopenharmony_ci if (rectFirst) { 2534cb93a386Sopenharmony_ci path1.addRect(-1, -1, 2, 2, SkPathDirection::kCW); 2535cb93a386Sopenharmony_ci } 2536cb93a386Sopenharmony_ci path1.moveTo(r1[0].fX, r1[0].fY); 2537cb93a386Sopenharmony_ci for (index = 1; index < SkToInt(SK_ARRAY_COUNT(r1)); ++index) { 2538cb93a386Sopenharmony_ci if (index == 2) { 2539cb93a386Sopenharmony_ci path1.cubicTo(1, .5f, 1, .5f, 1, .5f); 2540cb93a386Sopenharmony_ci } 2541cb93a386Sopenharmony_ci path1.lineTo(r1[index].fX, r1[index].fY); 2542cb93a386Sopenharmony_ci } 2543cb93a386Sopenharmony_ci path1.close(); 2544cb93a386Sopenharmony_ci if (!rectFirst) { 2545cb93a386Sopenharmony_ci path1.addRect(-1, -1, 2, 2, SkPathDirection::kCCW); 2546cb93a386Sopenharmony_ci } 2547cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsNestedFillRects(path1, nullptr)); 2548cb93a386Sopenharmony_ci 2549cb93a386Sopenharmony_ci // fail, not nested 2550cb93a386Sopenharmony_ci path1.reset(); 2551cb93a386Sopenharmony_ci path1.addRect(1, 1, 3, 3, SkPathDirection::kCW); 2552cb93a386Sopenharmony_ci path1.addRect(2, 2, 4, 4, SkPathDirection::kCW); 2553cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !SkPathPriv::IsNestedFillRects(path1, nullptr)); 2554cb93a386Sopenharmony_ci } 2555cb93a386Sopenharmony_ci 2556cb93a386Sopenharmony_ci // pass, constructed explicitly from manually closed rects specified as moves/lines. 2557cb93a386Sopenharmony_ci SkPath path; 2558cb93a386Sopenharmony_ci path.moveTo(0, 0); 2559cb93a386Sopenharmony_ci path.lineTo(10, 0); 2560cb93a386Sopenharmony_ci path.lineTo(10, 10); 2561cb93a386Sopenharmony_ci path.lineTo(0, 10); 2562cb93a386Sopenharmony_ci path.lineTo(0, 0); 2563cb93a386Sopenharmony_ci path.moveTo(1, 1); 2564cb93a386Sopenharmony_ci path.lineTo(9, 1); 2565cb93a386Sopenharmony_ci path.lineTo(9, 9); 2566cb93a386Sopenharmony_ci path.lineTo(1, 9); 2567cb93a386Sopenharmony_ci path.lineTo(1, 1); 2568cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::IsNestedFillRects(path, nullptr)); 2569cb93a386Sopenharmony_ci 2570cb93a386Sopenharmony_ci // pass, stroke rect 2571cb93a386Sopenharmony_ci SkPath src, dst; 2572cb93a386Sopenharmony_ci src.addRect(1, 1, 7, 7, SkPathDirection::kCW); 2573cb93a386Sopenharmony_ci SkPaint strokePaint; 2574cb93a386Sopenharmony_ci strokePaint.setStyle(SkPaint::kStroke_Style); 2575cb93a386Sopenharmony_ci strokePaint.setStrokeWidth(2); 2576cb93a386Sopenharmony_ci strokePaint.getFillPath(src, &dst); 2577cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::IsNestedFillRects(dst, nullptr)); 2578cb93a386Sopenharmony_ci} 2579cb93a386Sopenharmony_ci 2580cb93a386Sopenharmony_cistatic void write_and_read_back(skiatest::Reporter* reporter, 2581cb93a386Sopenharmony_ci const SkPath& p) { 2582cb93a386Sopenharmony_ci SkBinaryWriteBuffer writer; 2583cb93a386Sopenharmony_ci writer.writePath(p); 2584cb93a386Sopenharmony_ci size_t size = writer.bytesWritten(); 2585cb93a386Sopenharmony_ci SkAutoMalloc storage(size); 2586cb93a386Sopenharmony_ci writer.writeToMemory(storage.get()); 2587cb93a386Sopenharmony_ci SkReadBuffer reader(storage.get(), size); 2588cb93a386Sopenharmony_ci 2589cb93a386Sopenharmony_ci SkPath readBack; 2590cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, readBack != p); 2591cb93a386Sopenharmony_ci reader.readPath(&readBack); 2592cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, readBack == p); 2593cb93a386Sopenharmony_ci 2594cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::GetConvexityOrUnknown(readBack) == 2595cb93a386Sopenharmony_ci SkPathPriv::GetConvexityOrUnknown(p)); 2596cb93a386Sopenharmony_ci 2597cb93a386Sopenharmony_ci SkRect oval0, oval1; 2598cb93a386Sopenharmony_ci SkPathDirection dir0, dir1; 2599cb93a386Sopenharmony_ci unsigned start0, start1; 2600cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, readBack.isOval(nullptr) == p.isOval(nullptr)); 2601cb93a386Sopenharmony_ci if (SkPathPriv::IsOval(p, &oval0, &dir0, &start0) && 2602cb93a386Sopenharmony_ci SkPathPriv::IsOval(readBack, &oval1, &dir1, &start1)) { 2603cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, oval0 == oval1); 2604cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, dir0 == dir1); 2605cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, start0 == start1); 2606cb93a386Sopenharmony_ci } 2607cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, readBack.isRRect(nullptr) == p.isRRect(nullptr)); 2608cb93a386Sopenharmony_ci SkRRect rrect0, rrect1; 2609cb93a386Sopenharmony_ci if (SkPathPriv::IsRRect(p, &rrect0, &dir0, &start0) && 2610cb93a386Sopenharmony_ci SkPathPriv::IsRRect(readBack, &rrect1, &dir1, &start1)) { 2611cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, rrect0 == rrect1); 2612cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, dir0 == dir1); 2613cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, start0 == start1); 2614cb93a386Sopenharmony_ci } 2615cb93a386Sopenharmony_ci const SkRect& origBounds = p.getBounds(); 2616cb93a386Sopenharmony_ci const SkRect& readBackBounds = readBack.getBounds(); 2617cb93a386Sopenharmony_ci 2618cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, origBounds == readBackBounds); 2619cb93a386Sopenharmony_ci} 2620cb93a386Sopenharmony_ci 2621cb93a386Sopenharmony_cistatic void test_flattening(skiatest::Reporter* reporter) { 2622cb93a386Sopenharmony_ci SkPath p; 2623cb93a386Sopenharmony_ci 2624cb93a386Sopenharmony_ci static const SkPoint pts[] = { 2625cb93a386Sopenharmony_ci { 0, 0 }, 2626cb93a386Sopenharmony_ci { SkIntToScalar(10), SkIntToScalar(10) }, 2627cb93a386Sopenharmony_ci { SkIntToScalar(20), SkIntToScalar(10) }, { SkIntToScalar(20), 0 }, 2628cb93a386Sopenharmony_ci { 0, 0 }, { 0, SkIntToScalar(10) }, { SkIntToScalar(1), SkIntToScalar(10) } 2629cb93a386Sopenharmony_ci }; 2630cb93a386Sopenharmony_ci p.moveTo(pts[0]); 2631cb93a386Sopenharmony_ci p.lineTo(pts[1]); 2632cb93a386Sopenharmony_ci p.quadTo(pts[2], pts[3]); 2633cb93a386Sopenharmony_ci p.cubicTo(pts[4], pts[5], pts[6]); 2634cb93a386Sopenharmony_ci 2635cb93a386Sopenharmony_ci write_and_read_back(reporter, p); 2636cb93a386Sopenharmony_ci 2637cb93a386Sopenharmony_ci // create a buffer that should be much larger than the path so we don't 2638cb93a386Sopenharmony_ci // kill our stack if writer goes too far. 2639cb93a386Sopenharmony_ci char buffer[1024]; 2640cb93a386Sopenharmony_ci size_t size1 = p.writeToMemory(nullptr); 2641cb93a386Sopenharmony_ci size_t size2 = p.writeToMemory(buffer); 2642cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, size1 == size2); 2643cb93a386Sopenharmony_ci 2644cb93a386Sopenharmony_ci SkPath p2; 2645cb93a386Sopenharmony_ci size_t size3 = p2.readFromMemory(buffer, 1024); 2646cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, size1 == size3); 2647cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p == p2); 2648cb93a386Sopenharmony_ci 2649cb93a386Sopenharmony_ci size3 = p2.readFromMemory(buffer, 0); 2650cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !size3); 2651cb93a386Sopenharmony_ci 2652cb93a386Sopenharmony_ci SkPath tooShort; 2653cb93a386Sopenharmony_ci size3 = tooShort.readFromMemory(buffer, size1 - 1); 2654cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, tooShort.isEmpty()); 2655cb93a386Sopenharmony_ci 2656cb93a386Sopenharmony_ci char buffer2[1024]; 2657cb93a386Sopenharmony_ci size3 = p2.writeToMemory(buffer2); 2658cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, size1 == size3); 2659cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, memcmp(buffer, buffer2, size1) == 0); 2660cb93a386Sopenharmony_ci 2661cb93a386Sopenharmony_ci // test persistence of the oval flag & convexity 2662cb93a386Sopenharmony_ci { 2663cb93a386Sopenharmony_ci SkPath oval; 2664cb93a386Sopenharmony_ci SkRect rect = SkRect::MakeWH(10, 10); 2665cb93a386Sopenharmony_ci oval.addOval(rect); 2666cb93a386Sopenharmony_ci 2667cb93a386Sopenharmony_ci write_and_read_back(reporter, oval); 2668cb93a386Sopenharmony_ci } 2669cb93a386Sopenharmony_ci} 2670cb93a386Sopenharmony_ci 2671cb93a386Sopenharmony_cistatic void test_transform(skiatest::Reporter* reporter) { 2672cb93a386Sopenharmony_ci SkPath p; 2673cb93a386Sopenharmony_ci 2674cb93a386Sopenharmony_ci#define CONIC_PERSPECTIVE_BUG_FIXED 0 2675cb93a386Sopenharmony_ci static const SkPoint pts[] = { 2676cb93a386Sopenharmony_ci { 0, 0 }, // move 2677cb93a386Sopenharmony_ci { SkIntToScalar(10), SkIntToScalar(10) }, // line 2678cb93a386Sopenharmony_ci { SkIntToScalar(20), SkIntToScalar(10) }, { SkIntToScalar(20), 0 }, // quad 2679cb93a386Sopenharmony_ci { 0, 0 }, { 0, SkIntToScalar(10) }, { SkIntToScalar(1), SkIntToScalar(10) }, // cubic 2680cb93a386Sopenharmony_ci#if CONIC_PERSPECTIVE_BUG_FIXED 2681cb93a386Sopenharmony_ci { 0, 0 }, { SkIntToScalar(20), SkIntToScalar(10) }, // conic 2682cb93a386Sopenharmony_ci#endif 2683cb93a386Sopenharmony_ci }; 2684cb93a386Sopenharmony_ci const int kPtCount = SK_ARRAY_COUNT(pts); 2685cb93a386Sopenharmony_ci 2686cb93a386Sopenharmony_ci p.moveTo(pts[0]); 2687cb93a386Sopenharmony_ci p.lineTo(pts[1]); 2688cb93a386Sopenharmony_ci p.quadTo(pts[2], pts[3]); 2689cb93a386Sopenharmony_ci p.cubicTo(pts[4], pts[5], pts[6]); 2690cb93a386Sopenharmony_ci#if CONIC_PERSPECTIVE_BUG_FIXED 2691cb93a386Sopenharmony_ci p.conicTo(pts[4], pts[5], 0.5f); 2692cb93a386Sopenharmony_ci#endif 2693cb93a386Sopenharmony_ci p.close(); 2694cb93a386Sopenharmony_ci 2695cb93a386Sopenharmony_ci { 2696cb93a386Sopenharmony_ci SkMatrix matrix; 2697cb93a386Sopenharmony_ci matrix.reset(); 2698cb93a386Sopenharmony_ci SkPath p1; 2699cb93a386Sopenharmony_ci p.transform(matrix, &p1); 2700cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p == p1); 2701cb93a386Sopenharmony_ci } 2702cb93a386Sopenharmony_ci 2703cb93a386Sopenharmony_ci 2704cb93a386Sopenharmony_ci { 2705cb93a386Sopenharmony_ci SkMatrix matrix; 2706cb93a386Sopenharmony_ci matrix.setScale(SK_Scalar1 * 2, SK_Scalar1 * 3); 2707cb93a386Sopenharmony_ci 2708cb93a386Sopenharmony_ci SkPath p1; // Leave p1 non-unique (i.e., the empty path) 2709cb93a386Sopenharmony_ci 2710cb93a386Sopenharmony_ci p.transform(matrix, &p1); 2711cb93a386Sopenharmony_ci SkPoint pts1[kPtCount]; 2712cb93a386Sopenharmony_ci int count = p1.getPoints(pts1, kPtCount); 2713cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, kPtCount == count); 2714cb93a386Sopenharmony_ci for (int i = 0; i < count; ++i) { 2715cb93a386Sopenharmony_ci SkPoint newPt = SkPoint::Make(pts[i].fX * 2, pts[i].fY * 3); 2716cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, newPt == pts1[i]); 2717cb93a386Sopenharmony_ci } 2718cb93a386Sopenharmony_ci } 2719cb93a386Sopenharmony_ci 2720cb93a386Sopenharmony_ci { 2721cb93a386Sopenharmony_ci SkMatrix matrix; 2722cb93a386Sopenharmony_ci matrix.reset(); 2723cb93a386Sopenharmony_ci matrix.setPerspX(4); 2724cb93a386Sopenharmony_ci 2725cb93a386Sopenharmony_ci SkPath p1; 2726cb93a386Sopenharmony_ci p1.moveTo(SkPoint::Make(0, 0)); 2727cb93a386Sopenharmony_ci 2728cb93a386Sopenharmony_ci p.transform(matrix, &p1, SkApplyPerspectiveClip::kNo); 2729cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, matrix.invert(&matrix)); 2730cb93a386Sopenharmony_ci p1.transform(matrix, nullptr, SkApplyPerspectiveClip::kNo); 2731cb93a386Sopenharmony_ci SkRect pBounds = p.getBounds(); 2732cb93a386Sopenharmony_ci SkRect p1Bounds = p1.getBounds(); 2733cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkScalarNearlyEqual(pBounds.fLeft, p1Bounds.fLeft)); 2734cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkScalarNearlyEqual(pBounds.fTop, p1Bounds.fTop)); 2735cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkScalarNearlyEqual(pBounds.fRight, p1Bounds.fRight)); 2736cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkScalarNearlyEqual(pBounds.fBottom, p1Bounds.fBottom)); 2737cb93a386Sopenharmony_ci } 2738cb93a386Sopenharmony_ci 2739cb93a386Sopenharmony_ci p.reset(); 2740cb93a386Sopenharmony_ci p.addCircle(0, 0, 1, SkPathDirection::kCW); 2741cb93a386Sopenharmony_ci 2742cb93a386Sopenharmony_ci { 2743cb93a386Sopenharmony_ci SkMatrix matrix; 2744cb93a386Sopenharmony_ci matrix.reset(); 2745cb93a386Sopenharmony_ci SkPath p1; 2746cb93a386Sopenharmony_ci p1.moveTo(SkPoint::Make(0, 0)); 2747cb93a386Sopenharmony_ci 2748cb93a386Sopenharmony_ci p.transform(matrix, &p1); 2749cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::ComputeFirstDirection(p1) == SkPathFirstDirection::kCW); 2750cb93a386Sopenharmony_ci } 2751cb93a386Sopenharmony_ci 2752cb93a386Sopenharmony_ci 2753cb93a386Sopenharmony_ci { 2754cb93a386Sopenharmony_ci SkMatrix matrix; 2755cb93a386Sopenharmony_ci matrix.reset(); 2756cb93a386Sopenharmony_ci matrix.setScaleX(-1); 2757cb93a386Sopenharmony_ci SkPath p1; 2758cb93a386Sopenharmony_ci p1.moveTo(SkPoint::Make(0, 0)); // Make p1 unique (i.e., not empty path) 2759cb93a386Sopenharmony_ci 2760cb93a386Sopenharmony_ci p.transform(matrix, &p1); 2761cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::ComputeFirstDirection(p1) == SkPathFirstDirection::kCCW); 2762cb93a386Sopenharmony_ci } 2763cb93a386Sopenharmony_ci 2764cb93a386Sopenharmony_ci { 2765cb93a386Sopenharmony_ci SkMatrix matrix; 2766cb93a386Sopenharmony_ci matrix.setAll(1, 1, 0, 1, 1, 0, 0, 0, 1); 2767cb93a386Sopenharmony_ci SkPath p1; 2768cb93a386Sopenharmony_ci p1.moveTo(SkPoint::Make(0, 0)); // Make p1 unique (i.e., not empty path) 2769cb93a386Sopenharmony_ci 2770cb93a386Sopenharmony_ci p.transform(matrix, &p1); 2771cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::ComputeFirstDirection(p1) == SkPathFirstDirection::kUnknown); 2772cb93a386Sopenharmony_ci } 2773cb93a386Sopenharmony_ci 2774cb93a386Sopenharmony_ci { 2775cb93a386Sopenharmony_ci SkPath p1; 2776cb93a386Sopenharmony_ci p1.addRect({ 10, 20, 30, 40 }); 2777cb93a386Sopenharmony_ci SkPath p2; 2778cb93a386Sopenharmony_ci p2.addRect({ 10, 20, 30, 40 }); 2779cb93a386Sopenharmony_ci uint32_t id1 = p1.getGenerationID(); 2780cb93a386Sopenharmony_ci uint32_t id2 = p2.getGenerationID(); 2781cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, id1 != id2); 2782cb93a386Sopenharmony_ci SkMatrix matrix; 2783cb93a386Sopenharmony_ci matrix.setScale(2, 2); 2784cb93a386Sopenharmony_ci p1.transform(matrix, &p2); 2785cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, id1 == p1.getGenerationID()); 2786cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, id2 != p2.getGenerationID()); 2787cb93a386Sopenharmony_ci p1.transform(matrix); 2788cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, id1 != p1.getGenerationID()); 2789cb93a386Sopenharmony_ci } 2790cb93a386Sopenharmony_ci} 2791cb93a386Sopenharmony_ci 2792cb93a386Sopenharmony_cistatic void test_zero_length_paths(skiatest::Reporter* reporter) { 2793cb93a386Sopenharmony_ci SkPath p; 2794cb93a386Sopenharmony_ci uint8_t verbs[32]; 2795cb93a386Sopenharmony_ci 2796cb93a386Sopenharmony_ci struct SUPPRESS_VISIBILITY_WARNING zeroPathTestData { 2797cb93a386Sopenharmony_ci const char* testPath; 2798cb93a386Sopenharmony_ci const size_t numResultPts; 2799cb93a386Sopenharmony_ci const SkRect resultBound; 2800cb93a386Sopenharmony_ci const SkPath::Verb* resultVerbs; 2801cb93a386Sopenharmony_ci const size_t numResultVerbs; 2802cb93a386Sopenharmony_ci }; 2803cb93a386Sopenharmony_ci 2804cb93a386Sopenharmony_ci static const SkPath::Verb resultVerbs1[] = { SkPath::kMove_Verb }; 2805cb93a386Sopenharmony_ci static const SkPath::Verb resultVerbs2[] = { SkPath::kMove_Verb, SkPath::kMove_Verb }; 2806cb93a386Sopenharmony_ci static const SkPath::Verb resultVerbs3[] = { SkPath::kMove_Verb, SkPath::kClose_Verb }; 2807cb93a386Sopenharmony_ci static const SkPath::Verb resultVerbs4[] = { SkPath::kMove_Verb, SkPath::kClose_Verb, SkPath::kMove_Verb, SkPath::kClose_Verb }; 2808cb93a386Sopenharmony_ci static const SkPath::Verb resultVerbs5[] = { SkPath::kMove_Verb, SkPath::kLine_Verb }; 2809cb93a386Sopenharmony_ci static const SkPath::Verb resultVerbs6[] = { SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kMove_Verb, SkPath::kLine_Verb }; 2810cb93a386Sopenharmony_ci static const SkPath::Verb resultVerbs7[] = { SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kClose_Verb }; 2811cb93a386Sopenharmony_ci static const SkPath::Verb resultVerbs8[] = { 2812cb93a386Sopenharmony_ci SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kClose_Verb, SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kClose_Verb 2813cb93a386Sopenharmony_ci }; 2814cb93a386Sopenharmony_ci static const SkPath::Verb resultVerbs9[] = { SkPath::kMove_Verb, SkPath::kQuad_Verb }; 2815cb93a386Sopenharmony_ci static const SkPath::Verb resultVerbs10[] = { SkPath::kMove_Verb, SkPath::kQuad_Verb, SkPath::kMove_Verb, SkPath::kQuad_Verb }; 2816cb93a386Sopenharmony_ci static const SkPath::Verb resultVerbs11[] = { SkPath::kMove_Verb, SkPath::kQuad_Verb, SkPath::kClose_Verb }; 2817cb93a386Sopenharmony_ci static const SkPath::Verb resultVerbs12[] = { 2818cb93a386Sopenharmony_ci SkPath::kMove_Verb, SkPath::kQuad_Verb, SkPath::kClose_Verb, SkPath::kMove_Verb, SkPath::kQuad_Verb, SkPath::kClose_Verb 2819cb93a386Sopenharmony_ci }; 2820cb93a386Sopenharmony_ci static const SkPath::Verb resultVerbs13[] = { SkPath::kMove_Verb, SkPath::kCubic_Verb }; 2821cb93a386Sopenharmony_ci static const SkPath::Verb resultVerbs14[] = { SkPath::kMove_Verb, SkPath::kCubic_Verb, SkPath::kMove_Verb, SkPath::kCubic_Verb }; 2822cb93a386Sopenharmony_ci static const SkPath::Verb resultVerbs15[] = { SkPath::kMove_Verb, SkPath::kCubic_Verb, SkPath::kClose_Verb }; 2823cb93a386Sopenharmony_ci static const SkPath::Verb resultVerbs16[] = { 2824cb93a386Sopenharmony_ci SkPath::kMove_Verb, SkPath::kCubic_Verb, SkPath::kClose_Verb, SkPath::kMove_Verb, SkPath::kCubic_Verb, SkPath::kClose_Verb 2825cb93a386Sopenharmony_ci }; 2826cb93a386Sopenharmony_ci static const struct zeroPathTestData gZeroLengthTests[] = { 2827cb93a386Sopenharmony_ci { "M 1 1", 1, {1, 1, 1, 1}, resultVerbs1, SK_ARRAY_COUNT(resultVerbs1) }, 2828cb93a386Sopenharmony_ci { "M 1 1 M 2 1", 2, {SK_Scalar1, SK_Scalar1, 2*SK_Scalar1, SK_Scalar1}, resultVerbs2, SK_ARRAY_COUNT(resultVerbs2) }, 2829cb93a386Sopenharmony_ci { "M 1 1 z", 1, {1, 1, 1, 1}, resultVerbs3, SK_ARRAY_COUNT(resultVerbs3) }, 2830cb93a386Sopenharmony_ci { "M 1 1 z M 2 1 z", 2, {SK_Scalar1, SK_Scalar1, 2*SK_Scalar1, SK_Scalar1}, resultVerbs4, SK_ARRAY_COUNT(resultVerbs4) }, 2831cb93a386Sopenharmony_ci { "M 1 1 L 1 1", 2, {SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1}, resultVerbs5, SK_ARRAY_COUNT(resultVerbs5) }, 2832cb93a386Sopenharmony_ci { "M 1 1 L 1 1 M 2 1 L 2 1", 4, {SK_Scalar1, SK_Scalar1, 2*SK_Scalar1, SK_Scalar1}, resultVerbs6, SK_ARRAY_COUNT(resultVerbs6) }, 2833cb93a386Sopenharmony_ci { "M 1 1 L 1 1 z", 2, {SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1}, resultVerbs7, SK_ARRAY_COUNT(resultVerbs7) }, 2834cb93a386Sopenharmony_ci { "M 1 1 L 1 1 z M 2 1 L 2 1 z", 4, {SK_Scalar1, SK_Scalar1, 2*SK_Scalar1, SK_Scalar1}, resultVerbs8, SK_ARRAY_COUNT(resultVerbs8) }, 2835cb93a386Sopenharmony_ci { "M 1 1 Q 1 1 1 1", 3, {SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1}, resultVerbs9, SK_ARRAY_COUNT(resultVerbs9) }, 2836cb93a386Sopenharmony_ci { "M 1 1 Q 1 1 1 1 M 2 1 Q 2 1 2 1", 6, {SK_Scalar1, SK_Scalar1, 2*SK_Scalar1, SK_Scalar1}, resultVerbs10, SK_ARRAY_COUNT(resultVerbs10) }, 2837cb93a386Sopenharmony_ci { "M 1 1 Q 1 1 1 1 z", 3, {SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1}, resultVerbs11, SK_ARRAY_COUNT(resultVerbs11) }, 2838cb93a386Sopenharmony_ci { "M 1 1 Q 1 1 1 1 z M 2 1 Q 2 1 2 1 z", 6, {SK_Scalar1, SK_Scalar1, 2*SK_Scalar1, SK_Scalar1}, resultVerbs12, SK_ARRAY_COUNT(resultVerbs12) }, 2839cb93a386Sopenharmony_ci { "M 1 1 C 1 1 1 1 1 1", 4, {SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1}, resultVerbs13, SK_ARRAY_COUNT(resultVerbs13) }, 2840cb93a386Sopenharmony_ci { "M 1 1 C 1 1 1 1 1 1 M 2 1 C 2 1 2 1 2 1", 8, {SK_Scalar1, SK_Scalar1, 2*SK_Scalar1, SK_Scalar1}, resultVerbs14, 2841cb93a386Sopenharmony_ci SK_ARRAY_COUNT(resultVerbs14) 2842cb93a386Sopenharmony_ci }, 2843cb93a386Sopenharmony_ci { "M 1 1 C 1 1 1 1 1 1 z", 4, {SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1}, resultVerbs15, SK_ARRAY_COUNT(resultVerbs15) }, 2844cb93a386Sopenharmony_ci { "M 1 1 C 1 1 1 1 1 1 z M 2 1 C 2 1 2 1 2 1 z", 8, {SK_Scalar1, SK_Scalar1, 2*SK_Scalar1, SK_Scalar1}, resultVerbs16, 2845cb93a386Sopenharmony_ci SK_ARRAY_COUNT(resultVerbs16) 2846cb93a386Sopenharmony_ci } 2847cb93a386Sopenharmony_ci }; 2848cb93a386Sopenharmony_ci 2849cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(gZeroLengthTests); ++i) { 2850cb93a386Sopenharmony_ci p.reset(); 2851cb93a386Sopenharmony_ci bool valid = SkParsePath::FromSVGString(gZeroLengthTests[i].testPath, &p); 2852cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, valid); 2853cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.isEmpty()); 2854cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, gZeroLengthTests[i].numResultPts == (size_t)p.countPoints()); 2855cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, gZeroLengthTests[i].resultBound == p.getBounds()); 2856cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, gZeroLengthTests[i].numResultVerbs == (size_t)p.getVerbs(verbs, SK_ARRAY_COUNT(verbs))); 2857cb93a386Sopenharmony_ci for (size_t j = 0; j < gZeroLengthTests[i].numResultVerbs; ++j) { 2858cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, gZeroLengthTests[i].resultVerbs[j] == verbs[j]); 2859cb93a386Sopenharmony_ci } 2860cb93a386Sopenharmony_ci } 2861cb93a386Sopenharmony_ci} 2862cb93a386Sopenharmony_ci 2863cb93a386Sopenharmony_cistruct SegmentInfo { 2864cb93a386Sopenharmony_ci SkPath fPath; 2865cb93a386Sopenharmony_ci int fPointCount; 2866cb93a386Sopenharmony_ci}; 2867cb93a386Sopenharmony_ci 2868cb93a386Sopenharmony_ci#define kCurveSegmentMask (SkPath::kQuad_SegmentMask | SkPath::kCubic_SegmentMask) 2869cb93a386Sopenharmony_ci 2870cb93a386Sopenharmony_cistatic void test_segment_masks(skiatest::Reporter* reporter) { 2871cb93a386Sopenharmony_ci SkPath p, p2; 2872cb93a386Sopenharmony_ci 2873cb93a386Sopenharmony_ci p.moveTo(0, 0); 2874cb93a386Sopenharmony_ci p.quadTo(100, 100, 200, 200); 2875cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kQuad_SegmentMask == p.getSegmentMasks()); 2876cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.isEmpty()); 2877cb93a386Sopenharmony_ci p2 = p; 2878cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p2.getSegmentMasks() == p.getSegmentMasks()); 2879cb93a386Sopenharmony_ci p.cubicTo(100, 100, 200, 200, 300, 300); 2880cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, kCurveSegmentMask == p.getSegmentMasks()); 2881cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.isEmpty()); 2882cb93a386Sopenharmony_ci p2 = p; 2883cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p2.getSegmentMasks() == p.getSegmentMasks()); 2884cb93a386Sopenharmony_ci 2885cb93a386Sopenharmony_ci p.reset(); 2886cb93a386Sopenharmony_ci p.moveTo(0, 0); 2887cb93a386Sopenharmony_ci p.cubicTo(100, 100, 200, 200, 300, 300); 2888cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kCubic_SegmentMask == p.getSegmentMasks()); 2889cb93a386Sopenharmony_ci p2 = p; 2890cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p2.getSegmentMasks() == p.getSegmentMasks()); 2891cb93a386Sopenharmony_ci 2892cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.isEmpty()); 2893cb93a386Sopenharmony_ci} 2894cb93a386Sopenharmony_ci 2895cb93a386Sopenharmony_cistatic void test_iter(skiatest::Reporter* reporter) { 2896cb93a386Sopenharmony_ci SkPath p; 2897cb93a386Sopenharmony_ci SkPoint pts[4]; 2898cb93a386Sopenharmony_ci 2899cb93a386Sopenharmony_ci // Test an iterator with no path 2900cb93a386Sopenharmony_ci SkPath::Iter noPathIter; 2901cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, noPathIter.next(pts) == SkPath::kDone_Verb); 2902cb93a386Sopenharmony_ci 2903cb93a386Sopenharmony_ci // Test that setting an empty path works 2904cb93a386Sopenharmony_ci noPathIter.setPath(p, false); 2905cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, noPathIter.next(pts) == SkPath::kDone_Verb); 2906cb93a386Sopenharmony_ci 2907cb93a386Sopenharmony_ci // Test that close path makes no difference for an empty path 2908cb93a386Sopenharmony_ci noPathIter.setPath(p, true); 2909cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, noPathIter.next(pts) == SkPath::kDone_Verb); 2910cb93a386Sopenharmony_ci 2911cb93a386Sopenharmony_ci // Test an iterator with an initial empty path 2912cb93a386Sopenharmony_ci SkPath::Iter iter(p, false); 2913cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kDone_Verb); 2914cb93a386Sopenharmony_ci 2915cb93a386Sopenharmony_ci // Test that close path makes no difference 2916cb93a386Sopenharmony_ci iter.setPath(p, true); 2917cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kDone_Verb); 2918cb93a386Sopenharmony_ci 2919cb93a386Sopenharmony_ci 2920cb93a386Sopenharmony_ci struct iterTestData { 2921cb93a386Sopenharmony_ci const char* testPath; 2922cb93a386Sopenharmony_ci const bool forceClose; 2923cb93a386Sopenharmony_ci const size_t* numResultPtsPerVerb; 2924cb93a386Sopenharmony_ci const SkPoint* resultPts; 2925cb93a386Sopenharmony_ci const SkPath::Verb* resultVerbs; 2926cb93a386Sopenharmony_ci const size_t numResultVerbs; 2927cb93a386Sopenharmony_ci }; 2928cb93a386Sopenharmony_ci 2929cb93a386Sopenharmony_ci static const SkPath::Verb resultVerbs1[] = { SkPath::kDone_Verb }; 2930cb93a386Sopenharmony_ci static const SkPath::Verb resultVerbs2[] = { 2931cb93a386Sopenharmony_ci SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kMove_Verb, SkPath::kClose_Verb, SkPath::kDone_Verb 2932cb93a386Sopenharmony_ci }; 2933cb93a386Sopenharmony_ci static const SkPath::Verb resultVerbs3[] = { 2934cb93a386Sopenharmony_ci SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kClose_Verb, SkPath::kMove_Verb, SkPath::kClose_Verb, SkPath::kDone_Verb 2935cb93a386Sopenharmony_ci }; 2936cb93a386Sopenharmony_ci static const size_t resultPtsSizes1[] = { 0 }; 2937cb93a386Sopenharmony_ci static const size_t resultPtsSizes2[] = { 1, 2, 1, 1, 0 }; 2938cb93a386Sopenharmony_ci static const size_t resultPtsSizes3[] = { 1, 2, 1, 1, 1, 0 }; 2939cb93a386Sopenharmony_ci static const SkPoint* resultPts1 = nullptr; 2940cb93a386Sopenharmony_ci static const SkPoint resultPts2[] = { 2941cb93a386Sopenharmony_ci { SK_Scalar1, 0 }, { SK_Scalar1, 0 }, { SK_Scalar1, 0 }, { 0, 0 }, { 0, 0 } 2942cb93a386Sopenharmony_ci }; 2943cb93a386Sopenharmony_ci static const SkPoint resultPts3[] = { 2944cb93a386Sopenharmony_ci { SK_Scalar1, 0 }, { SK_Scalar1, 0 }, { SK_Scalar1, 0 }, { SK_Scalar1, 0 }, { 0, 0 }, { 0, 0 } 2945cb93a386Sopenharmony_ci }; 2946cb93a386Sopenharmony_ci static const struct iterTestData gIterTests[] = { 2947cb93a386Sopenharmony_ci { "M 1 0", false, resultPtsSizes1, resultPts1, resultVerbs1, SK_ARRAY_COUNT(resultVerbs1) }, 2948cb93a386Sopenharmony_ci { "z", false, resultPtsSizes1, resultPts1, resultVerbs1, SK_ARRAY_COUNT(resultVerbs1) }, 2949cb93a386Sopenharmony_ci { "z", true, resultPtsSizes1, resultPts1, resultVerbs1, SK_ARRAY_COUNT(resultVerbs1) }, 2950cb93a386Sopenharmony_ci { "M 1 0 L 1 0 M 0 0 z", false, resultPtsSizes2, resultPts2, resultVerbs2, SK_ARRAY_COUNT(resultVerbs2) }, 2951cb93a386Sopenharmony_ci { "M 1 0 L 1 0 M 0 0 z", true, resultPtsSizes3, resultPts3, resultVerbs3, SK_ARRAY_COUNT(resultVerbs3) } 2952cb93a386Sopenharmony_ci }; 2953cb93a386Sopenharmony_ci 2954cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(gIterTests); ++i) { 2955cb93a386Sopenharmony_ci p.reset(); 2956cb93a386Sopenharmony_ci bool valid = SkParsePath::FromSVGString(gIterTests[i].testPath, &p); 2957cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, valid); 2958cb93a386Sopenharmony_ci iter.setPath(p, gIterTests[i].forceClose); 2959cb93a386Sopenharmony_ci int j = 0, l = 0; 2960cb93a386Sopenharmony_ci do { 2961cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, iter.next(pts) == gIterTests[i].resultVerbs[j]); 2962cb93a386Sopenharmony_ci for (int k = 0; k < (int)gIterTests[i].numResultPtsPerVerb[j]; ++k) { 2963cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[k] == gIterTests[i].resultPts[l++]); 2964cb93a386Sopenharmony_ci } 2965cb93a386Sopenharmony_ci } while (gIterTests[i].resultVerbs[j++] != SkPath::kDone_Verb); 2966cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, j == (int)gIterTests[i].numResultVerbs); 2967cb93a386Sopenharmony_ci } 2968cb93a386Sopenharmony_ci 2969cb93a386Sopenharmony_ci p.reset(); 2970cb93a386Sopenharmony_ci iter.setPath(p, false); 2971cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !iter.isClosedContour()); 2972cb93a386Sopenharmony_ci p.lineTo(1, 1); 2973cb93a386Sopenharmony_ci p.close(); 2974cb93a386Sopenharmony_ci iter.setPath(p, false); 2975cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, iter.isClosedContour()); 2976cb93a386Sopenharmony_ci p.reset(); 2977cb93a386Sopenharmony_ci iter.setPath(p, true); 2978cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !iter.isClosedContour()); 2979cb93a386Sopenharmony_ci p.lineTo(1, 1); 2980cb93a386Sopenharmony_ci iter.setPath(p, true); 2981cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, iter.isClosedContour()); 2982cb93a386Sopenharmony_ci p.moveTo(0, 0); 2983cb93a386Sopenharmony_ci p.lineTo(2, 2); 2984cb93a386Sopenharmony_ci iter.setPath(p, false); 2985cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !iter.isClosedContour()); 2986cb93a386Sopenharmony_ci 2987cb93a386Sopenharmony_ci // this checks to see if the NaN logic is executed in SkPath::autoClose(), but does not 2988cb93a386Sopenharmony_ci // check to see if the result is correct. 2989cb93a386Sopenharmony_ci for (int setNaN = 0; setNaN < 4; ++setNaN) { 2990cb93a386Sopenharmony_ci p.reset(); 2991cb93a386Sopenharmony_ci p.moveTo(setNaN == 0 ? SK_ScalarNaN : 0, setNaN == 1 ? SK_ScalarNaN : 0); 2992cb93a386Sopenharmony_ci p.lineTo(setNaN == 2 ? SK_ScalarNaN : 1, setNaN == 3 ? SK_ScalarNaN : 1); 2993cb93a386Sopenharmony_ci iter.setPath(p, true); 2994cb93a386Sopenharmony_ci iter.next(pts); 2995cb93a386Sopenharmony_ci iter.next(pts); 2996cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kClose_Verb == iter.next(pts)); 2997cb93a386Sopenharmony_ci } 2998cb93a386Sopenharmony_ci 2999cb93a386Sopenharmony_ci p.reset(); 3000cb93a386Sopenharmony_ci p.quadTo(0, 0, 0, 0); 3001cb93a386Sopenharmony_ci iter.setPath(p, false); 3002cb93a386Sopenharmony_ci iter.next(pts); 3003cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kQuad_Verb == iter.next(pts)); 3004cb93a386Sopenharmony_ci 3005cb93a386Sopenharmony_ci p.reset(); 3006cb93a386Sopenharmony_ci p.conicTo(0, 0, 0, 0, 0.5f); 3007cb93a386Sopenharmony_ci iter.setPath(p, false); 3008cb93a386Sopenharmony_ci iter.next(pts); 3009cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kConic_Verb == iter.next(pts)); 3010cb93a386Sopenharmony_ci 3011cb93a386Sopenharmony_ci p.reset(); 3012cb93a386Sopenharmony_ci p.cubicTo(0, 0, 0, 0, 0, 0); 3013cb93a386Sopenharmony_ci iter.setPath(p, false); 3014cb93a386Sopenharmony_ci iter.next(pts); 3015cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kCubic_Verb == iter.next(pts)); 3016cb93a386Sopenharmony_ci 3017cb93a386Sopenharmony_ci p.moveTo(1, 1); // add a trailing moveto 3018cb93a386Sopenharmony_ci iter.setPath(p, false); 3019cb93a386Sopenharmony_ci iter.next(pts); 3020cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kCubic_Verb == iter.next(pts)); 3021cb93a386Sopenharmony_ci 3022cb93a386Sopenharmony_ci // The GM degeneratesegments.cpp test is more extensive 3023cb93a386Sopenharmony_ci 3024cb93a386Sopenharmony_ci // Test out mixed degenerate and non-degenerate geometry with Conics 3025cb93a386Sopenharmony_ci const SkVector radii[4] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 100, 100 } }; 3026cb93a386Sopenharmony_ci SkRect r = SkRect::MakeWH(100, 100); 3027cb93a386Sopenharmony_ci SkRRect rr; 3028cb93a386Sopenharmony_ci rr.setRectRadii(r, radii); 3029cb93a386Sopenharmony_ci p.reset(); 3030cb93a386Sopenharmony_ci p.addRRect(rr); 3031cb93a386Sopenharmony_ci iter.setPath(p, false); 3032cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kMove_Verb == iter.next(pts)); 3033cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kLine_Verb == iter.next(pts)); 3034cb93a386Sopenharmony_ci return; 3035cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kLine_Verb == iter.next(pts)); 3036cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kConic_Verb == iter.next(pts)); 3037cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SK_ScalarRoot2Over2 == iter.conicWeight()); 3038cb93a386Sopenharmony_ci} 3039cb93a386Sopenharmony_ci 3040cb93a386Sopenharmony_cistatic void test_range_iter(skiatest::Reporter* reporter) { 3041cb93a386Sopenharmony_ci SkPath path; 3042cb93a386Sopenharmony_ci 3043cb93a386Sopenharmony_ci // Test an iterator with an initial empty path 3044cb93a386Sopenharmony_ci SkPathPriv::Iterate iterate(path); 3045cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, iterate.begin() == iterate.end()); 3046cb93a386Sopenharmony_ci 3047cb93a386Sopenharmony_ci // Test that a move-only path returns the move. 3048cb93a386Sopenharmony_ci path.moveTo(SK_Scalar1, 0); 3049cb93a386Sopenharmony_ci iterate = SkPathPriv::Iterate(path); 3050cb93a386Sopenharmony_ci SkPathPriv::RangeIter iter = iterate.begin(); 3051cb93a386Sopenharmony_ci { 3052cb93a386Sopenharmony_ci auto [verb, pts, w] = *iter++; 3053cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verb == SkPathVerb::kMove); 3054cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1); 3055cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].fY == 0); 3056cb93a386Sopenharmony_ci } 3057cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, iter == iterate.end()); 3058cb93a386Sopenharmony_ci 3059cb93a386Sopenharmony_ci // No matter how many moves we add, we should get them all back 3060cb93a386Sopenharmony_ci path.moveTo(SK_Scalar1*2, SK_Scalar1); 3061cb93a386Sopenharmony_ci path.moveTo(SK_Scalar1*3, SK_Scalar1*2); 3062cb93a386Sopenharmony_ci iterate = SkPathPriv::Iterate(path); 3063cb93a386Sopenharmony_ci iter = iterate.begin(); 3064cb93a386Sopenharmony_ci { 3065cb93a386Sopenharmony_ci auto [verb, pts, w] = *iter++; 3066cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verb == SkPathVerb::kMove); 3067cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1); 3068cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].fY == 0); 3069cb93a386Sopenharmony_ci } 3070cb93a386Sopenharmony_ci { 3071cb93a386Sopenharmony_ci auto [verb, pts, w] = *iter++; 3072cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verb == SkPathVerb::kMove); 3073cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*2); 3074cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1); 3075cb93a386Sopenharmony_ci } 3076cb93a386Sopenharmony_ci { 3077cb93a386Sopenharmony_ci auto [verb, pts, w] = *iter++; 3078cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verb == SkPathVerb::kMove); 3079cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*3); 3080cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1*2); 3081cb93a386Sopenharmony_ci } 3082cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, iter == iterate.end()); 3083cb93a386Sopenharmony_ci 3084cb93a386Sopenharmony_ci // Initial close is never ever stored 3085cb93a386Sopenharmony_ci path.reset(); 3086cb93a386Sopenharmony_ci path.close(); 3087cb93a386Sopenharmony_ci iterate = SkPathPriv::Iterate(path); 3088cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, iterate.begin() == iterate.end()); 3089cb93a386Sopenharmony_ci 3090cb93a386Sopenharmony_ci // Move/close sequences 3091cb93a386Sopenharmony_ci path.reset(); 3092cb93a386Sopenharmony_ci path.close(); // Not stored, no purpose 3093cb93a386Sopenharmony_ci path.moveTo(SK_Scalar1, 0); 3094cb93a386Sopenharmony_ci path.close(); 3095cb93a386Sopenharmony_ci path.close(); // Not stored, no purpose 3096cb93a386Sopenharmony_ci path.moveTo(SK_Scalar1*2, SK_Scalar1); 3097cb93a386Sopenharmony_ci path.close(); 3098cb93a386Sopenharmony_ci path.moveTo(SK_Scalar1*3, SK_Scalar1*2); 3099cb93a386Sopenharmony_ci path.moveTo(SK_Scalar1*4, SK_Scalar1*3); 3100cb93a386Sopenharmony_ci path.close(); 3101cb93a386Sopenharmony_ci iterate = SkPathPriv::Iterate(path); 3102cb93a386Sopenharmony_ci iter = iterate.begin(); 3103cb93a386Sopenharmony_ci { 3104cb93a386Sopenharmony_ci auto [verb, pts, w] = *iter++; 3105cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verb == SkPathVerb::kMove); 3106cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1); 3107cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].fY == 0); 3108cb93a386Sopenharmony_ci } 3109cb93a386Sopenharmony_ci { 3110cb93a386Sopenharmony_ci auto [verb, pts, w] = *iter++; 3111cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verb == SkPathVerb::kClose); 3112cb93a386Sopenharmony_ci } 3113cb93a386Sopenharmony_ci { 3114cb93a386Sopenharmony_ci auto [verb, pts, w] = *iter++; 3115cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verb == SkPathVerb::kMove); 3116cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*2); 3117cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1); 3118cb93a386Sopenharmony_ci } 3119cb93a386Sopenharmony_ci { 3120cb93a386Sopenharmony_ci auto [verb, pts, w] = *iter++; 3121cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verb == SkPathVerb::kClose); 3122cb93a386Sopenharmony_ci } 3123cb93a386Sopenharmony_ci { 3124cb93a386Sopenharmony_ci auto [verb, pts, w] = *iter++; 3125cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verb == SkPathVerb::kMove); 3126cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*3); 3127cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1*2); 3128cb93a386Sopenharmony_ci } 3129cb93a386Sopenharmony_ci { 3130cb93a386Sopenharmony_ci auto [verb, pts, w] = *iter++; 3131cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verb == SkPathVerb::kMove); 3132cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*4); 3133cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1*3); 3134cb93a386Sopenharmony_ci } 3135cb93a386Sopenharmony_ci { 3136cb93a386Sopenharmony_ci auto [verb, pts, w] = *iter++; 3137cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verb == SkPathVerb::kClose); 3138cb93a386Sopenharmony_ci } 3139cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, iter == iterate.end()); 3140cb93a386Sopenharmony_ci 3141cb93a386Sopenharmony_ci // Generate random paths and verify 3142cb93a386Sopenharmony_ci SkPoint randomPts[25]; 3143cb93a386Sopenharmony_ci for (int i = 0; i < 5; ++i) { 3144cb93a386Sopenharmony_ci for (int j = 0; j < 5; ++j) { 3145cb93a386Sopenharmony_ci randomPts[i*5+j].set(SK_Scalar1*i, SK_Scalar1*j); 3146cb93a386Sopenharmony_ci } 3147cb93a386Sopenharmony_ci } 3148cb93a386Sopenharmony_ci 3149cb93a386Sopenharmony_ci // Max of 10 segments, max 3 points per segment 3150cb93a386Sopenharmony_ci SkRandom rand(9876543); 3151cb93a386Sopenharmony_ci SkPoint expectedPts[31]; // May have leading moveTo 3152cb93a386Sopenharmony_ci SkPathVerb expectedVerbs[22]; // May have leading moveTo 3153cb93a386Sopenharmony_ci SkPathVerb nextVerb; 3154cb93a386Sopenharmony_ci 3155cb93a386Sopenharmony_ci for (int i = 0; i < 500; ++i) { 3156cb93a386Sopenharmony_ci path.reset(); 3157cb93a386Sopenharmony_ci bool lastWasClose = true; 3158cb93a386Sopenharmony_ci bool haveMoveTo = false; 3159cb93a386Sopenharmony_ci SkPoint lastMoveToPt = { 0, 0 }; 3160cb93a386Sopenharmony_ci int numPoints = 0; 3161cb93a386Sopenharmony_ci int numVerbs = (rand.nextU() >> 16) % 10; 3162cb93a386Sopenharmony_ci int numIterVerbs = 0; 3163cb93a386Sopenharmony_ci for (int j = 0; j < numVerbs; ++j) { 3164cb93a386Sopenharmony_ci do { 3165cb93a386Sopenharmony_ci nextVerb = static_cast<SkPathVerb>((rand.nextU() >> 16) % SkPath::kDone_Verb); 3166cb93a386Sopenharmony_ci } while (lastWasClose && nextVerb == SkPathVerb::kClose); 3167cb93a386Sopenharmony_ci switch (nextVerb) { 3168cb93a386Sopenharmony_ci case SkPathVerb::kMove: 3169cb93a386Sopenharmony_ci expectedPts[numPoints] = randomPts[(rand.nextU() >> 16) % 25]; 3170cb93a386Sopenharmony_ci path.moveTo(expectedPts[numPoints]); 3171cb93a386Sopenharmony_ci lastMoveToPt = expectedPts[numPoints]; 3172cb93a386Sopenharmony_ci numPoints += 1; 3173cb93a386Sopenharmony_ci lastWasClose = false; 3174cb93a386Sopenharmony_ci haveMoveTo = true; 3175cb93a386Sopenharmony_ci break; 3176cb93a386Sopenharmony_ci case SkPathVerb::kLine: 3177cb93a386Sopenharmony_ci if (!haveMoveTo) { 3178cb93a386Sopenharmony_ci expectedPts[numPoints++] = lastMoveToPt; 3179cb93a386Sopenharmony_ci expectedVerbs[numIterVerbs++] = SkPathVerb::kMove; 3180cb93a386Sopenharmony_ci haveMoveTo = true; 3181cb93a386Sopenharmony_ci } 3182cb93a386Sopenharmony_ci expectedPts[numPoints] = randomPts[(rand.nextU() >> 16) % 25]; 3183cb93a386Sopenharmony_ci path.lineTo(expectedPts[numPoints]); 3184cb93a386Sopenharmony_ci numPoints += 1; 3185cb93a386Sopenharmony_ci lastWasClose = false; 3186cb93a386Sopenharmony_ci break; 3187cb93a386Sopenharmony_ci case SkPathVerb::kQuad: 3188cb93a386Sopenharmony_ci if (!haveMoveTo) { 3189cb93a386Sopenharmony_ci expectedPts[numPoints++] = lastMoveToPt; 3190cb93a386Sopenharmony_ci expectedVerbs[numIterVerbs++] = SkPathVerb::kMove; 3191cb93a386Sopenharmony_ci haveMoveTo = true; 3192cb93a386Sopenharmony_ci } 3193cb93a386Sopenharmony_ci expectedPts[numPoints] = randomPts[(rand.nextU() >> 16) % 25]; 3194cb93a386Sopenharmony_ci expectedPts[numPoints + 1] = randomPts[(rand.nextU() >> 16) % 25]; 3195cb93a386Sopenharmony_ci path.quadTo(expectedPts[numPoints], expectedPts[numPoints + 1]); 3196cb93a386Sopenharmony_ci numPoints += 2; 3197cb93a386Sopenharmony_ci lastWasClose = false; 3198cb93a386Sopenharmony_ci break; 3199cb93a386Sopenharmony_ci case SkPathVerb::kConic: 3200cb93a386Sopenharmony_ci if (!haveMoveTo) { 3201cb93a386Sopenharmony_ci expectedPts[numPoints++] = lastMoveToPt; 3202cb93a386Sopenharmony_ci expectedVerbs[numIterVerbs++] = SkPathVerb::kMove; 3203cb93a386Sopenharmony_ci haveMoveTo = true; 3204cb93a386Sopenharmony_ci } 3205cb93a386Sopenharmony_ci expectedPts[numPoints] = randomPts[(rand.nextU() >> 16) % 25]; 3206cb93a386Sopenharmony_ci expectedPts[numPoints + 1] = randomPts[(rand.nextU() >> 16) % 25]; 3207cb93a386Sopenharmony_ci path.conicTo(expectedPts[numPoints], expectedPts[numPoints + 1], 3208cb93a386Sopenharmony_ci rand.nextUScalar1() * 4); 3209cb93a386Sopenharmony_ci numPoints += 2; 3210cb93a386Sopenharmony_ci lastWasClose = false; 3211cb93a386Sopenharmony_ci break; 3212cb93a386Sopenharmony_ci case SkPathVerb::kCubic: 3213cb93a386Sopenharmony_ci if (!haveMoveTo) { 3214cb93a386Sopenharmony_ci expectedPts[numPoints++] = lastMoveToPt; 3215cb93a386Sopenharmony_ci expectedVerbs[numIterVerbs++] = SkPathVerb::kMove; 3216cb93a386Sopenharmony_ci haveMoveTo = true; 3217cb93a386Sopenharmony_ci } 3218cb93a386Sopenharmony_ci expectedPts[numPoints] = randomPts[(rand.nextU() >> 16) % 25]; 3219cb93a386Sopenharmony_ci expectedPts[numPoints + 1] = randomPts[(rand.nextU() >> 16) % 25]; 3220cb93a386Sopenharmony_ci expectedPts[numPoints + 2] = randomPts[(rand.nextU() >> 16) % 25]; 3221cb93a386Sopenharmony_ci path.cubicTo(expectedPts[numPoints], expectedPts[numPoints + 1], 3222cb93a386Sopenharmony_ci expectedPts[numPoints + 2]); 3223cb93a386Sopenharmony_ci numPoints += 3; 3224cb93a386Sopenharmony_ci lastWasClose = false; 3225cb93a386Sopenharmony_ci break; 3226cb93a386Sopenharmony_ci case SkPathVerb::kClose: 3227cb93a386Sopenharmony_ci path.close(); 3228cb93a386Sopenharmony_ci haveMoveTo = false; 3229cb93a386Sopenharmony_ci lastWasClose = true; 3230cb93a386Sopenharmony_ci break; 3231cb93a386Sopenharmony_ci default: 3232cb93a386Sopenharmony_ci SkDEBUGFAIL("unexpected verb"); 3233cb93a386Sopenharmony_ci } 3234cb93a386Sopenharmony_ci expectedVerbs[numIterVerbs++] = nextVerb; 3235cb93a386Sopenharmony_ci } 3236cb93a386Sopenharmony_ci 3237cb93a386Sopenharmony_ci numVerbs = numIterVerbs; 3238cb93a386Sopenharmony_ci numIterVerbs = 0; 3239cb93a386Sopenharmony_ci int numIterPts = 0; 3240cb93a386Sopenharmony_ci SkPoint lastMoveTo; 3241cb93a386Sopenharmony_ci SkPoint lastPt; 3242cb93a386Sopenharmony_ci lastMoveTo.set(0, 0); 3243cb93a386Sopenharmony_ci lastPt.set(0, 0); 3244cb93a386Sopenharmony_ci for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) { 3245cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verb == expectedVerbs[numIterVerbs]); 3246cb93a386Sopenharmony_ci numIterVerbs++; 3247cb93a386Sopenharmony_ci switch (verb) { 3248cb93a386Sopenharmony_ci case SkPathVerb::kMove: 3249cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, numIterPts < numPoints); 3250cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0] == expectedPts[numIterPts]); 3251cb93a386Sopenharmony_ci lastPt = lastMoveTo = pts[0]; 3252cb93a386Sopenharmony_ci numIterPts += 1; 3253cb93a386Sopenharmony_ci break; 3254cb93a386Sopenharmony_ci case SkPathVerb::kLine: 3255cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, numIterPts < numPoints + 1); 3256cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0] == lastPt); 3257cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[1] == expectedPts[numIterPts]); 3258cb93a386Sopenharmony_ci lastPt = pts[1]; 3259cb93a386Sopenharmony_ci numIterPts += 1; 3260cb93a386Sopenharmony_ci break; 3261cb93a386Sopenharmony_ci case SkPathVerb::kQuad: 3262cb93a386Sopenharmony_ci case SkPathVerb::kConic: 3263cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, numIterPts < numPoints + 2); 3264cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0] == lastPt); 3265cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[1] == expectedPts[numIterPts]); 3266cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[2] == expectedPts[numIterPts + 1]); 3267cb93a386Sopenharmony_ci lastPt = pts[2]; 3268cb93a386Sopenharmony_ci numIterPts += 2; 3269cb93a386Sopenharmony_ci break; 3270cb93a386Sopenharmony_ci case SkPathVerb::kCubic: 3271cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, numIterPts < numPoints + 3); 3272cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0] == lastPt); 3273cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[1] == expectedPts[numIterPts]); 3274cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[2] == expectedPts[numIterPts + 1]); 3275cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[3] == expectedPts[numIterPts + 2]); 3276cb93a386Sopenharmony_ci lastPt = pts[3]; 3277cb93a386Sopenharmony_ci numIterPts += 3; 3278cb93a386Sopenharmony_ci break; 3279cb93a386Sopenharmony_ci case SkPathVerb::kClose: 3280cb93a386Sopenharmony_ci lastPt = lastMoveTo; 3281cb93a386Sopenharmony_ci break; 3282cb93a386Sopenharmony_ci default: 3283cb93a386Sopenharmony_ci SkDEBUGFAIL("unexpected verb"); 3284cb93a386Sopenharmony_ci } 3285cb93a386Sopenharmony_ci } 3286cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, numIterPts == numPoints); 3287cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, numIterVerbs == numVerbs); 3288cb93a386Sopenharmony_ci } 3289cb93a386Sopenharmony_ci} 3290cb93a386Sopenharmony_ci 3291cb93a386Sopenharmony_cistatic void check_for_circle(skiatest::Reporter* reporter, 3292cb93a386Sopenharmony_ci const SkPath& path, 3293cb93a386Sopenharmony_ci bool expectedCircle, 3294cb93a386Sopenharmony_ci SkPathFirstDirection expectedDir) { 3295cb93a386Sopenharmony_ci SkRect rect = SkRect::MakeEmpty(); 3296cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isOval(&rect) == expectedCircle); 3297cb93a386Sopenharmony_ci SkPathDirection isOvalDir; 3298cb93a386Sopenharmony_ci unsigned isOvalStart; 3299cb93a386Sopenharmony_ci if (SkPathPriv::IsOval(path, &rect, &isOvalDir, &isOvalStart)) { 3300cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, rect.height() == rect.width()); 3301cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::AsFirstDirection(isOvalDir) == expectedDir); 3302cb93a386Sopenharmony_ci SkPath tmpPath; 3303cb93a386Sopenharmony_ci tmpPath.addOval(rect, isOvalDir, isOvalStart); 3304cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path == tmpPath); 3305cb93a386Sopenharmony_ci } 3306cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::ComputeFirstDirection(path) == expectedDir); 3307cb93a386Sopenharmony_ci} 3308cb93a386Sopenharmony_ci 3309cb93a386Sopenharmony_cistatic void test_circle_skew(skiatest::Reporter* reporter, 3310cb93a386Sopenharmony_ci const SkPath& path, 3311cb93a386Sopenharmony_ci SkPathFirstDirection dir) { 3312cb93a386Sopenharmony_ci SkPath tmp; 3313cb93a386Sopenharmony_ci 3314cb93a386Sopenharmony_ci SkMatrix m; 3315cb93a386Sopenharmony_ci m.setSkew(SkIntToScalar(3), SkIntToScalar(5)); 3316cb93a386Sopenharmony_ci path.transform(m, &tmp); 3317cb93a386Sopenharmony_ci // this matrix reverses the direction. 3318cb93a386Sopenharmony_ci if (SkPathFirstDirection::kCCW == dir) { 3319cb93a386Sopenharmony_ci dir = SkPathFirstDirection::kCW; 3320cb93a386Sopenharmony_ci } else { 3321cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathFirstDirection::kCW == dir); 3322cb93a386Sopenharmony_ci dir = SkPathFirstDirection::kCCW; 3323cb93a386Sopenharmony_ci } 3324cb93a386Sopenharmony_ci check_for_circle(reporter, tmp, false, dir); 3325cb93a386Sopenharmony_ci} 3326cb93a386Sopenharmony_ci 3327cb93a386Sopenharmony_cistatic void test_circle_translate(skiatest::Reporter* reporter, 3328cb93a386Sopenharmony_ci const SkPath& path, 3329cb93a386Sopenharmony_ci SkPathFirstDirection dir) { 3330cb93a386Sopenharmony_ci SkPath tmp; 3331cb93a386Sopenharmony_ci 3332cb93a386Sopenharmony_ci // translate at small offset 3333cb93a386Sopenharmony_ci SkMatrix m; 3334cb93a386Sopenharmony_ci m.setTranslate(SkIntToScalar(15), SkIntToScalar(15)); 3335cb93a386Sopenharmony_ci path.transform(m, &tmp); 3336cb93a386Sopenharmony_ci check_for_circle(reporter, tmp, true, dir); 3337cb93a386Sopenharmony_ci 3338cb93a386Sopenharmony_ci tmp.reset(); 3339cb93a386Sopenharmony_ci m.reset(); 3340cb93a386Sopenharmony_ci 3341cb93a386Sopenharmony_ci // translate at a relatively big offset 3342cb93a386Sopenharmony_ci m.setTranslate(SkIntToScalar(1000), SkIntToScalar(1000)); 3343cb93a386Sopenharmony_ci path.transform(m, &tmp); 3344cb93a386Sopenharmony_ci check_for_circle(reporter, tmp, true, dir); 3345cb93a386Sopenharmony_ci} 3346cb93a386Sopenharmony_ci 3347cb93a386Sopenharmony_cistatic void test_circle_rotate(skiatest::Reporter* reporter, 3348cb93a386Sopenharmony_ci const SkPath& path, 3349cb93a386Sopenharmony_ci SkPathFirstDirection dir) { 3350cb93a386Sopenharmony_ci for (int angle = 0; angle < 360; ++angle) { 3351cb93a386Sopenharmony_ci SkPath tmp; 3352cb93a386Sopenharmony_ci SkMatrix m; 3353cb93a386Sopenharmony_ci m.setRotate(SkIntToScalar(angle)); 3354cb93a386Sopenharmony_ci path.transform(m, &tmp); 3355cb93a386Sopenharmony_ci 3356cb93a386Sopenharmony_ci // TODO: a rotated circle whose rotated angle is not a multiple of 90 3357cb93a386Sopenharmony_ci // degrees is not an oval anymore, this can be improved. we made this 3358cb93a386Sopenharmony_ci // for the simplicity of our implementation. 3359cb93a386Sopenharmony_ci if (angle % 90 == 0) { 3360cb93a386Sopenharmony_ci check_for_circle(reporter, tmp, true, dir); 3361cb93a386Sopenharmony_ci } else { 3362cb93a386Sopenharmony_ci check_for_circle(reporter, tmp, false, dir); 3363cb93a386Sopenharmony_ci } 3364cb93a386Sopenharmony_ci } 3365cb93a386Sopenharmony_ci} 3366cb93a386Sopenharmony_ci 3367cb93a386Sopenharmony_cistatic void test_circle_mirror_x(skiatest::Reporter* reporter, 3368cb93a386Sopenharmony_ci const SkPath& path, 3369cb93a386Sopenharmony_ci SkPathFirstDirection dir) { 3370cb93a386Sopenharmony_ci SkPath tmp; 3371cb93a386Sopenharmony_ci SkMatrix m; 3372cb93a386Sopenharmony_ci m.reset(); 3373cb93a386Sopenharmony_ci m.setScaleX(-SK_Scalar1); 3374cb93a386Sopenharmony_ci path.transform(m, &tmp); 3375cb93a386Sopenharmony_ci if (SkPathFirstDirection::kCW == dir) { 3376cb93a386Sopenharmony_ci dir = SkPathFirstDirection::kCCW; 3377cb93a386Sopenharmony_ci } else { 3378cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathFirstDirection::kCCW == dir); 3379cb93a386Sopenharmony_ci dir = SkPathFirstDirection::kCW; 3380cb93a386Sopenharmony_ci } 3381cb93a386Sopenharmony_ci check_for_circle(reporter, tmp, true, dir); 3382cb93a386Sopenharmony_ci} 3383cb93a386Sopenharmony_ci 3384cb93a386Sopenharmony_cistatic void test_circle_mirror_y(skiatest::Reporter* reporter, 3385cb93a386Sopenharmony_ci const SkPath& path, 3386cb93a386Sopenharmony_ci SkPathFirstDirection dir) { 3387cb93a386Sopenharmony_ci SkPath tmp; 3388cb93a386Sopenharmony_ci SkMatrix m; 3389cb93a386Sopenharmony_ci m.reset(); 3390cb93a386Sopenharmony_ci m.setScaleY(-SK_Scalar1); 3391cb93a386Sopenharmony_ci path.transform(m, &tmp); 3392cb93a386Sopenharmony_ci 3393cb93a386Sopenharmony_ci if (SkPathFirstDirection::kCW == dir) { 3394cb93a386Sopenharmony_ci dir = SkPathFirstDirection::kCCW; 3395cb93a386Sopenharmony_ci } else { 3396cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathFirstDirection::kCCW == dir); 3397cb93a386Sopenharmony_ci dir = SkPathFirstDirection::kCW; 3398cb93a386Sopenharmony_ci } 3399cb93a386Sopenharmony_ci 3400cb93a386Sopenharmony_ci check_for_circle(reporter, tmp, true, dir); 3401cb93a386Sopenharmony_ci} 3402cb93a386Sopenharmony_ci 3403cb93a386Sopenharmony_cistatic void test_circle_mirror_xy(skiatest::Reporter* reporter, 3404cb93a386Sopenharmony_ci const SkPath& path, 3405cb93a386Sopenharmony_ci SkPathFirstDirection dir) { 3406cb93a386Sopenharmony_ci SkPath tmp; 3407cb93a386Sopenharmony_ci SkMatrix m; 3408cb93a386Sopenharmony_ci m.reset(); 3409cb93a386Sopenharmony_ci m.setScaleX(-SK_Scalar1); 3410cb93a386Sopenharmony_ci m.setScaleY(-SK_Scalar1); 3411cb93a386Sopenharmony_ci path.transform(m, &tmp); 3412cb93a386Sopenharmony_ci 3413cb93a386Sopenharmony_ci check_for_circle(reporter, tmp, true, dir); 3414cb93a386Sopenharmony_ci} 3415cb93a386Sopenharmony_ci 3416cb93a386Sopenharmony_cistatic void test_circle_with_direction(skiatest::Reporter* reporter, 3417cb93a386Sopenharmony_ci SkPathDirection inDir) { 3418cb93a386Sopenharmony_ci const SkPathFirstDirection dir = SkPathPriv::AsFirstDirection(inDir); 3419cb93a386Sopenharmony_ci SkPath path; 3420cb93a386Sopenharmony_ci 3421cb93a386Sopenharmony_ci // circle at origin 3422cb93a386Sopenharmony_ci path.addCircle(0, 0, SkIntToScalar(20), inDir); 3423cb93a386Sopenharmony_ci 3424cb93a386Sopenharmony_ci check_for_circle(reporter, path, true, dir); 3425cb93a386Sopenharmony_ci test_circle_rotate(reporter, path, dir); 3426cb93a386Sopenharmony_ci test_circle_translate(reporter, path, dir); 3427cb93a386Sopenharmony_ci test_circle_skew(reporter, path, dir); 3428cb93a386Sopenharmony_ci test_circle_mirror_x(reporter, path, dir); 3429cb93a386Sopenharmony_ci test_circle_mirror_y(reporter, path, dir); 3430cb93a386Sopenharmony_ci test_circle_mirror_xy(reporter, path, dir); 3431cb93a386Sopenharmony_ci 3432cb93a386Sopenharmony_ci // circle at an offset at (10, 10) 3433cb93a386Sopenharmony_ci path.reset(); 3434cb93a386Sopenharmony_ci path.addCircle(SkIntToScalar(10), SkIntToScalar(10), 3435cb93a386Sopenharmony_ci SkIntToScalar(20), inDir); 3436cb93a386Sopenharmony_ci 3437cb93a386Sopenharmony_ci check_for_circle(reporter, path, true, dir); 3438cb93a386Sopenharmony_ci test_circle_rotate(reporter, path, dir); 3439cb93a386Sopenharmony_ci test_circle_translate(reporter, path, dir); 3440cb93a386Sopenharmony_ci test_circle_skew(reporter, path, dir); 3441cb93a386Sopenharmony_ci test_circle_mirror_x(reporter, path, dir); 3442cb93a386Sopenharmony_ci test_circle_mirror_y(reporter, path, dir); 3443cb93a386Sopenharmony_ci test_circle_mirror_xy(reporter, path, dir); 3444cb93a386Sopenharmony_ci 3445cb93a386Sopenharmony_ci // Try different starting points for the contour. 3446cb93a386Sopenharmony_ci for (unsigned start = 0; start < 4; ++start) { 3447cb93a386Sopenharmony_ci path.reset(); 3448cb93a386Sopenharmony_ci path.addOval(SkRect::MakeXYWH(20, 10, 5, 5), inDir, start); 3449cb93a386Sopenharmony_ci test_circle_rotate(reporter, path, dir); 3450cb93a386Sopenharmony_ci test_circle_translate(reporter, path, dir); 3451cb93a386Sopenharmony_ci test_circle_skew(reporter, path, dir); 3452cb93a386Sopenharmony_ci test_circle_mirror_x(reporter, path, dir); 3453cb93a386Sopenharmony_ci test_circle_mirror_y(reporter, path, dir); 3454cb93a386Sopenharmony_ci test_circle_mirror_xy(reporter, path, dir); 3455cb93a386Sopenharmony_ci } 3456cb93a386Sopenharmony_ci} 3457cb93a386Sopenharmony_ci 3458cb93a386Sopenharmony_cistatic void test_circle_with_add_paths(skiatest::Reporter* reporter) { 3459cb93a386Sopenharmony_ci SkPath path; 3460cb93a386Sopenharmony_ci SkPath circle; 3461cb93a386Sopenharmony_ci SkPath rect; 3462cb93a386Sopenharmony_ci SkPath empty; 3463cb93a386Sopenharmony_ci 3464cb93a386Sopenharmony_ci const SkPathDirection kCircleDir = SkPathDirection::kCW; 3465cb93a386Sopenharmony_ci const SkPathDirection kCircleDirOpposite = SkPathDirection::kCCW; 3466cb93a386Sopenharmony_ci 3467cb93a386Sopenharmony_ci circle.addCircle(0, 0, SkIntToScalar(10), kCircleDir); 3468cb93a386Sopenharmony_ci rect.addRect(SkIntToScalar(5), SkIntToScalar(5), 3469cb93a386Sopenharmony_ci SkIntToScalar(20), SkIntToScalar(20), SkPathDirection::kCW); 3470cb93a386Sopenharmony_ci 3471cb93a386Sopenharmony_ci SkMatrix translate; 3472cb93a386Sopenharmony_ci translate.setTranslate(SkIntToScalar(12), SkIntToScalar(12)); 3473cb93a386Sopenharmony_ci 3474cb93a386Sopenharmony_ci // Although all the path concatenation related operations leave 3475cb93a386Sopenharmony_ci // the path a circle, most mark it as a non-circle for simplicity 3476cb93a386Sopenharmony_ci 3477cb93a386Sopenharmony_ci // empty + circle (translate) 3478cb93a386Sopenharmony_ci path = empty; 3479cb93a386Sopenharmony_ci path.addPath(circle, translate); 3480cb93a386Sopenharmony_ci check_for_circle(reporter, path, false, SkPathPriv::AsFirstDirection(kCircleDir)); 3481cb93a386Sopenharmony_ci 3482cb93a386Sopenharmony_ci // circle + empty (translate) 3483cb93a386Sopenharmony_ci path = circle; 3484cb93a386Sopenharmony_ci path.addPath(empty, translate); 3485cb93a386Sopenharmony_ci 3486cb93a386Sopenharmony_ci check_for_circle(reporter, path, true, SkPathPriv::AsFirstDirection(kCircleDir)); 3487cb93a386Sopenharmony_ci 3488cb93a386Sopenharmony_ci // test reverseAddPath 3489cb93a386Sopenharmony_ci path = circle; 3490cb93a386Sopenharmony_ci path.reverseAddPath(rect); 3491cb93a386Sopenharmony_ci check_for_circle(reporter, path, false, SkPathPriv::AsFirstDirection(kCircleDirOpposite)); 3492cb93a386Sopenharmony_ci} 3493cb93a386Sopenharmony_ci 3494cb93a386Sopenharmony_cistatic void test_circle(skiatest::Reporter* reporter) { 3495cb93a386Sopenharmony_ci test_circle_with_direction(reporter, SkPathDirection::kCW); 3496cb93a386Sopenharmony_ci test_circle_with_direction(reporter, SkPathDirection::kCCW); 3497cb93a386Sopenharmony_ci 3498cb93a386Sopenharmony_ci // multiple addCircle() 3499cb93a386Sopenharmony_ci SkPath path; 3500cb93a386Sopenharmony_ci path.addCircle(0, 0, SkIntToScalar(10), SkPathDirection::kCW); 3501cb93a386Sopenharmony_ci path.addCircle(0, 0, SkIntToScalar(20), SkPathDirection::kCW); 3502cb93a386Sopenharmony_ci check_for_circle(reporter, path, false, SkPathFirstDirection::kCW); 3503cb93a386Sopenharmony_ci 3504cb93a386Sopenharmony_ci // some extra lineTo() would make isOval() fail 3505cb93a386Sopenharmony_ci path.reset(); 3506cb93a386Sopenharmony_ci path.addCircle(0, 0, SkIntToScalar(10), SkPathDirection::kCW); 3507cb93a386Sopenharmony_ci path.lineTo(0, 0); 3508cb93a386Sopenharmony_ci check_for_circle(reporter, path, false, SkPathFirstDirection::kCW); 3509cb93a386Sopenharmony_ci 3510cb93a386Sopenharmony_ci // not back to the original point 3511cb93a386Sopenharmony_ci path.reset(); 3512cb93a386Sopenharmony_ci path.addCircle(0, 0, SkIntToScalar(10), SkPathDirection::kCW); 3513cb93a386Sopenharmony_ci path.setLastPt(SkIntToScalar(5), SkIntToScalar(5)); 3514cb93a386Sopenharmony_ci check_for_circle(reporter, path, false, SkPathFirstDirection::kCW); 3515cb93a386Sopenharmony_ci 3516cb93a386Sopenharmony_ci test_circle_with_add_paths(reporter); 3517cb93a386Sopenharmony_ci 3518cb93a386Sopenharmony_ci // test negative radius 3519cb93a386Sopenharmony_ci path.reset(); 3520cb93a386Sopenharmony_ci path.addCircle(0, 0, -1, SkPathDirection::kCW); 3521cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isEmpty()); 3522cb93a386Sopenharmony_ci} 3523cb93a386Sopenharmony_ci 3524cb93a386Sopenharmony_cistatic void test_oval(skiatest::Reporter* reporter) { 3525cb93a386Sopenharmony_ci SkRect rect; 3526cb93a386Sopenharmony_ci SkMatrix m; 3527cb93a386Sopenharmony_ci SkPath path; 3528cb93a386Sopenharmony_ci unsigned start = 0; 3529cb93a386Sopenharmony_ci SkPathDirection dir = SkPathDirection::kCCW; 3530cb93a386Sopenharmony_ci 3531cb93a386Sopenharmony_ci rect = SkRect::MakeWH(SkIntToScalar(30), SkIntToScalar(50)); 3532cb93a386Sopenharmony_ci path.addOval(rect); 3533cb93a386Sopenharmony_ci 3534cb93a386Sopenharmony_ci // Defaults to dir = CW and start = 1 3535cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isOval(nullptr)); 3536cb93a386Sopenharmony_ci 3537cb93a386Sopenharmony_ci m.setRotate(SkIntToScalar(90)); 3538cb93a386Sopenharmony_ci SkPath tmp; 3539cb93a386Sopenharmony_ci path.transform(m, &tmp); 3540cb93a386Sopenharmony_ci // an oval rotated 90 degrees is still an oval. The start index changes from 1 to 2. Direction 3541cb93a386Sopenharmony_ci // is unchanged. 3542cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::IsOval(tmp, nullptr, &dir, &start)); 3543cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 2 == start); 3544cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathDirection::kCW == dir); 3545cb93a386Sopenharmony_ci 3546cb93a386Sopenharmony_ci m.reset(); 3547cb93a386Sopenharmony_ci m.setRotate(SkIntToScalar(30)); 3548cb93a386Sopenharmony_ci tmp.reset(); 3549cb93a386Sopenharmony_ci path.transform(m, &tmp); 3550cb93a386Sopenharmony_ci // an oval rotated 30 degrees is not an oval anymore. 3551cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !tmp.isOval(nullptr)); 3552cb93a386Sopenharmony_ci 3553cb93a386Sopenharmony_ci // since empty path being transformed. 3554cb93a386Sopenharmony_ci path.reset(); 3555cb93a386Sopenharmony_ci tmp.reset(); 3556cb93a386Sopenharmony_ci m.reset(); 3557cb93a386Sopenharmony_ci path.transform(m, &tmp); 3558cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !tmp.isOval(nullptr)); 3559cb93a386Sopenharmony_ci 3560cb93a386Sopenharmony_ci // empty path is not an oval 3561cb93a386Sopenharmony_ci tmp.reset(); 3562cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !tmp.isOval(nullptr)); 3563cb93a386Sopenharmony_ci 3564cb93a386Sopenharmony_ci // only has moveTo()s 3565cb93a386Sopenharmony_ci tmp.reset(); 3566cb93a386Sopenharmony_ci tmp.moveTo(0, 0); 3567cb93a386Sopenharmony_ci tmp.moveTo(SkIntToScalar(10), SkIntToScalar(10)); 3568cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !tmp.isOval(nullptr)); 3569cb93a386Sopenharmony_ci 3570cb93a386Sopenharmony_ci // mimic WebKit's calling convention, 3571cb93a386Sopenharmony_ci // call moveTo() first and then call addOval() 3572cb93a386Sopenharmony_ci path.reset(); 3573cb93a386Sopenharmony_ci path.moveTo(0, 0); 3574cb93a386Sopenharmony_ci path.addOval(rect); 3575cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isOval(nullptr)); 3576cb93a386Sopenharmony_ci 3577cb93a386Sopenharmony_ci // copy path 3578cb93a386Sopenharmony_ci path.reset(); 3579cb93a386Sopenharmony_ci tmp.reset(); 3580cb93a386Sopenharmony_ci tmp.addOval(rect); 3581cb93a386Sopenharmony_ci path = tmp; 3582cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::IsOval(path, nullptr, &dir, &start)); 3583cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathDirection::kCW == dir); 3584cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 1 == start); 3585cb93a386Sopenharmony_ci} 3586cb93a386Sopenharmony_ci 3587cb93a386Sopenharmony_cistatic void test_empty(skiatest::Reporter* reporter, const SkPath& p) { 3588cb93a386Sopenharmony_ci SkPath empty; 3589cb93a386Sopenharmony_ci 3590cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.isEmpty()); 3591cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0 == p.countPoints()); 3592cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0 == p.countVerbs()); 3593cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0 == p.getSegmentMasks()); 3594cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.isConvex()); 3595cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.getFillType() == SkPathFillType::kWinding); 3596cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.isInverseFillType()); 3597cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p == empty); 3598cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !(p != empty)); 3599cb93a386Sopenharmony_ci} 3600cb93a386Sopenharmony_ci 3601cb93a386Sopenharmony_cistatic void test_rrect_is_convex(skiatest::Reporter* reporter, SkPath* path, 3602cb93a386Sopenharmony_ci SkPathDirection dir) { 3603cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path->isConvex()); 3604cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 3605cb93a386Sopenharmony_ci SkPathPriv::ComputeFirstDirection(*path) == SkPathPriv::AsFirstDirection(dir)); 3606cb93a386Sopenharmony_ci SkPathPriv::ForceComputeConvexity(*path); 3607cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path->isConvex()); 3608cb93a386Sopenharmony_ci path->reset(); 3609cb93a386Sopenharmony_ci} 3610cb93a386Sopenharmony_ci 3611cb93a386Sopenharmony_cistatic void test_rrect_convexity_is_unknown(skiatest::Reporter* reporter, SkPath* path, 3612cb93a386Sopenharmony_ci SkPathDirection dir) { 3613cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path->isConvex()); 3614cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 3615cb93a386Sopenharmony_ci SkPathPriv::ComputeFirstDirection(*path) == SkPathPriv::AsFirstDirection(dir)); 3616cb93a386Sopenharmony_ci SkPathPriv::ForceComputeConvexity(*path); 3617cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path->isConvex()); 3618cb93a386Sopenharmony_ci path->reset(); 3619cb93a386Sopenharmony_ci} 3620cb93a386Sopenharmony_ci 3621cb93a386Sopenharmony_cistatic void test_rrect(skiatest::Reporter* reporter) { 3622cb93a386Sopenharmony_ci SkPath p; 3623cb93a386Sopenharmony_ci SkRRect rr; 3624cb93a386Sopenharmony_ci SkVector radii[] = {{1, 2}, {3, 4}, {5, 6}, {7, 8}}; 3625cb93a386Sopenharmony_ci SkRect r = {10, 20, 30, 40}; 3626cb93a386Sopenharmony_ci rr.setRectRadii(r, radii); 3627cb93a386Sopenharmony_ci p.addRRect(rr); 3628cb93a386Sopenharmony_ci test_rrect_is_convex(reporter, &p, SkPathDirection::kCW); 3629cb93a386Sopenharmony_ci p.addRRect(rr, SkPathDirection::kCCW); 3630cb93a386Sopenharmony_ci test_rrect_is_convex(reporter, &p, SkPathDirection::kCCW); 3631cb93a386Sopenharmony_ci p.addRoundRect(r, &radii[0].fX); 3632cb93a386Sopenharmony_ci test_rrect_is_convex(reporter, &p, SkPathDirection::kCW); 3633cb93a386Sopenharmony_ci p.addRoundRect(r, &radii[0].fX, SkPathDirection::kCCW); 3634cb93a386Sopenharmony_ci test_rrect_is_convex(reporter, &p, SkPathDirection::kCCW); 3635cb93a386Sopenharmony_ci p.addRoundRect(r, radii[1].fX, radii[1].fY); 3636cb93a386Sopenharmony_ci test_rrect_is_convex(reporter, &p, SkPathDirection::kCW); 3637cb93a386Sopenharmony_ci p.addRoundRect(r, radii[1].fX, radii[1].fY, SkPathDirection::kCCW); 3638cb93a386Sopenharmony_ci test_rrect_is_convex(reporter, &p, SkPathDirection::kCCW); 3639cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(radii); ++i) { 3640cb93a386Sopenharmony_ci SkVector save = radii[i]; 3641cb93a386Sopenharmony_ci radii[i].set(0, 0); 3642cb93a386Sopenharmony_ci rr.setRectRadii(r, radii); 3643cb93a386Sopenharmony_ci p.addRRect(rr); 3644cb93a386Sopenharmony_ci test_rrect_is_convex(reporter, &p, SkPathDirection::kCW); 3645cb93a386Sopenharmony_ci radii[i] = save; 3646cb93a386Sopenharmony_ci } 3647cb93a386Sopenharmony_ci p.addRoundRect(r, 0, 0); 3648cb93a386Sopenharmony_ci SkRect returnedRect; 3649cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.isRect(&returnedRect)); 3650cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, returnedRect == r); 3651cb93a386Sopenharmony_ci test_rrect_is_convex(reporter, &p, SkPathDirection::kCW); 3652cb93a386Sopenharmony_ci SkVector zeroRadii[] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}}; 3653cb93a386Sopenharmony_ci rr.setRectRadii(r, zeroRadii); 3654cb93a386Sopenharmony_ci p.addRRect(rr); 3655cb93a386Sopenharmony_ci bool closed; 3656cb93a386Sopenharmony_ci SkPathDirection dir; 3657cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.isRect(nullptr, &closed, &dir)); 3658cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, closed); 3659cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathDirection::kCW == dir); 3660cb93a386Sopenharmony_ci test_rrect_is_convex(reporter, &p, SkPathDirection::kCW); 3661cb93a386Sopenharmony_ci p.addRRect(rr, SkPathDirection::kCW); 3662cb93a386Sopenharmony_ci p.addRRect(rr, SkPathDirection::kCW); 3663cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.isConvex()); 3664cb93a386Sopenharmony_ci p.reset(); 3665cb93a386Sopenharmony_ci p.addRRect(rr, SkPathDirection::kCCW); 3666cb93a386Sopenharmony_ci p.addRRect(rr, SkPathDirection::kCCW); 3667cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.isConvex()); 3668cb93a386Sopenharmony_ci p.reset(); 3669cb93a386Sopenharmony_ci SkRect emptyR = {10, 20, 10, 30}; 3670cb93a386Sopenharmony_ci rr.setRectRadii(emptyR, radii); 3671cb93a386Sopenharmony_ci p.addRRect(rr); 3672cb93a386Sopenharmony_ci // The round rect is "empty" in that it has no fill area. However, 3673cb93a386Sopenharmony_ci // the path isn't "empty" in that it should have verbs and points. 3674cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.isEmpty()); 3675cb93a386Sopenharmony_ci p.reset(); 3676cb93a386Sopenharmony_ci SkRect largeR = {0, 0, SK_ScalarMax, SK_ScalarMax}; 3677cb93a386Sopenharmony_ci rr.setRectRadii(largeR, radii); 3678cb93a386Sopenharmony_ci p.addRRect(rr); 3679cb93a386Sopenharmony_ci test_rrect_convexity_is_unknown(reporter, &p, SkPathDirection::kCW); 3680cb93a386Sopenharmony_ci 3681cb93a386Sopenharmony_ci // we check for non-finites 3682cb93a386Sopenharmony_ci SkRect infR = {0, 0, SK_ScalarMax, SK_ScalarInfinity}; 3683cb93a386Sopenharmony_ci rr.setRectRadii(infR, radii); 3684cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, rr.isEmpty()); 3685cb93a386Sopenharmony_ci} 3686cb93a386Sopenharmony_ci 3687cb93a386Sopenharmony_cistatic void test_arc(skiatest::Reporter* reporter) { 3688cb93a386Sopenharmony_ci SkPath p; 3689cb93a386Sopenharmony_ci SkRect emptyOval = {10, 20, 30, 20}; 3690cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, emptyOval.isEmpty()); 3691cb93a386Sopenharmony_ci p.addArc(emptyOval, 1, 2); 3692cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.isEmpty()); 3693cb93a386Sopenharmony_ci p.reset(); 3694cb93a386Sopenharmony_ci SkRect oval = {10, 20, 30, 40}; 3695cb93a386Sopenharmony_ci p.addArc(oval, 1, 0); 3696cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.isEmpty()); 3697cb93a386Sopenharmony_ci p.reset(); 3698cb93a386Sopenharmony_ci SkPath cwOval; 3699cb93a386Sopenharmony_ci cwOval.addOval(oval); 3700cb93a386Sopenharmony_ci p.addArc(oval, 0, 360); 3701cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p == cwOval); 3702cb93a386Sopenharmony_ci p.reset(); 3703cb93a386Sopenharmony_ci SkPath ccwOval; 3704cb93a386Sopenharmony_ci ccwOval.addOval(oval, SkPathDirection::kCCW); 3705cb93a386Sopenharmony_ci p.addArc(oval, 0, -360); 3706cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p == ccwOval); 3707cb93a386Sopenharmony_ci p.reset(); 3708cb93a386Sopenharmony_ci p.addArc(oval, 1, 180); 3709cb93a386Sopenharmony_ci // diagonal colinear points make arc convex 3710cb93a386Sopenharmony_ci // TODO: one way to keep it concave would be to introduce interpolated on curve points 3711cb93a386Sopenharmony_ci // between control points and computing the on curve point at scan conversion time 3712cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.isConvex()); 3713cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::ComputeFirstDirection(p) == SkPathFirstDirection::kCW); 3714cb93a386Sopenharmony_ci SkPathPriv::ForceComputeConvexity(p); 3715cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.isConvex()); 3716cb93a386Sopenharmony_ci} 3717cb93a386Sopenharmony_ci 3718cb93a386Sopenharmony_cistatic inline SkScalar oval_start_index_to_angle(unsigned start) { 3719cb93a386Sopenharmony_ci switch (start) { 3720cb93a386Sopenharmony_ci case 0: 3721cb93a386Sopenharmony_ci return 270.f; 3722cb93a386Sopenharmony_ci case 1: 3723cb93a386Sopenharmony_ci return 0.f; 3724cb93a386Sopenharmony_ci case 2: 3725cb93a386Sopenharmony_ci return 90.f; 3726cb93a386Sopenharmony_ci case 3: 3727cb93a386Sopenharmony_ci return 180.f; 3728cb93a386Sopenharmony_ci default: 3729cb93a386Sopenharmony_ci return -1.f; 3730cb93a386Sopenharmony_ci } 3731cb93a386Sopenharmony_ci} 3732cb93a386Sopenharmony_ci 3733cb93a386Sopenharmony_cistatic inline SkScalar canonical_start_angle(float angle) { 3734cb93a386Sopenharmony_ci while (angle < 0.f) { 3735cb93a386Sopenharmony_ci angle += 360.f; 3736cb93a386Sopenharmony_ci } 3737cb93a386Sopenharmony_ci while (angle >= 360.f) { 3738cb93a386Sopenharmony_ci angle -= 360.f; 3739cb93a386Sopenharmony_ci } 3740cb93a386Sopenharmony_ci return angle; 3741cb93a386Sopenharmony_ci} 3742cb93a386Sopenharmony_ci 3743cb93a386Sopenharmony_cistatic void check_oval_arc(skiatest::Reporter* reporter, SkScalar start, SkScalar sweep, 3744cb93a386Sopenharmony_ci const SkPath& path) { 3745cb93a386Sopenharmony_ci SkRect r = SkRect::MakeEmpty(); 3746cb93a386Sopenharmony_ci SkPathDirection d = SkPathDirection::kCCW; 3747cb93a386Sopenharmony_ci unsigned s = ~0U; 3748cb93a386Sopenharmony_ci bool isOval = SkPathPriv::IsOval(path, &r, &d, &s); 3749cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, isOval); 3750cb93a386Sopenharmony_ci SkPath recreatedPath; 3751cb93a386Sopenharmony_ci recreatedPath.addOval(r, d, s); 3752cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path == recreatedPath); 3753cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, oval_start_index_to_angle(s) == canonical_start_angle(start)); 3754cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, (SkPathDirection::kCW == d) == (sweep > 0.f)); 3755cb93a386Sopenharmony_ci} 3756cb93a386Sopenharmony_ci 3757cb93a386Sopenharmony_cistatic void test_arc_ovals(skiatest::Reporter* reporter) { 3758cb93a386Sopenharmony_ci SkRect oval = SkRect::MakeWH(10, 20); 3759cb93a386Sopenharmony_ci for (SkScalar sweep : {-720.f, -540.f, -360.f, 360.f, 432.f, 720.f}) { 3760cb93a386Sopenharmony_ci for (SkScalar start = -360.f; start <= 360.f; start += 1.f) { 3761cb93a386Sopenharmony_ci SkPath path; 3762cb93a386Sopenharmony_ci path.addArc(oval, start, sweep); 3763cb93a386Sopenharmony_ci // SkPath's interfaces for inserting and extracting ovals only allow contours 3764cb93a386Sopenharmony_ci // to start at multiples of 90 degrees. 3765cb93a386Sopenharmony_ci if (std::fmod(start, 90.f) == 0) { 3766cb93a386Sopenharmony_ci check_oval_arc(reporter, start, sweep, path); 3767cb93a386Sopenharmony_ci } else { 3768cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isOval(nullptr)); 3769cb93a386Sopenharmony_ci } 3770cb93a386Sopenharmony_ci } 3771cb93a386Sopenharmony_ci // Test start angles that are nearly at valid oval start angles. 3772cb93a386Sopenharmony_ci for (float start : {-180.f, -90.f, 90.f, 180.f}) { 3773cb93a386Sopenharmony_ci for (float delta : {-SK_ScalarNearlyZero, SK_ScalarNearlyZero}) { 3774cb93a386Sopenharmony_ci SkPath path; 3775cb93a386Sopenharmony_ci path.addArc(oval, start + delta, sweep); 3776cb93a386Sopenharmony_ci check_oval_arc(reporter, start, sweep, path); 3777cb93a386Sopenharmony_ci } 3778cb93a386Sopenharmony_ci } 3779cb93a386Sopenharmony_ci } 3780cb93a386Sopenharmony_ci} 3781cb93a386Sopenharmony_ci 3782cb93a386Sopenharmony_cistatic void check_move(skiatest::Reporter* reporter, SkPathPriv::RangeIter* iter, 3783cb93a386Sopenharmony_ci SkScalar x0, SkScalar y0) { 3784cb93a386Sopenharmony_ci auto [v, pts, w] = *(*iter)++; 3785cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, v == SkPathVerb::kMove); 3786cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].fX == x0); 3787cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0].fY == y0); 3788cb93a386Sopenharmony_ci} 3789cb93a386Sopenharmony_ci 3790cb93a386Sopenharmony_cistatic void check_line(skiatest::Reporter* reporter, SkPathPriv::RangeIter* iter, 3791cb93a386Sopenharmony_ci SkScalar x1, SkScalar y1) { 3792cb93a386Sopenharmony_ci auto [v, pts, w] = *(*iter)++; 3793cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, v == SkPathVerb::kLine); 3794cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[1].fX == x1); 3795cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[1].fY == y1); 3796cb93a386Sopenharmony_ci} 3797cb93a386Sopenharmony_ci 3798cb93a386Sopenharmony_cistatic void check_quad(skiatest::Reporter* reporter, SkPathPriv::RangeIter* iter, 3799cb93a386Sopenharmony_ci SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) { 3800cb93a386Sopenharmony_ci auto [v, pts, w] = *(*iter)++; 3801cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, v == SkPathVerb::kQuad); 3802cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[1].fX == x1); 3803cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[1].fY == y1); 3804cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[2].fX == x2); 3805cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[2].fY == y2); 3806cb93a386Sopenharmony_ci} 3807cb93a386Sopenharmony_ci 3808cb93a386Sopenharmony_cistatic void check_close(skiatest::Reporter* reporter, SkPathPriv::RangeIter* iter) { 3809cb93a386Sopenharmony_ci auto [v, pts, w] = *(*iter)++; 3810cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, v == SkPathVerb::kClose); 3811cb93a386Sopenharmony_ci} 3812cb93a386Sopenharmony_ci 3813cb93a386Sopenharmony_cistatic void check_done(skiatest::Reporter* reporter, SkPath* p, SkPathPriv::RangeIter* iter) { 3814cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, *iter == SkPathPriv::Iterate(*p).end()); 3815cb93a386Sopenharmony_ci} 3816cb93a386Sopenharmony_ci 3817cb93a386Sopenharmony_cistatic void check_done_and_reset(skiatest::Reporter* reporter, SkPath* p, 3818cb93a386Sopenharmony_ci SkPathPriv::RangeIter* iter) { 3819cb93a386Sopenharmony_ci check_done(reporter, p, iter); 3820cb93a386Sopenharmony_ci p->reset(); 3821cb93a386Sopenharmony_ci} 3822cb93a386Sopenharmony_ci 3823cb93a386Sopenharmony_cistatic void check_path_is_move_and_reset(skiatest::Reporter* reporter, SkPath* p, 3824cb93a386Sopenharmony_ci SkScalar x0, SkScalar y0) { 3825cb93a386Sopenharmony_ci SkPathPriv::RangeIter iter = SkPathPriv::Iterate(*p).begin(); 3826cb93a386Sopenharmony_ci check_move(reporter, &iter, x0, y0); 3827cb93a386Sopenharmony_ci check_done_and_reset(reporter, p, &iter); 3828cb93a386Sopenharmony_ci} 3829cb93a386Sopenharmony_ci 3830cb93a386Sopenharmony_cistatic void check_path_is_line_and_reset(skiatest::Reporter* reporter, SkPath* p, 3831cb93a386Sopenharmony_ci SkScalar x1, SkScalar y1) { 3832cb93a386Sopenharmony_ci SkPathPriv::RangeIter iter = SkPathPriv::Iterate(*p).begin(); 3833cb93a386Sopenharmony_ci check_move(reporter, &iter, 0, 0); 3834cb93a386Sopenharmony_ci check_line(reporter, &iter, x1, y1); 3835cb93a386Sopenharmony_ci check_done_and_reset(reporter, p, &iter); 3836cb93a386Sopenharmony_ci} 3837cb93a386Sopenharmony_ci 3838cb93a386Sopenharmony_cistatic void check_path_is_line(skiatest::Reporter* reporter, SkPath* p, 3839cb93a386Sopenharmony_ci SkScalar x1, SkScalar y1) { 3840cb93a386Sopenharmony_ci SkPathPriv::RangeIter iter = SkPathPriv::Iterate(*p).begin(); 3841cb93a386Sopenharmony_ci check_move(reporter, &iter, 0, 0); 3842cb93a386Sopenharmony_ci check_line(reporter, &iter, x1, y1); 3843cb93a386Sopenharmony_ci check_done(reporter, p, &iter); 3844cb93a386Sopenharmony_ci} 3845cb93a386Sopenharmony_ci 3846cb93a386Sopenharmony_cistatic void check_path_is_line_pair_and_reset(skiatest::Reporter* reporter, SkPath* p, 3847cb93a386Sopenharmony_ci SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) { 3848cb93a386Sopenharmony_ci SkPathPriv::RangeIter iter = SkPathPriv::Iterate(*p).begin(); 3849cb93a386Sopenharmony_ci check_move(reporter, &iter, 0, 0); 3850cb93a386Sopenharmony_ci check_line(reporter, &iter, x1, y1); 3851cb93a386Sopenharmony_ci check_line(reporter, &iter, x2, y2); 3852cb93a386Sopenharmony_ci check_done_and_reset(reporter, p, &iter); 3853cb93a386Sopenharmony_ci} 3854cb93a386Sopenharmony_ci 3855cb93a386Sopenharmony_cistatic void check_path_is_quad_and_reset(skiatest::Reporter* reporter, SkPath* p, 3856cb93a386Sopenharmony_ci SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) { 3857cb93a386Sopenharmony_ci SkPathPriv::RangeIter iter = SkPathPriv::Iterate(*p).begin(); 3858cb93a386Sopenharmony_ci check_move(reporter, &iter, 0, 0); 3859cb93a386Sopenharmony_ci check_quad(reporter, &iter, x1, y1, x2, y2); 3860cb93a386Sopenharmony_ci check_done_and_reset(reporter, p, &iter); 3861cb93a386Sopenharmony_ci} 3862cb93a386Sopenharmony_ci 3863cb93a386Sopenharmony_cistatic bool nearly_equal(const SkRect& a, const SkRect& b) { 3864cb93a386Sopenharmony_ci return SkScalarNearlyEqual(a.fLeft, b.fLeft) && 3865cb93a386Sopenharmony_ci SkScalarNearlyEqual(a.fTop, b.fTop) && 3866cb93a386Sopenharmony_ci SkScalarNearlyEqual(a.fRight, b.fRight) && 3867cb93a386Sopenharmony_ci SkScalarNearlyEqual(a.fBottom, b.fBottom); 3868cb93a386Sopenharmony_ci} 3869cb93a386Sopenharmony_ci 3870cb93a386Sopenharmony_cistatic void test_rMoveTo(skiatest::Reporter* reporter) { 3871cb93a386Sopenharmony_ci SkPath p; 3872cb93a386Sopenharmony_ci p.moveTo(10, 11); 3873cb93a386Sopenharmony_ci p.lineTo(20, 21); 3874cb93a386Sopenharmony_ci p.close(); 3875cb93a386Sopenharmony_ci p.rMoveTo(30, 31); 3876cb93a386Sopenharmony_ci SkPathPriv::RangeIter iter = SkPathPriv::Iterate(p).begin(); 3877cb93a386Sopenharmony_ci check_move(reporter, &iter, 10, 11); 3878cb93a386Sopenharmony_ci check_line(reporter, &iter, 20, 21); 3879cb93a386Sopenharmony_ci check_close(reporter, &iter); 3880cb93a386Sopenharmony_ci check_move(reporter, &iter, 10 + 30, 11 + 31); 3881cb93a386Sopenharmony_ci check_done_and_reset(reporter, &p, &iter); 3882cb93a386Sopenharmony_ci 3883cb93a386Sopenharmony_ci p.moveTo(10, 11); 3884cb93a386Sopenharmony_ci p.lineTo(20, 21); 3885cb93a386Sopenharmony_ci p.rMoveTo(30, 31); 3886cb93a386Sopenharmony_ci iter = SkPathPriv::Iterate(p).begin(); 3887cb93a386Sopenharmony_ci check_move(reporter, &iter, 10, 11); 3888cb93a386Sopenharmony_ci check_line(reporter, &iter, 20, 21); 3889cb93a386Sopenharmony_ci check_move(reporter, &iter, 20 + 30, 21 + 31); 3890cb93a386Sopenharmony_ci check_done_and_reset(reporter, &p, &iter); 3891cb93a386Sopenharmony_ci 3892cb93a386Sopenharmony_ci p.rMoveTo(30, 31); 3893cb93a386Sopenharmony_ci iter = SkPathPriv::Iterate(p).begin(); 3894cb93a386Sopenharmony_ci check_move(reporter, &iter, 30, 31); 3895cb93a386Sopenharmony_ci check_done_and_reset(reporter, &p, &iter); 3896cb93a386Sopenharmony_ci} 3897cb93a386Sopenharmony_ci 3898cb93a386Sopenharmony_cistatic void test_arcTo(skiatest::Reporter* reporter) { 3899cb93a386Sopenharmony_ci SkPath p; 3900cb93a386Sopenharmony_ci p.arcTo(0, 0, 1, 2, 1); 3901cb93a386Sopenharmony_ci check_path_is_line_and_reset(reporter, &p, 0, 0); 3902cb93a386Sopenharmony_ci p.arcTo(1, 2, 1, 2, 1); 3903cb93a386Sopenharmony_ci check_path_is_line_and_reset(reporter, &p, 1, 2); 3904cb93a386Sopenharmony_ci p.arcTo(1, 2, 3, 4, 0); 3905cb93a386Sopenharmony_ci check_path_is_line_and_reset(reporter, &p, 1, 2); 3906cb93a386Sopenharmony_ci p.arcTo(1, 2, 0, 0, 1); 3907cb93a386Sopenharmony_ci check_path_is_line_and_reset(reporter, &p, 1, 2); 3908cb93a386Sopenharmony_ci p.arcTo(1, 0, 1, 1, 1); 3909cb93a386Sopenharmony_ci SkPoint pt; 3910cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.getLastPt(&pt) && pt.fX == 1 && pt.fY == 1); 3911cb93a386Sopenharmony_ci p.reset(); 3912cb93a386Sopenharmony_ci p.arcTo(1, 0, 1, -1, 1); 3913cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.getLastPt(&pt) && pt.fX == 1 && pt.fY == -1); 3914cb93a386Sopenharmony_ci p.reset(); 3915cb93a386Sopenharmony_ci SkRect oval = {1, 2, 3, 4}; 3916cb93a386Sopenharmony_ci p.arcTo(oval, 0, 0, true); 3917cb93a386Sopenharmony_ci check_path_is_move_and_reset(reporter, &p, oval.fRight, oval.centerY()); 3918cb93a386Sopenharmony_ci p.arcTo(oval, 0, 0, false); 3919cb93a386Sopenharmony_ci check_path_is_move_and_reset(reporter, &p, oval.fRight, oval.centerY()); 3920cb93a386Sopenharmony_ci p.arcTo(oval, 360, 0, true); 3921cb93a386Sopenharmony_ci check_path_is_move_and_reset(reporter, &p, oval.fRight, oval.centerY()); 3922cb93a386Sopenharmony_ci p.arcTo(oval, 360, 0, false); 3923cb93a386Sopenharmony_ci check_path_is_move_and_reset(reporter, &p, oval.fRight, oval.centerY()); 3924cb93a386Sopenharmony_ci 3925cb93a386Sopenharmony_ci for (float sweep = 359, delta = 0.5f; sweep != (float) (sweep + delta); ) { 3926cb93a386Sopenharmony_ci p.arcTo(oval, 0, sweep, false); 3927cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, nearly_equal(p.getBounds(), oval)); 3928cb93a386Sopenharmony_ci sweep += delta; 3929cb93a386Sopenharmony_ci delta /= 2; 3930cb93a386Sopenharmony_ci } 3931cb93a386Sopenharmony_ci for (float sweep = 361, delta = 0.5f; sweep != (float) (sweep - delta);) { 3932cb93a386Sopenharmony_ci p.arcTo(oval, 0, sweep, false); 3933cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, nearly_equal(p.getBounds(), oval)); 3934cb93a386Sopenharmony_ci sweep -= delta; 3935cb93a386Sopenharmony_ci delta /= 2; 3936cb93a386Sopenharmony_ci } 3937cb93a386Sopenharmony_ci SkRect noOvalWidth = {1, 2, 0, 3}; 3938cb93a386Sopenharmony_ci p.reset(); 3939cb93a386Sopenharmony_ci p.arcTo(noOvalWidth, 0, 360, false); 3940cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.isEmpty()); 3941cb93a386Sopenharmony_ci 3942cb93a386Sopenharmony_ci SkRect noOvalHeight = {1, 2, 3, 1}; 3943cb93a386Sopenharmony_ci p.reset(); 3944cb93a386Sopenharmony_ci p.arcTo(noOvalHeight, 0, 360, false); 3945cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.isEmpty()); 3946cb93a386Sopenharmony_ci 3947cb93a386Sopenharmony_ci#ifndef SK_LEGACY_PATH_ARCTO_ENDPOINT 3948cb93a386Sopenharmony_ci // Inspired by http://code.google.com/p/chromium/issues/detail?id=1001768 3949cb93a386Sopenharmony_ci { 3950cb93a386Sopenharmony_ci p.reset(); 3951cb93a386Sopenharmony_ci p.moveTo(216, 216); 3952cb93a386Sopenharmony_ci p.arcTo(216, 108, 0, SkPath::ArcSize::kLarge_ArcSize, SkPathDirection::kCW, 216, 0); 3953cb93a386Sopenharmony_ci p.arcTo(270, 135, 0, SkPath::ArcSize::kLarge_ArcSize, SkPathDirection::kCCW, 216, 216); 3954cb93a386Sopenharmony_ci 3955cb93a386Sopenharmony_ci // The 'arcTo' call should end up exactly at the starting location. 3956cb93a386Sopenharmony_ci int n = p.countPoints(); 3957cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.getPoint(0) == p.getPoint(n - 1)); 3958cb93a386Sopenharmony_ci } 3959cb93a386Sopenharmony_ci#endif 3960cb93a386Sopenharmony_ci} 3961cb93a386Sopenharmony_ci 3962cb93a386Sopenharmony_cistatic void test_addPath(skiatest::Reporter* reporter) { 3963cb93a386Sopenharmony_ci SkPath p, q; 3964cb93a386Sopenharmony_ci p.lineTo(1, 2); 3965cb93a386Sopenharmony_ci q.moveTo(4, 4); 3966cb93a386Sopenharmony_ci q.lineTo(7, 8); 3967cb93a386Sopenharmony_ci q.conicTo(8, 7, 6, 5, 0.5f); 3968cb93a386Sopenharmony_ci q.quadTo(6, 7, 8, 6); 3969cb93a386Sopenharmony_ci q.cubicTo(5, 6, 7, 8, 7, 5); 3970cb93a386Sopenharmony_ci q.close(); 3971cb93a386Sopenharmony_ci p.addPath(q, -4, -4); 3972cb93a386Sopenharmony_ci SkRect expected = {0, 0, 4, 4}; 3973cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.getBounds() == expected); 3974cb93a386Sopenharmony_ci p.reset(); 3975cb93a386Sopenharmony_ci p.reverseAddPath(q); 3976cb93a386Sopenharmony_ci SkRect reverseExpected = {4, 4, 8, 8}; 3977cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.getBounds() == reverseExpected); 3978cb93a386Sopenharmony_ci} 3979cb93a386Sopenharmony_ci 3980cb93a386Sopenharmony_cistatic void test_addPathMode(skiatest::Reporter* reporter, bool explicitMoveTo, bool extend) { 3981cb93a386Sopenharmony_ci SkPath p, q; 3982cb93a386Sopenharmony_ci if (explicitMoveTo) { 3983cb93a386Sopenharmony_ci p.moveTo(1, 1); 3984cb93a386Sopenharmony_ci } 3985cb93a386Sopenharmony_ci p.lineTo(1, 2); 3986cb93a386Sopenharmony_ci if (explicitMoveTo) { 3987cb93a386Sopenharmony_ci q.moveTo(2, 1); 3988cb93a386Sopenharmony_ci } 3989cb93a386Sopenharmony_ci q.lineTo(2, 2); 3990cb93a386Sopenharmony_ci p.addPath(q, extend ? SkPath::kExtend_AddPathMode : SkPath::kAppend_AddPathMode); 3991cb93a386Sopenharmony_ci uint8_t verbs[4]; 3992cb93a386Sopenharmony_ci int verbcount = p.getVerbs(verbs, 4); 3993cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verbcount == 4); 3994cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verbs[0] == SkPath::kMove_Verb); 3995cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verbs[1] == SkPath::kLine_Verb); 3996cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verbs[2] == (extend ? SkPath::kLine_Verb : SkPath::kMove_Verb)); 3997cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verbs[3] == SkPath::kLine_Verb); 3998cb93a386Sopenharmony_ci} 3999cb93a386Sopenharmony_ci 4000cb93a386Sopenharmony_cistatic void test_extendClosedPath(skiatest::Reporter* reporter) { 4001cb93a386Sopenharmony_ci SkPath p, q; 4002cb93a386Sopenharmony_ci p.moveTo(1, 1); 4003cb93a386Sopenharmony_ci p.lineTo(1, 2); 4004cb93a386Sopenharmony_ci p.lineTo(2, 2); 4005cb93a386Sopenharmony_ci p.close(); 4006cb93a386Sopenharmony_ci q.moveTo(2, 1); 4007cb93a386Sopenharmony_ci q.lineTo(2, 3); 4008cb93a386Sopenharmony_ci p.addPath(q, SkPath::kExtend_AddPathMode); 4009cb93a386Sopenharmony_ci uint8_t verbs[7]; 4010cb93a386Sopenharmony_ci int verbcount = p.getVerbs(verbs, 7); 4011cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verbcount == 7); 4012cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verbs[0] == SkPath::kMove_Verb); 4013cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verbs[1] == SkPath::kLine_Verb); 4014cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verbs[2] == SkPath::kLine_Verb); 4015cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verbs[3] == SkPath::kClose_Verb); 4016cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verbs[4] == SkPath::kMove_Verb); 4017cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verbs[5] == SkPath::kLine_Verb); 4018cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, verbs[6] == SkPath::kLine_Verb); 4019cb93a386Sopenharmony_ci 4020cb93a386Sopenharmony_ci SkPoint pt; 4021cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.getLastPt(&pt)); 4022cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pt == SkPoint::Make(2, 3)); 4023cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.getPoint(3) == SkPoint::Make(1, 1)); 4024cb93a386Sopenharmony_ci} 4025cb93a386Sopenharmony_ci 4026cb93a386Sopenharmony_cistatic void test_addEmptyPath(skiatest::Reporter* reporter, SkPath::AddPathMode mode) { 4027cb93a386Sopenharmony_ci SkPath p, q, r; 4028cb93a386Sopenharmony_ci // case 1: dst is empty 4029cb93a386Sopenharmony_ci p.moveTo(2, 1); 4030cb93a386Sopenharmony_ci p.lineTo(2, 3); 4031cb93a386Sopenharmony_ci q.addPath(p, mode); 4032cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, q == p); 4033cb93a386Sopenharmony_ci // case 2: src is empty 4034cb93a386Sopenharmony_ci p.addPath(r, mode); 4035cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, q == p); 4036cb93a386Sopenharmony_ci // case 3: src and dst are empty 4037cb93a386Sopenharmony_ci q.reset(); 4038cb93a386Sopenharmony_ci q.addPath(r, mode); 4039cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, q.isEmpty()); 4040cb93a386Sopenharmony_ci} 4041cb93a386Sopenharmony_ci 4042cb93a386Sopenharmony_cistatic void test_conicTo_special_case(skiatest::Reporter* reporter) { 4043cb93a386Sopenharmony_ci SkPath p; 4044cb93a386Sopenharmony_ci p.conicTo(1, 2, 3, 4, -1); 4045cb93a386Sopenharmony_ci check_path_is_line_and_reset(reporter, &p, 3, 4); 4046cb93a386Sopenharmony_ci p.conicTo(1, 2, 3, 4, SK_ScalarInfinity); 4047cb93a386Sopenharmony_ci check_path_is_line_pair_and_reset(reporter, &p, 1, 2, 3, 4); 4048cb93a386Sopenharmony_ci p.conicTo(1, 2, 3, 4, 1); 4049cb93a386Sopenharmony_ci check_path_is_quad_and_reset(reporter, &p, 1, 2, 3, 4); 4050cb93a386Sopenharmony_ci} 4051cb93a386Sopenharmony_ci 4052cb93a386Sopenharmony_cistatic void test_get_point(skiatest::Reporter* reporter) { 4053cb93a386Sopenharmony_ci SkPath p; 4054cb93a386Sopenharmony_ci SkPoint pt = p.getPoint(0); 4055cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pt == SkPoint::Make(0, 0)); 4056cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.getLastPt(nullptr)); 4057cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.getLastPt(&pt) && pt == SkPoint::Make(0, 0)); 4058cb93a386Sopenharmony_ci p.setLastPt(10, 10); 4059cb93a386Sopenharmony_ci pt = p.getPoint(0); 4060cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pt == SkPoint::Make(10, 10)); 4061cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.getLastPt(nullptr)); 4062cb93a386Sopenharmony_ci p.rMoveTo(10, 10); 4063cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.getLastPt(&pt) && pt == SkPoint::Make(20, 20)); 4064cb93a386Sopenharmony_ci} 4065cb93a386Sopenharmony_ci 4066cb93a386Sopenharmony_cistatic void test_contains(skiatest::Reporter* reporter) { 4067cb93a386Sopenharmony_ci SkPath p; 4068cb93a386Sopenharmony_ci p.moveTo(SkBits2Float(0xe085e7b1), SkBits2Float(0x5f512c00)); // -7.7191e+19f, 1.50724e+19f 4069cb93a386Sopenharmony_ci p.conicTo(SkBits2Float(0xdfdaa221), SkBits2Float(0x5eaac338), SkBits2Float(0x60342f13), SkBits2Float(0xdf0cbb58), SkBits2Float(0x3f3504f3)); // -3.15084e+19f, 6.15237e+18f, 5.19345e+19f, -1.01408e+19f, 0.707107f 4070cb93a386Sopenharmony_ci p.conicTo(SkBits2Float(0x60ead799), SkBits2Float(0xdfb76c24), SkBits2Float(0x609b9872), SkBits2Float(0xdf730de8), SkBits2Float(0x3f3504f4)); // 1.35377e+20f, -2.6434e+19f, 8.96947e+19f, -1.75139e+19f, 0.707107f 4071cb93a386Sopenharmony_ci p.lineTo(SkBits2Float(0x609b9872), SkBits2Float(0xdf730de8)); // 8.96947e+19f, -1.75139e+19f 4072cb93a386Sopenharmony_ci p.conicTo(SkBits2Float(0x6018b296), SkBits2Float(0xdeee870d), SkBits2Float(0xe008cd8e), SkBits2Float(0x5ed5b2db), SkBits2Float(0x3f3504f3)); // 4.40121e+19f, -8.59386e+18f, -3.94308e+19f, 7.69931e+18f, 0.707107f 4073cb93a386Sopenharmony_ci p.conicTo(SkBits2Float(0xe0d526d9), SkBits2Float(0x5fa67b31), SkBits2Float(0xe085e7b2), SkBits2Float(0x5f512c01), SkBits2Float(0x3f3504f3)); // -1.22874e+20f, 2.39925e+19f, -7.7191e+19f, 1.50724e+19f, 0.707107f 4074cb93a386Sopenharmony_ci // this may return true or false, depending on the platform's numerics, but it should not crash 4075cb93a386Sopenharmony_ci (void) p.contains(-77.2027664f, 15.3066053f); 4076cb93a386Sopenharmony_ci 4077cb93a386Sopenharmony_ci p.reset(); 4078cb93a386Sopenharmony_ci p.setFillType(SkPathFillType::kInverseWinding); 4079cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(0, 0)); 4080cb93a386Sopenharmony_ci p.setFillType(SkPathFillType::kWinding); 4081cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.contains(0, 0)); 4082cb93a386Sopenharmony_ci p.moveTo(4, 4); 4083cb93a386Sopenharmony_ci p.lineTo(6, 8); 4084cb93a386Sopenharmony_ci p.lineTo(8, 4); 4085cb93a386Sopenharmony_ci // test on edge 4086cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(6, 4)); 4087cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(5, 6)); 4088cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(7, 6)); 4089cb93a386Sopenharmony_ci // test quick reject 4090cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.contains(4, 0)); 4091cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.contains(0, 4)); 4092cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.contains(4, 10)); 4093cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.contains(10, 4)); 4094cb93a386Sopenharmony_ci // test various crossings in x 4095cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.contains(5, 7)); 4096cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(6, 7)); 4097cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.contains(7, 7)); 4098cb93a386Sopenharmony_ci p.reset(); 4099cb93a386Sopenharmony_ci p.moveTo(4, 4); 4100cb93a386Sopenharmony_ci p.lineTo(8, 6); 4101cb93a386Sopenharmony_ci p.lineTo(4, 8); 4102cb93a386Sopenharmony_ci // test on edge 4103cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(4, 6)); 4104cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(6, 5)); 4105cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(6, 7)); 4106cb93a386Sopenharmony_ci // test various crossings in y 4107cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.contains(7, 5)); 4108cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(7, 6)); 4109cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.contains(7, 7)); 4110cb93a386Sopenharmony_ci p.reset(); 4111cb93a386Sopenharmony_ci p.moveTo(4, 4); 4112cb93a386Sopenharmony_ci p.lineTo(8, 4); 4113cb93a386Sopenharmony_ci p.lineTo(8, 8); 4114cb93a386Sopenharmony_ci p.lineTo(4, 8); 4115cb93a386Sopenharmony_ci // test on vertices 4116cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(4, 4)); 4117cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(8, 4)); 4118cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(8, 8)); 4119cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(4, 8)); 4120cb93a386Sopenharmony_ci p.reset(); 4121cb93a386Sopenharmony_ci p.moveTo(4, 4); 4122cb93a386Sopenharmony_ci p.lineTo(6, 8); 4123cb93a386Sopenharmony_ci p.lineTo(2, 8); 4124cb93a386Sopenharmony_ci // test on edge 4125cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(5, 6)); 4126cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(4, 8)); 4127cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(3, 6)); 4128cb93a386Sopenharmony_ci p.reset(); 4129cb93a386Sopenharmony_ci p.moveTo(4, 4); 4130cb93a386Sopenharmony_ci p.lineTo(0, 6); 4131cb93a386Sopenharmony_ci p.lineTo(4, 8); 4132cb93a386Sopenharmony_ci // test on edge 4133cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(2, 5)); 4134cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(2, 7)); 4135cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(4, 6)); 4136cb93a386Sopenharmony_ci // test canceling coincident edge (a smaller triangle is coincident with a larger one) 4137cb93a386Sopenharmony_ci p.reset(); 4138cb93a386Sopenharmony_ci p.moveTo(4, 0); 4139cb93a386Sopenharmony_ci p.lineTo(6, 4); 4140cb93a386Sopenharmony_ci p.lineTo(2, 4); 4141cb93a386Sopenharmony_ci p.moveTo(4, 0); 4142cb93a386Sopenharmony_ci p.lineTo(0, 8); 4143cb93a386Sopenharmony_ci p.lineTo(8, 8); 4144cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.contains(1, 2)); 4145cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.contains(3, 2)); 4146cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.contains(4, 0)); 4147cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(4, 4)); 4148cb93a386Sopenharmony_ci 4149cb93a386Sopenharmony_ci // test quads 4150cb93a386Sopenharmony_ci p.reset(); 4151cb93a386Sopenharmony_ci p.moveTo(4, 4); 4152cb93a386Sopenharmony_ci p.quadTo(6, 6, 8, 8); 4153cb93a386Sopenharmony_ci p.quadTo(6, 8, 4, 8); 4154cb93a386Sopenharmony_ci p.quadTo(4, 6, 4, 4); 4155cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(5, 6)); 4156cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.contains(6, 5)); 4157cb93a386Sopenharmony_ci // test quad edge 4158cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(5, 5)); 4159cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(5, 8)); 4160cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(4, 5)); 4161cb93a386Sopenharmony_ci // test quad endpoints 4162cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(4, 4)); 4163cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(8, 8)); 4164cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(4, 8)); 4165cb93a386Sopenharmony_ci 4166cb93a386Sopenharmony_ci p.reset(); 4167cb93a386Sopenharmony_ci const SkPoint qPts[] = {{6, 6}, {8, 8}, {6, 8}, {4, 8}, {4, 6}, {4, 4}, {6, 6}}; 4168cb93a386Sopenharmony_ci p.moveTo(qPts[0]); 4169cb93a386Sopenharmony_ci for (int index = 1; index < (int) SK_ARRAY_COUNT(qPts); index += 2) { 4170cb93a386Sopenharmony_ci p.quadTo(qPts[index], qPts[index + 1]); 4171cb93a386Sopenharmony_ci } 4172cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(5, 6)); 4173cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.contains(6, 5)); 4174cb93a386Sopenharmony_ci // test quad edge 4175cb93a386Sopenharmony_ci SkPoint halfway; 4176cb93a386Sopenharmony_ci for (int index = 0; index < (int) SK_ARRAY_COUNT(qPts) - 2; index += 2) { 4177cb93a386Sopenharmony_ci SkEvalQuadAt(&qPts[index], 0.5f, &halfway, nullptr); 4178cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(halfway.fX, halfway.fY)); 4179cb93a386Sopenharmony_ci } 4180cb93a386Sopenharmony_ci 4181cb93a386Sopenharmony_ci // test conics 4182cb93a386Sopenharmony_ci p.reset(); 4183cb93a386Sopenharmony_ci const SkPoint kPts[] = {{4, 4}, {6, 6}, {8, 8}, {6, 8}, {4, 8}, {4, 6}, {4, 4}}; 4184cb93a386Sopenharmony_ci p.moveTo(kPts[0]); 4185cb93a386Sopenharmony_ci for (int index = 1; index < (int) SK_ARRAY_COUNT(kPts); index += 2) { 4186cb93a386Sopenharmony_ci p.conicTo(kPts[index], kPts[index + 1], 0.5f); 4187cb93a386Sopenharmony_ci } 4188cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(5, 6)); 4189cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.contains(6, 5)); 4190cb93a386Sopenharmony_ci // test conic edge 4191cb93a386Sopenharmony_ci for (int index = 0; index < (int) SK_ARRAY_COUNT(kPts) - 2; index += 2) { 4192cb93a386Sopenharmony_ci SkConic conic(&kPts[index], 0.5f); 4193cb93a386Sopenharmony_ci halfway = conic.evalAt(0.5f); 4194cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(halfway.fX, halfway.fY)); 4195cb93a386Sopenharmony_ci } 4196cb93a386Sopenharmony_ci // test conic end points 4197cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(4, 4)); 4198cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(8, 8)); 4199cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(4, 8)); 4200cb93a386Sopenharmony_ci 4201cb93a386Sopenharmony_ci // test cubics 4202cb93a386Sopenharmony_ci SkPoint pts[] = {{5, 4}, {6, 5}, {7, 6}, {6, 6}, {4, 6}, {5, 7}, {5, 5}, {5, 4}, {6, 5}, {7, 6}}; 4203cb93a386Sopenharmony_ci for (int i = 0; i < 3; ++i) { 4204cb93a386Sopenharmony_ci p.reset(); 4205cb93a386Sopenharmony_ci p.setFillType(SkPathFillType::kEvenOdd); 4206cb93a386Sopenharmony_ci p.moveTo(pts[i].fX, pts[i].fY); 4207cb93a386Sopenharmony_ci p.cubicTo(pts[i + 1].fX, pts[i + 1].fY, pts[i + 2].fX, pts[i + 2].fY, pts[i + 3].fX, pts[i + 3].fY); 4208cb93a386Sopenharmony_ci p.cubicTo(pts[i + 4].fX, pts[i + 4].fY, pts[i + 5].fX, pts[i + 5].fY, pts[i + 6].fX, pts[i + 6].fY); 4209cb93a386Sopenharmony_ci p.close(); 4210cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(5.5f, 5.5f)); 4211cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.contains(4.5f, 5.5f)); 4212cb93a386Sopenharmony_ci // test cubic edge 4213cb93a386Sopenharmony_ci SkEvalCubicAt(&pts[i], 0.5f, &halfway, nullptr, nullptr); 4214cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(halfway.fX, halfway.fY)); 4215cb93a386Sopenharmony_ci SkEvalCubicAt(&pts[i + 3], 0.5f, &halfway, nullptr, nullptr); 4216cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(halfway.fX, halfway.fY)); 4217cb93a386Sopenharmony_ci // test cubic end points 4218cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(pts[i].fX, pts[i].fY)); 4219cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(pts[i + 3].fX, pts[i + 3].fY)); 4220cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.contains(pts[i + 6].fX, pts[i + 6].fY)); 4221cb93a386Sopenharmony_ci } 4222cb93a386Sopenharmony_ci} 4223cb93a386Sopenharmony_ci 4224cb93a386Sopenharmony_ciclass PathRefTest_Private { 4225cb93a386Sopenharmony_cipublic: 4226cb93a386Sopenharmony_ci static size_t GetFreeSpace(const SkPathRef& ref) { 4227cb93a386Sopenharmony_ci return (ref.fPoints.reserved() - ref.fPoints.count()) * sizeof(SkPoint) 4228cb93a386Sopenharmony_ci + (ref.fVerbs.reserved() - ref.fVerbs.count()) * sizeof(uint8_t); 4229cb93a386Sopenharmony_ci } 4230cb93a386Sopenharmony_ci 4231cb93a386Sopenharmony_ci static void TestPathRef(skiatest::Reporter* reporter) { 4232cb93a386Sopenharmony_ci static const int kRepeatCnt = 10; 4233cb93a386Sopenharmony_ci 4234cb93a386Sopenharmony_ci sk_sp<SkPathRef> pathRef(new SkPathRef); 4235cb93a386Sopenharmony_ci 4236cb93a386Sopenharmony_ci SkPathRef::Editor ed(&pathRef); 4237cb93a386Sopenharmony_ci 4238cb93a386Sopenharmony_ci { 4239cb93a386Sopenharmony_ci ed.growForRepeatedVerb(SkPath::kMove_Verb, kRepeatCnt); 4240cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, kRepeatCnt == pathRef->countVerbs()); 4241cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, kRepeatCnt == pathRef->countPoints()); 4242cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0 == pathRef->getSegmentMasks()); 4243cb93a386Sopenharmony_ci for (int i = 0; i < kRepeatCnt; ++i) { 4244cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kMove_Verb == pathRef->atVerb(i)); 4245cb93a386Sopenharmony_ci } 4246cb93a386Sopenharmony_ci ed.resetToSize(0, 0, 0); 4247cb93a386Sopenharmony_ci } 4248cb93a386Sopenharmony_ci 4249cb93a386Sopenharmony_ci { 4250cb93a386Sopenharmony_ci ed.growForRepeatedVerb(SkPath::kLine_Verb, kRepeatCnt); 4251cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, kRepeatCnt == pathRef->countVerbs()); 4252cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, kRepeatCnt == pathRef->countPoints()); 4253cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kLine_SegmentMask == pathRef->getSegmentMasks()); 4254cb93a386Sopenharmony_ci for (int i = 0; i < kRepeatCnt; ++i) { 4255cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kLine_Verb == pathRef->atVerb(i)); 4256cb93a386Sopenharmony_ci } 4257cb93a386Sopenharmony_ci ed.resetToSize(0, 0, 0); 4258cb93a386Sopenharmony_ci } 4259cb93a386Sopenharmony_ci 4260cb93a386Sopenharmony_ci { 4261cb93a386Sopenharmony_ci ed.growForRepeatedVerb(SkPath::kQuad_Verb, kRepeatCnt); 4262cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, kRepeatCnt == pathRef->countVerbs()); 4263cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 2*kRepeatCnt == pathRef->countPoints()); 4264cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kQuad_SegmentMask == pathRef->getSegmentMasks()); 4265cb93a386Sopenharmony_ci for (int i = 0; i < kRepeatCnt; ++i) { 4266cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kQuad_Verb == pathRef->atVerb(i)); 4267cb93a386Sopenharmony_ci } 4268cb93a386Sopenharmony_ci ed.resetToSize(0, 0, 0); 4269cb93a386Sopenharmony_ci } 4270cb93a386Sopenharmony_ci 4271cb93a386Sopenharmony_ci { 4272cb93a386Sopenharmony_ci SkScalar* weights = nullptr; 4273cb93a386Sopenharmony_ci ed.growForRepeatedVerb(SkPath::kConic_Verb, kRepeatCnt, &weights); 4274cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, kRepeatCnt == pathRef->countVerbs()); 4275cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 2*kRepeatCnt == pathRef->countPoints()); 4276cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, kRepeatCnt == pathRef->countWeights()); 4277cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kConic_SegmentMask == pathRef->getSegmentMasks()); 4278cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, weights); 4279cb93a386Sopenharmony_ci for (int i = 0; i < kRepeatCnt; ++i) { 4280cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kConic_Verb == pathRef->atVerb(i)); 4281cb93a386Sopenharmony_ci } 4282cb93a386Sopenharmony_ci ed.resetToSize(0, 0, 0); 4283cb93a386Sopenharmony_ci } 4284cb93a386Sopenharmony_ci 4285cb93a386Sopenharmony_ci { 4286cb93a386Sopenharmony_ci ed.growForRepeatedVerb(SkPath::kCubic_Verb, kRepeatCnt); 4287cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, kRepeatCnt == pathRef->countVerbs()); 4288cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 3*kRepeatCnt == pathRef->countPoints()); 4289cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kCubic_SegmentMask == pathRef->getSegmentMasks()); 4290cb93a386Sopenharmony_ci for (int i = 0; i < kRepeatCnt; ++i) { 4291cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kCubic_Verb == pathRef->atVerb(i)); 4292cb93a386Sopenharmony_ci } 4293cb93a386Sopenharmony_ci ed.resetToSize(0, 0, 0); 4294cb93a386Sopenharmony_ci } 4295cb93a386Sopenharmony_ci } 4296cb93a386Sopenharmony_ci}; 4297cb93a386Sopenharmony_ci 4298cb93a386Sopenharmony_cistatic void test_operatorEqual(skiatest::Reporter* reporter) { 4299cb93a386Sopenharmony_ci SkPath a; 4300cb93a386Sopenharmony_ci SkPath b; 4301cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, a == a); 4302cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, a == b); 4303cb93a386Sopenharmony_ci a.setFillType(SkPathFillType::kInverseWinding); 4304cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, a != b); 4305cb93a386Sopenharmony_ci a.reset(); 4306cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, a == b); 4307cb93a386Sopenharmony_ci a.lineTo(1, 1); 4308cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, a != b); 4309cb93a386Sopenharmony_ci a.reset(); 4310cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, a == b); 4311cb93a386Sopenharmony_ci a.lineTo(1, 1); 4312cb93a386Sopenharmony_ci b.lineTo(1, 2); 4313cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, a != b); 4314cb93a386Sopenharmony_ci a.reset(); 4315cb93a386Sopenharmony_ci a.lineTo(1, 2); 4316cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, a == b); 4317cb93a386Sopenharmony_ci} 4318cb93a386Sopenharmony_ci 4319cb93a386Sopenharmony_cistatic void compare_dump(skiatest::Reporter* reporter, const SkPath& path, bool dumpAsHex, 4320cb93a386Sopenharmony_ci const char* str) { 4321cb93a386Sopenharmony_ci SkDynamicMemoryWStream wStream; 4322cb93a386Sopenharmony_ci path.dump(&wStream, dumpAsHex); 4323cb93a386Sopenharmony_ci sk_sp<SkData> data = wStream.detachAsData(); 4324cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, data->size() == strlen(str)); 4325cb93a386Sopenharmony_ci if (strlen(str) > 0) { 4326cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !memcmp(data->data(), str, strlen(str))); 4327cb93a386Sopenharmony_ci } else { 4328cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, data->data() == nullptr || !memcmp(data->data(), str, strlen(str))); 4329cb93a386Sopenharmony_ci } 4330cb93a386Sopenharmony_ci} 4331cb93a386Sopenharmony_ci 4332cb93a386Sopenharmony_cistatic void test_dump(skiatest::Reporter* reporter) { 4333cb93a386Sopenharmony_ci SkPath p; 4334cb93a386Sopenharmony_ci compare_dump(reporter, p, false, "path.setFillType(SkPathFillType::kWinding);\n"); 4335cb93a386Sopenharmony_ci p.moveTo(1, 2); 4336cb93a386Sopenharmony_ci p.lineTo(3, 4); 4337cb93a386Sopenharmony_ci compare_dump(reporter, p, false, "path.setFillType(SkPathFillType::kWinding);\n" 4338cb93a386Sopenharmony_ci "path.moveTo(1, 2);\n" 4339cb93a386Sopenharmony_ci "path.lineTo(3, 4);\n"); 4340cb93a386Sopenharmony_ci p.reset(); 4341cb93a386Sopenharmony_ci p.setFillType(SkPathFillType::kEvenOdd); 4342cb93a386Sopenharmony_ci p.moveTo(1, 2); 4343cb93a386Sopenharmony_ci p.quadTo(3, 4, 5, 6); 4344cb93a386Sopenharmony_ci compare_dump(reporter, p, false, "path.setFillType(SkPathFillType::kEvenOdd);\n" 4345cb93a386Sopenharmony_ci "path.moveTo(1, 2);\n" 4346cb93a386Sopenharmony_ci "path.quadTo(3, 4, 5, 6);\n"); 4347cb93a386Sopenharmony_ci p.reset(); 4348cb93a386Sopenharmony_ci p.setFillType(SkPathFillType::kInverseWinding); 4349cb93a386Sopenharmony_ci p.moveTo(1, 2); 4350cb93a386Sopenharmony_ci p.conicTo(3, 4, 5, 6, 0.5f); 4351cb93a386Sopenharmony_ci compare_dump(reporter, p, false, "path.setFillType(SkPathFillType::kInverseWinding);\n" 4352cb93a386Sopenharmony_ci "path.moveTo(1, 2);\n" 4353cb93a386Sopenharmony_ci "path.conicTo(3, 4, 5, 6, 0.5f);\n"); 4354cb93a386Sopenharmony_ci p.reset(); 4355cb93a386Sopenharmony_ci p.setFillType(SkPathFillType::kInverseEvenOdd); 4356cb93a386Sopenharmony_ci p.moveTo(1, 2); 4357cb93a386Sopenharmony_ci p.cubicTo(3, 4, 5, 6, 7, 8); 4358cb93a386Sopenharmony_ci compare_dump(reporter, p, false, "path.setFillType(SkPathFillType::kInverseEvenOdd);\n" 4359cb93a386Sopenharmony_ci "path.moveTo(1, 2);\n" 4360cb93a386Sopenharmony_ci "path.cubicTo(3, 4, 5, 6, 7, 8);\n"); 4361cb93a386Sopenharmony_ci p.reset(); 4362cb93a386Sopenharmony_ci p.setFillType(SkPathFillType::kWinding); 4363cb93a386Sopenharmony_ci p.moveTo(1, 2); 4364cb93a386Sopenharmony_ci p.lineTo(3, 4); 4365cb93a386Sopenharmony_ci compare_dump(reporter, p, true, 4366cb93a386Sopenharmony_ci "path.setFillType(SkPathFillType::kWinding);\n" 4367cb93a386Sopenharmony_ci "path.moveTo(SkBits2Float(0x3f800000), SkBits2Float(0x40000000)); // 1, 2\n" 4368cb93a386Sopenharmony_ci "path.lineTo(SkBits2Float(0x40400000), SkBits2Float(0x40800000)); // 3, 4\n"); 4369cb93a386Sopenharmony_ci p.reset(); 4370cb93a386Sopenharmony_ci p.moveTo(SkBits2Float(0x3f800000), SkBits2Float(0x40000000)); 4371cb93a386Sopenharmony_ci p.lineTo(SkBits2Float(0x40400000), SkBits2Float(0x40800000)); 4372cb93a386Sopenharmony_ci compare_dump(reporter, p, false, "path.setFillType(SkPathFillType::kWinding);\n" 4373cb93a386Sopenharmony_ci "path.moveTo(1, 2);\n" 4374cb93a386Sopenharmony_ci "path.lineTo(3, 4);\n"); 4375cb93a386Sopenharmony_ci} 4376cb93a386Sopenharmony_ci 4377cb93a386Sopenharmony_cinamespace { 4378cb93a386Sopenharmony_ci 4379cb93a386Sopenharmony_ciclass ChangeListener : public SkIDChangeListener { 4380cb93a386Sopenharmony_cipublic: 4381cb93a386Sopenharmony_ci ChangeListener(bool *changed) : fChanged(changed) { *fChanged = false; } 4382cb93a386Sopenharmony_ci ~ChangeListener() override {} 4383cb93a386Sopenharmony_ci void changed() override { *fChanged = true; } 4384cb93a386Sopenharmony_ci 4385cb93a386Sopenharmony_ciprivate: 4386cb93a386Sopenharmony_ci bool* fChanged; 4387cb93a386Sopenharmony_ci}; 4388cb93a386Sopenharmony_ci 4389cb93a386Sopenharmony_ci} // namespace 4390cb93a386Sopenharmony_ci 4391cb93a386Sopenharmony_ciclass PathTest_Private { 4392cb93a386Sopenharmony_cipublic: 4393cb93a386Sopenharmony_ci static size_t GetFreeSpace(const SkPath& path) { 4394cb93a386Sopenharmony_ci return PathRefTest_Private::GetFreeSpace(*path.fPathRef); 4395cb93a386Sopenharmony_ci } 4396cb93a386Sopenharmony_ci 4397cb93a386Sopenharmony_ci static void TestPathTo(skiatest::Reporter* reporter) { 4398cb93a386Sopenharmony_ci SkPath p, q; 4399cb93a386Sopenharmony_ci p.lineTo(4, 4); 4400cb93a386Sopenharmony_ci p.reversePathTo(q); 4401cb93a386Sopenharmony_ci check_path_is_line(reporter, &p, 4, 4); 4402cb93a386Sopenharmony_ci q.moveTo(-4, -4); 4403cb93a386Sopenharmony_ci p.reversePathTo(q); 4404cb93a386Sopenharmony_ci check_path_is_line(reporter, &p, 4, 4); 4405cb93a386Sopenharmony_ci q.lineTo(7, 8); 4406cb93a386Sopenharmony_ci q.conicTo(8, 7, 6, 5, 0.5f); 4407cb93a386Sopenharmony_ci q.quadTo(6, 7, 8, 6); 4408cb93a386Sopenharmony_ci q.cubicTo(5, 6, 7, 8, 7, 5); 4409cb93a386Sopenharmony_ci q.close(); 4410cb93a386Sopenharmony_ci p.reversePathTo(q); 4411cb93a386Sopenharmony_ci SkRect reverseExpected = {-4, -4, 8, 8}; 4412cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.getBounds() == reverseExpected); 4413cb93a386Sopenharmony_ci } 4414cb93a386Sopenharmony_ci 4415cb93a386Sopenharmony_ci static void TestPathrefListeners(skiatest::Reporter* reporter) { 4416cb93a386Sopenharmony_ci SkPath p; 4417cb93a386Sopenharmony_ci 4418cb93a386Sopenharmony_ci bool changed = false; 4419cb93a386Sopenharmony_ci p.moveTo(0, 0); 4420cb93a386Sopenharmony_ci 4421cb93a386Sopenharmony_ci // Check that listener is notified on moveTo(). 4422cb93a386Sopenharmony_ci 4423cb93a386Sopenharmony_ci SkPathPriv::AddGenIDChangeListener(p, sk_make_sp<ChangeListener>(&changed)); 4424cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !changed); 4425cb93a386Sopenharmony_ci p.moveTo(10, 0); 4426cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, changed); 4427cb93a386Sopenharmony_ci 4428cb93a386Sopenharmony_ci // Check that listener is notified on lineTo(). 4429cb93a386Sopenharmony_ci SkPathPriv::AddGenIDChangeListener(p, sk_make_sp<ChangeListener>(&changed)); 4430cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !changed); 4431cb93a386Sopenharmony_ci p.lineTo(20, 0); 4432cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, changed); 4433cb93a386Sopenharmony_ci 4434cb93a386Sopenharmony_ci // Check that listener is notified on reset(). 4435cb93a386Sopenharmony_ci SkPathPriv::AddGenIDChangeListener(p, sk_make_sp<ChangeListener>(&changed)); 4436cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !changed); 4437cb93a386Sopenharmony_ci p.reset(); 4438cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, changed); 4439cb93a386Sopenharmony_ci 4440cb93a386Sopenharmony_ci p.moveTo(0, 0); 4441cb93a386Sopenharmony_ci 4442cb93a386Sopenharmony_ci // Check that listener is notified on rewind(). 4443cb93a386Sopenharmony_ci SkPathPriv::AddGenIDChangeListener(p, sk_make_sp<ChangeListener>(&changed)); 4444cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !changed); 4445cb93a386Sopenharmony_ci p.rewind(); 4446cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, changed); 4447cb93a386Sopenharmony_ci 4448cb93a386Sopenharmony_ci // Check that listener is notified on transform(). 4449cb93a386Sopenharmony_ci { 4450cb93a386Sopenharmony_ci SkPath q; 4451cb93a386Sopenharmony_ci q.moveTo(10, 10); 4452cb93a386Sopenharmony_ci SkPathPriv::AddGenIDChangeListener(q, sk_make_sp<ChangeListener>(&changed)); 4453cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !changed); 4454cb93a386Sopenharmony_ci SkMatrix matrix; 4455cb93a386Sopenharmony_ci matrix.setScale(2, 2); 4456cb93a386Sopenharmony_ci p.transform(matrix, &q); 4457cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, changed); 4458cb93a386Sopenharmony_ci } 4459cb93a386Sopenharmony_ci 4460cb93a386Sopenharmony_ci // Check that listener is notified when pathref is deleted. 4461cb93a386Sopenharmony_ci { 4462cb93a386Sopenharmony_ci SkPath q; 4463cb93a386Sopenharmony_ci q.moveTo(10, 10); 4464cb93a386Sopenharmony_ci SkPathPriv::AddGenIDChangeListener(q, sk_make_sp<ChangeListener>(&changed)); 4465cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !changed); 4466cb93a386Sopenharmony_ci } 4467cb93a386Sopenharmony_ci // q went out of scope. 4468cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, changed); 4469cb93a386Sopenharmony_ci } 4470cb93a386Sopenharmony_ci}; 4471cb93a386Sopenharmony_ci 4472cb93a386Sopenharmony_cistatic void test_crbug_629455(skiatest::Reporter* reporter) { 4473cb93a386Sopenharmony_ci SkPath path; 4474cb93a386Sopenharmony_ci path.moveTo(0, 0); 4475cb93a386Sopenharmony_ci path.cubicTo(SkBits2Float(0xcdcdcd00), SkBits2Float(0xcdcdcdcd), 4476cb93a386Sopenharmony_ci SkBits2Float(0xcdcdcdcd), SkBits2Float(0xcdcdcdcd), 4477cb93a386Sopenharmony_ci SkBits2Float(0x423fcdcd), SkBits2Float(0x40ed9341)); 4478cb93a386Sopenharmony_ci// AKA: cubicTo(-4.31596e+08f, -4.31602e+08f, -4.31602e+08f, -4.31602e+08f, 47.951f, 7.42423f); 4479cb93a386Sopenharmony_ci path.lineTo(0, 0); 4480cb93a386Sopenharmony_ci test_draw_AA_path(100, 100, path); 4481cb93a386Sopenharmony_ci} 4482cb93a386Sopenharmony_ci 4483cb93a386Sopenharmony_cistatic void test_fuzz_crbug_662952(skiatest::Reporter* reporter) { 4484cb93a386Sopenharmony_ci SkPath path; 4485cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0x4109999a), SkBits2Float(0x411c0000)); // 8.6f, 9.75f 4486cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x410a6666), SkBits2Float(0x411c0000)); // 8.65f, 9.75f 4487cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x410a6666), SkBits2Float(0x411e6666)); // 8.65f, 9.9f 4488cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x4109999a), SkBits2Float(0x411e6666)); // 8.6f, 9.9f 4489cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x4109999a), SkBits2Float(0x411c0000)); // 8.6f, 9.75f 4490cb93a386Sopenharmony_ci path.close(); 4491cb93a386Sopenharmony_ci 4492cb93a386Sopenharmony_ci auto surface = SkSurface::MakeRasterN32Premul(100, 100); 4493cb93a386Sopenharmony_ci SkPaint paint; 4494cb93a386Sopenharmony_ci paint.setAntiAlias(true); 4495cb93a386Sopenharmony_ci surface->getCanvas()->clipPath(path, true); 4496cb93a386Sopenharmony_ci surface->getCanvas()->drawRect(SkRect::MakeWH(100, 100), paint); 4497cb93a386Sopenharmony_ci} 4498cb93a386Sopenharmony_ci 4499cb93a386Sopenharmony_cistatic void test_path_crbugskia6003() { 4500cb93a386Sopenharmony_ci auto surface(SkSurface::MakeRasterN32Premul(500, 500)); 4501cb93a386Sopenharmony_ci SkCanvas* canvas = surface->getCanvas(); 4502cb93a386Sopenharmony_ci SkPaint paint; 4503cb93a386Sopenharmony_ci paint.setAntiAlias(true); 4504cb93a386Sopenharmony_ci SkPath path; 4505cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0x4325e666), SkBits2Float(0x42a1999a)); // 165.9f, 80.8f 4506cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x4325e666), SkBits2Float(0x42a2999a)); // 165.9f, 81.3f 4507cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x4325b333), SkBits2Float(0x42a2999a)); // 165.7f, 81.3f 4508cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x4325b333), SkBits2Float(0x42a16666)); // 165.7f, 80.7f 4509cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x4325b333), SkBits2Float(0x429f6666)); // 165.7f, 79.7f 4510cb93a386Sopenharmony_ci // 165.7f, 79.7f, 165.8f, 79.7f, 165.8f, 79.7f 4511cb93a386Sopenharmony_ci path.cubicTo(SkBits2Float(0x4325b333), SkBits2Float(0x429f6666), SkBits2Float(0x4325cccc), 4512cb93a386Sopenharmony_ci SkBits2Float(0x429f6666), SkBits2Float(0x4325cccc), SkBits2Float(0x429f6666)); 4513cb93a386Sopenharmony_ci // 165.8f, 79.7f, 165.8f, 79.7f, 165.9f, 79.7f 4514cb93a386Sopenharmony_ci path.cubicTo(SkBits2Float(0x4325cccc), SkBits2Float(0x429f6666), SkBits2Float(0x4325cccc), 4515cb93a386Sopenharmony_ci SkBits2Float(0x429f6666), SkBits2Float(0x4325e666), SkBits2Float(0x429f6666)); 4516cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x4325e666), SkBits2Float(0x42a1999a)); // 165.9f, 80.8f 4517cb93a386Sopenharmony_ci path.close(); 4518cb93a386Sopenharmony_ci canvas->clipPath(path, true); 4519cb93a386Sopenharmony_ci canvas->drawRect(SkRect::MakeWH(500, 500), paint); 4520cb93a386Sopenharmony_ci} 4521cb93a386Sopenharmony_ci 4522cb93a386Sopenharmony_cistatic void test_fuzz_crbug_662730(skiatest::Reporter* reporter) { 4523cb93a386Sopenharmony_ci SkPath path; 4524cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0 4525cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xd5394437), SkBits2Float(0x37373737)); // -1.2731e+13f, 1.09205e-05f 4526cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x37373737), SkBits2Float(0x37373737)); // 1.09205e-05f, 1.09205e-05f 4527cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x37373745), SkBits2Float(0x0001b800)); // 1.09205e-05f, 1.57842e-40f 4528cb93a386Sopenharmony_ci path.close(); 4529cb93a386Sopenharmony_ci test_draw_AA_path(100, 100, path); 4530cb93a386Sopenharmony_ci} 4531cb93a386Sopenharmony_ci 4532cb93a386Sopenharmony_cistatic void test_skbug_6947() { 4533cb93a386Sopenharmony_ci SkPath path; 4534cb93a386Sopenharmony_ci SkPoint points[] = 4535cb93a386Sopenharmony_ci {{125.126022f, -0.499872506f}, {125.288895f, -0.499338806f}, 4536cb93a386Sopenharmony_ci {125.299316f, -0.499290764f}, {126.294594f, 0.505449712f}, 4537cb93a386Sopenharmony_ci {125.999992f, 62.5047531f}, {124.0f, 62.4980202f}, 4538cb93a386Sopenharmony_ci {124.122749f, 0.498142242f}, {125.126022f, -0.499872506f}, 4539cb93a386Sopenharmony_ci {125.119476f, 1.50011659f}, {125.122749f, 0.50012207f}, 4540cb93a386Sopenharmony_ci {126.122749f, 0.502101898f}, {126.0f, 62.5019798f}, 4541cb93a386Sopenharmony_ci {125.0f, 62.5f}, {124.000008f, 62.4952469f}, 4542cb93a386Sopenharmony_ci {124.294609f, 0.495946467f}, {125.294601f, 0.50069809f}, 4543cb93a386Sopenharmony_ci {125.289886f, 1.50068688f}, {125.282349f, 1.50065041f}, 4544cb93a386Sopenharmony_ci {125.119476f, 1.50011659f}}; 4545cb93a386Sopenharmony_ci constexpr SkPath::Verb kMove = SkPath::kMove_Verb; 4546cb93a386Sopenharmony_ci constexpr SkPath::Verb kLine = SkPath::kLine_Verb; 4547cb93a386Sopenharmony_ci constexpr SkPath::Verb kClose = SkPath::kClose_Verb; 4548cb93a386Sopenharmony_ci SkPath::Verb verbs[] = {kMove, kLine, kLine, kLine, kLine, kLine, kLine, kLine, kClose, 4549cb93a386Sopenharmony_ci kMove, kLine, kLine, kLine, kLine, kLine, kLine, kLine, kLine, kLine, kLine, kClose}; 4550cb93a386Sopenharmony_ci int pointIndex = 0; 4551cb93a386Sopenharmony_ci for(auto verb : verbs) { 4552cb93a386Sopenharmony_ci switch (verb) { 4553cb93a386Sopenharmony_ci case kMove: 4554cb93a386Sopenharmony_ci path.moveTo(points[pointIndex++]); 4555cb93a386Sopenharmony_ci break; 4556cb93a386Sopenharmony_ci case kLine: 4557cb93a386Sopenharmony_ci path.lineTo(points[pointIndex++]); 4558cb93a386Sopenharmony_ci break; 4559cb93a386Sopenharmony_ci case kClose: 4560cb93a386Sopenharmony_ci default: 4561cb93a386Sopenharmony_ci path.close(); 4562cb93a386Sopenharmony_ci break; 4563cb93a386Sopenharmony_ci } 4564cb93a386Sopenharmony_ci } 4565cb93a386Sopenharmony_ci test_draw_AA_path(250, 125, path); 4566cb93a386Sopenharmony_ci} 4567cb93a386Sopenharmony_ci 4568cb93a386Sopenharmony_cistatic void test_skbug_7015() { 4569cb93a386Sopenharmony_ci SkPath path; 4570cb93a386Sopenharmony_ci path.setFillType(SkPathFillType::kWinding); 4571cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0x4388c000), SkBits2Float(0x43947c08)); // 273.5f, 296.969f 4572cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x4386c000), SkBits2Float(0x43947c08)); // 269.5f, 296.969f 4573cb93a386Sopenharmony_ci // 269.297f, 292.172f, 273.695f, 292.172f, 273.5f, 296.969f 4574cb93a386Sopenharmony_ci path.cubicTo(SkBits2Float(0x4386a604), SkBits2Float(0x43921604), 4575cb93a386Sopenharmony_ci SkBits2Float(0x4388d8f6), SkBits2Float(0x43921604), 4576cb93a386Sopenharmony_ci SkBits2Float(0x4388c000), SkBits2Float(0x43947c08)); 4577cb93a386Sopenharmony_ci path.close(); 4578cb93a386Sopenharmony_ci test_draw_AA_path(500, 500, path); 4579cb93a386Sopenharmony_ci} 4580cb93a386Sopenharmony_ci 4581cb93a386Sopenharmony_cistatic void test_skbug_7051() { 4582cb93a386Sopenharmony_ci SkPath path; 4583cb93a386Sopenharmony_ci path.moveTo(10, 10); 4584cb93a386Sopenharmony_ci path.cubicTo(10, 20, 10, 30, 30, 30); 4585cb93a386Sopenharmony_ci path.lineTo(50, 20); 4586cb93a386Sopenharmony_ci path.lineTo(50, 10); 4587cb93a386Sopenharmony_ci path.close(); 4588cb93a386Sopenharmony_ci test_draw_AA_path(100, 100, path); 4589cb93a386Sopenharmony_ci} 4590cb93a386Sopenharmony_ci 4591cb93a386Sopenharmony_cistatic void test_skbug_7435() { 4592cb93a386Sopenharmony_ci SkPaint paint; 4593cb93a386Sopenharmony_ci SkPath path; 4594cb93a386Sopenharmony_ci path.setFillType(SkPathFillType::kWinding); 4595cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0x7f07a5af), SkBits2Float(0xff07ff1d)); // 1.80306e+38f, -1.8077e+38f 4596cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7edf4b2d), SkBits2Float(0xfedffe0a)); // 1.48404e+38f, -1.48868e+38f 4597cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7edf4585), SkBits2Float(0xfee003b2)); // 1.48389e+38f, -1.48883e+38f 4598cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7ef348e9), SkBits2Float(0xfef403c6)); // 1.6169e+38f, -1.62176e+38f 4599cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7ef74c4e), SkBits2Float(0xfef803cb)); // 1.64358e+38f, -1.64834e+38f 4600cb93a386Sopenharmony_ci path.conicTo(SkBits2Float(0x7ef74f23), SkBits2Float(0xfef8069e), SkBits2Float(0x7ef751f6), SkBits2Float(0xfef803c9), SkBits2Float(0x3f3504f3)); // 1.64365e+38f, -1.64841e+38f, 1.64372e+38f, -1.64834e+38f, 0.707107f 4601cb93a386Sopenharmony_ci path.conicTo(SkBits2Float(0x7ef754c8), SkBits2Float(0xfef800f5), SkBits2Float(0x7ef751f5), SkBits2Float(0xfef7fe22), SkBits2Float(0x3f353472)); // 1.6438e+38f, -1.64827e+38f, 1.64372e+38f, -1.64819e+38f, 0.707832f 4602cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7edb57a9), SkBits2Float(0xfedbfe06)); // 1.45778e+38f, -1.4621e+38f 4603cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7e875976), SkBits2Float(0xfe87fdb3)); // 8.99551e+37f, -9.03815e+37f 4604cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7ded5c2b), SkBits2Float(0xfdeff59e)); // 3.94382e+37f, -3.98701e+37f 4605cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7d7a78a7), SkBits2Float(0xfd7fda0f)); // 2.08083e+37f, -2.12553e+37f 4606cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7d7a6403), SkBits2Float(0xfd7fe461)); // 2.08016e+37f, -2.12587e+37f 4607cb93a386Sopenharmony_ci path.conicTo(SkBits2Float(0x7d7a4764), SkBits2Float(0xfd7ff2b0), SkBits2Float(0x7d7a55b4), SkBits2Float(0xfd8007a8), SkBits2Float(0x3f3504f3)); // 2.07924e+37f, -2.12633e+37f, 2.0797e+37f, -2.12726e+37f, 0.707107f 4608cb93a386Sopenharmony_ci path.conicTo(SkBits2Float(0x7d7a5803), SkBits2Float(0xfd8009f7), SkBits2Float(0x7d7a5ba9), SkBits2Float(0xfd800bcc), SkBits2Float(0x3f7cba66)); // 2.07977e+37f, -2.12741e+37f, 2.07989e+37f, -2.12753e+37f, 0.987219f 4609cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7d8d2067), SkBits2Float(0xfd900bdb)); // 2.34487e+37f, -2.39338e+37f 4610cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7ddd137a), SkBits2Float(0xfde00c2d)); // 3.67326e+37f, -3.72263e+37f 4611cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7ddd2a1b), SkBits2Float(0xfddff58e)); // 3.67473e+37f, -3.72116e+37f 4612cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7c694ae5), SkBits2Float(0xfc7fa67c)); // 4.8453e+36f, -5.30965e+36f 4613cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfc164a8b), SkBits2Float(0x7c005af5)); // -3.12143e+36f, 2.66584e+36f 4614cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfc8ae983), SkBits2Float(0x7c802da7)); // -5.77019e+36f, 5.32432e+36f 4615cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfc8b16d9), SkBits2Float(0x7c80007b)); // -5.77754e+36f, 5.31699e+36f 4616cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfc8b029c), SkBits2Float(0x7c7f8788)); // -5.77426e+36f, 5.30714e+36f 4617cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfc8b0290), SkBits2Float(0x7c7f8790)); // -5.77425e+36f, 5.30714e+36f 4618cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfc8b16cd), SkBits2Float(0x7c80007f)); // -5.77753e+36f, 5.31699e+36f 4619cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfc8b4409), SkBits2Float(0x7c7fa672)); // -5.78487e+36f, 5.30965e+36f 4620cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7d7aa2ba), SkBits2Float(0xfd800bd1)); // 2.0822e+37f, -2.12753e+37f 4621cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7e8757ee), SkBits2Float(0xfe88035b)); // 8.99512e+37f, -9.03962e+37f 4622cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7ef7552d), SkBits2Float(0xfef803ca)); // 1.64381e+38f, -1.64834e+38f 4623cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7f0fa653), SkBits2Float(0xff1001f9)); // 1.90943e+38f, -1.91419e+38f 4624cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7f0fa926), SkBits2Float(0xff0fff24)); // 1.90958e+38f, -1.91404e+38f 4625cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7f0da75c), SkBits2Float(0xff0dff22)); // 1.8829e+38f, -1.88746e+38f 4626cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7f07a5af), SkBits2Float(0xff07ff1d)); // 1.80306e+38f, -1.8077e+38f 4627cb93a386Sopenharmony_ci path.close(); 4628cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0x7f07a2db), SkBits2Float(0xff0801f1)); // 1.80291e+38f, -1.80785e+38f 4629cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7f0da48a), SkBits2Float(0xff0e01f8)); // 1.88275e+38f, -1.88761e+38f 4630cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7f0fa654), SkBits2Float(0xff1001fa)); // 1.90943e+38f, -1.91419e+38f 4631cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7f0fa7bd), SkBits2Float(0xff10008f)); // 1.90951e+38f, -1.91412e+38f 4632cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7f0fa927), SkBits2Float(0xff0fff25)); // 1.90958e+38f, -1.91404e+38f 4633cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7ef75ad5), SkBits2Float(0xfef7fe22)); // 1.64395e+38f, -1.64819e+38f 4634cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7e875d96), SkBits2Float(0xfe87fdb3)); // 8.99659e+37f, -9.03815e+37f 4635cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7d7acff6), SkBits2Float(0xfd7fea5b)); // 2.08367e+37f, -2.12606e+37f 4636cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfc8b0588), SkBits2Float(0x7c8049b7)); // -5.77473e+36f, 5.32887e+36f 4637cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfc8b2b16), SkBits2Float(0x7c803d32)); // -5.78083e+36f, 5.32684e+36f 4638cb93a386Sopenharmony_ci path.conicTo(SkBits2Float(0xfc8b395c), SkBits2Float(0x7c803870), SkBits2Float(0xfc8b4405), SkBits2Float(0x7c802dd1), SkBits2Float(0x3f79349d)); // -5.78314e+36f, 5.32607e+36f, -5.78487e+36f, 5.32435e+36f, 0.973459f 4639cb93a386Sopenharmony_ci path.conicTo(SkBits2Float(0xfc8b715b), SkBits2Float(0x7c8000a5), SkBits2Float(0xfc8b442f), SkBits2Float(0x7c7fa69e), SkBits2Float(0x3f3504f3)); // -5.79223e+36f, 5.31702e+36f, -5.7849e+36f, 5.30966e+36f, 0.707107f 4640cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfc16ffaa), SkBits2Float(0x7bff4c12)); // -3.13612e+36f, 2.65116e+36f 4641cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7c6895e0), SkBits2Float(0xfc802dc0)); // 4.83061e+36f, -5.32434e+36f 4642cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7ddd137b), SkBits2Float(0xfde00c2e)); // 3.67326e+37f, -3.72263e+37f 4643cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7ddd1ecb), SkBits2Float(0xfde000de)); // 3.67399e+37f, -3.72189e+37f 4644cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7ddd2a1c), SkBits2Float(0xfddff58f)); // 3.67473e+37f, -3.72116e+37f 4645cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7d8d3711), SkBits2Float(0xfd8ff543)); // 2.34634e+37f, -2.39191e+37f 4646cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7d7a88fe), SkBits2Float(0xfd7fea69)); // 2.08136e+37f, -2.12606e+37f 4647cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7d7a7254), SkBits2Float(0xfd800080)); // 2.08063e+37f, -2.1268e+37f 4648cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7d7a80a4), SkBits2Float(0xfd800ed0)); // 2.08109e+37f, -2.12773e+37f 4649cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7d7a80a8), SkBits2Float(0xfd800ecf)); // 2.08109e+37f, -2.12773e+37f 4650cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7d7a7258), SkBits2Float(0xfd80007f)); // 2.08063e+37f, -2.1268e+37f 4651cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7d7a5bb9), SkBits2Float(0xfd800bd0)); // 2.0799e+37f, -2.12753e+37f 4652cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7ded458b), SkBits2Float(0xfdf00c3e)); // 3.94235e+37f, -3.98848e+37f 4653cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7e8753ce), SkBits2Float(0xfe88035b)); // 8.99405e+37f, -9.03962e+37f 4654cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7edb5201), SkBits2Float(0xfedc03ae)); // 1.45763e+38f, -1.46225e+38f 4655cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7ef74c4d), SkBits2Float(0xfef803ca)); // 1.64358e+38f, -1.64834e+38f 4656cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7ef74f21), SkBits2Float(0xfef800f6)); // 1.64365e+38f, -1.64827e+38f 4657cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7ef751f4), SkBits2Float(0xfef7fe21)); // 1.64372e+38f, -1.64819e+38f 4658cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7ef34e91), SkBits2Float(0xfef3fe1e)); // 1.61705e+38f, -1.62161e+38f 4659cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7edf4b2d), SkBits2Float(0xfedffe0a)); // 1.48404e+38f, -1.48868e+38f 4660cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7edf4859), SkBits2Float(0xfee000de)); // 1.48397e+38f, -1.48876e+38f 4661cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7edf4585), SkBits2Float(0xfee003b2)); // 1.48389e+38f, -1.48883e+38f 4662cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7f07a2db), SkBits2Float(0xff0801f1)); // 1.80291e+38f, -1.80785e+38f 4663cb93a386Sopenharmony_ci path.close(); 4664cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0xfab120db), SkBits2Float(0x77b50b4f)); // -4.59851e+35f, 7.34402e+33f 4665cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfd6597e5), SkBits2Float(0x7d60177f)); // -1.90739e+37f, 1.86168e+37f 4666cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfde2cea1), SkBits2Float(0x7de00c2e)); // -3.76848e+37f, 3.72263e+37f 4667cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe316511), SkBits2Float(0x7e300657)); // -5.89495e+37f, 5.84943e+37f 4668cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe415da1), SkBits2Float(0x7e400666)); // -6.42568e+37f, 6.38112e+37f 4669cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe41634a), SkBits2Float(0x7e4000be)); // -6.42641e+37f, 6.38039e+37f 4670cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe41634a), SkBits2Float(0x7e3ff8be)); // -6.42641e+37f, 6.37935e+37f 4671cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe416349), SkBits2Float(0x7e3ff8be)); // -6.42641e+37f, 6.37935e+37f 4672cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe415f69), SkBits2Float(0x7e3ff8be)); // -6.42591e+37f, 6.37935e+37f 4673cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe415bc9), SkBits2Float(0x7e3ff8be)); // -6.42544e+37f, 6.37935e+37f 4674cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe415bc9), SkBits2Float(0x7e4000be)); // -6.42544e+37f, 6.38039e+37f 4675cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe416171), SkBits2Float(0x7e3ffb16)); // -6.42617e+37f, 6.37966e+37f 4676cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe016131), SkBits2Float(0x7dfff5ae)); // -4.29938e+37f, 4.25286e+37f 4677cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe0155e2), SkBits2Float(0x7e000628)); // -4.29791e+37f, 4.25433e+37f 4678cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe0958ea), SkBits2Float(0x7e080630)); // -4.56415e+37f, 4.52018e+37f 4679cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe115c92), SkBits2Float(0x7e100638)); // -4.83047e+37f, 4.78603e+37f 4680cb93a386Sopenharmony_ci path.conicTo(SkBits2Float(0xfe11623c), SkBits2Float(0x7e100bdf), SkBits2Float(0xfe1167e2), SkBits2Float(0x7e100636), SkBits2Float(0x3f3504f3)); // -4.8312e+37f, 4.78676e+37f, -4.83194e+37f, 4.78603e+37f, 0.707107f 4681cb93a386Sopenharmony_ci path.conicTo(SkBits2Float(0xfe116d87), SkBits2Float(0x7e10008e), SkBits2Float(0xfe1167e2), SkBits2Float(0x7e0ffae8), SkBits2Float(0x3f35240a)); // -4.83267e+37f, 4.78529e+37f, -4.83194e+37f, 4.78456e+37f, 0.707581f 4682cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe016b92), SkBits2Float(0x7dfff5af)); // -4.30072e+37f, 4.25286e+37f 4683cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfdc2d963), SkBits2Float(0x7dbff56e)); // -3.23749e+37f, 3.18946e+37f 4684cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfd65ae25), SkBits2Float(0x7d5fea3d)); // -1.90811e+37f, 1.86021e+37f 4685cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfab448de), SkBits2Float(0xf7b50a19)); // -4.68046e+35f, -7.34383e+33f 4686cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfab174d9), SkBits2Float(0x43480000)); // -4.60703e+35f, 200 4687cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfab174d9), SkBits2Float(0x7800007f)); // -4.60703e+35f, 1.03848e+34f 4688cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfab3f4db), SkBits2Float(0x7800007f)); // -4.67194e+35f, 1.03848e+34f 4689cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfab3f4db), SkBits2Float(0x43480000)); // -4.67194e+35f, 200 4690cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfab120db), SkBits2Float(0x77b50b4f)); // -4.59851e+35f, 7.34402e+33f 4691cb93a386Sopenharmony_ci path.close(); 4692cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0xfab59cf2), SkBits2Float(0xf800007e)); // -4.71494e+35f, -1.03847e+34f 4693cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfaa7cc52), SkBits2Float(0xf800007f)); // -4.35629e+35f, -1.03848e+34f 4694cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfd6580e5), SkBits2Float(0x7d60177f)); // -1.90664e+37f, 1.86168e+37f 4695cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfdc2c2c1), SkBits2Float(0x7dc00c0f)); // -3.23602e+37f, 3.19093e+37f 4696cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe016040), SkBits2Float(0x7e000626)); // -4.29925e+37f, 4.25433e+37f 4697cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe115c90), SkBits2Float(0x7e100636)); // -4.83047e+37f, 4.78603e+37f 4698cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe116239), SkBits2Float(0x7e10008f)); // -4.8312e+37f, 4.78529e+37f 4699cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe1167e0), SkBits2Float(0x7e0ffae6)); // -4.83194e+37f, 4.78456e+37f 4700cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe096438), SkBits2Float(0x7e07fade)); // -4.56562e+37f, 4.51871e+37f 4701cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe016130), SkBits2Float(0x7dfff5ac)); // -4.29938e+37f, 4.25286e+37f 4702cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe015b89), SkBits2Float(0x7e00007f)); // -4.29864e+37f, 4.25359e+37f 4703cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe0155e1), SkBits2Float(0x7e000627)); // -4.29791e+37f, 4.25433e+37f 4704cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe415879), SkBits2Float(0x7e4008bf)); // -6.42501e+37f, 6.38143e+37f 4705cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe415f69), SkBits2Float(0x7e4008bf)); // -6.42591e+37f, 6.38143e+37f 4706cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe416349), SkBits2Float(0x7e4008bf)); // -6.42641e+37f, 6.38143e+37f 4707cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe41634a), SkBits2Float(0x7e4008bf)); // -6.42641e+37f, 6.38143e+37f 4708cb93a386Sopenharmony_ci path.conicTo(SkBits2Float(0xfe416699), SkBits2Float(0x7e4008bf), SkBits2Float(0xfe4168f1), SkBits2Float(0x7e400668), SkBits2Float(0x3f6c8ed9)); // -6.42684e+37f, 6.38143e+37f, -6.42715e+37f, 6.38113e+37f, 0.924055f 4709cb93a386Sopenharmony_ci path.conicTo(SkBits2Float(0xfe416e9a), SkBits2Float(0x7e4000c2), SkBits2Float(0xfe4168f3), SkBits2Float(0x7e3ffb17), SkBits2Float(0x3f3504f3)); // -6.42788e+37f, 6.38039e+37f, -6.42715e+37f, 6.37966e+37f, 0.707107f 4710cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe317061), SkBits2Float(0x7e2ffb07)); // -5.89642e+37f, 5.84796e+37f 4711cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfde2e542), SkBits2Float(0x7ddff58e)); // -3.76995e+37f, 3.72116e+37f 4712cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfd65c525), SkBits2Float(0x7d5fea3d)); // -1.90886e+37f, 1.86021e+37f 4713cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfab6c8db), SkBits2Float(0xf7b50b4f)); // -4.74536e+35f, -7.34402e+33f 4714cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfab59cf2), SkBits2Float(0xf800007e)); // -4.71494e+35f, -1.03847e+34f 4715cb93a386Sopenharmony_ci path.close(); 4716cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0xfab3f4db), SkBits2Float(0x43480000)); // -4.67194e+35f, 200 4717cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfab174d9), SkBits2Float(0x43480000)); // -4.60703e+35f, 200 4718cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0xfd0593a5), SkBits2Float(0x7d00007f), SkBits2Float(0xfd659785), SkBits2Float(0x7d6000de)); // -1.10971e+37f, 1.0634e+37f, -1.90737e+37f, 1.86095e+37f 4719cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0xfda2cdf2), SkBits2Float(0x7da0009f), SkBits2Float(0xfdc2ce12), SkBits2Float(0x7dc000be)); // -2.70505e+37f, 2.6585e+37f, -3.23675e+37f, 3.1902e+37f 4720cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0xfde2ce31), SkBits2Float(0x7de000de), SkBits2Float(0xfe0165e9), SkBits2Float(0x7e00007f)); // -3.76845e+37f, 3.72189e+37f, -4.29999e+37f, 4.25359e+37f 4721cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0xfe1164b9), SkBits2Float(0x7e10008f), SkBits2Float(0xfe116239), SkBits2Float(0x7e10008f)); // -4.83153e+37f, 4.78529e+37f, -4.8312e+37f, 4.78529e+37f 4722cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0xfe116039), SkBits2Float(0x7e10008f), SkBits2Float(0xfe095e91), SkBits2Float(0x7e080087)); // -4.83094e+37f, 4.78529e+37f, -4.56488e+37f, 4.51944e+37f 4723cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0xfe015d09), SkBits2Float(0x7e00007f), SkBits2Float(0xfe015b89), SkBits2Float(0x7e00007f)); // -4.29884e+37f, 4.25359e+37f, -4.29864e+37f, 4.25359e+37f 4724cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0xfe415bc9), SkBits2Float(0x7e4000be)); // -6.42544e+37f, 6.38039e+37f 4725cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0xfe415da9), SkBits2Float(0x7e4000be), SkBits2Float(0xfe415f69), SkBits2Float(0x7e4000be)); // -6.42568e+37f, 6.38039e+37f, -6.42591e+37f, 6.38039e+37f 4726cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0xfe416149), SkBits2Float(0x7e4000be), SkBits2Float(0xfe416349), SkBits2Float(0x7e4000be)); // -6.42615e+37f, 6.38039e+37f, -6.42641e+37f, 6.38039e+37f 4727cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0xfe416849), SkBits2Float(0x7e4000be), SkBits2Float(0xfe316ab9), SkBits2Float(0x7e3000af)); // -6.42706e+37f, 6.38039e+37f, -5.89569e+37f, 5.84869e+37f 4728cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0xfe216d29), SkBits2Float(0x7e20009f), SkBits2Float(0xfde2d9f2), SkBits2Float(0x7de000de)); // -5.36431e+37f, 5.31699e+37f, -3.76921e+37f, 3.72189e+37f 4729cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0xfda2d9b2), SkBits2Float(0x7da0009f), SkBits2Float(0xfd65ae85), SkBits2Float(0x7d6000de)); // -2.70582e+37f, 2.6585e+37f, -1.90812e+37f, 1.86095e+37f 4730cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0xfd05a9a6), SkBits2Float(0x7d00007f), SkBits2Float(0xfab3f4db), SkBits2Float(0x43480000)); // -1.11043e+37f, 1.0634e+37f, -4.67194e+35f, 200 4731cb93a386Sopenharmony_ci path.close(); 4732cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0x7f07a445), SkBits2Float(0xff080087)); // 1.80299e+38f, -1.80778e+38f 4733cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0x7f0ba519), SkBits2Float(0xff0c008b), SkBits2Float(0x7f0da5f3), SkBits2Float(0xff0e008d)); // 1.8562e+38f, -1.86095e+38f, 1.88283e+38f, -1.88753e+38f 4734cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0x7f0fa6d5), SkBits2Float(0xff10008f), SkBits2Float(0x7f0fa7bd), SkBits2Float(0xff10008f)); // 1.90946e+38f, -1.91412e+38f, 1.90951e+38f, -1.91412e+38f 4735cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0x7f0faa7d), SkBits2Float(0xff10008f), SkBits2Float(0x7ef75801), SkBits2Float(0xfef800f6)); // 1.90965e+38f, -1.91412e+38f, 1.64388e+38f, -1.64827e+38f 4736cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0x7ecf5b09), SkBits2Float(0xfed000ce), SkBits2Float(0x7e875ac2), SkBits2Float(0xfe880087)); // 1.37811e+38f, -1.38242e+38f, 8.99585e+37f, -9.03889e+37f 4737cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0x7e0eb505), SkBits2Float(0xfe10008f), SkBits2Float(0x7d7ab958), SkBits2Float(0xfd80007f)); // 4.74226e+37f, -4.78529e+37f, 2.08293e+37f, -2.1268e+37f 4738cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0xfc8ac1cd), SkBits2Float(0x7c80007f), SkBits2Float(0xfc8b16cd), SkBits2Float(0x7c80007f)); // -5.76374e+36f, 5.31699e+36f, -5.77753e+36f, 5.31699e+36f 4739cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0xfc8b36cd), SkBits2Float(0x7c80007f), SkBits2Float(0xfc16a51a), SkBits2Float(0x7c00007f)); // -5.78273e+36f, 5.31699e+36f, -3.12877e+36f, 2.6585e+36f 4740cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0xfab6e4de), SkBits2Float(0x43480000), SkBits2Float(0x7c68f062), SkBits2Float(0xfc80007f)); // -4.7482e+35f, 200, 4.83795e+36f, -5.31699e+36f 4741cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7ddd1ecb), SkBits2Float(0xfde000de)); // 3.67399e+37f, -3.72189e+37f 4742cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0x7d9d254b), SkBits2Float(0xfda0009f), SkBits2Float(0x7d8d2bbc), SkBits2Float(0xfd90008f)); // 2.61103e+37f, -2.6585e+37f, 2.3456e+37f, -2.39265e+37f 4743cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0x7d7a64d8), SkBits2Float(0xfd80007f), SkBits2Float(0x7d7a7258), SkBits2Float(0xfd80007f)); // 2.08019e+37f, -2.1268e+37f, 2.08063e+37f, -2.1268e+37f 4744cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0x7d7a9058), SkBits2Float(0xfd80007f), SkBits2Float(0x7ded50db), SkBits2Float(0xfdf000ee)); // 2.0816e+37f, -2.1268e+37f, 3.94309e+37f, -3.98774e+37f 4745cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0x7e2eace5), SkBits2Float(0xfe3000af), SkBits2Float(0x7e8756a2), SkBits2Float(0xfe880087)); // 5.80458e+37f, -5.84869e+37f, 8.99478e+37f, -9.03889e+37f 4746cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0x7ebf56d9), SkBits2Float(0xfec000be), SkBits2Float(0x7edb54d5), SkBits2Float(0xfedc00da)); // 1.27167e+38f, -1.27608e+38f, 1.45771e+38f, -1.46217e+38f 4747cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0x7ef752e1), SkBits2Float(0xfef800f6), SkBits2Float(0x7ef74f21), SkBits2Float(0xfef800f6)); // 1.64375e+38f, -1.64827e+38f, 1.64365e+38f, -1.64827e+38f 4748cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0x7ef74d71), SkBits2Float(0xfef800f6), SkBits2Float(0x7ef34bbd), SkBits2Float(0xfef400f2)); // 1.64361e+38f, -1.64827e+38f, 1.61698e+38f, -1.62168e+38f 4749cb93a386Sopenharmony_ci path.quadTo(SkBits2Float(0x7eef4a19), SkBits2Float(0xfef000ee), SkBits2Float(0x7edf4859), SkBits2Float(0xfee000de)); // 1.59035e+38f, -1.5951e+38f, 1.48397e+38f, -1.48876e+38f 4750cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x7f07a445), SkBits2Float(0xff080087)); // 1.80299e+38f, -1.80778e+38f 4751cb93a386Sopenharmony_ci path.close(); 4752cb93a386Sopenharmony_ci SkSurface::MakeRasterN32Premul(250, 250, nullptr)->getCanvas()->drawPath(path, paint); 4753cb93a386Sopenharmony_ci} 4754cb93a386Sopenharmony_ci 4755cb93a386Sopenharmony_cistatic void test_interp(skiatest::Reporter* reporter) { 4756cb93a386Sopenharmony_ci SkPath p1, p2, out; 4757cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p1.isInterpolatable(p2)); 4758cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p1.interpolate(p2, 0, &out)); 4759cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p1 == out); 4760cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p1.interpolate(p2, 1, &out)); 4761cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p1 == out); 4762cb93a386Sopenharmony_ci p1.moveTo(0, 2); 4763cb93a386Sopenharmony_ci p1.lineTo(0, 4); 4764cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p1.isInterpolatable(p2)); 4765cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p1.interpolate(p2, 1, &out)); 4766cb93a386Sopenharmony_ci p2.moveTo(6, 0); 4767cb93a386Sopenharmony_ci p2.lineTo(8, 0); 4768cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p1.isInterpolatable(p2)); 4769cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p1.interpolate(p2, 0, &out)); 4770cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p2 == out); 4771cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p1.interpolate(p2, 1, &out)); 4772cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p1 == out); 4773cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p1.interpolate(p2, 0.5f, &out)); 4774cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, out.getBounds() == SkRect::MakeLTRB(3, 1, 4, 2)); 4775cb93a386Sopenharmony_ci p1.reset(); 4776cb93a386Sopenharmony_ci p1.moveTo(4, 4); 4777cb93a386Sopenharmony_ci p1.conicTo(5, 4, 5, 5, 1 / SkScalarSqrt(2)); 4778cb93a386Sopenharmony_ci p2.reset(); 4779cb93a386Sopenharmony_ci p2.moveTo(4, 2); 4780cb93a386Sopenharmony_ci p2.conicTo(7, 2, 7, 5, 1 / SkScalarSqrt(2)); 4781cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p1.isInterpolatable(p2)); 4782cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p1.interpolate(p2, 0.5f, &out)); 4783cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, out.getBounds() == SkRect::MakeLTRB(4, 3, 6, 5)); 4784cb93a386Sopenharmony_ci p2.reset(); 4785cb93a386Sopenharmony_ci p2.moveTo(4, 2); 4786cb93a386Sopenharmony_ci p2.conicTo(6, 3, 6, 5, 1); 4787cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p1.isInterpolatable(p2)); 4788cb93a386Sopenharmony_ci p2.reset(); 4789cb93a386Sopenharmony_ci p2.moveTo(4, 4); 4790cb93a386Sopenharmony_ci p2.conicTo(5, 4, 5, 5, 0.5f); 4791cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p1.isInterpolatable(p2)); 4792cb93a386Sopenharmony_ci} 4793cb93a386Sopenharmony_ci 4794cb93a386Sopenharmony_ciDEF_TEST(PathInterp, reporter) { 4795cb93a386Sopenharmony_ci test_interp(reporter); 4796cb93a386Sopenharmony_ci} 4797cb93a386Sopenharmony_ci 4798cb93a386Sopenharmony_ci#include "include/core/SkSurface.h" 4799cb93a386Sopenharmony_ciDEF_TEST(PathBigCubic, reporter) { 4800cb93a386Sopenharmony_ci SkPath path; 4801cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0 4802cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0x44000000), SkBits2Float(0x373938b8)); // 512, 1.10401e-05f 4803cb93a386Sopenharmony_ci path.cubicTo(SkBits2Float(0x00000001), SkBits2Float(0xdf000052), SkBits2Float(0x00000100), SkBits2Float(0x00000000), SkBits2Float(0x00000100), SkBits2Float(0x00000000)); // 1.4013e-45f, -9.22346e+18f, 3.58732e-43f, 0, 3.58732e-43f, 0 4804cb93a386Sopenharmony_ci path.moveTo(0, 512); 4805cb93a386Sopenharmony_ci 4806cb93a386Sopenharmony_ci // this call should not assert 4807cb93a386Sopenharmony_ci SkSurface::MakeRasterN32Premul(255, 255, nullptr)->getCanvas()->drawPath(path, SkPaint()); 4808cb93a386Sopenharmony_ci} 4809cb93a386Sopenharmony_ci 4810cb93a386Sopenharmony_ciDEF_TEST(PathContains, reporter) { 4811cb93a386Sopenharmony_ci test_contains(reporter); 4812cb93a386Sopenharmony_ci} 4813cb93a386Sopenharmony_ci 4814cb93a386Sopenharmony_ciDEF_TEST(Paths, reporter) { 4815cb93a386Sopenharmony_ci test_fuzz_crbug_647922(); 4816cb93a386Sopenharmony_ci test_fuzz_crbug_643933(); 4817cb93a386Sopenharmony_ci test_sect_with_horizontal_needs_pinning(); 4818cb93a386Sopenharmony_ci test_crbug_629455(reporter); 4819cb93a386Sopenharmony_ci test_fuzz_crbug_627414(reporter); 4820cb93a386Sopenharmony_ci test_path_crbug364224(); 4821cb93a386Sopenharmony_ci test_fuzz_crbug_662952(reporter); 4822cb93a386Sopenharmony_ci test_fuzz_crbug_662730(reporter); 4823cb93a386Sopenharmony_ci test_fuzz_crbug_662780(); 4824cb93a386Sopenharmony_ci test_mask_overflow(); 4825cb93a386Sopenharmony_ci test_path_crbugskia6003(); 4826cb93a386Sopenharmony_ci test_fuzz_crbug_668907(); 4827cb93a386Sopenharmony_ci test_skbug_6947(); 4828cb93a386Sopenharmony_ci test_skbug_7015(); 4829cb93a386Sopenharmony_ci test_skbug_7051(); 4830cb93a386Sopenharmony_ci test_skbug_7435(); 4831cb93a386Sopenharmony_ci 4832cb93a386Sopenharmony_ci SkSize::Make(3, 4); 4833cb93a386Sopenharmony_ci 4834cb93a386Sopenharmony_ci SkPath p, empty; 4835cb93a386Sopenharmony_ci SkRect bounds, bounds2; 4836cb93a386Sopenharmony_ci test_empty(reporter, p); 4837cb93a386Sopenharmony_ci 4838cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.getBounds().isEmpty()); 4839cb93a386Sopenharmony_ci 4840cb93a386Sopenharmony_ci // this triggers a code path in SkPath::operator= which is otherwise unexercised 4841cb93a386Sopenharmony_ci SkPath& self = p; 4842cb93a386Sopenharmony_ci p = self; 4843cb93a386Sopenharmony_ci 4844cb93a386Sopenharmony_ci // this triggers a code path in SkPath::swap which is otherwise unexercised 4845cb93a386Sopenharmony_ci p.swap(self); 4846cb93a386Sopenharmony_ci 4847cb93a386Sopenharmony_ci bounds.setLTRB(0, 0, SK_Scalar1, SK_Scalar1); 4848cb93a386Sopenharmony_ci 4849cb93a386Sopenharmony_ci p.addRoundRect(bounds, SK_Scalar1, SK_Scalar1); 4850cb93a386Sopenharmony_ci check_convex_bounds(reporter, p, bounds); 4851cb93a386Sopenharmony_ci // we have quads or cubics 4852cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 4853cb93a386Sopenharmony_ci p.getSegmentMasks() & (kCurveSegmentMask | SkPath::kConic_SegmentMask)); 4854cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.isEmpty()); 4855cb93a386Sopenharmony_ci 4856cb93a386Sopenharmony_ci p.reset(); 4857cb93a386Sopenharmony_ci test_empty(reporter, p); 4858cb93a386Sopenharmony_ci 4859cb93a386Sopenharmony_ci p.addOval(bounds); 4860cb93a386Sopenharmony_ci check_convex_bounds(reporter, p, bounds); 4861cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.isEmpty()); 4862cb93a386Sopenharmony_ci 4863cb93a386Sopenharmony_ci p.rewind(); 4864cb93a386Sopenharmony_ci test_empty(reporter, p); 4865cb93a386Sopenharmony_ci 4866cb93a386Sopenharmony_ci p.addRect(bounds); 4867cb93a386Sopenharmony_ci check_convex_bounds(reporter, p, bounds); 4868cb93a386Sopenharmony_ci // we have only lines 4869cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kLine_SegmentMask == p.getSegmentMasks()); 4870cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.isEmpty()); 4871cb93a386Sopenharmony_ci 4872cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p != empty); 4873cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !(p == empty)); 4874cb93a386Sopenharmony_ci 4875cb93a386Sopenharmony_ci // do getPoints and getVerbs return the right result 4876cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.getPoints(nullptr, 0) == 4); 4877cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.getVerbs(nullptr, 0) == 5); 4878cb93a386Sopenharmony_ci SkPoint pts[4]; 4879cb93a386Sopenharmony_ci int count = p.getPoints(pts, 4); 4880cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, count == 4); 4881cb93a386Sopenharmony_ci uint8_t verbs[6]; 4882cb93a386Sopenharmony_ci verbs[5] = 0xff; 4883cb93a386Sopenharmony_ci p.getVerbs(verbs, 5); 4884cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kMove_Verb == verbs[0]); 4885cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kLine_Verb == verbs[1]); 4886cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kLine_Verb == verbs[2]); 4887cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kLine_Verb == verbs[3]); 4888cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPath::kClose_Verb == verbs[4]); 4889cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0xff == verbs[5]); 4890cb93a386Sopenharmony_ci bounds2.setBounds(pts, 4); 4891cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, bounds == bounds2); 4892cb93a386Sopenharmony_ci 4893cb93a386Sopenharmony_ci bounds.offset(SK_Scalar1*3, SK_Scalar1*4); 4894cb93a386Sopenharmony_ci p.offset(SK_Scalar1*3, SK_Scalar1*4); 4895cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, bounds == p.getBounds()); 4896cb93a386Sopenharmony_ci 4897cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.isRect(nullptr)); 4898cb93a386Sopenharmony_ci bounds2.setEmpty(); 4899cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.isRect(&bounds2)); 4900cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, bounds == bounds2); 4901cb93a386Sopenharmony_ci 4902cb93a386Sopenharmony_ci // now force p to not be a rect 4903cb93a386Sopenharmony_ci bounds.setWH(SK_Scalar1/2, SK_Scalar1/2); 4904cb93a386Sopenharmony_ci p.addRect(bounds); 4905cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !p.isRect(nullptr)); 4906cb93a386Sopenharmony_ci 4907cb93a386Sopenharmony_ci // Test an edge case w.r.t. the bound returned by isRect (i.e., the 4908cb93a386Sopenharmony_ci // path has a trailing moveTo. Please see crbug.com\445368) 4909cb93a386Sopenharmony_ci { 4910cb93a386Sopenharmony_ci SkRect r; 4911cb93a386Sopenharmony_ci p.reset(); 4912cb93a386Sopenharmony_ci p.addRect(bounds); 4913cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.isRect(&r)); 4914cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, r == bounds); 4915cb93a386Sopenharmony_ci // add a moveTo outside of our bounds 4916cb93a386Sopenharmony_ci p.moveTo(bounds.fLeft + 10, bounds.fBottom + 10); 4917cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p.isRect(&r)); 4918cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, r == bounds); 4919cb93a386Sopenharmony_ci } 4920cb93a386Sopenharmony_ci 4921cb93a386Sopenharmony_ci test_operatorEqual(reporter); 4922cb93a386Sopenharmony_ci test_isLine(reporter); 4923cb93a386Sopenharmony_ci test_isRect(reporter); 4924cb93a386Sopenharmony_ci test_is_closed_rect(reporter); 4925cb93a386Sopenharmony_ci test_isNestedFillRects(reporter); 4926cb93a386Sopenharmony_ci test_zero_length_paths(reporter); 4927cb93a386Sopenharmony_ci test_direction(reporter); 4928cb93a386Sopenharmony_ci test_convexity(reporter); 4929cb93a386Sopenharmony_ci test_convexity2(reporter); 4930cb93a386Sopenharmony_ci test_convexity_doubleback(reporter); 4931cb93a386Sopenharmony_ci test_conservativelyContains(reporter); 4932cb93a386Sopenharmony_ci test_close(reporter); 4933cb93a386Sopenharmony_ci test_segment_masks(reporter); 4934cb93a386Sopenharmony_ci test_flattening(reporter); 4935cb93a386Sopenharmony_ci test_transform(reporter); 4936cb93a386Sopenharmony_ci test_bounds(reporter); 4937cb93a386Sopenharmony_ci test_iter(reporter); 4938cb93a386Sopenharmony_ci test_range_iter(reporter); 4939cb93a386Sopenharmony_ci test_circle(reporter); 4940cb93a386Sopenharmony_ci test_oval(reporter); 4941cb93a386Sopenharmony_ci test_strokerec(reporter); 4942cb93a386Sopenharmony_ci test_addPoly(reporter); 4943cb93a386Sopenharmony_ci test_isfinite(reporter); 4944cb93a386Sopenharmony_ci test_isfinite_after_transform(reporter); 4945cb93a386Sopenharmony_ci test_islastcontourclosed(reporter); 4946cb93a386Sopenharmony_ci test_arb_round_rect_is_convex(reporter); 4947cb93a386Sopenharmony_ci test_arb_zero_rad_round_rect_is_rect(reporter); 4948cb93a386Sopenharmony_ci test_addrect(reporter); 4949cb93a386Sopenharmony_ci test_addrect_isfinite(reporter); 4950cb93a386Sopenharmony_ci test_tricky_cubic(); 4951cb93a386Sopenharmony_ci test_clipped_cubic(); 4952cb93a386Sopenharmony_ci test_crbug_170666(); 4953cb93a386Sopenharmony_ci test_crbug_493450(reporter); 4954cb93a386Sopenharmony_ci test_crbug_495894(reporter); 4955cb93a386Sopenharmony_ci test_crbug_613918(); 4956cb93a386Sopenharmony_ci test_bad_cubic_crbug229478(); 4957cb93a386Sopenharmony_ci test_bad_cubic_crbug234190(); 4958cb93a386Sopenharmony_ci test_gen_id(reporter); 4959cb93a386Sopenharmony_ci test_path_close_issue1474(reporter); 4960cb93a386Sopenharmony_ci test_path_to_region(reporter); 4961cb93a386Sopenharmony_ci test_rrect(reporter); 4962cb93a386Sopenharmony_ci test_rMoveTo(reporter); 4963cb93a386Sopenharmony_ci test_arc(reporter); 4964cb93a386Sopenharmony_ci test_arc_ovals(reporter); 4965cb93a386Sopenharmony_ci test_arcTo(reporter); 4966cb93a386Sopenharmony_ci test_addPath(reporter); 4967cb93a386Sopenharmony_ci test_addPathMode(reporter, false, false); 4968cb93a386Sopenharmony_ci test_addPathMode(reporter, true, false); 4969cb93a386Sopenharmony_ci test_addPathMode(reporter, false, true); 4970cb93a386Sopenharmony_ci test_addPathMode(reporter, true, true); 4971cb93a386Sopenharmony_ci test_extendClosedPath(reporter); 4972cb93a386Sopenharmony_ci test_addEmptyPath(reporter, SkPath::kExtend_AddPathMode); 4973cb93a386Sopenharmony_ci test_addEmptyPath(reporter, SkPath::kAppend_AddPathMode); 4974cb93a386Sopenharmony_ci test_conicTo_special_case(reporter); 4975cb93a386Sopenharmony_ci test_get_point(reporter); 4976cb93a386Sopenharmony_ci test_contains(reporter); 4977cb93a386Sopenharmony_ci PathTest_Private::TestPathTo(reporter); 4978cb93a386Sopenharmony_ci PathRefTest_Private::TestPathRef(reporter); 4979cb93a386Sopenharmony_ci PathTest_Private::TestPathrefListeners(reporter); 4980cb93a386Sopenharmony_ci test_dump(reporter); 4981cb93a386Sopenharmony_ci test_path_crbug389050(reporter); 4982cb93a386Sopenharmony_ci test_path_crbugskia2820(reporter); 4983cb93a386Sopenharmony_ci test_path_crbugskia5995(); 4984cb93a386Sopenharmony_ci test_skbug_3469(reporter); 4985cb93a386Sopenharmony_ci test_skbug_3239(reporter); 4986cb93a386Sopenharmony_ci test_bounds_crbug_513799(reporter); 4987cb93a386Sopenharmony_ci test_fuzz_crbug_638223(); 4988cb93a386Sopenharmony_ci} 4989cb93a386Sopenharmony_ci 4990cb93a386Sopenharmony_ciDEF_TEST(conservatively_contains_rect, reporter) { 4991cb93a386Sopenharmony_ci SkPath path; 4992cb93a386Sopenharmony_ci 4993cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0x44000000), SkBits2Float(0x373938b8)); // 512, 1.10401e-05f 4994cb93a386Sopenharmony_ci // 1.4013e-45f, -9.22346e+18f, 3.58732e-43f, 0, 3.58732e-43f, 0 4995cb93a386Sopenharmony_ci path.cubicTo(SkBits2Float(0x00000001), SkBits2Float(0xdf000052), 4996cb93a386Sopenharmony_ci SkBits2Float(0x00000100), SkBits2Float(0x00000000), 4997cb93a386Sopenharmony_ci SkBits2Float(0x00000100), SkBits2Float(0x00000000)); 4998cb93a386Sopenharmony_ci path.moveTo(0, 0); 4999cb93a386Sopenharmony_ci 5000cb93a386Sopenharmony_ci // this should not assert 5001cb93a386Sopenharmony_ci path.conservativelyContainsRect({ -211747, 12.1115f, -197893, 25.0321f }); 5002cb93a386Sopenharmony_ci} 5003cb93a386Sopenharmony_ci 5004cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////////////////////////// 5005cb93a386Sopenharmony_ci 5006cb93a386Sopenharmony_cistatic void rand_path(SkPath* path, SkRandom& rand, SkPath::Verb verb, int n) { 5007cb93a386Sopenharmony_ci for (int i = 0; i < n; ++i) { 5008cb93a386Sopenharmony_ci switch (verb) { 5009cb93a386Sopenharmony_ci case SkPath::kLine_Verb: 5010cb93a386Sopenharmony_ci path->lineTo(rand.nextF()*100, rand.nextF()*100); 5011cb93a386Sopenharmony_ci break; 5012cb93a386Sopenharmony_ci case SkPath::kQuad_Verb: 5013cb93a386Sopenharmony_ci path->quadTo(rand.nextF()*100, rand.nextF()*100, 5014cb93a386Sopenharmony_ci rand.nextF()*100, rand.nextF()*100); 5015cb93a386Sopenharmony_ci break; 5016cb93a386Sopenharmony_ci case SkPath::kConic_Verb: 5017cb93a386Sopenharmony_ci path->conicTo(rand.nextF()*100, rand.nextF()*100, 5018cb93a386Sopenharmony_ci rand.nextF()*100, rand.nextF()*100, rand.nextF()*10); 5019cb93a386Sopenharmony_ci break; 5020cb93a386Sopenharmony_ci case SkPath::kCubic_Verb: 5021cb93a386Sopenharmony_ci path->cubicTo(rand.nextF()*100, rand.nextF()*100, 5022cb93a386Sopenharmony_ci rand.nextF()*100, rand.nextF()*100, 5023cb93a386Sopenharmony_ci rand.nextF()*100, rand.nextF()*100); 5024cb93a386Sopenharmony_ci break; 5025cb93a386Sopenharmony_ci default: 5026cb93a386Sopenharmony_ci SkASSERT(false); 5027cb93a386Sopenharmony_ci } 5028cb93a386Sopenharmony_ci } 5029cb93a386Sopenharmony_ci} 5030cb93a386Sopenharmony_ci 5031cb93a386Sopenharmony_ci#include "include/pathops/SkPathOps.h" 5032cb93a386Sopenharmony_ciDEF_TEST(path_tight_bounds, reporter) { 5033cb93a386Sopenharmony_ci SkRandom rand; 5034cb93a386Sopenharmony_ci 5035cb93a386Sopenharmony_ci const SkPath::Verb verbs[] = { 5036cb93a386Sopenharmony_ci SkPath::kLine_Verb, SkPath::kQuad_Verb, SkPath::kConic_Verb, SkPath::kCubic_Verb, 5037cb93a386Sopenharmony_ci }; 5038cb93a386Sopenharmony_ci for (int i = 0; i < 1000; ++i) { 5039cb93a386Sopenharmony_ci for (int n = 1; n <= 10; n += 9) { 5040cb93a386Sopenharmony_ci for (SkPath::Verb verb : verbs) { 5041cb93a386Sopenharmony_ci SkPath path; 5042cb93a386Sopenharmony_ci rand_path(&path, rand, verb, n); 5043cb93a386Sopenharmony_ci SkRect bounds = path.getBounds(); 5044cb93a386Sopenharmony_ci SkRect tight = path.computeTightBounds(); 5045cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, bounds.contains(tight)); 5046cb93a386Sopenharmony_ci 5047cb93a386Sopenharmony_ci SkRect tight2; 5048cb93a386Sopenharmony_ci TightBounds(path, &tight2); 5049cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, nearly_equal(tight, tight2)); 5050cb93a386Sopenharmony_ci } 5051cb93a386Sopenharmony_ci } 5052cb93a386Sopenharmony_ci } 5053cb93a386Sopenharmony_ci} 5054cb93a386Sopenharmony_ci 5055cb93a386Sopenharmony_ciDEF_TEST(skbug_6450, r) { 5056cb93a386Sopenharmony_ci SkRect ri = { 0.18554693f, 195.26283f, 0.185784385f, 752.644409f }; 5057cb93a386Sopenharmony_ci SkVector rdi[4] = { 5058cb93a386Sopenharmony_ci { 1.81159976e-09f, 7.58768801e-05f }, 5059cb93a386Sopenharmony_ci { 0.000118725002f, 0.000118725002f }, 5060cb93a386Sopenharmony_ci { 0.000118725002f, 0.000118725002f }, 5061cb93a386Sopenharmony_ci { 0.000118725002f, 0.486297607f } 5062cb93a386Sopenharmony_ci }; 5063cb93a386Sopenharmony_ci SkRRect irr; 5064cb93a386Sopenharmony_ci irr.setRectRadii(ri, rdi); 5065cb93a386Sopenharmony_ci SkRect ro = { 9.18354821e-39f, 2.1710848e+9f, 2.16945843e+9f, 3.47808128e+9f }; 5066cb93a386Sopenharmony_ci SkVector rdo[4] = { 5067cb93a386Sopenharmony_ci { 0, 0 }, 5068cb93a386Sopenharmony_ci { 0.0103298295f, 0.185887396f }, 5069cb93a386Sopenharmony_ci { 2.52999727e-29f, 169.001938f }, 5070cb93a386Sopenharmony_ci { 195.262741f, 195.161255f } 5071cb93a386Sopenharmony_ci }; 5072cb93a386Sopenharmony_ci SkRRect orr; 5073cb93a386Sopenharmony_ci orr.setRectRadii(ro, rdo); 5074cb93a386Sopenharmony_ci SkMakeNullCanvas()->drawDRRect(orr, irr, SkPaint()); 5075cb93a386Sopenharmony_ci} 5076cb93a386Sopenharmony_ci 5077cb93a386Sopenharmony_ciDEF_TEST(PathRefSerialization, reporter) { 5078cb93a386Sopenharmony_ci SkPath path; 5079cb93a386Sopenharmony_ci const size_t numMoves = 5; 5080cb93a386Sopenharmony_ci const size_t numConics = 7; 5081cb93a386Sopenharmony_ci const size_t numPoints = numMoves + 2 * numConics; 5082cb93a386Sopenharmony_ci const size_t numVerbs = numMoves + numConics; 5083cb93a386Sopenharmony_ci for (size_t i = 0; i < numMoves; ++i) path.moveTo(1, 2); 5084cb93a386Sopenharmony_ci for (size_t i = 0; i < numConics; ++i) path.conicTo(1, 2, 3, 4, 5); 5085cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.countPoints() == numPoints); 5086cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.countVerbs() == numVerbs); 5087cb93a386Sopenharmony_ci 5088cb93a386Sopenharmony_ci // Verify that path serializes/deserializes properly. 5089cb93a386Sopenharmony_ci sk_sp<SkData> data = path.serialize(); 5090cb93a386Sopenharmony_ci size_t bytesWritten = data->size(); 5091cb93a386Sopenharmony_ci 5092cb93a386Sopenharmony_ci { 5093cb93a386Sopenharmony_ci SkPath readBack; 5094cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, readBack != path); 5095cb93a386Sopenharmony_ci size_t bytesRead = readBack.readFromMemory(data->data(), bytesWritten); 5096cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, bytesRead == bytesWritten); 5097cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, readBack == path); 5098cb93a386Sopenharmony_ci } 5099cb93a386Sopenharmony_ci 5100cb93a386Sopenharmony_ci // One less byte (rounded down to alignment) than was written will also 5101cb93a386Sopenharmony_ci // fail to be deserialized. 5102cb93a386Sopenharmony_ci { 5103cb93a386Sopenharmony_ci SkPath readBack; 5104cb93a386Sopenharmony_ci size_t bytesRead = readBack.readFromMemory(data->data(), bytesWritten - 4); 5105cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !bytesRead); 5106cb93a386Sopenharmony_ci } 5107cb93a386Sopenharmony_ci} 5108cb93a386Sopenharmony_ci 5109cb93a386Sopenharmony_ciDEF_TEST(NonFinitePathIteration, reporter) { 5110cb93a386Sopenharmony_ci SkPath path; 5111cb93a386Sopenharmony_ci path.moveTo(SK_ScalarInfinity, SK_ScalarInfinity); 5112cb93a386Sopenharmony_ci SkPathPriv::Iterate iterate(path); 5113cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, iterate.begin() == iterate.end()); 5114cb93a386Sopenharmony_ci} 5115cb93a386Sopenharmony_ci 5116cb93a386Sopenharmony_ciDEF_TEST(AndroidArc, reporter) { 5117cb93a386Sopenharmony_ci const char* tests[] = { 5118cb93a386Sopenharmony_ci "M50,0A50,50,0,0 1 100,50 L100,85 A15,15,0,0 1 85,100 L50,100 A50,50,0,0 1 50,0z", 5119cb93a386Sopenharmony_ci ("M50,0L92,0 A8,8,0,0 1 100,8 L100,92 A8,8,0,0 1 92,100 L8,100" 5120cb93a386Sopenharmony_ci " A8,8,0,0 1 0,92 L 0,8 A8,8,0,0 1 8,0z"), 5121cb93a386Sopenharmony_ci "M50 0A50 50,0,1,1,50 100A50 50,0,1,1,50 0" 5122cb93a386Sopenharmony_ci }; 5123cb93a386Sopenharmony_ci for (auto test : tests) { 5124cb93a386Sopenharmony_ci SkPath aPath; 5125cb93a386Sopenharmony_ci SkAssertResult(SkParsePath::FromSVGString(test, &aPath)); 5126cb93a386Sopenharmony_ci SkASSERT(aPath.isConvex()); 5127cb93a386Sopenharmony_ci for (SkScalar scale = 1; scale < 1000; scale *= 1.1f) { 5128cb93a386Sopenharmony_ci SkPath scalePath = aPath; 5129cb93a386Sopenharmony_ci SkMatrix matrix; 5130cb93a386Sopenharmony_ci matrix.setScale(scale, scale); 5131cb93a386Sopenharmony_ci scalePath.transform(matrix); 5132cb93a386Sopenharmony_ci SkASSERT(scalePath.isConvex()); 5133cb93a386Sopenharmony_ci } 5134cb93a386Sopenharmony_ci for (SkScalar scale = 1; scale < .001; scale /= 1.1f) { 5135cb93a386Sopenharmony_ci SkPath scalePath = aPath; 5136cb93a386Sopenharmony_ci SkMatrix matrix; 5137cb93a386Sopenharmony_ci matrix.setScale(scale, scale); 5138cb93a386Sopenharmony_ci scalePath.transform(matrix); 5139cb93a386Sopenharmony_ci SkASSERT(scalePath.isConvex()); 5140cb93a386Sopenharmony_ci } 5141cb93a386Sopenharmony_ci } 5142cb93a386Sopenharmony_ci} 5143cb93a386Sopenharmony_ci 5144cb93a386Sopenharmony_ci/* 5145cb93a386Sopenharmony_ci * Try a range of crazy values, just to ensure that we don't assert/crash. 5146cb93a386Sopenharmony_ci */ 5147cb93a386Sopenharmony_ciDEF_TEST(HugeGeometry, reporter) { 5148cb93a386Sopenharmony_ci auto surf = SkSurface::MakeRasterN32Premul(100, 100); 5149cb93a386Sopenharmony_ci auto canvas = surf->getCanvas(); 5150cb93a386Sopenharmony_ci 5151cb93a386Sopenharmony_ci const bool aas[] = { false, true }; 5152cb93a386Sopenharmony_ci const SkPaint::Style styles[] = { 5153cb93a386Sopenharmony_ci SkPaint::kFill_Style, SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style 5154cb93a386Sopenharmony_ci }; 5155cb93a386Sopenharmony_ci const SkScalar values[] = { 5156cb93a386Sopenharmony_ci 0, 1, 1000, 1000 * 1000, 1000.f * 1000 * 10000, SK_ScalarMax / 2, SK_ScalarMax, 5157cb93a386Sopenharmony_ci SK_ScalarInfinity 5158cb93a386Sopenharmony_ci }; 5159cb93a386Sopenharmony_ci 5160cb93a386Sopenharmony_ci SkPaint paint; 5161cb93a386Sopenharmony_ci for (auto x : values) { 5162cb93a386Sopenharmony_ci SkRect r = { -x, -x, x, x }; 5163cb93a386Sopenharmony_ci for (auto width : values) { 5164cb93a386Sopenharmony_ci paint.setStrokeWidth(width); 5165cb93a386Sopenharmony_ci for (auto aa : aas) { 5166cb93a386Sopenharmony_ci paint.setAntiAlias(aa); 5167cb93a386Sopenharmony_ci for (auto style : styles) { 5168cb93a386Sopenharmony_ci paint.setStyle(style); 5169cb93a386Sopenharmony_ci canvas->drawRect(r, paint); 5170cb93a386Sopenharmony_ci canvas->drawOval(r, paint); 5171cb93a386Sopenharmony_ci } 5172cb93a386Sopenharmony_ci } 5173cb93a386Sopenharmony_ci } 5174cb93a386Sopenharmony_ci } 5175cb93a386Sopenharmony_ci 5176cb93a386Sopenharmony_ci} 5177cb93a386Sopenharmony_ci 5178cb93a386Sopenharmony_ci// Treat nonfinite paths as "empty" or "full", depending on inverse-filltype 5179cb93a386Sopenharmony_ciDEF_TEST(ClipPath_nonfinite, reporter) { 5180cb93a386Sopenharmony_ci auto surf = SkSurface::MakeRasterN32Premul(10, 10); 5181cb93a386Sopenharmony_ci SkCanvas* canvas = surf->getCanvas(); 5182cb93a386Sopenharmony_ci 5183cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !canvas->isClipEmpty()); 5184cb93a386Sopenharmony_ci for (bool aa : {false, true}) { 5185cb93a386Sopenharmony_ci for (auto ft : {SkPathFillType::kWinding, SkPathFillType::kInverseWinding}) { 5186cb93a386Sopenharmony_ci for (SkScalar bad : {SK_ScalarInfinity, SK_ScalarNaN}) { 5187cb93a386Sopenharmony_ci for (int bits = 1; bits <= 15; ++bits) { 5188cb93a386Sopenharmony_ci SkPoint p0 = { 0, 0 }; 5189cb93a386Sopenharmony_ci SkPoint p1 = { 0, 0 }; 5190cb93a386Sopenharmony_ci if (bits & 1) p0.fX = -bad; 5191cb93a386Sopenharmony_ci if (bits & 2) p0.fY = -bad; 5192cb93a386Sopenharmony_ci if (bits & 4) p1.fX = bad; 5193cb93a386Sopenharmony_ci if (bits & 8) p1.fY = bad; 5194cb93a386Sopenharmony_ci 5195cb93a386Sopenharmony_ci SkPath path; 5196cb93a386Sopenharmony_ci path.moveTo(p0); 5197cb93a386Sopenharmony_ci path.lineTo(p1); 5198cb93a386Sopenharmony_ci path.setFillType(ft); 5199cb93a386Sopenharmony_ci canvas->save(); 5200cb93a386Sopenharmony_ci canvas->clipPath(path, aa); 5201cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, canvas->isClipEmpty() == !path.isInverseFillType()); 5202cb93a386Sopenharmony_ci canvas->restore(); 5203cb93a386Sopenharmony_ci } 5204cb93a386Sopenharmony_ci } 5205cb93a386Sopenharmony_ci } 5206cb93a386Sopenharmony_ci } 5207cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !canvas->isClipEmpty()); 5208cb93a386Sopenharmony_ci} 5209cb93a386Sopenharmony_ci 5210cb93a386Sopenharmony_ci// skbug.com/7792 5211cb93a386Sopenharmony_ciDEF_TEST(Path_isRect, reporter) { 5212cb93a386Sopenharmony_ci auto makePath = [](const SkPoint* points, size_t count, bool close) -> SkPath { 5213cb93a386Sopenharmony_ci SkPath path; 5214cb93a386Sopenharmony_ci for (size_t index = 0; index < count; ++index) { 5215cb93a386Sopenharmony_ci index < 2 ? path.moveTo(points[index]) : path.lineTo(points[index]); 5216cb93a386Sopenharmony_ci } 5217cb93a386Sopenharmony_ci if (close) { 5218cb93a386Sopenharmony_ci path.close(); 5219cb93a386Sopenharmony_ci } 5220cb93a386Sopenharmony_ci return path; 5221cb93a386Sopenharmony_ci }; 5222cb93a386Sopenharmony_ci auto makePath2 = [](const SkPoint* points, const SkPath::Verb* verbs, size_t count) -> SkPath { 5223cb93a386Sopenharmony_ci SkPath path; 5224cb93a386Sopenharmony_ci for (size_t index = 0; index < count; ++index) { 5225cb93a386Sopenharmony_ci switch (verbs[index]) { 5226cb93a386Sopenharmony_ci case SkPath::kMove_Verb: 5227cb93a386Sopenharmony_ci path.moveTo(*points++); 5228cb93a386Sopenharmony_ci break; 5229cb93a386Sopenharmony_ci case SkPath::kLine_Verb: 5230cb93a386Sopenharmony_ci path.lineTo(*points++); 5231cb93a386Sopenharmony_ci break; 5232cb93a386Sopenharmony_ci case SkPath::kClose_Verb: 5233cb93a386Sopenharmony_ci path.close(); 5234cb93a386Sopenharmony_ci break; 5235cb93a386Sopenharmony_ci default: 5236cb93a386Sopenharmony_ci SkASSERT(0); 5237cb93a386Sopenharmony_ci } 5238cb93a386Sopenharmony_ci } 5239cb93a386Sopenharmony_ci return path; 5240cb93a386Sopenharmony_ci }; 5241cb93a386Sopenharmony_ci // isolated from skbug.com/7792 (bug description) 5242cb93a386Sopenharmony_ci SkRect rect; 5243cb93a386Sopenharmony_ci SkPoint points[] = { {10, 10}, {75, 75}, {150, 75}, {150, 150}, {75, 150} }; 5244cb93a386Sopenharmony_ci SkPath path = makePath(points, SK_ARRAY_COUNT(points), false); 5245cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isRect(&rect)); 5246cb93a386Sopenharmony_ci SkRect compare; 5247cb93a386Sopenharmony_ci compare.setBounds(&points[1], SK_ARRAY_COUNT(points) - 1); 5248cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, rect == compare); 5249cb93a386Sopenharmony_ci // isolated from skbug.com/7792#c3 5250cb93a386Sopenharmony_ci SkPoint points3[] = { {75, 50}, {100, 75}, {150, 75}, {150, 150}, {75, 150}, {75, 50} }; 5251cb93a386Sopenharmony_ci path = makePath(points3, SK_ARRAY_COUNT(points3), true); 5252cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isRect(&rect)); 5253cb93a386Sopenharmony_ci // isolated from skbug.com/7792#c9 5254cb93a386Sopenharmony_ci SkPoint points9[] = { {10, 10}, {75, 75}, {150, 75}, {150, 150}, {75, 150} }; 5255cb93a386Sopenharmony_ci path = makePath(points9, SK_ARRAY_COUNT(points9), true); 5256cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isRect(&rect)); 5257cb93a386Sopenharmony_ci compare.setBounds(&points9[1], SK_ARRAY_COUNT(points9) - 1); 5258cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, rect == compare); 5259cb93a386Sopenharmony_ci // isolated from skbug.com/7792#c11 5260cb93a386Sopenharmony_ci SkPath::Verb verbs11[] = { SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kLine_Verb, 5261cb93a386Sopenharmony_ci SkPath::kLine_Verb, SkPath::kLine_Verb, SkPath::kMove_Verb }; 5262cb93a386Sopenharmony_ci SkPoint points11[] = { {75, 150}, {75, 75}, {150, 75}, {150, 150}, {75, 150}, {75, 150} }; 5263cb93a386Sopenharmony_ci path = makePath2(points11, verbs11, SK_ARRAY_COUNT(verbs11)); 5264cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isRect(&rect)); 5265cb93a386Sopenharmony_ci compare.setBounds(&points11[0], SK_ARRAY_COUNT(points11)); 5266cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, rect == compare); 5267cb93a386Sopenharmony_ci // isolated from skbug.com/7792#c14 5268cb93a386Sopenharmony_ci SkPath::Verb verbs14[] = { SkPath::kMove_Verb, SkPath::kMove_Verb, SkPath::kMove_Verb, 5269cb93a386Sopenharmony_ci SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kLine_Verb, 5270cb93a386Sopenharmony_ci SkPath::kLine_Verb, SkPath::kLine_Verb, SkPath::kClose_Verb, 5271cb93a386Sopenharmony_ci SkPath::kLine_Verb, SkPath::kClose_Verb }; 5272cb93a386Sopenharmony_ci SkPoint points14[] = { {250, 75}, {250, 75}, {250, 75}, {100, 75}, 5273cb93a386Sopenharmony_ci {150, 75}, {150, 150}, {75, 150}, {75, 75}, {0, 0} }; 5274cb93a386Sopenharmony_ci path = makePath2(points14, verbs14, SK_ARRAY_COUNT(verbs14)); 5275cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isRect(&rect)); 5276cb93a386Sopenharmony_ci // isolated from skbug.com/7792#c15 5277cb93a386Sopenharmony_ci SkPath::Verb verbs15[] = { SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kLine_Verb, 5278cb93a386Sopenharmony_ci SkPath::kLine_Verb, SkPath::kMove_Verb }; 5279cb93a386Sopenharmony_ci SkPoint points15[] = { {75, 75}, {150, 75}, {150, 150}, {75, 150}, {250, 75} }; 5280cb93a386Sopenharmony_ci path = makePath2(points15, verbs15, SK_ARRAY_COUNT(verbs15)); 5281cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isRect(&rect)); 5282cb93a386Sopenharmony_ci compare.setBounds(&points15[0], SK_ARRAY_COUNT(points15) - 1); 5283cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, rect == compare); 5284cb93a386Sopenharmony_ci // isolated from skbug.com/7792#c17 5285cb93a386Sopenharmony_ci SkPoint points17[] = { {75, 10}, {75, 75}, {150, 75}, {150, 150}, {75, 150}, {75, 10} }; 5286cb93a386Sopenharmony_ci path = makePath(points17, SK_ARRAY_COUNT(points17), true); 5287cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isRect(&rect)); 5288cb93a386Sopenharmony_ci // isolated from skbug.com/7792#c19 5289cb93a386Sopenharmony_ci SkPath::Verb verbs19[] = { SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kLine_Verb, 5290cb93a386Sopenharmony_ci SkPath::kLine_Verb, SkPath::kLine_Verb, SkPath::kLine_Verb, 5291cb93a386Sopenharmony_ci SkPath::kLine_Verb, SkPath::kClose_Verb, SkPath::kMove_Verb, 5292cb93a386Sopenharmony_ci SkPath::kLine_Verb, SkPath::kLine_Verb }; 5293cb93a386Sopenharmony_ci SkPoint points19[] = { {75, 75}, {75, 75}, {75, 75}, {75, 75}, {150, 75}, {150, 150}, 5294cb93a386Sopenharmony_ci {75, 150}, {10, 10}, {30, 10}, {10, 30} }; 5295cb93a386Sopenharmony_ci path = makePath2(points19, verbs19, SK_ARRAY_COUNT(verbs19)); 5296cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isRect(&rect)); 5297cb93a386Sopenharmony_ci // isolated from skbug.com/7792#c23 5298cb93a386Sopenharmony_ci SkPath::Verb verbs23[] = { SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kMove_Verb, 5299cb93a386Sopenharmony_ci SkPath::kLine_Verb, SkPath::kLine_Verb, SkPath::kLine_Verb, 5300cb93a386Sopenharmony_ci SkPath::kLine_Verb, SkPath::kClose_Verb }; 5301cb93a386Sopenharmony_ci SkPoint points23[] = { {75, 75}, {75, 75}, {75, 75}, {75, 75}, {150, 75}, {150, 150}, 5302cb93a386Sopenharmony_ci {75, 150} }; 5303cb93a386Sopenharmony_ci path = makePath2(points23, verbs23, SK_ARRAY_COUNT(verbs23)); 5304cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isRect(&rect)); 5305cb93a386Sopenharmony_ci compare.setBounds(&points23[0], SK_ARRAY_COUNT(points23)); 5306cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, rect == compare); 5307cb93a386Sopenharmony_ci // isolated from skbug.com/7792#c29 5308cb93a386Sopenharmony_ci SkPath::Verb verbs29[] = { SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kLine_Verb, 5309cb93a386Sopenharmony_ci SkPath::kLine_Verb, SkPath::kLine_Verb, SkPath::kMove_Verb, 5310cb93a386Sopenharmony_ci SkPath::kClose_Verb }; 5311cb93a386Sopenharmony_ci SkPoint points29[] = { {75, 75}, {150, 75}, {150, 150}, {75, 150}, {75, 250}, {75, 75} }; 5312cb93a386Sopenharmony_ci path = makePath2(points29, verbs29, SK_ARRAY_COUNT(verbs29)); 5313cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isRect(&rect)); 5314cb93a386Sopenharmony_ci // isolated from skbug.com/7792#c31 5315cb93a386Sopenharmony_ci SkPath::Verb verbs31[] = { SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kLine_Verb, 5316cb93a386Sopenharmony_ci SkPath::kLine_Verb, SkPath::kLine_Verb, SkPath::kMove_Verb, 5317cb93a386Sopenharmony_ci SkPath::kClose_Verb }; 5318cb93a386Sopenharmony_ci SkPoint points31[] = { {75, 75}, {150, 75}, {150, 150}, {75, 150}, {75, 10}, {75, 75} }; 5319cb93a386Sopenharmony_ci path = makePath2(points31, verbs31, SK_ARRAY_COUNT(verbs31)); 5320cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isRect(&rect)); 5321cb93a386Sopenharmony_ci compare.setBounds(&points31[0], 4); 5322cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, rect == compare); 5323cb93a386Sopenharmony_ci // isolated from skbug.com/7792#c36 5324cb93a386Sopenharmony_ci SkPath::Verb verbs36[] = { SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kLine_Verb, 5325cb93a386Sopenharmony_ci SkPath::kLine_Verb, SkPath::kMove_Verb, SkPath::kLine_Verb }; 5326cb93a386Sopenharmony_ci SkPoint points36[] = { {75, 75}, {150, 75}, {150, 150}, {10, 150}, {75, 75}, {75, 75} }; 5327cb93a386Sopenharmony_ci path = makePath2(points36, verbs36, SK_ARRAY_COUNT(verbs36)); 5328cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isRect(&rect)); 5329cb93a386Sopenharmony_ci // isolated from skbug.com/7792#c39 5330cb93a386Sopenharmony_ci SkPath::Verb verbs39[] = { SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kLine_Verb, 5331cb93a386Sopenharmony_ci SkPath::kLine_Verb }; 5332cb93a386Sopenharmony_ci SkPoint points39[] = { {150, 75}, {150, 150}, {75, 150}, {75, 100} }; 5333cb93a386Sopenharmony_ci path = makePath2(points39, verbs39, SK_ARRAY_COUNT(verbs39)); 5334cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !path.isRect(&rect)); 5335cb93a386Sopenharmony_ci // isolated from zero_length_paths_aa 5336cb93a386Sopenharmony_ci SkPath::Verb verbsAA[] = { SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kLine_Verb, 5337cb93a386Sopenharmony_ci SkPath::kLine_Verb, SkPath::kLine_Verb, SkPath::kLine_Verb, 5338cb93a386Sopenharmony_ci SkPath::kLine_Verb, SkPath::kClose_Verb }; 5339cb93a386Sopenharmony_ci SkPoint pointsAA[] = { {32, 9.5f}, {32, 9.5f}, {32, 17}, {17, 17}, {17, 9.5f}, {17, 2}, 5340cb93a386Sopenharmony_ci {32, 2} }; 5341cb93a386Sopenharmony_ci path = makePath2(pointsAA, verbsAA, SK_ARRAY_COUNT(verbsAA)); 5342cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isRect(&rect)); 5343cb93a386Sopenharmony_ci compare.setBounds(&pointsAA[0], SK_ARRAY_COUNT(pointsAA)); 5344cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, rect == compare); 5345cb93a386Sopenharmony_ci // isolated from skbug.com/7792#c41 5346cb93a386Sopenharmony_ci SkPath::Verb verbs41[] = { SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kLine_Verb, 5347cb93a386Sopenharmony_ci SkPath::kLine_Verb, SkPath::kLine_Verb, SkPath::kMove_Verb, 5348cb93a386Sopenharmony_ci SkPath::kClose_Verb }; 5349cb93a386Sopenharmony_ci SkPoint points41[] = { {75, 75}, {150, 75}, {150, 150}, {140, 150}, {140, 75}, {75, 75} }; 5350cb93a386Sopenharmony_ci path = makePath2(points41, verbs41, SK_ARRAY_COUNT(verbs41)); 5351cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isRect(&rect)); 5352cb93a386Sopenharmony_ci compare.setBounds(&points41[1], 4); 5353cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, rect == compare); 5354cb93a386Sopenharmony_ci // isolated from skbug.com/7792#c53 5355cb93a386Sopenharmony_ci SkPath::Verb verbs53[] = { SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kLine_Verb, 5356cb93a386Sopenharmony_ci SkPath::kLine_Verb, SkPath::kLine_Verb, SkPath::kMove_Verb, 5357cb93a386Sopenharmony_ci SkPath::kClose_Verb }; 5358cb93a386Sopenharmony_ci SkPoint points53[] = { {75, 75}, {150, 75}, {150, 150}, {140, 150}, {140, 75}, {75, 75} }; 5359cb93a386Sopenharmony_ci path = makePath2(points53, verbs53, SK_ARRAY_COUNT(verbs53)); 5360cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path.isRect(&rect)); 5361cb93a386Sopenharmony_ci compare.setBounds(&points53[1], 4); 5362cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, rect == compare); 5363cb93a386Sopenharmony_ci} 5364cb93a386Sopenharmony_ci 5365cb93a386Sopenharmony_ci// Be sure we can safely add ourselves 5366cb93a386Sopenharmony_ciDEF_TEST(Path_self_add, reporter) { 5367cb93a386Sopenharmony_ci // The possible problem is that during path.add() we may have to grow the dst buffers as 5368cb93a386Sopenharmony_ci // we append the src pts/verbs, but all the while we are iterating over the src. If src == dst 5369cb93a386Sopenharmony_ci // we could realloc the buffer's (on behalf of dst) leaving the src iterator pointing at 5370cb93a386Sopenharmony_ci // garbage. 5371cb93a386Sopenharmony_ci // 5372cb93a386Sopenharmony_ci // The test runs though verious sized src paths, since its not defined publicly what the 5373cb93a386Sopenharmony_ci // reserve allocation strategy is for SkPath, therefore we can't know when an append operation 5374cb93a386Sopenharmony_ci // will trigger a realloc. At the time of this writing, these loops were sufficient to trigger 5375cb93a386Sopenharmony_ci // an ASAN error w/o the fix to SkPath::addPath(). 5376cb93a386Sopenharmony_ci // 5377cb93a386Sopenharmony_ci for (int count = 0; count < 10; ++count) { 5378cb93a386Sopenharmony_ci SkPath path; 5379cb93a386Sopenharmony_ci for (int add = 0; add < count; ++add) { 5380cb93a386Sopenharmony_ci // just add some stuff, so we have something to copy/append in addPath() 5381cb93a386Sopenharmony_ci path.moveTo(1, 2).lineTo(3, 4).cubicTo(1,2,3,4,5,6).conicTo(1,2,3,4,5); 5382cb93a386Sopenharmony_ci } 5383cb93a386Sopenharmony_ci path.addPath(path, 1, 2); 5384cb93a386Sopenharmony_ci path.addPath(path, 3, 4); 5385cb93a386Sopenharmony_ci } 5386cb93a386Sopenharmony_ci} 5387cb93a386Sopenharmony_ci 5388cb93a386Sopenharmony_ci#include "include/core/SkVertices.h" 5389cb93a386Sopenharmony_cistatic void draw_triangle(SkCanvas* canvas, const SkPoint pts[]) { 5390cb93a386Sopenharmony_ci // draw in different ways, looking for an assert 5391cb93a386Sopenharmony_ci 5392cb93a386Sopenharmony_ci { 5393cb93a386Sopenharmony_ci SkPath path; 5394cb93a386Sopenharmony_ci path.addPoly(pts, 3, false); 5395cb93a386Sopenharmony_ci canvas->drawPath(path, SkPaint()); 5396cb93a386Sopenharmony_ci } 5397cb93a386Sopenharmony_ci 5398cb93a386Sopenharmony_ci const SkColor colors[] = { SK_ColorBLACK, SK_ColorBLACK, SK_ColorBLACK }; 5399cb93a386Sopenharmony_ci auto v = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode, 3, pts, nullptr, colors); 5400cb93a386Sopenharmony_ci canvas->drawVertices(v, SkBlendMode::kSrcOver, SkPaint()); 5401cb93a386Sopenharmony_ci} 5402cb93a386Sopenharmony_ci 5403cb93a386Sopenharmony_ciDEF_TEST(triangle_onehalf, reporter) { 5404cb93a386Sopenharmony_ci auto surface(SkSurface::MakeRasterN32Premul(100, 100)); 5405cb93a386Sopenharmony_ci 5406cb93a386Sopenharmony_ci const SkPoint pts[] = { 5407cb93a386Sopenharmony_ci { 0.499069244f, 9.63295173f }, 5408cb93a386Sopenharmony_ci { 0.499402374f, 7.88207579f }, 5409cb93a386Sopenharmony_ci { 10.2363272f, 0.49999997f } 5410cb93a386Sopenharmony_ci }; 5411cb93a386Sopenharmony_ci draw_triangle(surface->getCanvas(), pts); 5412cb93a386Sopenharmony_ci} 5413cb93a386Sopenharmony_ci 5414cb93a386Sopenharmony_ciDEF_TEST(triangle_big, reporter) { 5415cb93a386Sopenharmony_ci auto surface(SkSurface::MakeRasterN32Premul(4, 4304)); 5416cb93a386Sopenharmony_ci 5417cb93a386Sopenharmony_ci // The first two points, when sent through our fixed-point SkEdge, can walk negative beyond 5418cb93a386Sopenharmony_ci // -0.5 due to accumulated += error of the slope. We have since make the bounds calculation 5419cb93a386Sopenharmony_ci // be conservative, so we invoke clipping if we get in this situation. 5420cb93a386Sopenharmony_ci // This test was added to demonstrate the need for this conservative bounds calc. 5421cb93a386Sopenharmony_ci // (found by a fuzzer) 5422cb93a386Sopenharmony_ci const SkPoint pts[] = { 5423cb93a386Sopenharmony_ci { 0.327190518f, -114.945152f }, 5424cb93a386Sopenharmony_ci { -0.5f, 1.00003874f }, 5425cb93a386Sopenharmony_ci { 0.666425824f, 4304.26172f }, 5426cb93a386Sopenharmony_ci }; 5427cb93a386Sopenharmony_ci draw_triangle(surface->getCanvas(), pts); 5428cb93a386Sopenharmony_ci} 5429cb93a386Sopenharmony_ci 5430cb93a386Sopenharmony_cistatic void add_verbs(SkPath* path, int count) { 5431cb93a386Sopenharmony_ci path->moveTo(0, 0); 5432cb93a386Sopenharmony_ci for (int i = 0; i < count; ++i) { 5433cb93a386Sopenharmony_ci switch (i & 3) { 5434cb93a386Sopenharmony_ci case 0: path->lineTo(10, 20); break; 5435cb93a386Sopenharmony_ci case 1: path->quadTo(5, 6, 7, 8); break; 5436cb93a386Sopenharmony_ci case 2: path->conicTo(1, 2, 3, 4, 0.5f); break; 5437cb93a386Sopenharmony_ci case 3: path->cubicTo(2, 4, 6, 8, 10, 12); break; 5438cb93a386Sopenharmony_ci } 5439cb93a386Sopenharmony_ci } 5440cb93a386Sopenharmony_ci} 5441cb93a386Sopenharmony_ci 5442cb93a386Sopenharmony_ci// Make sure when we call shrinkToFit() that we always shrink (or stay the same) 5443cb93a386Sopenharmony_ci// and that if we call twice, we stay the same. 5444cb93a386Sopenharmony_ciDEF_TEST(Path_shrinkToFit, reporter) { 5445cb93a386Sopenharmony_ci size_t max_free = 0; 5446cb93a386Sopenharmony_ci for (int verbs = 0; verbs < 100; ++verbs) { 5447cb93a386Sopenharmony_ci SkPath unique_path, shared_path; 5448cb93a386Sopenharmony_ci add_verbs(&unique_path, verbs); 5449cb93a386Sopenharmony_ci add_verbs(&shared_path, verbs); 5450cb93a386Sopenharmony_ci 5451cb93a386Sopenharmony_ci const SkPath copy = shared_path; 5452cb93a386Sopenharmony_ci 5453cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, shared_path == unique_path); 5454cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, shared_path == copy); 5455cb93a386Sopenharmony_ci 5456cb93a386Sopenharmony_ci uint32_t uID = unique_path.getGenerationID(); 5457cb93a386Sopenharmony_ci uint32_t sID = shared_path.getGenerationID(); 5458cb93a386Sopenharmony_ci uint32_t cID = copy.getGenerationID(); 5459cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, sID == cID); 5460cb93a386Sopenharmony_ci 5461cb93a386Sopenharmony_ci#ifdef SK_DEBUG 5462cb93a386Sopenharmony_ci size_t before = PathTest_Private::GetFreeSpace(unique_path); 5463cb93a386Sopenharmony_ci#endif 5464cb93a386Sopenharmony_ci SkPathPriv::ShrinkToFit(&unique_path); 5465cb93a386Sopenharmony_ci SkPathPriv::ShrinkToFit(&shared_path); 5466cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, shared_path == unique_path); 5467cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, shared_path == copy); 5468cb93a386Sopenharmony_ci 5469cb93a386Sopenharmony_ci // since the unique_path is "unique", it's genID need not have changed even though 5470cb93a386Sopenharmony_ci // unique_path has changed (been shrunk) 5471cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, uID == unique_path.getGenerationID()); 5472cb93a386Sopenharmony_ci // since the copy has not been changed, its ID should be the same 5473cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, cID == copy.getGenerationID()); 5474cb93a386Sopenharmony_ci // but since shared_path has changed, and was not uniquely owned, it's gen ID needs to have 5475cb93a386Sopenharmony_ci // changed, breaking the "sharing" -- this is done defensively in case there were any 5476cb93a386Sopenharmony_ci // outstanding Iterators active on copy, which could have been invalidated during 5477cb93a386Sopenharmony_ci // shrinkToFit. 5478cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, sID != shared_path.getGenerationID()); 5479cb93a386Sopenharmony_ci 5480cb93a386Sopenharmony_ci#ifdef SK_DEBUG 5481cb93a386Sopenharmony_ci size_t after = PathTest_Private::GetFreeSpace(unique_path); 5482cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, before >= after); 5483cb93a386Sopenharmony_ci max_free = std::max(max_free, before - after); 5484cb93a386Sopenharmony_ci 5485cb93a386Sopenharmony_ci size_t after2 = PathTest_Private::GetFreeSpace(unique_path); 5486cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, after == after2); 5487cb93a386Sopenharmony_ci#endif 5488cb93a386Sopenharmony_ci } 5489cb93a386Sopenharmony_ci if (false) { 5490cb93a386Sopenharmony_ci SkDebugf("max_free %zu\n", max_free); 5491cb93a386Sopenharmony_ci } 5492cb93a386Sopenharmony_ci} 5493cb93a386Sopenharmony_ci 5494cb93a386Sopenharmony_ciDEF_TEST(Path_setLastPt, r) { 5495cb93a386Sopenharmony_ci // There was a time where SkPath::setLastPoint() didn't invalidate cached path bounds. 5496cb93a386Sopenharmony_ci SkPath p; 5497cb93a386Sopenharmony_ci p.moveTo(0,0); 5498cb93a386Sopenharmony_ci p.moveTo(20,01); 5499cb93a386Sopenharmony_ci p.moveTo(20,10); 5500cb93a386Sopenharmony_ci p.moveTo(20,61); 5501cb93a386Sopenharmony_ci REPORTER_ASSERT(r, p.getBounds() == SkRect::MakeLTRB(0,0, 20,61)); 5502cb93a386Sopenharmony_ci 5503cb93a386Sopenharmony_ci p.setLastPt(30,01); 5504cb93a386Sopenharmony_ci REPORTER_ASSERT(r, p.getBounds() == SkRect::MakeLTRB(0,0, 30,10)); // was {0,0, 20,61} 5505cb93a386Sopenharmony_ci 5506cb93a386Sopenharmony_ci REPORTER_ASSERT(r, p.isValid()); 5507cb93a386Sopenharmony_ci} 5508cb93a386Sopenharmony_ci 5509cb93a386Sopenharmony_ciDEF_TEST(Path_increserve_handle_neg_crbug_883666, r) { 5510cb93a386Sopenharmony_ci SkPath path; 5511cb93a386Sopenharmony_ci 5512cb93a386Sopenharmony_ci path.conicTo({0, 0}, {1, 1}, SK_FloatNegativeInfinity); 5513cb93a386Sopenharmony_ci 5514cb93a386Sopenharmony_ci // <== use a copy path object to force SkPathRef::copy() and SkPathRef::resetToSize() 5515cb93a386Sopenharmony_ci SkPath shallowPath = path; 5516cb93a386Sopenharmony_ci 5517cb93a386Sopenharmony_ci // make sure we don't assert/crash on this. 5518cb93a386Sopenharmony_ci shallowPath.incReserve(0xffffffff); 5519cb93a386Sopenharmony_ci} 5520cb93a386Sopenharmony_ci 5521cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////////////////////// 5522cb93a386Sopenharmony_ci 5523cb93a386Sopenharmony_ci/* 5524cb93a386Sopenharmony_ci * For speed, we tried to preserve useful/expensive attributes about paths, 5525cb93a386Sopenharmony_ci * - convexity, isrect, isoval, ... 5526cb93a386Sopenharmony_ci * Axis-aligned shapes (rect, oval, rrect) should survive, including convexity if the matrix 5527cb93a386Sopenharmony_ci * is axis-aligned (e.g. scale+translate) 5528cb93a386Sopenharmony_ci */ 5529cb93a386Sopenharmony_ci 5530cb93a386Sopenharmony_cistruct Xforms { 5531cb93a386Sopenharmony_ci SkMatrix fIM, fTM, fSM, fRM; 5532cb93a386Sopenharmony_ci 5533cb93a386Sopenharmony_ci Xforms() { 5534cb93a386Sopenharmony_ci fIM.reset(); 5535cb93a386Sopenharmony_ci fTM.setTranslate(10, 20); 5536cb93a386Sopenharmony_ci fSM.setScale(2, 3); 5537cb93a386Sopenharmony_ci fRM.setRotate(30); 5538cb93a386Sopenharmony_ci } 5539cb93a386Sopenharmony_ci}; 5540cb93a386Sopenharmony_ci 5541cb93a386Sopenharmony_cistatic bool conditional_convex(const SkPath& path, bool is_convex) { 5542cb93a386Sopenharmony_ci SkPathConvexity c = SkPathPriv::GetConvexityOrUnknown(path); 5543cb93a386Sopenharmony_ci return is_convex ? (c == SkPathConvexity::kConvex) : (c != SkPathConvexity::kConvex); 5544cb93a386Sopenharmony_ci} 5545cb93a386Sopenharmony_ci 5546cb93a386Sopenharmony_ci// expect axis-aligned shape to survive assignment, identity and scale/translate matrices 5547cb93a386Sopenharmony_citemplate <typename ISA> 5548cb93a386Sopenharmony_civoid survive(SkPath* path, const Xforms& x, bool isAxisAligned, skiatest::Reporter* reporter, 5549cb93a386Sopenharmony_ci ISA isa_proc) { 5550cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, isa_proc(*path)); 5551cb93a386Sopenharmony_ci // force the issue (computing convexity) the first time. 5552cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path->isConvex()); 5553cb93a386Sopenharmony_ci 5554cb93a386Sopenharmony_ci SkPath path2; 5555cb93a386Sopenharmony_ci 5556cb93a386Sopenharmony_ci // a path's isa and convexity should survive assignment 5557cb93a386Sopenharmony_ci path2 = *path; 5558cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, isa_proc(path2)); 5559cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::GetConvexityOrUnknown(path2) == SkPathConvexity::kConvex); 5560cb93a386Sopenharmony_ci 5561cb93a386Sopenharmony_ci // a path's isa and convexity should identity transform 5562cb93a386Sopenharmony_ci path->transform(x.fIM, &path2); 5563cb93a386Sopenharmony_ci path->transform(x.fIM); 5564cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, isa_proc(path2)); 5565cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::GetConvexityOrUnknown(path2) == SkPathConvexity::kConvex); 5566cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, isa_proc(*path)); 5567cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::GetConvexityOrUnknown(*path) == SkPathConvexity::kConvex); 5568cb93a386Sopenharmony_ci 5569cb93a386Sopenharmony_ci // a path's isa should survive translation, convexity depends on axis alignment 5570cb93a386Sopenharmony_ci path->transform(x.fTM, &path2); 5571cb93a386Sopenharmony_ci path->transform(x.fTM); 5572cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, isa_proc(path2)); 5573cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, isa_proc(*path)); 5574cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, conditional_convex(path2, isAxisAligned)); 5575cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, conditional_convex(*path, isAxisAligned)); 5576cb93a386Sopenharmony_ci 5577cb93a386Sopenharmony_ci // a path's isa should survive scaling, convexity depends on axis alignment 5578cb93a386Sopenharmony_ci path->transform(x.fSM, &path2); 5579cb93a386Sopenharmony_ci path->transform(x.fSM); 5580cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, isa_proc(path2)); 5581cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, isa_proc(*path)); 5582cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, conditional_convex(path2, isAxisAligned)); 5583cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, conditional_convex(*path, isAxisAligned)); 5584cb93a386Sopenharmony_ci 5585cb93a386Sopenharmony_ci // For security, post-rotation, we can't assume we're still convex. It might prove to be, 5586cb93a386Sopenharmony_ci // in fact, still be convex, be we can't have cached that setting, hence the call to 5587cb93a386Sopenharmony_ci // getConvexityOrUnknown() instead of getConvexity(). 5588cb93a386Sopenharmony_ci path->transform(x.fRM, &path2); 5589cb93a386Sopenharmony_ci path->transform(x.fRM); 5590cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::GetConvexityOrUnknown(path2) != SkPathConvexity::kConvex); 5591cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::GetConvexityOrUnknown(*path) != SkPathConvexity::kConvex); 5592cb93a386Sopenharmony_ci 5593cb93a386Sopenharmony_ci if (isAxisAligned) { 5594cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !isa_proc(path2)); 5595cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !isa_proc(*path)); 5596cb93a386Sopenharmony_ci } 5597cb93a386Sopenharmony_ci} 5598cb93a386Sopenharmony_ci 5599cb93a386Sopenharmony_ciDEF_TEST(Path_survive_transform, r) { 5600cb93a386Sopenharmony_ci const Xforms x; 5601cb93a386Sopenharmony_ci 5602cb93a386Sopenharmony_ci SkPath path; 5603cb93a386Sopenharmony_ci path.addRect({10, 10, 40, 50}); 5604cb93a386Sopenharmony_ci survive(&path, x, true, r, [](const SkPath& p) { return p.isRect(nullptr); }); 5605cb93a386Sopenharmony_ci 5606cb93a386Sopenharmony_ci path.reset(); 5607cb93a386Sopenharmony_ci path.addOval({10, 10, 40, 50}); 5608cb93a386Sopenharmony_ci survive(&path, x, true, r, [](const SkPath& p) { return p.isOval(nullptr); }); 5609cb93a386Sopenharmony_ci 5610cb93a386Sopenharmony_ci path.reset(); 5611cb93a386Sopenharmony_ci path.addRRect(SkRRect::MakeRectXY({10, 10, 40, 50}, 5, 5)); 5612cb93a386Sopenharmony_ci survive(&path, x, true, r, [](const SkPath& p) { return p.isRRect(nullptr); }); 5613cb93a386Sopenharmony_ci 5614cb93a386Sopenharmony_ci // make a trapazoid; definitely convex, but not marked as axis-aligned (e.g. oval, rrect) 5615cb93a386Sopenharmony_ci path.reset(); 5616cb93a386Sopenharmony_ci path.moveTo(0, 0).lineTo(100, 0).lineTo(70, 100).lineTo(30, 100); 5617cb93a386Sopenharmony_ci REPORTER_ASSERT(r, path.isConvex()); 5618cb93a386Sopenharmony_ci survive(&path, x, false, r, [](const SkPath& p) { return true; }); 5619cb93a386Sopenharmony_ci} 5620cb93a386Sopenharmony_ci 5621cb93a386Sopenharmony_ciDEF_TEST(path_last_move_to_index, r) { 5622cb93a386Sopenharmony_ci // Make sure that copyPath is safe after the call to path.offset(). 5623cb93a386Sopenharmony_ci // Previously, we would leave its fLastMoveToIndex alone after the copy, but now we should 5624cb93a386Sopenharmony_ci // set it to path's value inside SkPath::transform() 5625cb93a386Sopenharmony_ci 5626cb93a386Sopenharmony_ci const char text[] = "hello"; 5627cb93a386Sopenharmony_ci constexpr size_t len = sizeof(text) - 1; 5628cb93a386Sopenharmony_ci SkGlyphID glyphs[len]; 5629cb93a386Sopenharmony_ci 5630cb93a386Sopenharmony_ci SkFont font; 5631cb93a386Sopenharmony_ci font.textToGlyphs(text, len, SkTextEncoding::kUTF8, glyphs, len); 5632cb93a386Sopenharmony_ci 5633cb93a386Sopenharmony_ci SkPath copyPath; 5634cb93a386Sopenharmony_ci SkFont().getPaths(glyphs, len, [](const SkPath* src, const SkMatrix& mx, void* ctx) { 5635cb93a386Sopenharmony_ci if (src) { 5636cb93a386Sopenharmony_ci ((SkPath*)ctx)->addPath(*src, mx); 5637cb93a386Sopenharmony_ci } 5638cb93a386Sopenharmony_ci }, ©Path); 5639cb93a386Sopenharmony_ci 5640cb93a386Sopenharmony_ci SkScalar radii[] = { 80, 100, 0, 0, 40, 60, 0, 0 }; 5641cb93a386Sopenharmony_ci SkPath path; 5642cb93a386Sopenharmony_ci path.addRoundRect({10, 10, 110, 110}, radii); 5643cb93a386Sopenharmony_ci path.offset(0, 5, &(copyPath)); // <== change buffer copyPath.fPathRef->fPoints but not reset copyPath.fLastMoveToIndex lead to out of bound 5644cb93a386Sopenharmony_ci 5645cb93a386Sopenharmony_ci copyPath.rConicTo(1, 1, 3, 3, 0.707107f); 5646cb93a386Sopenharmony_ci} 5647cb93a386Sopenharmony_ci 5648cb93a386Sopenharmony_cistatic void test_edger(skiatest::Reporter* r, 5649cb93a386Sopenharmony_ci const std::initializer_list<SkPath::Verb>& in, 5650cb93a386Sopenharmony_ci const std::initializer_list<SkPath::Verb>& expected) { 5651cb93a386Sopenharmony_ci SkPath path; 5652cb93a386Sopenharmony_ci SkScalar x = 0, y = 0; 5653cb93a386Sopenharmony_ci for (auto v : in) { 5654cb93a386Sopenharmony_ci switch (v) { 5655cb93a386Sopenharmony_ci case SkPath::kMove_Verb: path.moveTo(x++, y++); break; 5656cb93a386Sopenharmony_ci case SkPath::kLine_Verb: path.lineTo(x++, y++); break; 5657cb93a386Sopenharmony_ci case SkPath::kClose_Verb: path.close(); break; 5658cb93a386Sopenharmony_ci default: SkASSERT(false); 5659cb93a386Sopenharmony_ci } 5660cb93a386Sopenharmony_ci } 5661cb93a386Sopenharmony_ci 5662cb93a386Sopenharmony_ci SkPathEdgeIter iter(path); 5663cb93a386Sopenharmony_ci for (auto v : expected) { 5664cb93a386Sopenharmony_ci auto e = iter.next(); 5665cb93a386Sopenharmony_ci REPORTER_ASSERT(r, e); 5666cb93a386Sopenharmony_ci REPORTER_ASSERT(r, SkPathEdgeIter::EdgeToVerb(e.fEdge) == v); 5667cb93a386Sopenharmony_ci } 5668cb93a386Sopenharmony_ci REPORTER_ASSERT(r, !iter.next()); 5669cb93a386Sopenharmony_ci} 5670cb93a386Sopenharmony_ci 5671cb93a386Sopenharmony_cistatic void assert_points(skiatest::Reporter* reporter, 5672cb93a386Sopenharmony_ci const SkPath& path, const std::initializer_list<SkPoint>& list) { 5673cb93a386Sopenharmony_ci const SkPoint* expected = list.begin(); 5674cb93a386Sopenharmony_ci SkPath::RawIter iter(path); 5675cb93a386Sopenharmony_ci for (size_t i = 0;;) { 5676cb93a386Sopenharmony_ci SkPoint pts[4]; 5677cb93a386Sopenharmony_ci switch (iter.next(pts)) { 5678cb93a386Sopenharmony_ci case SkPath::kDone_Verb: 5679cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, i == list.size()); 5680cb93a386Sopenharmony_ci return; 5681cb93a386Sopenharmony_ci case SkPath::kMove_Verb: 5682cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[0] == expected[i]); 5683cb93a386Sopenharmony_ci i++; 5684cb93a386Sopenharmony_ci break; 5685cb93a386Sopenharmony_ci case SkPath::kLine_Verb: 5686cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pts[1] == expected[i]); 5687cb93a386Sopenharmony_ci i++; 5688cb93a386Sopenharmony_ci break; 5689cb93a386Sopenharmony_ci case SkPath::kClose_Verb: break; 5690cb93a386Sopenharmony_ci default: SkASSERT(false); 5691cb93a386Sopenharmony_ci } 5692cb93a386Sopenharmony_ci } 5693cb93a386Sopenharmony_ci} 5694cb93a386Sopenharmony_ci 5695cb93a386Sopenharmony_cistatic void test_addRect_and_trailing_lineTo(skiatest::Reporter* reporter) { 5696cb93a386Sopenharmony_ci SkPath path; 5697cb93a386Sopenharmony_ci const SkRect r = {1, 2, 3, 4}; 5698cb93a386Sopenharmony_ci // build our default p-array clockwise 5699cb93a386Sopenharmony_ci const SkPoint p[] = { 5700cb93a386Sopenharmony_ci {r.fLeft, r.fTop}, {r.fRight, r.fTop}, 5701cb93a386Sopenharmony_ci {r.fRight, r.fBottom}, {r.fLeft, r.fBottom}, 5702cb93a386Sopenharmony_ci }; 5703cb93a386Sopenharmony_ci 5704cb93a386Sopenharmony_ci for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) { 5705cb93a386Sopenharmony_ci int increment = dir == SkPathDirection::kCW ? 1 : 3; 5706cb93a386Sopenharmony_ci for (int i = 0; i < 4; ++i) { 5707cb93a386Sopenharmony_ci path.reset(); 5708cb93a386Sopenharmony_ci path.addRect(r, dir, i); 5709cb93a386Sopenharmony_ci 5710cb93a386Sopenharmony_ci // check that we return the 4 ponts in the expected order 5711cb93a386Sopenharmony_ci SkPoint e[4]; 5712cb93a386Sopenharmony_ci for (int j = 0; j < 4; ++j) { 5713cb93a386Sopenharmony_ci int index = (i + j*increment) % 4; 5714cb93a386Sopenharmony_ci e[j] = p[index]; 5715cb93a386Sopenharmony_ci } 5716cb93a386Sopenharmony_ci assert_points(reporter, path, { 5717cb93a386Sopenharmony_ci e[0], e[1], e[2], e[3] 5718cb93a386Sopenharmony_ci }); 5719cb93a386Sopenharmony_ci 5720cb93a386Sopenharmony_ci // check that the new line begins where the rect began 5721cb93a386Sopenharmony_ci path.lineTo(7,8); 5722cb93a386Sopenharmony_ci assert_points(reporter, path, { 5723cb93a386Sopenharmony_ci e[0], e[1], e[2], e[3], 5724cb93a386Sopenharmony_ci e[0], {7,8}, 5725cb93a386Sopenharmony_ci }); 5726cb93a386Sopenharmony_ci } 5727cb93a386Sopenharmony_ci } 5728cb93a386Sopenharmony_ci 5729cb93a386Sopenharmony_ci // now add a moveTo before the rect, just to be sure we don't always look at 5730cb93a386Sopenharmony_ci // the "first" point in the path when we handle the trailing lineTo 5731cb93a386Sopenharmony_ci path.reset(); 5732cb93a386Sopenharmony_ci path.moveTo(7, 8); 5733cb93a386Sopenharmony_ci path.addRect(r, SkPathDirection::kCW, 2); 5734cb93a386Sopenharmony_ci path.lineTo(5, 6); 5735cb93a386Sopenharmony_ci 5736cb93a386Sopenharmony_ci assert_points(reporter, path, { 5737cb93a386Sopenharmony_ci {7,8}, // initial moveTo 5738cb93a386Sopenharmony_ci p[2], p[3], p[0], p[1], // rect 5739cb93a386Sopenharmony_ci p[2], {5, 6}, // trailing line 5740cb93a386Sopenharmony_ci }); 5741cb93a386Sopenharmony_ci} 5742cb93a386Sopenharmony_ci 5743cb93a386Sopenharmony_ci/* 5744cb93a386Sopenharmony_ci * SkPath allows the caller to "skip" calling moveTo for contours. If lineTo (or a curve) is 5745cb93a386Sopenharmony_ci * called on an empty path, a 'moveTo(0,0)' will automatically be injected. If the path is 5746cb93a386Sopenharmony_ci * not empty, but its last contour has been "closed", then it will inject a moveTo corresponding 5747cb93a386Sopenharmony_ci * to where the last contour itself started (i.e. its moveTo). 5748cb93a386Sopenharmony_ci * 5749cb93a386Sopenharmony_ci * This test exercises this in a particular case: 5750cb93a386Sopenharmony_ci * path.moveTo(...) <-- needed to show the bug 5751cb93a386Sopenharmony_ci * path.moveTo....close() 5752cb93a386Sopenharmony_ci * // at this point, the path's verbs are: M M ... C 5753cb93a386Sopenharmony_ci * 5754cb93a386Sopenharmony_ci * path.lineTo(...) 5755cb93a386Sopenharmony_ci * // after lineTo, the path's verbs are: M M ... C M L 5756cb93a386Sopenharmony_ci */ 5757cb93a386Sopenharmony_cistatic void test_addPath_and_injected_moveTo(skiatest::Reporter* reporter) { 5758cb93a386Sopenharmony_ci /* 5759cb93a386Sopenharmony_ci * Given a path, and the expected last-point and last-move-to in it, 5760cb93a386Sopenharmony_ci * assert that, after a lineTo(), that the injected moveTo corresponds 5761cb93a386Sopenharmony_ci * to the expected value. 5762cb93a386Sopenharmony_ci */ 5763cb93a386Sopenharmony_ci auto test_before_after_lineto = [reporter](SkPath& path, 5764cb93a386Sopenharmony_ci SkPoint expectedLastPt, 5765cb93a386Sopenharmony_ci SkPoint expectedMoveTo) { 5766cb93a386Sopenharmony_ci SkPoint p = path.getPoint(path.countPoints() - 1); 5767cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p == expectedLastPt); 5768cb93a386Sopenharmony_ci 5769cb93a386Sopenharmony_ci const SkPoint newLineTo = {1234, 5678}; 5770cb93a386Sopenharmony_ci path.lineTo(newLineTo); 5771cb93a386Sopenharmony_ci 5772cb93a386Sopenharmony_ci p = path.getPoint(path.countPoints() - 2); 5773cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p == expectedMoveTo); // this was injected by lineTo() 5774cb93a386Sopenharmony_ci 5775cb93a386Sopenharmony_ci p = path.getPoint(path.countPoints() - 1); 5776cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p == newLineTo); 5777cb93a386Sopenharmony_ci }; 5778cb93a386Sopenharmony_ci 5779cb93a386Sopenharmony_ci SkPath path1; 5780cb93a386Sopenharmony_ci SkPath path2; 5781cb93a386Sopenharmony_ci 5782cb93a386Sopenharmony_ci path1.moveTo(230, 230); // Needed to show the bug: a moveTo before the addRect 5783cb93a386Sopenharmony_ci 5784cb93a386Sopenharmony_ci // add a rect, but the shape doesn't really matter 5785cb93a386Sopenharmony_ci path1.moveTo(20,30).lineTo(40,30).lineTo(40,50).lineTo(20,50).close(); 5786cb93a386Sopenharmony_ci 5787cb93a386Sopenharmony_ci path2.addPath(path1); // this must correctly update its "last-move-to" so that when 5788cb93a386Sopenharmony_ci // lineTo is called, it will inject the correct moveTo. 5789cb93a386Sopenharmony_ci 5790cb93a386Sopenharmony_ci // at this point, path1 and path2 should be the same... 5791cb93a386Sopenharmony_ci 5792cb93a386Sopenharmony_ci test_before_after_lineto(path1, {20,50}, {20,30}); 5793cb93a386Sopenharmony_ci test_before_after_lineto(path2, {20,50}, {20,30}); 5794cb93a386Sopenharmony_ci} 5795cb93a386Sopenharmony_ci 5796cb93a386Sopenharmony_ciDEF_TEST(pathedger, r) { 5797cb93a386Sopenharmony_ci auto M = SkPath::kMove_Verb; 5798cb93a386Sopenharmony_ci auto L = SkPath::kLine_Verb; 5799cb93a386Sopenharmony_ci auto C = SkPath::kClose_Verb; 5800cb93a386Sopenharmony_ci 5801cb93a386Sopenharmony_ci test_edger(r, { M }, {}); 5802cb93a386Sopenharmony_ci test_edger(r, { M, M }, {}); 5803cb93a386Sopenharmony_ci test_edger(r, { M, C }, {}); 5804cb93a386Sopenharmony_ci test_edger(r, { M, M, C }, {}); 5805cb93a386Sopenharmony_ci test_edger(r, { M, L }, { L, L }); 5806cb93a386Sopenharmony_ci test_edger(r, { M, L, C }, { L, L }); 5807cb93a386Sopenharmony_ci test_edger(r, { M, L, L }, { L, L, L }); 5808cb93a386Sopenharmony_ci test_edger(r, { M, L, L, C }, { L, L, L }); 5809cb93a386Sopenharmony_ci 5810cb93a386Sopenharmony_ci test_edger(r, { M, L, L, M, L, L }, { L, L, L, L, L, L }); 5811cb93a386Sopenharmony_ci 5812cb93a386Sopenharmony_ci test_addRect_and_trailing_lineTo(r); 5813cb93a386Sopenharmony_ci test_addPath_and_injected_moveTo(r); 5814cb93a386Sopenharmony_ci} 5815cb93a386Sopenharmony_ci 5816cb93a386Sopenharmony_ciDEF_TEST(path_addpath_crbug_1153516, r) { 5817cb93a386Sopenharmony_ci // When we add a path to another path, we need to sniff out in case the argument ended 5818cb93a386Sopenharmony_ci // with a kClose, in which case we need to fiddle with our lastMoveIndex (as ::close() does) 5819cb93a386Sopenharmony_ci SkPath p1, p2; 5820cb93a386Sopenharmony_ci p1.addRect({143,226,200,241}); 5821cb93a386Sopenharmony_ci p1.addPath(p1); 5822cb93a386Sopenharmony_ci p1.lineTo(262,513); // this should not assert 5823cb93a386Sopenharmony_ci} 5824cb93a386Sopenharmony_ci 5825cb93a386Sopenharmony_ciDEF_TEST(path_convexity_scale_way_down, r) { 5826cb93a386Sopenharmony_ci SkPath path = SkPathBuilder().moveTo(0,0).lineTo(1, 0) 5827cb93a386Sopenharmony_ci .lineTo(1,1).lineTo(0,1) 5828cb93a386Sopenharmony_ci .detach(); 5829cb93a386Sopenharmony_ci 5830cb93a386Sopenharmony_ci REPORTER_ASSERT(r, path.isConvex()); 5831cb93a386Sopenharmony_ci SkPath path2; 5832cb93a386Sopenharmony_ci const SkScalar scale = 1e-8f; 5833cb93a386Sopenharmony_ci path.transform(SkMatrix::Scale(scale, scale), &path2); 5834cb93a386Sopenharmony_ci SkPathPriv::ForceComputeConvexity(path2); 5835cb93a386Sopenharmony_ci REPORTER_ASSERT(r, path2.isConvex()); 5836cb93a386Sopenharmony_ci} 5837cb93a386Sopenharmony_ci 5838cb93a386Sopenharmony_ci// crbug.com/1187385 5839cb93a386Sopenharmony_ciDEF_TEST(path_moveto_addrect, r) { 5840cb93a386Sopenharmony_ci // Test both an empty and non-empty rect passed to SkPath::addRect 5841cb93a386Sopenharmony_ci SkRect rects[] = {{207.0f, 237.0f, 300.0f, 237.0f}, 5842cb93a386Sopenharmony_ci {207.0f, 237.0f, 300.0f, 267.0f}}; 5843cb93a386Sopenharmony_ci 5844cb93a386Sopenharmony_ci for (SkRect rect: rects) { 5845cb93a386Sopenharmony_ci for (int numExtraMoveTos : {0, 1, 2, 3}) { 5846cb93a386Sopenharmony_ci SkPath path; 5847cb93a386Sopenharmony_ci // Convexity and contains functions treat the path as a simple fill, so consecutive 5848cb93a386Sopenharmony_ci // moveTos are collapsed together. 5849cb93a386Sopenharmony_ci for (int i = 0; i < numExtraMoveTos; ++i) { 5850cb93a386Sopenharmony_ci path.moveTo(i, i); 5851cb93a386Sopenharmony_ci } 5852cb93a386Sopenharmony_ci path.addRect(rect); 5853cb93a386Sopenharmony_ci 5854cb93a386Sopenharmony_ci REPORTER_ASSERT(r, (numExtraMoveTos + 1) == SkPathPriv::LeadingMoveToCount(path)); 5855cb93a386Sopenharmony_ci 5856cb93a386Sopenharmony_ci // addRect should mark the path as known convex automatically (i.e. it wasn't set 5857cb93a386Sopenharmony_ci // to unknown after edits) 5858cb93a386Sopenharmony_ci SkPathConvexity origConvexity = SkPathPriv::GetConvexityOrUnknown(path); 5859cb93a386Sopenharmony_ci REPORTER_ASSERT(r, origConvexity == SkPathConvexity::kConvex); 5860cb93a386Sopenharmony_ci 5861cb93a386Sopenharmony_ci // but it should also agree with the regular convexity computation 5862cb93a386Sopenharmony_ci SkPathPriv::ForceComputeConvexity(path); 5863cb93a386Sopenharmony_ci REPORTER_ASSERT(r, path.isConvex()); 5864cb93a386Sopenharmony_ci 5865cb93a386Sopenharmony_ci SkRect query = rect.makeInset(10.f, 0.f); 5866cb93a386Sopenharmony_ci REPORTER_ASSERT(r, path.conservativelyContainsRect(query)); 5867cb93a386Sopenharmony_ci } 5868cb93a386Sopenharmony_ci } 5869cb93a386Sopenharmony_ci} 5870cb93a386Sopenharmony_ci 5871cb93a386Sopenharmony_ci// crbug.com/1220754 5872cb93a386Sopenharmony_ciDEF_TEST(path_moveto_twopass_convexity, r) { 5873cb93a386Sopenharmony_ci // There had been a bug when the last moveTo index > 0, the calculated point count was incorrect 5874cb93a386Sopenharmony_ci // and the BySign convexity pass would not evaluate the entire path, effectively only using the 5875cb93a386Sopenharmony_ci // winding rule for determining convexity. 5876cb93a386Sopenharmony_ci SkPath path; 5877cb93a386Sopenharmony_ci path.setFillType(SkPathFillType::kWinding); 5878cb93a386Sopenharmony_ci path.moveTo(3.25f, 115.5f); 5879cb93a386Sopenharmony_ci path.conicTo(9.98099e+17f, 2.83874e+15f, 1.75098e-30f, 1.75097e-30f, 1.05385e+18f); 5880cb93a386Sopenharmony_ci path.conicTo(9.96938e+17f, 6.3804e+19f, 9.96934e+17f, 1.75096e-30f, 1.75096e-30f); 5881cb93a386Sopenharmony_ci path.quadTo(1.28886e+10f, 9.9647e+17f, 9.98101e+17f, 2.61006e+15f); 5882cb93a386Sopenharmony_ci REPORTER_ASSERT(r, !path.isConvex()); 5883cb93a386Sopenharmony_ci 5884cb93a386Sopenharmony_ci SkPath pathWithExtraMoveTo; 5885cb93a386Sopenharmony_ci pathWithExtraMoveTo.setFillType(SkPathFillType::kWinding); 5886cb93a386Sopenharmony_ci pathWithExtraMoveTo.moveTo(5.90043e-39f, 1.34525e-43f); 5887cb93a386Sopenharmony_ci pathWithExtraMoveTo.addPath(path); 5888cb93a386Sopenharmony_ci REPORTER_ASSERT(r, !pathWithExtraMoveTo.isConvex()); 5889cb93a386Sopenharmony_ci} 5890