Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Macros | Typedefs | Functions | Variables
PathTest.cpp File Reference
#include "include/core/SkBlendMode.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkData.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontTypes.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPathTypes.h"
#include "include/core/SkPathUtils.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkRegion.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkStream.h"
#include "include/core/SkStrokeRec.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTypes.h"
#include "include/core/SkVertices.h"
#include "include/pathops/SkPathOps.h"
#include "include/private/SkIDChangeListener.h"
#include "include/private/SkPathRef.h"
#include "include/private/base/SkFloatingPoint.h"
#include "include/private/base/SkMalloc.h"
#include "include/private/base/SkTo.h"
#include "include/utils/SkNullCanvas.h"
#include "include/utils/SkParse.h"
#include "include/utils/SkParsePath.h"
#include "src/base/SkAutoMalloc.h"
#include "src/base/SkFloatBits.h"
#include "src/base/SkRandom.h"
#include "src/core/SkGeometry.h"
#include "src/core/SkPathEnums.h"
#include "src/core/SkPathPriv.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkWriteBuffer.h"
#include "tests/Test.h"
#include "tools/fonts/FontToolUtils.h"
#include <algorithm>
#include <cfloat>
#include <cmath>
#include <cstdint>
#include <cstring>
#include <initializer_list>
#include <memory>
#include <vector>

Go to the source code of this file.

Classes

struct  SegmentInfo
 
class  PathRefTest_Private
 
class  PathTest_Private
 
struct  Xforms
 

Macros

#define SUPPRESS_VISIBILITY_WARNING   __attribute__((visibility("hidden")))
 
#define CONIC_PERSPECTIVE_BUG_FIXED   0
 
#define kCurveSegmentMask   (SkPath::kQuad_SegmentMask | SkPath::kCubic_SegmentMask)
 

Typedefs

typedef void(* PathProc) (SkPath *)
 

Functions

static void set_radii (SkVector radii[4], int index, float rad)
 
static void test_add_rrect (skiatest::Reporter *reporter, const SkRect &bounds, const SkVector radii[4])
 
static void test_skbug_3469 (skiatest::Reporter *reporter)
 
static void test_skbug_3239 (skiatest::Reporter *reporter)
 
static void make_path_crbug364224 (SkPath *path)
 
static void make_path_crbug364224_simplified (SkPath *path)
 
static void test_sect_with_horizontal_needs_pinning ()
 
static void test_iterative_intersect_line ()
 
static void test_path_crbug364224 ()
 
static void test_draw_AA_path (int width, int height, const SkPath &path)
 
static void test_fuzz_crbug_638223 ()
 
static void test_fuzz_crbug_643933 ()
 
static void test_fuzz_crbug_647922 ()
 
static void test_fuzz_crbug_662780 ()
 
static void test_mask_overflow ()
 
static void test_fuzz_crbug_668907 ()
 
static void make_path_crbugskia2820 (SkPath *path, skiatest::Reporter *reporter)
 
static void test_path_crbugskia2820 (skiatest::Reporter *reporter)
 
static void test_path_crbugskia5995 ()
 
static void make_path0 (SkPath *path)
 
static void make_path1 (SkPath *path)
 
static void test_path_to_region (skiatest::Reporter *reporter)
 
static void test_path_close_issue1474 (skiatest::Reporter *reporter)
 
static void test_gen_id (skiatest::Reporter *reporter)
 
static void test_bad_cubic_crbug234190 ()
 
static void test_bad_cubic_crbug229478 ()
 
static void build_path_170666 (SkPath &path)
 
static void build_path_simple_170666 (SkPath &path)
 
static void test_crbug_170666 ()
 
static void test_tiny_path_convexity (skiatest::Reporter *reporter, const char *pathBug, SkScalar tx, SkScalar ty, SkScalar scale)
 
static void test_crbug_493450 (skiatest::Reporter *reporter)
 
static void test_crbug_495894 (skiatest::Reporter *reporter)
 
static void test_crbug_613918 ()
 
static void test_addrect (skiatest::Reporter *reporter)
 
static void test_addrect_isfinite (skiatest::Reporter *reporter)
 
static void build_big_path (SkPath *path, bool reducedCase)
 
static void test_clipped_cubic ()
 
static void dump_if_ne (skiatest::Reporter *reporter, const SkRect &expected, const SkRect &bounds)
 
static void test_bounds_crbug_513799 (skiatest::Reporter *reporter)
 
static void test_fuzz_crbug_627414 (skiatest::Reporter *reporter)
 
static void test_tricky_cubic ()
 
static void test_isfinite_after_transform (skiatest::Reporter *reporter)
 
static void add_corner_arc (SkPath *path, const SkRect &rect, SkScalar xIn, SkScalar yIn, int startAngle)
 
static void make_arb_round_rect (SkPath *path, const SkRect &r, SkScalar xCorner, SkScalar yCorner)
 
static void test_arb_round_rect_is_convex (skiatest::Reporter *reporter)
 
static void test_arb_zero_rad_round_rect_is_rect (skiatest::Reporter *reporter)
 
static void test_rect_isfinite (skiatest::Reporter *reporter)
 
static void test_path_isfinite (skiatest::Reporter *reporter)
 
static void test_isfinite (skiatest::Reporter *reporter)
 
static void test_islastcontourclosed (skiatest::Reporter *reporter)
 
static void test_poly (skiatest::Reporter *reporter, const SkPath &path, const SkPoint srcPts[], bool expectClose)
 
static void test_addPoly (skiatest::Reporter *reporter)
 
static void test_strokerec (skiatest::Reporter *reporter)
 
static void check_direction (skiatest::Reporter *reporter, const SkPath &path, SkPathFirstDirection expected)
 
static void test_direction (skiatest::Reporter *reporter)
 
static void add_rect (SkPath *path, const SkRect &r)
 
static void test_bounds (skiatest::Reporter *reporter)
 
static void stroke_cubic (const SkPoint pts[4])
 
static void stroke_tiny_cubic ()
 
static void check_close (skiatest::Reporter *reporter, const SkPath &path)
 
static void test_close (skiatest::Reporter *reporter)
 
static void check_convexity (skiatest::Reporter *reporter, const SkPath &path, bool expectedConvexity)
 
static void test_path_crbug389050 (skiatest::Reporter *reporter)
 
static void test_convexity2 (skiatest::Reporter *reporter)
 
static void test_convexity_doubleback (skiatest::Reporter *reporter)
 
static void check_convex_bounds (skiatest::Reporter *reporter, const SkPath &p, const SkRect &bounds)
 
static void setFromString (SkPath *path, const char str[])
 
static void test_convexity (skiatest::Reporter *reporter)
 
static void test_isLine (skiatest::Reporter *reporter)
 
static void test_conservativelyContains (skiatest::Reporter *reporter)
 
static void test_isRect_open_close (skiatest::Reporter *reporter)
 
static void test_isRect (skiatest::Reporter *reporter)
 
static void check_simple_rect (skiatest::Reporter *reporter, const SkPath &path, bool isClosed, const SkRect &rect, SkPathDirection dir, unsigned start)
 
static void test_is_closed_rect (skiatest::Reporter *reporter)
 
static void test_isArc (skiatest::Reporter *reporter)
 
static void test_isNestedFillRects (skiatest::Reporter *reporter)
 
static void write_and_read_back (skiatest::Reporter *reporter, const SkPath &p)
 
static void test_flattening (skiatest::Reporter *reporter)
 
static void test_transform (skiatest::Reporter *reporter)
 
static void test_zero_length_paths (skiatest::Reporter *reporter)
 
static void test_segment_masks (skiatest::Reporter *reporter)
 
static void test_iter (skiatest::Reporter *reporter)
 
static void test_range_iter (skiatest::Reporter *reporter)
 
static void check_for_circle (skiatest::Reporter *reporter, const SkPath &path, bool expectedCircle, SkPathFirstDirection expectedDir)
 
static void test_circle_skew (skiatest::Reporter *reporter, const SkPath &path, SkPathFirstDirection dir)
 
static void test_circle_translate (skiatest::Reporter *reporter, const SkPath &path, SkPathFirstDirection dir)
 
static void test_circle_rotate (skiatest::Reporter *reporter, const SkPath &path, SkPathFirstDirection dir)
 
static void test_circle_mirror_x (skiatest::Reporter *reporter, const SkPath &path, SkPathFirstDirection dir)
 
static void test_circle_mirror_y (skiatest::Reporter *reporter, const SkPath &path, SkPathFirstDirection dir)
 
static void test_circle_mirror_xy (skiatest::Reporter *reporter, const SkPath &path, SkPathFirstDirection dir)
 
static void test_circle_with_direction (skiatest::Reporter *reporter, SkPathDirection inDir)
 
static void test_circle_with_add_paths (skiatest::Reporter *reporter)
 
static void test_circle (skiatest::Reporter *reporter)
 
static void test_oval (skiatest::Reporter *reporter)
 
static void test_empty (skiatest::Reporter *reporter, const SkPath &p)
 
static void test_rrect_is_convex (skiatest::Reporter *reporter, SkPath *path, SkPathDirection dir)
 
static void test_rrect_convexity_is_unknown (skiatest::Reporter *reporter, SkPath *path, SkPathDirection dir)
 
static void test_rrect (skiatest::Reporter *reporter)
 
static void test_arc (skiatest::Reporter *reporter)
 
static SkScalar oval_start_index_to_angle (unsigned start)
 
static SkScalar canonical_start_angle (float angle)
 
static void check_oval_arc (skiatest::Reporter *reporter, SkScalar start, SkScalar sweep, const SkPath &path)
 
static void test_arc_ovals (skiatest::Reporter *reporter)
 
static void check_move (skiatest::Reporter *reporter, SkPathPriv::RangeIter *iter, SkScalar x0, SkScalar y0)
 
static void check_line (skiatest::Reporter *reporter, SkPathPriv::RangeIter *iter, SkScalar x1, SkScalar y1)
 
static void check_quad (skiatest::Reporter *reporter, SkPathPriv::RangeIter *iter, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
 
static void check_close (skiatest::Reporter *reporter, SkPathPriv::RangeIter *iter)
 
static void check_done (skiatest::Reporter *reporter, SkPath *p, SkPathPriv::RangeIter *iter)
 
static void check_done_and_reset (skiatest::Reporter *reporter, SkPath *p, SkPathPriv::RangeIter *iter)
 
static void check_path_is_move_and_reset (skiatest::Reporter *reporter, SkPath *p, SkScalar x0, SkScalar y0)
 
static void check_path_is_line_and_reset (skiatest::Reporter *reporter, SkPath *p, SkScalar x1, SkScalar y1)
 
static void check_path_is_line (skiatest::Reporter *reporter, SkPath *p, SkScalar x1, SkScalar y1)
 
static void check_path_is_line_pair_and_reset (skiatest::Reporter *reporter, SkPath *p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
 
static void check_path_is_quad_and_reset (skiatest::Reporter *reporter, SkPath *p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
 
static bool nearly_equal (const SkRect &a, const SkRect &b)
 
static void test_rMoveTo (skiatest::Reporter *reporter)
 
static void test_arcTo (skiatest::Reporter *reporter)
 
static void test_addPath (skiatest::Reporter *reporter)
 
static void test_addPathMode (skiatest::Reporter *reporter, bool explicitMoveTo, bool extend)
 
static void test_extendClosedPath (skiatest::Reporter *reporter)
 
static void test_addEmptyPath (skiatest::Reporter *reporter, SkPath::AddPathMode mode)
 
static void test_conicTo_special_case (skiatest::Reporter *reporter)
 
static void test_get_point (skiatest::Reporter *reporter)
 
static void test_contains (skiatest::Reporter *reporter)
 
static void test_operatorEqual (skiatest::Reporter *reporter)
 
static void compare_dump (skiatest::Reporter *reporter, const SkPath &path, bool dumpAsHex, const char *str)
 
static void test_dump (skiatest::Reporter *reporter)
 
static void test_crbug_629455 (skiatest::Reporter *reporter)
 
static void test_fuzz_crbug_662952 (skiatest::Reporter *reporter)
 
static void test_path_crbugskia6003 ()
 
static void test_fuzz_crbug_662730 (skiatest::Reporter *reporter)
 
static void test_skbug_6947 ()
 
static void test_skbug_7015 ()
 
static void test_skbug_7051 ()
 
static void test_skbug_7435 ()
 
static void test_interp (skiatest::Reporter *reporter)
 
 DEF_TEST (PathInterp, reporter)
 
 DEF_TEST (PathBigCubic, reporter)
 
 DEF_TEST (PathContains, reporter)
 
 DEF_TEST (Paths, reporter)
 
 DEF_TEST (conservatively_contains_rect, reporter)
 
static void rand_path (SkPath *path, SkRandom &rand, SkPath::Verb verb, int n)
 
 DEF_TEST (path_tight_bounds, reporter)
 
 DEF_TEST (skbug_6450, r)
 
 DEF_TEST (PathRefSerialization, reporter)
 
 DEF_TEST (NonFinitePathIteration, reporter)
 
 DEF_TEST (AndroidArc, reporter)
 
 DEF_TEST (HugeGeometry, reporter)
 
 DEF_TEST (ClipPath_nonfinite, reporter)
 
 DEF_TEST (Path_isRect, reporter)
 
 DEF_TEST (Path_self_add, reporter)
 
static void draw_triangle (SkCanvas *canvas, const SkPoint pts[])
 
 DEF_TEST (triangle_onehalf, reporter)
 
 DEF_TEST (triangle_big, reporter)
 
static void add_verbs (SkPath *path, int count)
 
 DEF_TEST (Path_shrinkToFit, reporter)
 
 DEF_TEST (Path_setLastPt, r)
 
 DEF_TEST (Path_increserve_handle_neg_crbug_883666, r)
 
static bool conditional_convex (const SkPath &path, bool is_convex)
 
template<typename ISA >
void survive (SkPath *path, const Xforms &x, bool isAxisAligned, skiatest::Reporter *reporter, ISA isa_proc)
 
 DEF_TEST (Path_survive_transform, r)
 
 DEF_TEST (path_last_move_to_index, r)
 
static void test_edger (skiatest::Reporter *r, const std::initializer_list< SkPath::Verb > &in, const std::initializer_list< SkPath::Verb > &expected)
 
static void assert_points (skiatest::Reporter *reporter, const SkPath &path, const std::initializer_list< SkPoint > &list)
 
static void test_addRect_and_trailing_lineTo (skiatest::Reporter *reporter)
 
static void test_addPath_and_injected_moveTo (skiatest::Reporter *reporter)
 
 DEF_TEST (pathedger, r)
 
 DEF_TEST (path_addpath_crbug_1153516, r)
 
 DEF_TEST (path_convexity_scale_way_down, r)
 
 DEF_TEST (path_moveto_addrect, r)
 
 DEF_TEST (path_moveto_twopass_convexity, r)
 
 DEF_TEST (path_walk_simple_edges_1154864, r)
 

Variables

const SkPathFirstDirection kDontCheckDir = static_cast<SkPathFirstDirection>(3)
 

Macro Definition Documentation

◆ CONIC_PERSPECTIVE_BUG_FIXED

#define CONIC_PERSPECTIVE_BUG_FIXED   0

◆ kCurveSegmentMask

#define kCurveSegmentMask   (SkPath::kQuad_SegmentMask | SkPath::kCubic_SegmentMask)

Definition at line 3031 of file PathTest.cpp.

◆ SUPPRESS_VISIBILITY_WARNING

#define SUPPRESS_VISIBILITY_WARNING   __attribute__((visibility("hidden")))

Definition at line 356 of file PathTest.cpp.

Typedef Documentation

◆ PathProc

typedef void(* PathProc) (SkPath *)

Definition at line 324 of file PathTest.cpp.

Function Documentation

◆ add_corner_arc()

static void add_corner_arc ( SkPath path,
const SkRect rect,
SkScalar  xIn,
SkScalar  yIn,
int  startAngle 
)
static

Definition at line 836 of file PathTest.cpp.

839{
840
841 SkScalar rx = std::min(rect.width(), xIn);
842 SkScalar ry = std::min(rect.height(), yIn);
843
844 SkRect arcRect;
845 arcRect.setLTRB(-rx, -ry, rx, ry);
846 switch (startAngle) {
847 case 0:
848 arcRect.offset(rect.fRight - arcRect.fRight, rect.fBottom - arcRect.fBottom);
849 break;
850 case 90:
851 arcRect.offset(rect.fLeft - arcRect.fLeft, rect.fBottom - arcRect.fBottom);
852 break;
853 case 180:
854 arcRect.offset(rect.fLeft - arcRect.fLeft, rect.fTop - arcRect.fTop);
855 break;
856 case 270:
857 arcRect.offset(rect.fRight - arcRect.fRight, rect.fTop - arcRect.fTop);
858 break;
859 default:
860 break;
861 }
862
863 path->arcTo(arcRect, SkIntToScalar(startAngle), SkIntToScalar(90), false);
864}
#define SkIntToScalar(x)
Definition SkScalar.h:57
float SkScalar
Definition extension.cpp:12
sk_sp< SkBlender > blender SkRect rect
Definition SkRecords.h:350
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switches.h:57
SkScalar fBottom
larger y-axis bounds
Definition extension.cpp:17
SkScalar fLeft
smaller x-axis bounds
Definition extension.cpp:14
SkScalar fRight
larger x-axis bounds
Definition extension.cpp:16
void offset(float dx, float dy)
Definition SkRect.h:1016
void setLTRB(float left, float top, float right, float bottom)
Definition SkRect.h:865
SkScalar fTop
smaller y-axis bounds
Definition extension.cpp:15

◆ add_rect()

static void add_rect ( SkPath path,
const SkRect r 
)
static

Definition at line 1200 of file PathTest.cpp.

1200 {
1201 path->moveTo(r.fLeft, r.fTop);
1202 path->lineTo(r.fRight, r.fTop);
1203 path->lineTo(r.fRight, r.fBottom);
1204 path->lineTo(r.fLeft, r.fBottom);
1205 path->close();
1206}

◆ add_verbs()

static void add_verbs ( SkPath path,
int  count 
)
static

Definition at line 5598 of file PathTest.cpp.

5598 {
5599 path->moveTo(0, 0);
5600 for (int i = 0; i < count; ++i) {
5601 switch (i & 3) {
5602 case 0: path->lineTo(10, 20); break;
5603 case 1: path->quadTo(5, 6, 7, 8); break;
5604 case 2: path->conicTo(1, 2, 3, 4, 0.5f); break;
5605 case 3: path->cubicTo(2, 4, 6, 8, 10, 12); break;
5606 }
5607 }
5608}
int count

◆ assert_points()

static void assert_points ( skiatest::Reporter reporter,
const SkPath path,
const std::initializer_list< SkPoint > &  list 
)
static

Definition at line 5823 of file PathTest.cpp.

5824 {
5825 const SkPoint* expected = list.begin();
5826 SkPath::RawIter iter(path);
5827 for (size_t i = 0;;) {
5828 SkPoint pts[4];
5829 switch (iter.next(pts)) {
5830 case SkPath::kDone_Verb:
5831 REPORTER_ASSERT(reporter, i == list.size());
5832 return;
5833 case SkPath::kMove_Verb:
5834 REPORTER_ASSERT(reporter, pts[0] == expected[i]);
5835 i++;
5836 break;
5837 case SkPath::kLine_Verb:
5838 REPORTER_ASSERT(reporter, pts[1] == expected[i]);
5839 i++;
5840 break;
5841 case SkPath::kClose_Verb: break;
5842 default: SkASSERT(false);
5843 }
5844 }
5845}
reporter
#define SkASSERT(cond)
Definition SkAssert.h:116
#define REPORTER_ASSERT(r, cond,...)
Definition Test.h:286
@ kClose_Verb
Definition SkPath.h:1463
@ kMove_Verb
Definition SkPath.h:1458
@ kDone_Verb
Definition SkPath.h:1464
@ kLine_Verb
Definition SkPath.h:1459

◆ build_big_path()

static void build_big_path ( SkPath path,
bool  reducedCase 
)
static

Definition at line 707 of file PathTest.cpp.

707 {
708 if (reducedCase) {
709 path->moveTo(577330, 1971.72f);
710 path->cubicTo(10.7082f, -116.596f, 262.057f, 45.6468f, 294.694f, 1.96237f);
711 } else {
712 path->moveTo(60.1631f, 7.70567f);
713 path->quadTo(60.1631f, 7.70567f, 0.99474f, 0.901199f);
714 path->lineTo(577379, 1977.77f);
715 path->quadTo(577364, 1979.57f, 577325, 1980.26f);
716 path->quadTo(577286, 1980.95f, 577245, 1980.13f);
717 path->quadTo(577205, 1979.3f, 577187, 1977.45f);
718 path->quadTo(577168, 1975.6f, 577183, 1973.8f);
719 path->quadTo(577198, 1972, 577238, 1971.31f);
720 path->quadTo(577277, 1970.62f, 577317, 1971.45f);
721 path->quadTo(577330, 1971.72f, 577341, 1972.11f);
722 path->cubicTo(10.7082f, -116.596f, 262.057f, 45.6468f, 294.694f, 1.96237f);
723 path->moveTo(306.718f, -32.912f);
724 path->cubicTo(30.531f, 10.0005f, 1502.47f, 13.2804f, 84.3088f, 9.99601f);
725 }
726}

◆ build_path_170666()

static void build_path_170666 ( SkPath path)
static

Definition at line 489 of file PathTest.cpp.

489 {
490 path.moveTo(17.9459f, 21.6344f);
491 path.lineTo(139.545f, -47.8105f);
492 path.lineTo(139.545f, -47.8105f);
493 path.lineTo(131.07f, -47.3888f);
494 path.lineTo(131.07f, -47.3888f);
495 path.lineTo(122.586f, -46.9532f);
496 path.lineTo(122.586f, -46.9532f);
497 path.lineTo(18076.6f, 31390.9f);
498 path.lineTo(18076.6f, 31390.9f);
499 path.lineTo(18085.1f, 31390.5f);
500 path.lineTo(18085.1f, 31390.5f);
501 path.lineTo(18076.6f, 31390.9f);
502 path.lineTo(18076.6f, 31390.9f);
503 path.lineTo(17955, 31460.3f);
504 path.lineTo(17955, 31460.3f);
505 path.lineTo(17963.5f, 31459.9f);
506 path.lineTo(17963.5f, 31459.9f);
507 path.lineTo(17971.9f, 31459.5f);
508 path.lineTo(17971.9f, 31459.5f);
509 path.lineTo(17.9551f, 21.6205f);
510 path.lineTo(17.9551f, 21.6205f);
511 path.lineTo(9.47091f, 22.0561f);
512 path.lineTo(9.47091f, 22.0561f);
513 path.lineTo(17.9459f, 21.6344f);
514 path.lineTo(17.9459f, 21.6344f);
515 path.close();path.moveTo(0.995934f, 22.4779f);
516 path.lineTo(0.986725f, 22.4918f);
517 path.lineTo(0.986725f, 22.4918f);
518 path.lineTo(17955, 31460.4f);
519 path.lineTo(17955, 31460.4f);
520 path.lineTo(17971.9f, 31459.5f);
521 path.lineTo(17971.9f, 31459.5f);
522 path.lineTo(18093.6f, 31390.1f);
523 path.lineTo(18093.6f, 31390.1f);
524 path.lineTo(18093.6f, 31390);
525 path.lineTo(18093.6f, 31390);
526 path.lineTo(139.555f, -47.8244f);
527 path.lineTo(139.555f, -47.8244f);
528 path.lineTo(122.595f, -46.9671f);
529 path.lineTo(122.595f, -46.9671f);
530 path.lineTo(0.995934f, 22.4779f);
531 path.lineTo(0.995934f, 22.4779f);
532 path.close();
533 path.moveTo(5.43941f, 25.5223f);
534 path.lineTo(798267, -28871.1f);
535 path.lineTo(798267, -28871.1f);
536 path.lineTo(3.12512e+06f, -113102);
537 path.lineTo(3.12512e+06f, -113102);
538 path.cubicTo(5.16324e+06f, -186882, 8.15247e+06f, -295092, 1.1957e+07f, -432813);
539 path.cubicTo(1.95659e+07f, -708257, 3.04359e+07f, -1.10175e+06f, 4.34798e+07f, -1.57394e+06f);
540 path.cubicTo(6.95677e+07f, -2.51831e+06f, 1.04352e+08f, -3.77748e+06f, 1.39135e+08f, -5.03666e+06f);
541 path.cubicTo(1.73919e+08f, -6.29583e+06f, 2.08703e+08f, -7.555e+06f, 2.34791e+08f, -8.49938e+06f);
542 path.cubicTo(2.47835e+08f, -8.97157e+06f, 2.58705e+08f, -9.36506e+06f, 2.66314e+08f, -9.6405e+06f);
543 path.cubicTo(2.70118e+08f, -9.77823e+06f, 2.73108e+08f, -9.88644e+06f, 2.75146e+08f, -9.96022e+06f);
544 path.cubicTo(2.76165e+08f, -9.99711e+06f, 2.76946e+08f, -1.00254e+07f, 2.77473e+08f, -1.00444e+07f);
545 path.lineTo(2.78271e+08f, -1.00733e+07f);
546 path.lineTo(2.78271e+08f, -1.00733e+07f);
547 path.cubicTo(2.78271e+08f, -1.00733e+07f, 2.08703e+08f, -7.555e+06f, 135.238f, 23.3517f);
548 path.cubicTo(131.191f, 23.4981f, 125.995f, 23.7976f, 123.631f, 24.0206f);
549 path.cubicTo(121.267f, 24.2436f, 122.631f, 24.3056f, 126.677f, 24.1591f);
550 path.cubicTo(2.08703e+08f, -7.555e+06f, 2.78271e+08f, -1.00733e+07f, 2.78271e+08f, -1.00733e+07f);
551 path.lineTo(2.77473e+08f, -1.00444e+07f);
552 path.lineTo(2.77473e+08f, -1.00444e+07f);
553 path.cubicTo(2.76946e+08f, -1.00254e+07f, 2.76165e+08f, -9.99711e+06f, 2.75146e+08f, -9.96022e+06f);
554 path.cubicTo(2.73108e+08f, -9.88644e+06f, 2.70118e+08f, -9.77823e+06f, 2.66314e+08f, -9.6405e+06f);
555 path.cubicTo(2.58705e+08f, -9.36506e+06f, 2.47835e+08f, -8.97157e+06f, 2.34791e+08f, -8.49938e+06f);
556 path.cubicTo(2.08703e+08f, -7.555e+06f, 1.73919e+08f, -6.29583e+06f, 1.39135e+08f, -5.03666e+06f);
557 path.cubicTo(1.04352e+08f, -3.77749e+06f, 6.95677e+07f, -2.51831e+06f, 4.34798e+07f, -1.57394e+06f);
558 path.cubicTo(3.04359e+07f, -1.10175e+06f, 1.95659e+07f, -708258, 1.1957e+07f, -432814);
559 path.cubicTo(8.15248e+06f, -295092, 5.16324e+06f, -186883, 3.12513e+06f, -113103);
560 path.lineTo(798284, -28872);
561 path.lineTo(798284, -28872);
562 path.lineTo(22.4044f, 24.6677f);
563 path.lineTo(22.4044f, 24.6677f);
564 path.cubicTo(22.5186f, 24.5432f, 18.8134f, 24.6337f, 14.1287f, 24.8697f);
565 path.cubicTo(9.4439f, 25.1057f, 5.55359f, 25.3978f, 5.43941f, 25.5223f);
566 path.close();
567}

◆ build_path_simple_170666()

static void build_path_simple_170666 ( SkPath path)
static

Definition at line 569 of file PathTest.cpp.

569 {
570 path.moveTo(126.677f, 24.1591f);
571 path.cubicTo(2.08703e+08f, -7.555e+06f, 2.78271e+08f, -1.00733e+07f, 2.78271e+08f, -1.00733e+07f);
572}

◆ canonical_start_angle()

static SkScalar canonical_start_angle ( float  angle)
inlinestatic

Definition at line 3896 of file PathTest.cpp.

3896 {
3897 while (angle < 0.f) {
3898 angle += 360.f;
3899 }
3900 while (angle >= 360.f) {
3901 angle -= 360.f;
3902 }
3903 return angle;
3904}

◆ check_close() [1/2]

static void check_close ( skiatest::Reporter reporter,
const SkPath path 
)
static

Definition at line 1261 of file PathTest.cpp.

1261 {
1262 for (int i = 0; i < 2; ++i) {
1263 SkPath::Iter iter(path, SkToBool(i));
1264 SkPoint mv;
1265 SkPoint pts[4];
1266 SkPath::Verb v;
1267 int nMT = 0;
1268 int nCL = 0;
1269 mv.set(0, 0);
1270 while (SkPath::kDone_Verb != (v = iter.next(pts))) {
1271 switch (v) {
1272 case SkPath::kMove_Verb:
1273 mv = pts[0];
1274 ++nMT;
1275 break;
1277 REPORTER_ASSERT(reporter, mv == pts[0]);
1278 ++nCL;
1279 break;
1280 default:
1281 break;
1282 }
1283 }
1284 // if we force a close on the interator we should have a close
1285 // for every moveTo
1286 REPORTER_ASSERT(reporter, !i || nMT == nCL);
1287 }
1288}
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35
void set(float x, float y)

◆ check_close() [2/2]

static void check_close ( skiatest::Reporter reporter,
SkPathPriv::RangeIter iter 
)
static

Definition at line 3971 of file PathTest.cpp.

3971 {
3972 auto [v, pts, w] = *(*iter)++;
3974}
@ kClose
SkPath::RawIter returns 0 points.
SkScalar w

◆ check_convex_bounds()

static void check_convex_bounds ( skiatest::Reporter reporter,
const SkPath p,
const SkRect bounds 
)
static

Definition at line 1607 of file PathTest.cpp.

1608 {
1609 REPORTER_ASSERT(reporter, p.isConvex());
1610 REPORTER_ASSERT(reporter, p.getBounds() == bounds);
1611
1612 SkPath p2(p);
1613 REPORTER_ASSERT(reporter, p2.isConvex());
1614 REPORTER_ASSERT(reporter, p2.getBounds() == bounds);
1615
1616 SkPath other;
1617 other.swap(p2);
1619 REPORTER_ASSERT(reporter, other.getBounds() == bounds);
1620}
bool isConvex() const
Definition SkPath.cpp:416
const SkRect & getBounds() const
Definition SkPath.cpp:420
void swap(SkPath &other)
Definition SkPath.cpp:217

◆ check_convexity()

static void check_convexity ( skiatest::Reporter reporter,
const SkPath path,
bool  expectedConvexity 
)
static

Definition at line 1357 of file PathTest.cpp.

1358 {
1359 // We make a copy so that we don't cache the result on the passed in path.
1360 SkPath copy(path); // NOLINT(performance-unnecessary-copy-initialization)
1361 bool convexity = copy.isConvex();
1362 REPORTER_ASSERT(reporter, convexity == expectedConvexity);
1363}
Definition copy.py:1

◆ check_direction()

static void check_direction ( skiatest::Reporter reporter,
const SkPath path,
SkPathFirstDirection  expected 
)
static

Definition at line 1099 of file PathTest.cpp.

1100 {
1101 if (expected == kDontCheckDir) {
1102 return;
1103 }
1104 // We make a copy so that we don't cache the result on the passed in path.
1105 SkPath copy(path); // NOLINT(performance-unnecessary-copy-initialization)
1106
1108 if (dir != SkPathFirstDirection::kUnknown) {
1109 REPORTER_ASSERT(reporter, dir == expected);
1110 }
1111}
const SkPathFirstDirection kDontCheckDir
SkPathFirstDirection
Definition SkPathEnums.h:19
static SkPathFirstDirection ComputeFirstDirection(const SkPath &)
Definition SkPath.cpp:2563
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets dir
Definition switches.h:145

◆ check_done()

static void check_done ( skiatest::Reporter reporter,
SkPath p,
SkPathPriv::RangeIter iter 
)
static

Definition at line 3976 of file PathTest.cpp.

3976 {
3978}
SkPath::RangeIter end()
Definition SkPathPriv.h:187

◆ check_done_and_reset()

static void check_done_and_reset ( skiatest::Reporter reporter,
SkPath p,
SkPathPriv::RangeIter iter 
)
static

Definition at line 3980 of file PathTest.cpp.

3981 {
3982 check_done(reporter, p, iter);
3983 p->reset();
3984}
static void check_done(skiatest::Reporter *reporter, SkPath *p, SkPathPriv::RangeIter *iter)

◆ check_for_circle()

static void check_for_circle ( skiatest::Reporter reporter,
const SkPath path,
bool  expectedCircle,
SkPathFirstDirection  expectedDir 
)
static

Definition at line 3454 of file PathTest.cpp.

3457 {
3459 REPORTER_ASSERT(reporter, path.isOval(&rect) == expectedCircle);
3460 SkPathDirection isOvalDir;
3461 unsigned isOvalStart;
3462 if (SkPathPriv::IsOval(path, &rect, &isOvalDir, &isOvalStart)) {
3463 REPORTER_ASSERT(reporter, rect.height() == rect.width());
3464 REPORTER_ASSERT(reporter, SkPathPriv::AsFirstDirection(isOvalDir) == expectedDir);
3465 SkPath tmpPath;
3466 tmpPath.addOval(rect, isOvalDir, isOvalStart);
3467 REPORTER_ASSERT(reporter, path == tmpPath);
3468 }
3470}
SkPathDirection
Definition SkPathTypes.h:34
static bool IsOval(const SkPath &path, SkRect *rect, SkPathDirection *dir, unsigned *start)
Definition SkPathPriv.h:245
static SkPathFirstDirection AsFirstDirection(SkPathDirection dir)
Definition SkPathPriv.h:42
SkPath & addOval(const SkRect &oval, SkPathDirection dir=SkPathDirection::kCW)
Definition SkPath.cpp:1101
static constexpr SkRect MakeEmpty()
Definition SkRect.h:595

◆ check_line()

static void check_line ( skiatest::Reporter reporter,
SkPathPriv::RangeIter iter,
SkScalar  x1,
SkScalar  y1 
)
static

Definition at line 3953 of file PathTest.cpp.

3954 {
3955 auto [v, pts, w] = *(*iter)++;
3957 REPORTER_ASSERT(reporter, pts[1].fX == x1);
3958 REPORTER_ASSERT(reporter, pts[1].fY == y1);
3959}
@ kLine
SkPath::RawIter returns 2 points.

◆ check_move()

static void check_move ( skiatest::Reporter reporter,
SkPathPriv::RangeIter iter,
SkScalar  x0,
SkScalar  y0 
)
static

Definition at line 3945 of file PathTest.cpp.

3946 {
3947 auto [v, pts, w] = *(*iter)++;
3949 REPORTER_ASSERT(reporter, pts[0].fX == x0);
3950 REPORTER_ASSERT(reporter, pts[0].fY == y0);
3951}
@ kMove
SkPath::RawIter returns 1 point.

◆ check_oval_arc()

static void check_oval_arc ( skiatest::Reporter reporter,
SkScalar  start,
SkScalar  sweep,
const SkPath path 
)
static

Definition at line 3906 of file PathTest.cpp.

3907 {
3910 unsigned s = ~0U;
3911 bool isOval = SkPathPriv::IsOval(path, &r, &d, &s);
3912 REPORTER_ASSERT(reporter, isOval);
3913 SkPath recreatedPath;
3914 recreatedPath.addOval(r, d, s);
3915 REPORTER_ASSERT(reporter, path == recreatedPath);
3917 REPORTER_ASSERT(reporter, (SkPathDirection::kCW == d) == (sweep > 0.f));
3918}
static SkScalar oval_start_index_to_angle(unsigned start)
static SkScalar canonical_start_angle(float angle)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19
struct MyStruct s

◆ check_path_is_line()

static void check_path_is_line ( skiatest::Reporter reporter,
SkPath p,
SkScalar  x1,
SkScalar  y1 
)
static

Definition at line 4001 of file PathTest.cpp.

4002 {
4004 check_move(reporter, &iter, 0, 0);
4005 check_line(reporter, &iter, x1, y1);
4006 check_done(reporter, p, &iter);
4007}
static void check_line(skiatest::Reporter *reporter, SkPathPriv::RangeIter *iter, SkScalar x1, SkScalar y1)
static void check_move(skiatest::Reporter *reporter, SkPathPriv::RangeIter *iter, SkScalar x0, SkScalar y0)
SkPath::RangeIter RangeIter
Definition SkPathPriv.h:164
SkPath::RangeIter begin()
Definition SkPathPriv.h:186

◆ check_path_is_line_and_reset()

static void check_path_is_line_and_reset ( skiatest::Reporter reporter,
SkPath p,
SkScalar  x1,
SkScalar  y1 
)
static

Definition at line 3993 of file PathTest.cpp.

3994 {
3996 check_move(reporter, &iter, 0, 0);
3997 check_line(reporter, &iter, x1, y1);
3998 check_done_and_reset(reporter, p, &iter);
3999}
static void check_done_and_reset(skiatest::Reporter *reporter, SkPath *p, SkPathPriv::RangeIter *iter)

◆ check_path_is_line_pair_and_reset()

static void check_path_is_line_pair_and_reset ( skiatest::Reporter reporter,
SkPath p,
SkScalar  x1,
SkScalar  y1,
SkScalar  x2,
SkScalar  y2 
)
static

Definition at line 4009 of file PathTest.cpp.

4010 {
4012 check_move(reporter, &iter, 0, 0);
4013 check_line(reporter, &iter, x1, y1);
4014 check_line(reporter, &iter, x2, y2);
4015 check_done_and_reset(reporter, p, &iter);
4016}

◆ check_path_is_move_and_reset()

static void check_path_is_move_and_reset ( skiatest::Reporter reporter,
SkPath p,
SkScalar  x0,
SkScalar  y0 
)
static

Definition at line 3986 of file PathTest.cpp.

3987 {
3989 check_move(reporter, &iter, x0, y0);
3990 check_done_and_reset(reporter, p, &iter);
3991}

◆ check_path_is_quad_and_reset()

static void check_path_is_quad_and_reset ( skiatest::Reporter reporter,
SkPath p,
SkScalar  x1,
SkScalar  y1,
SkScalar  x2,
SkScalar  y2 
)
static

Definition at line 4018 of file PathTest.cpp.

4019 {
4021 check_move(reporter, &iter, 0, 0);
4022 check_quad(reporter, &iter, x1, y1, x2, y2);
4023 check_done_and_reset(reporter, p, &iter);
4024}
static void check_quad(skiatest::Reporter *reporter, SkPathPriv::RangeIter *iter, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)

◆ check_quad()

static void check_quad ( skiatest::Reporter reporter,
SkPathPriv::RangeIter iter,
SkScalar  x1,
SkScalar  y1,
SkScalar  x2,
SkScalar  y2 
)
static

Definition at line 3961 of file PathTest.cpp.

3962 {
3963 auto [v, pts, w] = *(*iter)++;
3965 REPORTER_ASSERT(reporter, pts[1].fX == x1);
3966 REPORTER_ASSERT(reporter, pts[1].fY == y1);
3967 REPORTER_ASSERT(reporter, pts[2].fX == x2);
3968 REPORTER_ASSERT(reporter, pts[2].fY == y2);
3969}
@ kQuad
SkPath::RawIter returns 3 points.

◆ check_simple_rect()

static void check_simple_rect ( skiatest::Reporter reporter,
const SkPath path,
bool  isClosed,
const SkRect rect,
SkPathDirection  dir,
unsigned  start 
)
static

Definition at line 2299 of file PathTest.cpp.

2300 {
2303 unsigned s = ~0U;
2304
2305 REPORTER_ASSERT(reporter, SkPathPriv::IsSimpleRect(path, false, &r, &d, &s) == isClosed);
2306 REPORTER_ASSERT(reporter, SkPathPriv::IsSimpleRect(path, true, &r, &d, &s));
2307 REPORTER_ASSERT(reporter, r == rect);
2308 REPORTER_ASSERT(reporter, d == dir);
2310}
static bool IsSimpleRect(const SkPath &path, bool isSimpleFill, SkRect *rect, SkPathDirection *direction, unsigned *start)
Definition SkPath.cpp:3180

◆ compare_dump()

static void compare_dump ( skiatest::Reporter reporter,
const SkPath path,
bool  dumpAsHex,
const char *  str 
)
static

Definition at line 4484 of file PathTest.cpp.

4485 {
4486 SkDynamicMemoryWStream wStream;
4487 path.dump(&wStream, dumpAsHex);
4488 sk_sp<SkData> data = wStream.detachAsData();
4489 REPORTER_ASSERT(reporter, data->size() == strlen(str));
4490 if (strlen(str) > 0) {
4491 REPORTER_ASSERT(reporter, !memcmp(data->data(), str, strlen(str)));
4492 } else {
4493 REPORTER_ASSERT(reporter, data->data() == nullptr || !memcmp(data->data(), str, strlen(str)));
4494 }
4495}
sk_sp< SkData > detachAsData()
Definition SkStream.cpp:707
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switches.h:41

◆ conditional_convex()

static bool conditional_convex ( const SkPath path,
bool  is_convex 
)
static

Definition at line 5693 of file PathTest.cpp.

5693 {
5695 return is_convex ? (c == SkPathConvexity::kConvex) : (c != SkPathConvexity::kConvex);
5696}
SkPathConvexity
Definition SkPathEnums.h:13
static SkPathConvexity GetConvexityOrUnknown(const SkPath &path)
Definition SkPathPriv.h:410

◆ DEF_TEST() [1/27]

DEF_TEST ( AndroidArc  ,
reporter   
)

Definition at line 5285 of file PathTest.cpp.

5285 {
5286 const char* tests[] = {
5287 "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",
5288 ("M50,0L92,0 A8,8,0,0 1 100,8 L100,92 A8,8,0,0 1 92,100 L8,100"
5289 " A8,8,0,0 1 0,92 L 0,8 A8,8,0,0 1 8,0z"),
5290 "M50 0A50 50,0,1,1,50 100A50 50,0,1,1,50 0"
5291 };
5292 for (auto test : tests) {
5293 SkPath aPath;
5295 SkASSERT(aPath.isConvex());
5296 for (SkScalar scale = 1; scale < 1000; scale *= 1.1f) {
5297 SkPath scalePath = aPath;
5299 matrix.setScale(scale, scale);
5300 scalePath.transform(matrix);
5301 SkASSERT(scalePath.isConvex());
5302 }
5303 for (SkScalar scale = 1; scale < .001; scale /= 1.1f) {
5304 SkPath scalePath = aPath;
5306 matrix.setScale(scale, scale);
5307 scalePath.transform(matrix);
5308 SkASSERT(scalePath.isConvex());
5309 }
5310 }
5311}
static BlurTest tests[]
Definition BlurTest.cpp:84
#define SkAssertResult(cond)
Definition SkAssert.h:123
static bool FromSVGString(const char str[], SkPath *)
void transform(const SkMatrix &matrix, SkPath *dst, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
Definition SkPath.cpp:1647
unsigned useCenter Optional< SkMatrix > matrix
Definition SkRecords.h:258
const Scalar scale

◆ DEF_TEST() [2/27]

DEF_TEST ( ClipPath_nonfinite  ,
reporter   
)

Definition at line 5348 of file PathTest.cpp.

5348 {
5350 SkCanvas* canvas = surf->getCanvas();
5351
5353 for (bool aa : {false, true}) {
5355 for (SkScalar bad : {SK_ScalarInfinity, SK_ScalarNaN}) {
5356 for (int bits = 1; bits <= 15; ++bits) {
5357 SkPoint p0 = { 0, 0 };
5358 SkPoint p1 = { 0, 0 };
5359 if (bits & 1) p0.fX = -bad;
5360 if (bits & 2) p0.fY = -bad;
5361 if (bits & 4) p1.fX = bad;
5362 if (bits & 8) p1.fY = bad;
5363
5364 SkPath path;
5365 path.moveTo(p0);
5366 path.lineTo(p1);
5367 path.setFillType(ft);
5368 canvas->save();
5369 canvas->clipPath(path, aa);
5370 REPORTER_ASSERT(reporter, canvas->isClipEmpty() == !path.isInverseFillType());
5371 canvas->restore();
5372 }
5373 }
5374 }
5375 }
5377}
#define SK_ScalarNaN
Definition SkScalar.h:28
#define SK_ScalarInfinity
Definition SkScalar.h:26
virtual bool isClipEmpty() const
void restore()
Definition SkCanvas.cpp:465
void clipPath(const SkPath &path, SkClipOp op, bool doAntiAlias)
int save()
Definition SkCanvas.cpp:451
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
static SkImageInfo MakeN32Premul(int width, int height)
float fX
x-axis value
float fY
y-axis value

◆ DEF_TEST() [3/27]

DEF_TEST ( conservatively_contains_rect  ,
reporter   
)

Definition at line 5160 of file PathTest.cpp.

5160 {
5161 SkPath path;
5162
5163 path.moveTo(SkBits2Float(0x44000000), SkBits2Float(0x373938b8)); // 512, 1.10401e-05f
5164 // 1.4013e-45f, -9.22346e+18f, 3.58732e-43f, 0, 3.58732e-43f, 0
5165 path.cubicTo(SkBits2Float(0x00000001), SkBits2Float(0xdf000052),
5166 SkBits2Float(0x00000100), SkBits2Float(0x00000000),
5167 SkBits2Float(0x00000100), SkBits2Float(0x00000000));
5168 path.moveTo(0, 0);
5169
5170 // this should not assert
5171 path.conservativelyContainsRect({ -211747, 12.1115f, -197893, 25.0321f });
5172}
static float SkBits2Float(uint32_t bits)
Definition SkFloatBits.h:48

◆ DEF_TEST() [4/27]

DEF_TEST ( HugeGeometry  ,
reporter   
)

Definition at line 5316 of file PathTest.cpp.

5316 {
5317 auto surf = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(100, 100));
5318 auto canvas = surf->getCanvas();
5319
5320 const bool aas[] = { false, true };
5321 const SkPaint::Style styles[] = {
5323 };
5324 const SkScalar values[] = {
5325 0, 1, 1000, 1000 * 1000, 1000.f * 1000 * 10000, SK_ScalarMax / 2, SK_ScalarMax,
5327 };
5328
5329 SkPaint paint;
5330 for (auto x : values) {
5331 SkRect r = { -x, -x, x, x };
5332 for (auto width : values) {
5333 paint.setStrokeWidth(width);
5334 for (auto aa : aas) {
5335 paint.setAntiAlias(aa);
5336 for (auto style : styles) {
5337 paint.setStyle(style);
5338 canvas->drawRect(r, paint);
5339 canvas->drawOval(r, paint);
5340 }
5341 }
5342 }
5343 }
5344
5345}
#define SK_ScalarMax
Definition SkScalar.h:24
@ kStroke_Style
set to stroke geometry
Definition SkPaint.h:194
@ kFill_Style
set to fill geometry
Definition SkPaint.h:193
@ kStrokeAndFill_Style
sets to stroke and fill geometry
Definition SkPaint.h:195
const Paint & paint
double x
int32_t width

◆ DEF_TEST() [5/27]

DEF_TEST ( NonFinitePathIteration  ,
reporter   
)

Definition at line 5278 of file PathTest.cpp.

5278 {
5279 SkPath path;
5281 SkPathPriv::Iterate iterate(path);
5282 REPORTER_ASSERT(reporter, iterate.begin() == iterate.end());
5283}

◆ DEF_TEST() [6/27]

DEF_TEST ( path_addpath_crbug_1153516  ,
 
)

Definition at line 5986 of file PathTest.cpp.

5986 {
5987 // When we add a closed path to another path, verify
5988 // that the result has the right value for last contour start point.
5989 SkPath p1, p2;
5990 p2.lineTo(10,20);
5991 p1.addRect({143,226,200,241});
5992 p2.addPath(p1);
5993 p2.lineTo(262,513); // this should not assert
5994 SkPoint rectangleStart = {143, 226};
5995 SkPoint lineEnd = {262, 513};
5996 SkPoint actualMoveTo = p2.getPoint(p2.countPoints() - 2);
5997 REPORTER_ASSERT(r, actualMoveTo == rectangleStart );
5998 SkPoint actualLineTo = p2.getPoint(p2.countPoints() - 1);
5999 REPORTER_ASSERT(r, actualLineTo == lineEnd);
6000
6001 // Verify adding a closed path to itself
6002 p1.addPath(p1);
6003 p1.lineTo(262,513);
6004 actualMoveTo = p1.getPoint(p1.countPoints() - 2);
6005 REPORTER_ASSERT(r, actualMoveTo == rectangleStart );
6006 actualLineTo = p1.getPoint(p1.countPoints() - 1);
6007 REPORTER_ASSERT(r, actualLineTo == lineEnd);
6008 }
int countPoints() const
Definition SkPath.cpp:525
SkPoint getPoint(int index) const
Definition SkPath.cpp:539
SkPath & lineTo(SkScalar x, SkScalar y)
Definition SkPath.cpp:718
SkPath & addPath(const SkPath &src, SkScalar dx, SkScalar dy, AddPathMode mode=kAppend_AddPathMode)
Definition SkPath.cpp:1442
SkPath & addRect(const SkRect &rect, SkPathDirection dir, unsigned start)
Definition SkPath.cpp:854

◆ DEF_TEST() [7/27]

DEF_TEST ( path_convexity_scale_way_down  ,
 
)

Definition at line 6010 of file PathTest.cpp.

6010 {
6011 SkPath path = SkPathBuilder().moveTo(0,0).lineTo(1, 0)
6012 .lineTo(1,1).lineTo(0,1)
6013 .detach();
6014
6015 REPORTER_ASSERT(r, path.isConvex());
6016 SkPath path2;
6017 const SkScalar scale = 1e-8f;
6018 path.transform(SkMatrix::Scale(scale, scale), &path2);
6021}
static SkPath path2()
static SkMatrix Scale(SkScalar sx, SkScalar sy)
Definition SkMatrix.h:75
SkPathBuilder & lineTo(SkPoint pt)
SkPathBuilder & moveTo(SkPoint pt)
static void ForceComputeConvexity(const SkPath &path)
Definition SkPathPriv.h:416

◆ DEF_TEST() [8/27]

DEF_TEST ( Path_increserve_handle_neg_crbug_883666  ,
 
)

Definition at line 5661 of file PathTest.cpp.

5661 {
5662 SkPath path;
5663
5664 path.conicTo({0, 0}, {1, 1}, SK_FloatNegativeInfinity);
5665
5666 // <== use a copy path object to force SkPathRef::copy() and SkPathRef::resetToSize()
5667 SkPath shallowPath = path;
5668
5669 // make sure we don't assert/crash on this.
5670 shallowPath.incReserve(0xffffffff);
5671}
constexpr float SK_FloatNegativeInfinity
void incReserve(int extraPtCount, int extraVerbCount=0, int extraConicCount=0)
Definition SkPath.cpp:668

◆ DEF_TEST() [9/27]

DEF_TEST ( Path_isRect  ,
reporter   
)

Definition at line 5380 of file PathTest.cpp.

5380 {
5381 auto makePath = [](const SkPoint* points, size_t count, bool close) -> SkPath {
5382 SkPath path;
5383 for (size_t index = 0; index < count; ++index) {
5384 index < 2 ? path.moveTo(points[index]) : path.lineTo(points[index]);
5385 }
5386 if (close) {
5387 path.close();
5388 }
5389 return path;
5390 };
5391 auto makePath2 = [](const SkPoint* points, const SkPath::Verb* verbs, size_t count) -> SkPath {
5392 SkPath path;
5393 for (size_t index = 0; index < count; ++index) {
5394 switch (verbs[index]) {
5395 case SkPath::kMove_Verb:
5396 path.moveTo(*points++);
5397 break;
5398 case SkPath::kLine_Verb:
5399 path.lineTo(*points++);
5400 break;
5402 path.close();
5403 break;
5404 default:
5405 SkASSERT(0);
5406 }
5407 }
5408 return path;
5409 };
5410 // isolated from skbug.com/7792 (bug description)
5411 SkRect rect;
5412 SkPoint points[] = { {10, 10}, {75, 75}, {150, 75}, {150, 150}, {75, 150} };
5413 SkPath path = makePath(points, std::size(points), false);
5414 REPORTER_ASSERT(reporter, path.isRect(&rect));
5416 compare.setBounds(&points[1], std::size(points) - 1);
5418 // isolated from skbug.com/7792#c3
5419 SkPoint points3[] = { {75, 50}, {100, 75}, {150, 75}, {150, 150}, {75, 150}, {75, 50} };
5420 path = makePath(points3, std::size(points3), true);
5421 REPORTER_ASSERT(reporter, !path.isRect(&rect));
5422 // isolated from skbug.com/7792#c9
5423 SkPoint points9[] = { {10, 10}, {75, 75}, {150, 75}, {150, 150}, {75, 150} };
5424 path = makePath(points9, std::size(points9), true);
5425 REPORTER_ASSERT(reporter, path.isRect(&rect));
5426 compare.setBounds(&points9[1], std::size(points9) - 1);
5428 // isolated from skbug.com/7792#c11
5431 SkPoint points11[] = { {75, 150}, {75, 75}, {150, 75}, {150, 150}, {75, 150}, {75, 150} };
5432 path = makePath2(points11, verbs11, std::size(verbs11));
5433 REPORTER_ASSERT(reporter, path.isRect(&rect));
5434 compare.setBounds(&points11[0], std::size(points11));
5436 // isolated from skbug.com/7792#c14
5441 SkPoint points14[] = { {250, 75}, {250, 75}, {250, 75}, {100, 75},
5442 {150, 75}, {150, 150}, {75, 150}, {75, 75}, {0, 0} };
5443 path = makePath2(points14, verbs14, std::size(verbs14));
5444 REPORTER_ASSERT(reporter, !path.isRect(&rect));
5445 // isolated from skbug.com/7792#c15
5448 SkPoint points15[] = { {75, 75}, {150, 75}, {150, 150}, {75, 150}, {250, 75} };
5449 path = makePath2(points15, verbs15, std::size(verbs15));
5450 REPORTER_ASSERT(reporter, path.isRect(&rect));
5451 compare.setBounds(&points15[0], std::size(points15) - 1);
5453 // isolated from skbug.com/7792#c17
5454 SkPoint points17[] = { {75, 10}, {75, 75}, {150, 75}, {150, 150}, {75, 150}, {75, 10} };
5455 path = makePath(points17, std::size(points17), true);
5456 REPORTER_ASSERT(reporter, !path.isRect(&rect));
5457 // isolated from skbug.com/7792#c19
5462 SkPoint points19[] = { {75, 75}, {75, 75}, {75, 75}, {75, 75}, {150, 75}, {150, 150},
5463 {75, 150}, {10, 10}, {30, 10}, {10, 30} };
5464 path = makePath2(points19, verbs19, std::size(verbs19));
5465 REPORTER_ASSERT(reporter, !path.isRect(&rect));
5466 // isolated from skbug.com/7792#c23
5470 SkPoint points23[] = { {75, 75}, {75, 75}, {75, 75}, {75, 75}, {150, 75}, {150, 150},
5471 {75, 150} };
5472 path = makePath2(points23, verbs23, std::size(verbs23));
5473 REPORTER_ASSERT(reporter, path.isRect(&rect));
5474 compare.setBounds(&points23[0], std::size(points23));
5476 // isolated from skbug.com/7792#c29
5480 SkPoint points29[] = { {75, 75}, {150, 75}, {150, 150}, {75, 150}, {75, 250}, {75, 75} };
5481 path = makePath2(points29, verbs29, std::size(verbs29));
5482 REPORTER_ASSERT(reporter, !path.isRect(&rect));
5483 // isolated from skbug.com/7792#c31
5487 SkPoint points31[] = { {75, 75}, {150, 75}, {150, 150}, {75, 150}, {75, 10}, {75, 75} };
5488 path = makePath2(points31, verbs31, std::size(verbs31));
5489 REPORTER_ASSERT(reporter, path.isRect(&rect));
5490 compare.setBounds(&points31[0], 4);
5492 // isolated from skbug.com/7792#c36
5495 SkPoint points36[] = { {75, 75}, {150, 75}, {150, 150}, {10, 150}, {75, 75}, {75, 75} };
5496 path = makePath2(points36, verbs36, std::size(verbs36));
5497 REPORTER_ASSERT(reporter, !path.isRect(&rect));
5498 // isolated from skbug.com/7792#c39
5501 SkPoint points39[] = { {150, 75}, {150, 150}, {75, 150}, {75, 100} };
5502 path = makePath2(points39, verbs39, std::size(verbs39));
5503 REPORTER_ASSERT(reporter, !path.isRect(&rect));
5504 // isolated from zero_length_paths_aa
5508 SkPoint pointsAA[] = { {32, 9.5f}, {32, 9.5f}, {32, 17}, {17, 17}, {17, 9.5f}, {17, 2},
5509 {32, 2} };
5510 path = makePath2(pointsAA, verbsAA, std::size(verbsAA));
5511 REPORTER_ASSERT(reporter, path.isRect(&rect));
5512 compare.setBounds(&pointsAA[0], std::size(pointsAA));
5514 // isolated from skbug.com/7792#c41
5518 SkPoint points41[] = { {75, 75}, {150, 75}, {150, 150}, {140, 150}, {140, 75}, {75, 75} };
5519 path = makePath2(points41, verbs41, std::size(verbs41));
5520 REPORTER_ASSERT(reporter, path.isRect(&rect));
5521 compare.setBounds(&points41[1], 4);
5523 // isolated from skbug.com/7792#c53
5527 SkPoint points53[] = { {75, 75}, {150, 75}, {150, 150}, {140, 150}, {140, 75}, {75, 75} };
5528 path = makePath2(points53, verbs53, std::size(verbs53));
5529 REPORTER_ASSERT(reporter, path.isRect(&rect));
5530 compare.setBounds(&points53[1], 4);
5532}
static bool compare(const SkBitmap &ref, const SkIRect &iref, const SkBitmap &test, const SkIRect &itest)
Definition BlurTest.cpp:100
static const int points[]
void setBounds(const SkPoint pts[], int count)
Definition SkRect.h:881

◆ DEF_TEST() [10/27]

DEF_TEST ( path_last_move_to_index  ,
 
)

Definition at line 5773 of file PathTest.cpp.

5773 {
5774 // Make sure that copyPath is safe after the call to path.offset().
5775 // Previously, we would leave its fLastMoveToIndex alone after the copy, but now we should
5776 // set it to path's value inside SkPath::transform()
5777
5778 const char text[] = "hello";
5779 constexpr size_t len = sizeof(text) - 1;
5781
5783 font.textToGlyphs(text, len, SkTextEncoding::kUTF8, glyphs, len);
5784
5785 SkPath copyPath;
5786 font.getPaths(glyphs, len, [](const SkPath* src, const SkMatrix& mx, void* ctx) {
5787 if (src) {
5788 ((SkPath*)ctx)->addPath(*src, mx);
5789 }
5790 }, &copyPath);
5791
5792 SkScalar radii[] = { 80, 100, 0, 0, 40, 60, 0, 0 };
5793 SkPath path;
5794 path.addRoundRect({10, 10, 110, 110}, radii);
5795 path.offset(0, 5, &(copyPath)); // <== change buffer copyPath.fPathRef->fPoints but not reset copyPath.fLastMoveToIndex lead to out of bound
5796
5797 copyPath.rConicTo(1, 1, 3, 3, 0.707107f);
5798}
uint16_t glyphs[5]
@ kUTF8
uses bytes to represent UTF-8 or ASCII
uint16_t SkGlyphID
Definition SkTypes.h:179
SkPath & rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, SkScalar w)
Definition SkPath.cpp:781
std::u16string text
SkFont DefaultFont()
font
Font Metadata and Metrics.

◆ DEF_TEST() [11/27]

DEF_TEST ( path_moveto_addrect  ,
 
)

Definition at line 6024 of file PathTest.cpp.

6024 {
6025 // Test both an empty and non-empty rect passed to SkPath::addRect
6026 SkRect rects[] = {{207.0f, 237.0f, 300.0f, 237.0f},
6027 {207.0f, 237.0f, 300.0f, 267.0f}};
6028
6029 for (SkRect rect: rects) {
6030 for (int numExtraMoveTos : {0, 1, 2, 3}) {
6031 SkPath path;
6032 // Convexity and contains functions treat the path as a simple fill, so consecutive
6033 // moveTos are collapsed together.
6034 for (int i = 0; i < numExtraMoveTos; ++i) {
6035 path.moveTo(i, i);
6036 }
6037 path.addRect(rect);
6038
6039 REPORTER_ASSERT(r, (numExtraMoveTos + 1) == SkPathPriv::LeadingMoveToCount(path));
6040
6041 // addRect should mark the path as known convex automatically (i.e. it wasn't set
6042 // to unknown after edits)
6044 REPORTER_ASSERT(r, origConvexity == SkPathConvexity::kConvex);
6045
6046 // but it should also agree with the regular convexity computation
6048 REPORTER_ASSERT(r, path.isConvex());
6049
6050 SkRect query = rect.makeInset(10.f, 0.f);
6051 REPORTER_ASSERT(r, path.conservativelyContainsRect(query));
6052 }
6053 }
6054}
static int LeadingMoveToCount(const SkPath &path)
Definition SkPathPriv.h:94

◆ DEF_TEST() [12/27]

DEF_TEST ( path_moveto_twopass_convexity  ,
 
)

Definition at line 6057 of file PathTest.cpp.

6057 {
6058 // There had been a bug when the last moveTo index > 0, the calculated point count was incorrect
6059 // and the BySign convexity pass would not evaluate the entire path, effectively only using the
6060 // winding rule for determining convexity.
6061 SkPath path;
6062 path.setFillType(SkPathFillType::kWinding);
6063 path.moveTo(3.25f, 115.5f);
6064 path.conicTo(9.98099e+17f, 2.83874e+15f, 1.75098e-30f, 1.75097e-30f, 1.05385e+18f);
6065 path.conicTo(9.96938e+17f, 6.3804e+19f, 9.96934e+17f, 1.75096e-30f, 1.75096e-30f);
6066 path.quadTo(1.28886e+10f, 9.9647e+17f, 9.98101e+17f, 2.61006e+15f);
6067 REPORTER_ASSERT(r, !path.isConvex());
6068
6069 SkPath pathWithExtraMoveTo;
6070 pathWithExtraMoveTo.setFillType(SkPathFillType::kWinding);
6071 pathWithExtraMoveTo.moveTo(5.90043e-39f, 1.34525e-43f);
6072 pathWithExtraMoveTo.addPath(path);
6073 REPORTER_ASSERT(r, !pathWithExtraMoveTo.isConvex());
6074}
SkPath & moveTo(SkScalar x, SkScalar y)
Definition SkPath.cpp:678
void setFillType(SkPathFillType ft)
Definition SkPath.h:235

◆ DEF_TEST() [13/27]

DEF_TEST ( Path_self_add  ,
reporter   
)

Definition at line 5535 of file PathTest.cpp.

5535 {
5536 // The possible problem is that during path.add() we may have to grow the dst buffers as
5537 // we append the src pts/verbs, but all the while we are iterating over the src. If src == dst
5538 // we could realloc the buffer's (on behalf of dst) leaving the src iterator pointing at
5539 // garbage.
5540 //
5541 // The test runs though verious sized src paths, since its not defined publicly what the
5542 // reserve allocation strategy is for SkPath, therefore we can't know when an append operation
5543 // will trigger a realloc. At the time of this writing, these loops were sufficient to trigger
5544 // an ASAN error w/o the fix to SkPath::addPath().
5545 //
5546 for (int count = 0; count < 10; ++count) {
5547 SkPath path;
5548 for (int add = 0; add < count; ++add) {
5549 // just add some stuff, so we have something to copy/append in addPath()
5550 path.moveTo(1, 2).lineTo(3, 4).cubicTo(1,2,3,4,5,6).conicTo(1,2,3,4,5);
5551 }
5552 path.addPath(path, 1, 2);
5553 path.addPath(path, 3, 4);
5554 }
5555}

◆ DEF_TEST() [14/27]

DEF_TEST ( Path_setLastPt  ,
 
)

Definition at line 5646 of file PathTest.cpp.

5646 {
5647 // There was a time where SkPath::setLastPoint() didn't invalidate cached path bounds.
5648 SkPath p;
5649 p.moveTo(0,0);
5650 p.moveTo(20,01);
5651 p.moveTo(20,10);
5652 p.moveTo(20,61);
5653 REPORTER_ASSERT(r, p.getBounds() == SkRect::MakeLTRB(0,0, 20,61));
5654
5655 p.setLastPt(30,01);
5656 REPORTER_ASSERT(r, p.getBounds() == SkRect::MakeLTRB(0,0, 30,10)); // was {0,0, 20,61}
5657
5658 REPORTER_ASSERT(r, p.isValid());
5659}
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition SkRect.h:646

◆ DEF_TEST() [15/27]

DEF_TEST ( Path_shrinkToFit  ,
reporter   
)

Definition at line 5612 of file PathTest.cpp.

5612 {
5613 for (int verbs = 0; verbs < 100; ++verbs) {
5614 SkPath unique_path, shared_path;
5615 add_verbs(&unique_path, verbs);
5616 add_verbs(&shared_path, verbs);
5617
5618 const SkPath copy = shared_path;
5619
5620 REPORTER_ASSERT(reporter, shared_path == unique_path);
5621 REPORTER_ASSERT(reporter, shared_path == copy);
5622
5623 uint32_t uID = unique_path.getGenerationID();
5624 uint32_t sID = shared_path.getGenerationID();
5625 uint32_t cID = copy.getGenerationID();
5626 REPORTER_ASSERT(reporter, sID == cID);
5627
5628 SkPathPriv::ShrinkToFit(&unique_path);
5629 SkPathPriv::ShrinkToFit(&shared_path);
5630 REPORTER_ASSERT(reporter, shared_path == unique_path);
5631 REPORTER_ASSERT(reporter, shared_path == copy);
5632
5633 // since the unique_path is "unique", it's genID need not have changed even though
5634 // unique_path has changed (been shrunk)
5635 REPORTER_ASSERT(reporter, uID == unique_path.getGenerationID());
5636 // since the copy has not been changed, its ID should be the same
5637 REPORTER_ASSERT(reporter, cID == copy.getGenerationID());
5638 // but since shared_path has changed, and was not uniquely owned, it's gen ID needs to have
5639 // changed, breaking the "sharing" -- this is done defensively in case there were any
5640 // outstanding Iterators active on copy, which could have been invalidated during
5641 // shrinkToFit.
5642 REPORTER_ASSERT(reporter, sID != shared_path.getGenerationID());
5643 }
5644}
static void add_verbs(SkPath *path, int count)
static void ShrinkToFit(SkPath *path)
Definition SkPathPriv.h:130
uint32_t getGenerationID() const
Definition SkPath.cpp:356

◆ DEF_TEST() [16/27]

DEF_TEST ( Path_survive_transform  ,
 
)

Definition at line 5751 of file PathTest.cpp.

5751 {
5752 const Xforms x;
5753
5754 SkPath path;
5755 path.addRect({10, 10, 40, 50});
5756 survive(&path, x, true, r, [](const SkPath& p) { return p.isRect(nullptr); });
5757
5758 path.reset();
5759 path.addOval({10, 10, 40, 50});
5760 survive(&path, x, true, r, [](const SkPath& p) { return p.isOval(nullptr); });
5761
5762 path.reset();
5763 path.addRRect(SkRRect::MakeRectXY({10, 10, 40, 50}, 5, 5));
5764 survive(&path, x, true, r, [](const SkPath& p) { return p.isRRect(nullptr); });
5765
5766 // make a trapazoid; definitely convex, but not marked as axis-aligned (e.g. oval, rrect)
5767 path.reset();
5768 path.moveTo(0, 0).lineTo(100, 0).lineTo(70, 100).lineTo(30, 100);
5769 REPORTER_ASSERT(r, path.isConvex());
5770 survive(&path, x, false, r, [](const SkPath& p) { return true; });
5771}
void survive(SkPath *path, const Xforms &x, bool isAxisAligned, skiatest::Reporter *reporter, ISA isa_proc)
static SkRRect MakeRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
Definition SkRRect.h:180

◆ DEF_TEST() [17/27]

DEF_TEST ( path_tight_bounds  ,
reporter   
)

Definition at line 5201 of file PathTest.cpp.

5201 {
5202 SkRandom rand;
5203
5204 const SkPath::Verb verbs[] = {
5206 };
5207 for (int i = 0; i < 1000; ++i) {
5208 for (int n = 1; n <= 10; n += 9) {
5209 for (SkPath::Verb verb : verbs) {
5210 SkPath path;
5211 rand_path(&path, rand, verb, n);
5212 SkRect bounds = path.getBounds();
5213 SkRect tight = path.computeTightBounds();
5214 REPORTER_ASSERT(reporter, bounds.contains(tight));
5215
5216 SkRect tight2;
5217 TightBounds(path, &tight2);
5218 REPORTER_ASSERT(reporter, nearly_equal(tight, tight2));
5219 }
5220 }
5221 }
5222}
static bool nearly_equal(const SkRect &a, const SkRect &b)
static void rand_path(SkPath *path, SkRandom &rand, SkPath::Verb verb, int n)
bool SK_API TightBounds(const SkPath &path, SkRect *result)
@ kConic_Verb
Definition SkPath.h:1461
@ kCubic_Verb
Definition SkPath.h:1462
@ kQuad_Verb
Definition SkPath.h:1460
Optional< SkRect > bounds
Definition SkRecords.h:189

◆ DEF_TEST() [18/27]

DEF_TEST ( path_walk_simple_edges_1154864  ,
 
)

Definition at line 6077 of file PathTest.cpp.

6077 {
6078 // Drawing this path triggered an assert in walk_simple_edges:
6080
6081 SkPath path;
6082 path.setFillType(SkPathFillType::kWinding);
6083 path.moveTo(0.00665998459f, 2);
6084 path.quadTo(0.00665998459f, 4, -1.99334002f, 4);
6085 path.quadTo(-3.99334002f, 4, -3.99334002f, 2);
6086 path.quadTo(-3.99334002f, 0, -1.99334002f, 0);
6087 path.quadTo(0.00665998459f, 0, 0.00665998459f, 2);
6088 path.close();
6089
6090 SkPaint paint;
6091 paint.setAntiAlias(true);
6092 surface->getCanvas()->drawPath(path, paint);
6093}
VkSurfaceKHR surface
Definition main.cc:49

◆ DEF_TEST() [19/27]

DEF_TEST ( PathBigCubic  ,
reporter   
)

Definition at line 4965 of file PathTest.cpp.

4965 {
4966 SkPath path;
4967 path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0
4968 path.moveTo(SkBits2Float(0x44000000), SkBits2Float(0x373938b8)); // 512, 1.10401e-05f
4969 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
4970 path.moveTo(0, 512);
4971
4972 // this call should not assert
4974 ->getCanvas()
4975 ->drawPath(path, SkPaint());
4976}
void drawPath(const SkPath &path, const SkPaint &paint)
SkCanvas * getCanvas()
Definition SkSurface.cpp:82

◆ DEF_TEST() [20/27]

DEF_TEST ( PathContains  ,
reporter   
)

Definition at line 4978 of file PathTest.cpp.

4978 {
4980}
static void test_contains(skiatest::Reporter *reporter)

◆ DEF_TEST() [21/27]

DEF_TEST ( pathedger  ,
 
)

Definition at line 5966 of file PathTest.cpp.

5966 {
5967 auto M = SkPath::kMove_Verb;
5968 auto L = SkPath::kLine_Verb;
5969 auto C = SkPath::kClose_Verb;
5970
5971 test_edger(r, { M }, {});
5972 test_edger(r, { M, M }, {});
5973 test_edger(r, { M, C }, {});
5974 test_edger(r, { M, M, C }, {});
5975 test_edger(r, { M, L }, { L, L });
5976 test_edger(r, { M, L, C }, { L, L });
5977 test_edger(r, { M, L, L }, { L, L, L });
5978 test_edger(r, { M, L, L, C }, { L, L, L });
5979
5980 test_edger(r, { M, L, L, M, L, L }, { L, L, L, L, L, L });
5981
5984}
static void test_addPath_and_injected_moveTo(skiatest::Reporter *reporter)
static void test_edger(skiatest::Reporter *r, const std::initializer_list< SkPath::Verb > &in, const std::initializer_list< SkPath::Verb > &expected)
static void test_addRect_and_trailing_lineTo(skiatest::Reporter *reporter)
#define M(PROC, DITHER)

◆ DEF_TEST() [22/27]

DEF_TEST ( PathInterp  ,
reporter   
)

Definition at line 4961 of file PathTest.cpp.

4961 {
4963}
static void test_interp(skiatest::Reporter *reporter)

◆ DEF_TEST() [23/27]

DEF_TEST ( PathRefSerialization  ,
reporter   
)

Definition at line 5246 of file PathTest.cpp.

5246 {
5247 SkPath path;
5248 const size_t numMoves = 5;
5249 const size_t numConics = 7;
5250 const size_t numPoints = numMoves + 2 * numConics;
5251 const size_t numVerbs = numMoves + numConics;
5252 for (size_t i = 0; i < numMoves; ++i) path.moveTo(1, 2);
5253 for (size_t i = 0; i < numConics; ++i) path.conicTo(1, 2, 3, 4, 5);
5254 REPORTER_ASSERT(reporter, path.countPoints() == numPoints);
5255 REPORTER_ASSERT(reporter, path.countVerbs() == numVerbs);
5256
5257 // Verify that path serializes/deserializes properly.
5258 sk_sp<SkData> data = path.serialize();
5259 size_t bytesWritten = data->size();
5260
5261 {
5262 SkPath readBack;
5263 REPORTER_ASSERT(reporter, readBack != path);
5264 size_t bytesRead = readBack.readFromMemory(data->data(), bytesWritten);
5265 REPORTER_ASSERT(reporter, bytesRead == bytesWritten);
5266 REPORTER_ASSERT(reporter, readBack == path);
5267 }
5268
5269 // One less byte (rounded down to alignment) than was written will also
5270 // fail to be deserialized.
5271 {
5272 SkPath readBack;
5273 size_t bytesRead = readBack.readFromMemory(data->data(), bytesWritten - 4);
5274 REPORTER_ASSERT(reporter, !bytesRead);
5275 }
5276}
size_t readFromMemory(const void *buffer, size_t length)

◆ DEF_TEST() [24/27]

DEF_TEST ( Paths  ,
reporter   
)

Definition at line 4982 of file PathTest.cpp.

4982 {
5000
5001 SkSize::Make(3, 4);
5002
5003 SkPath p, empty;
5004 SkRect bounds, bounds2;
5005 test_empty(reporter, p);
5006
5007 REPORTER_ASSERT(reporter, p.getBounds().isEmpty());
5008
5009 // this triggers a code path in SkPath::operator= which is otherwise unexercised
5010 SkPath& self = p;
5011 p = self;
5012
5013 // this triggers a code path in SkPath::swap which is otherwise unexercised
5014 p.swap(self);
5015
5016 bounds.setLTRB(0, 0, SK_Scalar1, SK_Scalar1);
5017
5018 p.addRoundRect(bounds, SK_Scalar1, SK_Scalar1);
5019 check_convex_bounds(reporter, p, bounds);
5020 // we have quads or cubics
5022 p.getSegmentMasks() & (kCurveSegmentMask | SkPath::kConic_SegmentMask));
5023 REPORTER_ASSERT(reporter, !p.isEmpty());
5024
5025 p.reset();
5026 test_empty(reporter, p);
5027
5028 p.addOval(bounds);
5029 check_convex_bounds(reporter, p, bounds);
5030 REPORTER_ASSERT(reporter, !p.isEmpty());
5031
5032 p.rewind();
5033 test_empty(reporter, p);
5034
5035 p.addRect(bounds);
5036 check_convex_bounds(reporter, p, bounds);
5037 // we have only lines
5038 REPORTER_ASSERT(reporter, SkPath::kLine_SegmentMask == p.getSegmentMasks());
5039 REPORTER_ASSERT(reporter, !p.isEmpty());
5040
5042 REPORTER_ASSERT(reporter, !(p == empty));
5043
5044 // do getPoints and getVerbs return the right result
5045 REPORTER_ASSERT(reporter, p.getPoints(nullptr, 0) == 4);
5046 REPORTER_ASSERT(reporter, p.getVerbs(nullptr, 0) == 5);
5047 SkPoint pts[4];
5048 int count = p.getPoints(pts, 4);
5050 uint8_t verbs[6];
5051 verbs[5] = 0xff;
5052 p.getVerbs(verbs, 5);
5058 REPORTER_ASSERT(reporter, 0xff == verbs[5]);
5059 bounds2.setBounds(pts, 4);
5060 REPORTER_ASSERT(reporter, bounds == bounds2);
5061
5062 bounds.offset(SK_Scalar1*3, SK_Scalar1*4);
5063 p.offset(SK_Scalar1*3, SK_Scalar1*4);
5064 REPORTER_ASSERT(reporter, bounds == p.getBounds());
5065
5066 REPORTER_ASSERT(reporter, p.isRect(nullptr));
5067 bounds2.setEmpty();
5068 REPORTER_ASSERT(reporter, p.isRect(&bounds2));
5069 REPORTER_ASSERT(reporter, bounds == bounds2);
5070
5071 // now force p to not be a rect
5072 bounds.setWH(SK_Scalar1/2, SK_Scalar1/2);
5073 p.addRect(bounds);
5074 REPORTER_ASSERT(reporter, !p.isRect(nullptr));
5075
5076 // Test an edge case w.r.t. the bound returned by isRect (i.e., the
5077 // path has a trailing moveTo. Please see crbug.com\445368)
5078 {
5079 SkRect r;
5080 p.reset();
5081 p.addRect(bounds);
5082 REPORTER_ASSERT(reporter, p.isRect(&r));
5083 REPORTER_ASSERT(reporter, r == bounds);
5084 // add a moveTo outside of our bounds
5085 p.moveTo(bounds.fLeft + 10, bounds.fBottom + 10);
5086 REPORTER_ASSERT(reporter, p.isRect(&r));
5087 REPORTER_ASSERT(reporter, r == bounds);
5088 }
5089
5137 test_addPathMode(reporter, false, false);
5138 test_addPathMode(reporter, true, false);
5139 test_addPathMode(reporter, false, true);
5140 test_addPathMode(reporter, true, true);
5158}
static void test_arb_round_rect_is_convex(skiatest::Reporter *reporter)
Definition PathTest.cpp:880
static void test_transform(skiatest::Reporter *reporter)
static void test_fuzz_crbug_638223()
Definition PathTest.cpp:189
static void test_arc_ovals(skiatest::Reporter *reporter)
static void check_convex_bounds(skiatest::Reporter *reporter, const SkPath &p, const SkRect &bounds)
static void test_bad_cubic_crbug229478()
Definition PathTest.cpp:467
static void test_skbug_6947()
static void test_arcTo(skiatest::Reporter *reporter)
static void test_conicTo_special_case(skiatest::Reporter *reporter)
static void test_isNestedFillRects(skiatest::Reporter *reporter)
static void test_arb_zero_rad_round_rect_is_rect(skiatest::Reporter *reporter)
Definition PathTest.cpp:907
static void test_range_iter(skiatest::Reporter *reporter)
static void test_path_crbug389050(skiatest::Reporter *reporter)
static void test_rMoveTo(skiatest::Reporter *reporter)
static void test_iterative_intersect_line()
Definition PathTest.cpp:149
static void test_get_point(skiatest::Reporter *reporter)
#define kCurveSegmentMask
static void test_is_closed_rect(skiatest::Reporter *reporter)
static void test_circle(skiatest::Reporter *reporter)
static void test_direction(skiatest::Reporter *reporter)
static void test_addPathMode(skiatest::Reporter *reporter, bool explicitMoveTo, bool extend)
static void test_bad_cubic_crbug234190()
Definition PathTest.cpp:458
static void test_bounds_crbug_513799(skiatest::Reporter *reporter)
Definition PathTest.cpp:754
static void test_convexity(skiatest::Reporter *reporter)
static void test_dump(skiatest::Reporter *reporter)
static void test_fuzz_crbug_627414(skiatest::Reporter *reporter)
Definition PathTest.cpp:783
static void test_zero_length_paths(skiatest::Reporter *reporter)
static void test_isLine(skiatest::Reporter *reporter)
static void test_fuzz_crbug_643933()
Definition PathTest.cpp:198
static void test_mask_overflow()
Definition PathTest.cpp:250
static void test_path_crbugskia5995()
Definition PathTest.cpp:300
static void test_empty(skiatest::Reporter *reporter, const SkPath &p)
static void test_addrect_isfinite(skiatest::Reporter *reporter)
Definition PathTest.cpp:687
static void test_convexity2(skiatest::Reporter *reporter)
static void test_iter(skiatest::Reporter *reporter)
static void test_fuzz_crbug_668907()
Definition PathTest.cpp:264
static void test_fuzz_crbug_662780()
Definition PathTest.cpp:222
static void test_close(skiatest::Reporter *reporter)
static void test_isArc(skiatest::Reporter *reporter)
static void test_arc(skiatest::Reporter *reporter)
static void test_skbug_7435()
static void test_isRect(skiatest::Reporter *reporter)
static void test_crbug_629455(skiatest::Reporter *reporter)
static void test_clipped_cubic()
Definition PathTest.cpp:728
static void test_extendClosedPath(skiatest::Reporter *reporter)
static void test_isfinite_after_transform(skiatest::Reporter *reporter)
Definition PathTest.cpp:810
static void test_skbug_3469(skiatest::Reporter *reporter)
Definition PathTest.cpp:79
static void test_crbug_493450(skiatest::Reporter *reporter)
Definition PathTest.cpp:603
static void test_operatorEqual(skiatest::Reporter *reporter)
static void test_islastcontourclosed(skiatest::Reporter *reporter)
Definition PathTest.cpp:995
static void test_addrect(skiatest::Reporter *reporter)
Definition PathTest.cpp:659
static void test_bounds(skiatest::Reporter *reporter)
static void test_skbug_7015()
static void test_tricky_cubic()
Definition PathTest.cpp:794
static void test_addPoly(skiatest::Reporter *reporter)
static void test_segment_masks(skiatest::Reporter *reporter)
static void test_strokerec(skiatest::Reporter *reporter)
static void test_isfinite(skiatest::Reporter *reporter)
Definition PathTest.cpp:990
static void test_fuzz_crbug_662730(skiatest::Reporter *reporter)
static void test_skbug_7051()
static void test_fuzz_crbug_662952(skiatest::Reporter *reporter)
static void test_convexity_doubleback(skiatest::Reporter *reporter)
static void test_skbug_3239(skiatest::Reporter *reporter)
Definition PathTest.cpp:87
static void test_path_crbugskia2820(skiatest::Reporter *reporter)
Definition PathTest.cpp:291
static void test_oval(skiatest::Reporter *reporter)
static void test_path_close_issue1474(skiatest::Reporter *reporter)
Definition PathTest.cpp:359
static void test_rrect(skiatest::Reporter *reporter)
static void test_crbug_613918()
Definition PathTest.cpp:648
static void test_crbug_170666()
Definition PathTest.cpp:577
static void test_fuzz_crbug_647922()
Definition PathTest.cpp:213
static void test_addEmptyPath(skiatest::Reporter *reporter, SkPath::AddPathMode mode)
static void test_crbug_495894(skiatest::Reporter *reporter)
Definition PathTest.cpp:622
static void test_gen_id(skiatest::Reporter *reporter)
Definition PathTest.cpp:409
static void test_flattening(skiatest::Reporter *reporter)
static void test_addPath(skiatest::Reporter *reporter)
static void test_path_to_region(skiatest::Reporter *reporter)
Definition PathTest.cpp:333
static void test_path_crbugskia6003()
static void test_sect_with_horizontal_needs_pinning()
Definition PathTest.cpp:135
static void test_path_crbug364224()
Definition PathTest.cpp:167
static void test_conservativelyContains(skiatest::Reporter *reporter)
#define SK_Scalar1
Definition SkScalar.h:18
static void TestPathRef(skiatest::Reporter *reporter)
static void TestPathTo(skiatest::Reporter *reporter)
static void TestPathrefListeners(skiatest::Reporter *reporter)
@ kLine_SegmentMask
Definition SkPath.h:1437
@ kConic_SegmentMask
Definition SkPath.h:1439
@ kExtend_AddPathMode
Definition SkPath.h:1285
@ kAppend_AddPathMode
Definition SkPath.h:1278
EMSCRIPTEN_KEEPALIVE void empty()
void setEmpty()
Definition SkRect.h:842
static constexpr SkSize Make(SkScalar w, SkScalar h)
Definition SkSize.h:56

◆ DEF_TEST() [25/27]

DEF_TEST ( skbug_6450  ,
 
)

Definition at line 5224 of file PathTest.cpp.

5224 {
5225 SkRect ri = { 0.18554693f, 195.26283f, 0.185784385f, 752.644409f };
5226 SkVector rdi[4] = {
5227 { 1.81159976e-09f, 7.58768801e-05f },
5228 { 0.000118725002f, 0.000118725002f },
5229 { 0.000118725002f, 0.000118725002f },
5230 { 0.000118725002f, 0.486297607f }
5231 };
5232 SkRRect irr;
5233 irr.setRectRadii(ri, rdi);
5234 SkRect ro = { 9.18354821e-39f, 2.1710848e+9f, 2.16945843e+9f, 3.47808128e+9f };
5235 SkVector rdo[4] = {
5236 { 0, 0 },
5237 { 0.0103298295f, 0.185887396f },
5238 { 2.52999727e-29f, 169.001938f },
5239 { 195.262741f, 195.161255f }
5240 };
5241 SkRRect orr;
5242 orr.setRectRadii(ro, rdo);
5243 SkMakeNullCanvas()->drawDRRect(orr, irr, SkPaint());
5244}
SK_API std::unique_ptr< SkCanvas > SkMakeNullCanvas()
void setRectRadii(const SkRect &rect, const SkVector radii[4])
Definition SkRRect.cpp:189

◆ DEF_TEST() [26/27]

DEF_TEST ( triangle_big  ,
reporter   
)

Definition at line 5582 of file PathTest.cpp.

5582 {
5584
5585 // The first two points, when sent through our fixed-point SkEdge, can walk negative beyond
5586 // -0.5 due to accumulated += error of the slope. We have since make the bounds calculation
5587 // be conservative, so we invoke clipping if we get in this situation.
5588 // This test was added to demonstrate the need for this conservative bounds calc.
5589 // (found by a fuzzer)
5590 const SkPoint pts[] = {
5591 { 0.327190518f, -114.945152f },
5592 { -0.5f, 1.00003874f },
5593 { 0.666425824f, 4304.26172f },
5594 };
5595 draw_triangle(surface->getCanvas(), pts);
5596}
static void draw_triangle(SkCanvas *canvas, const SkPoint pts[])

◆ DEF_TEST() [27/27]

DEF_TEST ( triangle_onehalf  ,
reporter   
)

Definition at line 5571 of file PathTest.cpp.

5571 {
5573
5574 const SkPoint pts[] = {
5575 { 0.499069244f, 9.63295173f },
5576 { 0.499402374f, 7.88207579f },
5577 { 10.2363272f, 0.49999997f }
5578 };
5579 draw_triangle(surface->getCanvas(), pts);
5580}

◆ draw_triangle()

static void draw_triangle ( SkCanvas canvas,
const SkPoint  pts[] 
)
static

Definition at line 5557 of file PathTest.cpp.

5557 {
5558 // draw in different ways, looking for an assert
5559
5560 {
5561 SkPath path;
5562 path.addPoly(pts, 3, false);
5563 canvas->drawPath(path, SkPaint());
5564 }
5565
5567 auto v = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode, 3, pts, nullptr, colors);
5569}
@ kSrcOver
r = s + (1-sa)*d
uint32_t SkColor
Definition SkColor.h:37
constexpr SkColor SK_ColorBLACK
Definition SkColor.h:103
void drawVertices(const SkVertices *vertices, SkBlendMode mode, const SkPaint &paint)
static sk_sp< SkVertices > MakeCopy(VertexMode mode, int vertexCount, const SkPoint positions[], const SkPoint texs[], const SkColor colors[], int indexCount, const uint16_t indices[])
@ kTriangles_VertexMode
Definition SkVertices.h:31
PODArray< SkColor > colors
Definition SkRecords.h:276

◆ dump_if_ne()

static void dump_if_ne ( skiatest::Reporter reporter,
const SkRect expected,
const SkRect bounds 
)
static

Definition at line 746 of file PathTest.cpp.

746 {
747 if (expected != bounds) {
748 ERRORF(reporter, "path.getBounds() returned [%g %g %g %g], but expected [%g %g %g %g]",
749 bounds.left(), bounds.top(), bounds.right(), bounds.bottom(),
750 expected.left(), expected.top(), expected.right(), expected.bottom());
751 }
752}
#define ERRORF(r,...)
Definition Test.h:293
constexpr float left() const
Definition SkRect.h:734
constexpr float top() const
Definition SkRect.h:741
constexpr float right() const
Definition SkRect.h:748
constexpr float bottom() const
Definition SkRect.h:755

◆ make_arb_round_rect()

static void make_arb_round_rect ( SkPath path,
const SkRect r,
SkScalar  xCorner,
SkScalar  yCorner 
)
static

Definition at line 866 of file PathTest.cpp.

867 {
868 // we are lazy here and use the same x & y for each corner
869 add_corner_arc(path, r, xCorner, yCorner, 270);
870 add_corner_arc(path, r, xCorner, yCorner, 0);
871 add_corner_arc(path, r, xCorner, yCorner, 90);
872 add_corner_arc(path, r, xCorner, yCorner, 180);
873 path->close();
874}
static void add_corner_arc(SkPath *path, const SkRect &rect, SkScalar xIn, SkScalar yIn, int startAngle)
Definition PathTest.cpp:836

◆ make_path0()

static void make_path0 ( SkPath path)
static

Definition at line 309 of file PathTest.cpp.

309 {
310 // from * https://code.google.com/p/skia/issues/detail?id=1706
311
312 path->moveTo(146.939f, 1012.84f);
313 path->lineTo(181.747f, 1009.18f);
314 path->lineTo(182.165f, 1013.16f);
315 path->lineTo(147.357f, 1016.82f);
316 path->lineTo(146.939f, 1012.84f);
317 path->close();
318}

◆ make_path1()

static void make_path1 ( SkPath path)
static

Definition at line 320 of file PathTest.cpp.

320 {
321 path->addRect(SkRect::MakeXYWH(10, 10, 10, 1));
322}
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition SkRect.h:659

◆ make_path_crbug364224()

static void make_path_crbug364224 ( SkPath path)
static

Definition at line 105 of file PathTest.cpp.

105 {
106 path->reset();
107 path->moveTo(3.747501373f, 2.724499941f);
108 path->lineTo(3.747501373f, 3.75f);
109 path->cubicTo(3.747501373f, 3.88774991f, 3.635501385f, 4.0f, 3.497501373f, 4.0f);
110 path->lineTo(0.7475013733f, 4.0f);
111 path->cubicTo(0.6095013618f, 4.0f, 0.4975013733f, 3.88774991f, 0.4975013733f, 3.75f);
112 path->lineTo(0.4975013733f, 1.0f);
113 path->cubicTo(0.4975013733f, 0.8622499704f, 0.6095013618f, 0.75f, 0.7475013733f,0.75f);
114 path->lineTo(3.497501373f, 0.75f);
115 path->cubicTo(3.50275135f, 0.75f, 3.5070014f, 0.7527500391f, 3.513001442f, 0.753000021f);
116 path->lineTo(3.715001345f, 0.5512499809f);
117 path->cubicTo(3.648251295f, 0.5194999576f, 3.575501442f, 0.4999999702f, 3.497501373f, 0.4999999702f);
118 path->lineTo(0.7475013733f, 0.4999999702f);
119 path->cubicTo(0.4715013802f, 0.4999999702f, 0.2475013733f, 0.7239999771f, 0.2475013733f, 1.0f);
120 path->lineTo(0.2475013733f, 3.75f);
121 path->cubicTo(0.2475013733f, 4.026000023f, 0.4715013504f, 4.25f, 0.7475013733f, 4.25f);
122 path->lineTo(3.497501373f, 4.25f);
123 path->cubicTo(3.773501396f, 4.25f, 3.997501373f, 4.026000023f, 3.997501373f, 3.75f);
124 path->lineTo(3.997501373f, 2.474750042f);
125 path->lineTo(3.747501373f, 2.724499941f);
126 path->close();
127}

◆ make_path_crbug364224_simplified()

static void make_path_crbug364224_simplified ( SkPath path)
static

Definition at line 129 of file PathTest.cpp.

129 {
130 path->moveTo(3.747501373f, 2.724499941f);
131 path->cubicTo(3.648251295f, 0.5194999576f, 3.575501442f, 0.4999999702f, 3.497501373f, 0.4999999702f);
132 path->close();
133}

◆ make_path_crbugskia2820()

static void make_path_crbugskia2820 ( SkPath path,
skiatest::Reporter reporter 
)
static

In debug mode, this path was causing an assertion to fail in SkPathStroker::preJoinTo() and, in Release, the use of an unitialized value.

Definition at line 278 of file PathTest.cpp.

278 {
279 SkPoint orig, p1, p2, p3;
280 orig = SkPoint::Make(1.f, 1.f);
281 p1 = SkPoint::Make(1.f - SK_ScalarNearlyZero, 1.f);
282 p2 = SkPoint::Make(1.f, 1.f + SK_ScalarNearlyZero);
283 p3 = SkPoint::Make(2.f, 2.f);
284
285 path->reset();
286 path->moveTo(orig);
287 path->cubicTo(p1, p2, p3);
288 path->close();
289}
#define SK_ScalarNearlyZero
Definition SkScalar.h:99
static constexpr SkPoint Make(float x, float y)

◆ nearly_equal()

static bool nearly_equal ( const SkRect a,
const SkRect b 
)
static

Definition at line 4026 of file PathTest.cpp.

4026 {
4027 return SkScalarNearlyEqual(a.fLeft, b.fLeft) &&
4028 SkScalarNearlyEqual(a.fTop, b.fTop) &&
4029 SkScalarNearlyEqual(a.fRight, b.fRight) &&
4030 SkScalarNearlyEqual(a.fBottom, b.fBottom);
4031}
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
Definition SkScalar.h:107
static bool b
struct MyStruct a[10]

◆ oval_start_index_to_angle()

static SkScalar oval_start_index_to_angle ( unsigned  start)
inlinestatic

Definition at line 3881 of file PathTest.cpp.

3881 {
3882 switch (start) {
3883 case 0:
3884 return 270.f;
3885 case 1:
3886 return 0.f;
3887 case 2:
3888 return 90.f;
3889 case 3:
3890 return 180.f;
3891 default:
3892 return -1.f;
3893 }
3894}

◆ rand_path()

static void rand_path ( SkPath path,
SkRandom rand,
SkPath::Verb  verb,
int  n 
)
static

Definition at line 5176 of file PathTest.cpp.

5176 {
5177 for (int i = 0; i < n; ++i) {
5178 switch (verb) {
5179 case SkPath::kLine_Verb:
5180 path->lineTo(rand.nextF()*100, rand.nextF()*100);
5181 break;
5182 case SkPath::kQuad_Verb:
5183 path->quadTo(rand.nextF()*100, rand.nextF()*100,
5184 rand.nextF()*100, rand.nextF()*100);
5185 break;
5187 path->conicTo(rand.nextF()*100, rand.nextF()*100,
5188 rand.nextF()*100, rand.nextF()*100, rand.nextF()*10);
5189 break;
5191 path->cubicTo(rand.nextF()*100, rand.nextF()*100,
5192 rand.nextF()*100, rand.nextF()*100,
5193 rand.nextF()*100, rand.nextF()*100);
5194 break;
5195 default:
5196 SkASSERT(false);
5197 }
5198 }
5199}
float nextF()
Definition SkRandom.h:55

◆ set_radii()

static void set_radii ( SkVector  radii[4],
int  index,
float  rad 
)
static

Definition at line 62 of file PathTest.cpp.

62 {
63 sk_bzero(radii, sizeof(SkVector) * 4);
64 radii[index].set(rad, rad);
65}
static void sk_bzero(void *buffer, size_t size)
Definition SkMalloc.h:105

◆ setFromString()

static void setFromString ( SkPath path,
const char  str[] 
)
static

Definition at line 1622 of file PathTest.cpp.

1622 {
1623 bool first = true;
1624 while (str) {
1625 SkScalar x, y;
1626 str = SkParse::FindScalar(str, &x);
1627 if (nullptr == str) {
1628 break;
1629 }
1630 str = SkParse::FindScalar(str, &y);
1631 SkASSERT(str);
1632 if (first) {
1633 path->moveTo(x, y);
1634 first = false;
1635 } else {
1636 path->lineTo(x, y);
1637 }
1638 }
1639}
static const char * FindScalar(const char str[], SkScalar *value)
Definition SkParse.cpp:216
double y

◆ stroke_cubic()

static void stroke_cubic ( const SkPoint  pts[4])
static

Definition at line 1225 of file PathTest.cpp.

1225 {
1226 SkPath path;
1227 path.moveTo(pts[0]);
1228 path.cubicTo(pts[1], pts[2], pts[3]);
1229
1230 SkPaint paint;
1231 paint.setStyle(SkPaint::kStroke_Style);
1232 paint.setStrokeWidth(SK_Scalar1 * 2);
1233
1234 SkPath fill;
1236}
SK_API bool FillPathWithPaint(const SkPath &src, const SkPaint &paint, SkPath *dst, const SkRect *cullRect, SkScalar resScale=1)

◆ stroke_tiny_cubic()

static void stroke_tiny_cubic ( )
static

Definition at line 1241 of file PathTest.cpp.

1241 {
1242 SkPoint p0[] = {
1243 { 372.0f, 92.0f },
1244 { 372.0f, 92.0f },
1245 { 372.0f, 92.0f },
1246 { 372.0f, 92.0f },
1247 };
1248
1249 stroke_cubic(p0);
1250
1251 SkPoint p1[] = {
1252 { 372.0f, 92.0f },
1253 { 372.0007f, 92.000755f },
1254 { 371.99927f, 92.003922f },
1255 { 371.99826f, 92.003899f },
1256 };
1257
1258 stroke_cubic(p1);
1259}
static void stroke_cubic(const SkPoint pts[4])

◆ survive()

template<typename ISA >
void survive ( SkPath path,
const Xforms x,
bool  isAxisAligned,
skiatest::Reporter reporter,
ISA  isa_proc 
)

Definition at line 5700 of file PathTest.cpp.

5701 {
5702 REPORTER_ASSERT(reporter, isa_proc(*path));
5703 // force the issue (computing convexity) the first time.
5704 REPORTER_ASSERT(reporter, path->isConvex());
5705
5706 SkPath path2;
5707
5708 // a path's isa and convexity should survive assignment
5709 path2 = *path;
5710 REPORTER_ASSERT(reporter, isa_proc(path2));
5712
5713 // a path's isa and convexity should identity transform
5714 path->transform(x.fIM, &path2);
5715 path->transform(x.fIM);
5716 REPORTER_ASSERT(reporter, isa_proc(path2));
5718 REPORTER_ASSERT(reporter, isa_proc(*path));
5720
5721 // a path's isa should survive translation, convexity depends on axis alignment
5722 path->transform(x.fTM, &path2);
5723 path->transform(x.fTM);
5724 REPORTER_ASSERT(reporter, isa_proc(path2));
5725 REPORTER_ASSERT(reporter, isa_proc(*path));
5728
5729 // a path's isa should survive scaling, convexity depends on axis alignment
5730 path->transform(x.fSM, &path2);
5731 path->transform(x.fSM);
5732 REPORTER_ASSERT(reporter, isa_proc(path2));
5733 REPORTER_ASSERT(reporter, isa_proc(*path));
5736
5737 // For security, post-rotation, we can't assume we're still convex. It might prove to be,
5738 // in fact, still be convex, be we can't have cached that setting, hence the call to
5739 // getConvexityOrUnknown() instead of getConvexity().
5740 path->transform(x.fRM, &path2);
5741 path->transform(x.fRM);
5744
5745 if (isAxisAligned) {
5746 REPORTER_ASSERT(reporter, !isa_proc(path2));
5747 REPORTER_ASSERT(reporter, !isa_proc(*path));
5748 }
5749}
static bool conditional_convex(const SkPath &path, bool is_convex)
static bool isAxisAligned(const SkScalerContextRec &rec)

◆ test_add_rrect()

static void test_add_rrect ( skiatest::Reporter reporter,
const SkRect bounds,
const SkVector  radii[4] 
)
static

Definition at line 67 of file PathTest.cpp.

68 {
70 rrect.setRectRadii(bounds, radii);
71 REPORTER_ASSERT(reporter, bounds == rrect.rect());
72
74 // this line should not assert in the debug build (from validate)
75 path.addRRect(rrect);
76 REPORTER_ASSERT(reporter, bounds == path.getBounds());
77}
const SkRect & rect() const
Definition SkRRect.h:264
SkRRect rrect
Definition SkRecords.h:232

◆ test_addEmptyPath()

static void test_addEmptyPath ( skiatest::Reporter reporter,
SkPath::AddPathMode  mode 
)
static

Definition at line 4191 of file PathTest.cpp.

4191 {
4192 SkPath p, q, r;
4193 // case 1: dst is empty
4194 p.moveTo(2, 1);
4195 p.lineTo(2, 3);
4196 q.addPath(p, mode);
4197 REPORTER_ASSERT(reporter, q == p);
4198 // case 2: src is empty
4199 p.addPath(r, mode);
4200 REPORTER_ASSERT(reporter, q == p);
4201 // case 3: src and dst are empty
4202 q.reset();
4203 q.addPath(r, mode);
4205}
bool isEmpty() const
Definition SkPath.cpp:406
SkPath & reset()
Definition SkPath.cpp:360

◆ test_addPath()

static void test_addPath ( skiatest::Reporter reporter)
static

Definition at line 4127 of file PathTest.cpp.

4127 {
4128 SkPath p, q;
4129 p.lineTo(1, 2);
4130 q.moveTo(4, 4);
4131 q.lineTo(7, 8);
4132 q.conicTo(8, 7, 6, 5, 0.5f);
4133 q.quadTo(6, 7, 8, 6);
4134 q.cubicTo(5, 6, 7, 8, 7, 5);
4135 q.close();
4136 p.addPath(q, -4, -4);
4137 SkRect expected = {0, 0, 4, 4};
4138 REPORTER_ASSERT(reporter, p.getBounds() == expected);
4139 p.reset();
4140 p.reverseAddPath(q);
4141 SkRect reverseExpected = {4, 4, 8, 8};
4142 REPORTER_ASSERT(reporter, p.getBounds() == reverseExpected);
4143}
SkPath & quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
Definition SkPath.cpp:736
SkPath & cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3)
Definition SkPath.cpp:789
SkPath & conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w)
Definition SkPath.cpp:756
SkPath & close()
Definition SkPath.cpp:813

◆ test_addPath_and_injected_moveTo()

static void test_addPath_and_injected_moveTo ( skiatest::Reporter reporter)
static

Definition at line 5909 of file PathTest.cpp.

5909 {
5910 /*
5911 * Given a path, and the expected last-point and last-move-to in it,
5912 * assert that, after a lineTo(), that the injected moveTo corresponds
5913 * to the expected value.
5914 */
5915 auto test_before_after_lineto = [reporter](SkPath& path,
5916 SkPoint expectedLastPt,
5917 SkPoint expectedMoveTo) {
5918 SkPoint p = path.getPoint(path.countPoints() - 1);
5919 REPORTER_ASSERT(reporter, p == expectedLastPt);
5920
5921 const SkPoint newLineTo = {1234, 5678};
5922 path.lineTo(newLineTo);
5923
5924 p = path.getPoint(path.countPoints() - 2);
5925 REPORTER_ASSERT(reporter, p == expectedMoveTo); // this was injected by lineTo()
5926
5927 p = path.getPoint(path.countPoints() - 1);
5928 REPORTER_ASSERT(reporter, p == newLineTo);
5929 };
5930
5931 SkPath path1;
5932 path1.moveTo(230, 230); // Needed to show the bug: a moveTo before the addRect
5933 path1.moveTo(20,30).lineTo(40,30).lineTo(40,50).lineTo(20,50);
5934 SkPath path1c(path1);
5935 path1c.close();
5936
5937 SkPath path2;
5938 // If path2 contains zero points, the update calculation isn't tested.
5939 path2.moveTo(144, 72);
5940 path2.lineTo(146, 72);
5941 SkPath path2c(path2);
5942 path2c.close();
5944 SkPath path3c(path2c);
5945
5946 // Test addPath, adding a path that ends with close.
5947 // The start point of the last contour added,
5948 // and the internal flag tracking whether it is closed,
5949 // must be updated correctly.
5950 path2.addPath(path1c);
5951 path2c.addPath(path1c);
5952 // At this point, path1c, path2, and path2c should end the same way.
5953 test_before_after_lineto(path1c, {20,50}, {20,30});
5954 test_before_after_lineto(path2, {20,50}, {20,30});
5955 test_before_after_lineto(path2c, {20,50}, {20,30});
5956
5957 // Test addPath, adding a path not ending in close.
5959 path3c.addPath(path1);
5960 // At this point, path1, path3, and path3c should end the same way.
5961 test_before_after_lineto(path1, {20,50}, {20,50});
5962 test_before_after_lineto(path3, {20,50}, {20,50});
5963 test_before_after_lineto(path3c, {20,50}, {20,50});
5964}
static SkPath path1()
static SkPath path3()

◆ test_addPathMode()

static void test_addPathMode ( skiatest::Reporter reporter,
bool  explicitMoveTo,
bool  extend 
)
static

Definition at line 4145 of file PathTest.cpp.

4145 {
4146 SkPath p, q;
4147 if (explicitMoveTo) {
4148 p.moveTo(1, 1);
4149 }
4150 p.lineTo(1, 2);
4151 if (explicitMoveTo) {
4152 q.moveTo(2, 1);
4153 }
4154 q.lineTo(2, 2);
4155 p.addPath(q, extend ? SkPath::kExtend_AddPathMode : SkPath::kAppend_AddPathMode);
4156 uint8_t verbs[4];
4157 int verbcount = p.getVerbs(verbs, 4);
4158 REPORTER_ASSERT(reporter, verbcount == 4);
4161 REPORTER_ASSERT(reporter, verbs[2] == (extend ? SkPath::kLine_Verb : SkPath::kMove_Verb));
4163}

◆ test_addPoly()

static void test_addPoly ( skiatest::Reporter reporter)
static

Definition at line 1056 of file PathTest.cpp.

1056 {
1057 SkPoint pts[32];
1058 SkRandom rand;
1059
1060 for (size_t i = 0; i < std::size(pts); ++i) {
1061 pts[i].fX = rand.nextSScalar1();
1062 pts[i].fY = rand.nextSScalar1();
1063 }
1064
1065 for (int doClose = 0; doClose <= 1; ++doClose) {
1066 for (size_t count = 1; count <= std::size(pts); ++count) {
1067 SkPath path;
1068 path.addPoly(pts, SkToInt(count), SkToBool(doClose));
1069 test_poly(reporter, path, pts, SkToBool(doClose));
1070 }
1071 }
1072}
static void test_poly(skiatest::Reporter *reporter, const SkPath &path, const SkPoint srcPts[], bool expectClose)
constexpr int SkToInt(S x)
Definition SkTo.h:29
SkScalar nextSScalar1()
Definition SkRandom.h:113

◆ test_addrect()

static void test_addrect ( skiatest::Reporter reporter)
static

Definition at line 659 of file PathTest.cpp.

659 {
660 SkPath path;
661 path.lineTo(0, 0);
662 path.addRect(SkRect::MakeWH(50, 100));
663 REPORTER_ASSERT(reporter, path.isRect(nullptr));
664
665 path.reset();
666 path.lineTo(FLT_EPSILON, FLT_EPSILON);
667 path.addRect(SkRect::MakeWH(50, 100));
668 REPORTER_ASSERT(reporter, !path.isRect(nullptr));
669
670 path.reset();
671 path.quadTo(0, 0, 0, 0);
672 path.addRect(SkRect::MakeWH(50, 100));
673 REPORTER_ASSERT(reporter, !path.isRect(nullptr));
674
675 path.reset();
676 path.conicTo(0, 0, 0, 0, 0.5f);
677 path.addRect(SkRect::MakeWH(50, 100));
678 REPORTER_ASSERT(reporter, !path.isRect(nullptr));
679
680 path.reset();
681 path.cubicTo(0, 0, 0, 0, 0, 0);
682 path.addRect(SkRect::MakeWH(50, 100));
683 REPORTER_ASSERT(reporter, !path.isRect(nullptr));
684}
static constexpr SkRect MakeWH(float w, float h)
Definition SkRect.h:609

◆ test_addRect_and_trailing_lineTo()

static void test_addRect_and_trailing_lineTo ( skiatest::Reporter reporter)
static

Definition at line 5847 of file PathTest.cpp.

5847 {
5848 SkPath path;
5849 const SkRect r = {1, 2, 3, 4};
5850 // build our default p-array clockwise
5851 const SkPoint p[] = {
5852 {r.fLeft, r.fTop}, {r.fRight, r.fTop},
5853 {r.fRight, r.fBottom}, {r.fLeft, r.fBottom},
5854 };
5855
5856 for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
5857 int increment = dir == SkPathDirection::kCW ? 1 : 3;
5858 for (int i = 0; i < 4; ++i) {
5859 path.reset();
5860 path.addRect(r, dir, i);
5861
5862 // check that we return the 4 ponts in the expected order
5863 SkPoint e[4];
5864 for (int j = 0; j < 4; ++j) {
5865 int index = (i + j*increment) % 4;
5866 e[j] = p[index];
5867 }
5868 assert_points(reporter, path, {
5869 e[0], e[1], e[2], e[3]
5870 });
5871
5872 // check that the new line begins where the rect began
5873 path.lineTo(7,8);
5874 assert_points(reporter, path, {
5875 e[0], e[1], e[2], e[3],
5876 e[0], {7,8},
5877 });
5878 }
5879 }
5880
5881 // now add a moveTo before the rect, just to be sure we don't always look at
5882 // the "first" point in the path when we handle the trailing lineTo
5883 path.reset();
5884 path.moveTo(7, 8);
5885 path.addRect(r, SkPathDirection::kCW, 2);
5886 path.lineTo(5, 6);
5887
5888 assert_points(reporter, path, {
5889 {7,8}, // initial moveTo
5890 p[2], p[3], p[0], p[1], // rect
5891 p[2], {5, 6}, // trailing line
5892 });
5893}
static void assert_points(skiatest::Reporter *reporter, const SkPath &path, const std::initializer_list< SkPoint > &list)

◆ test_addrect_isfinite()

static void test_addrect_isfinite ( skiatest::Reporter reporter)
static

Definition at line 687 of file PathTest.cpp.

687 {
688 SkPath path;
689
690 path.addRect(SkRect::MakeWH(50, 100));
691 REPORTER_ASSERT(reporter, path.isFinite());
692
693 path.moveTo(0, 0);
694 path.lineTo(SK_ScalarInfinity, 42);
695 REPORTER_ASSERT(reporter, !path.isFinite());
696
697 path.addRect(SkRect::MakeWH(50, 100));
698 REPORTER_ASSERT(reporter, !path.isFinite());
699
700 path.reset();
701 REPORTER_ASSERT(reporter, path.isFinite());
702
703 path.addRect(SkRect::MakeWH(50, 100));
704 REPORTER_ASSERT(reporter, path.isFinite());
705}

◆ test_arb_round_rect_is_convex()

static void test_arb_round_rect_is_convex ( skiatest::Reporter reporter)
static

Definition at line 880 of file PathTest.cpp.

880 {
881 SkRandom rand;
882 SkRect r;
883
884 for (int i = 0; i < 5000; ++i) {
885
886 SkScalar size = rand.nextUScalar1() * 30;
887 if (size < SK_Scalar1) {
888 continue;
889 }
890 r.fLeft = rand.nextUScalar1() * 300;
891 r.fTop = rand.nextUScalar1() * 300;
892 r.fRight = r.fLeft + 2 * size;
893 r.fBottom = r.fTop + 2 * size;
894
895 SkPath temp;
896
897 make_arb_round_rect(&temp, r, r.width() / 10, r.height() / 15);
898
900 }
901}
static void make_arb_round_rect(SkPath *path, const SkRect &r, SkScalar xCorner, SkScalar yCorner)
Definition PathTest.cpp:866
SkScalar nextUScalar1()
Definition SkRandom.h:101
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition switches.h:259
constexpr float height() const
Definition SkRect.h:769
constexpr float width() const
Definition SkRect.h:762

◆ test_arb_zero_rad_round_rect_is_rect()

static void test_arb_zero_rad_round_rect_is_rect ( skiatest::Reporter reporter)
static

Definition at line 907 of file PathTest.cpp.

907 {
908 SkRandom rand;
909 SkRect r;
910
911 for (int i = 0; i < 5000; ++i) {
912
913 SkScalar size = rand.nextUScalar1() * 30;
914 if (size < SK_Scalar1) {
915 continue;
916 }
917 r.fLeft = rand.nextUScalar1() * 300;
918 r.fTop = rand.nextUScalar1() * 300;
919 r.fRight = r.fLeft + 2 * size;
920 r.fBottom = r.fTop + 2 * size;
921
922 SkPath temp;
923
924 make_arb_round_rect(&temp, r, 0, 0);
925
929 }
930}
bool isRect(SkRect *rect, bool *isClosed=nullptr, SkPathDirection *direction=nullptr) const
Definition SkPath.cpp:506
GAsyncResult * result

◆ test_arc()

static void test_arc ( skiatest::Reporter reporter)
static

Definition at line 3850 of file PathTest.cpp.

3850 {
3851 SkPath p;
3852 SkRect emptyOval = {10, 20, 30, 20};
3853 REPORTER_ASSERT(reporter, emptyOval.isEmpty());
3854 p.addArc(emptyOval, 1, 2);
3855 REPORTER_ASSERT(reporter, p.isEmpty());
3856 p.reset();
3857 SkRect oval = {10, 20, 30, 40};
3858 p.addArc(oval, 1, 0);
3859 REPORTER_ASSERT(reporter, p.isEmpty());
3860 p.reset();
3861 SkPath cwOval;
3862 cwOval.addOval(oval);
3863 p.addArc(oval, 0, 360);
3864 REPORTER_ASSERT(reporter, p == cwOval);
3865 p.reset();
3866 SkPath ccwOval;
3867 ccwOval.addOval(oval, SkPathDirection::kCCW);
3868 p.addArc(oval, 0, -360);
3869 REPORTER_ASSERT(reporter, p == ccwOval);
3870 p.reset();
3871 p.addArc(oval, 1, 180);
3872 // diagonal colinear points make arc convex
3873 // TODO: one way to keep it concave would be to introduce interpolated on curve points
3874 // between control points and computing the on curve point at scan conversion time
3875 REPORTER_ASSERT(reporter, p.isConvex());
3878 REPORTER_ASSERT(reporter, p.isConvex());
3879}
SkRect oval
Definition SkRecords.h:249
bool isEmpty() const
Definition SkRect.h:693

◆ test_arc_ovals()

static void test_arc_ovals ( skiatest::Reporter reporter)
static

Definition at line 3920 of file PathTest.cpp.

3920 {
3921 SkRect oval = SkRect::MakeWH(10, 20);
3922 for (SkScalar sweep : {-720.f, -540.f, -360.f, 360.f, 432.f, 720.f}) {
3923 for (SkScalar start = -360.f; start <= 360.f; start += 1.f) {
3924 SkPath path;
3925 path.addArc(oval, start, sweep);
3926 // SkPath's interfaces for inserting and extracting ovals only allow contours
3927 // to start at multiples of 90 degrees.
3928 if (std::fmod(start, 90.f) == 0) {
3929 check_oval_arc(reporter, start, sweep, path);
3930 } else {
3931 REPORTER_ASSERT(reporter, !path.isOval(nullptr));
3932 }
3933 }
3934 // Test start angles that are nearly at valid oval start angles.
3935 for (float start : {-180.f, -90.f, 90.f, 180.f}) {
3936 for (float delta : {-SK_ScalarNearlyZero, SK_ScalarNearlyZero}) {
3937 SkPath path;
3938 path.addArc(oval, start + delta, sweep);
3939 check_oval_arc(reporter, start, sweep, path);
3940 }
3941 }
3942 }
3943}
static void check_oval_arc(skiatest::Reporter *reporter, SkScalar start, SkScalar sweep, const SkPath &path)

◆ test_arcTo()

static void test_arcTo ( skiatest::Reporter reporter)
static

Definition at line 4061 of file PathTest.cpp.

4061 {
4062 SkPath p;
4063 p.arcTo(0, 0, 1, 2, 1);
4065 p.arcTo(1, 2, 1, 2, 1);
4067 p.arcTo(1, 2, 3, 4, 0);
4069 p.arcTo(1, 2, 0, 0, 1);
4071 p.arcTo(1, 0, 1, 1, 1);
4072 SkPoint pt;
4073 REPORTER_ASSERT(reporter, p.getLastPt(&pt) && pt.fX == 1 && pt.fY == 1);
4074 p.reset();
4075 p.arcTo(1, 0, 1, -1, 1);
4076 REPORTER_ASSERT(reporter, p.getLastPt(&pt) && pt.fX == 1 && pt.fY == -1);
4077 p.reset();
4078 SkRect oval = {1, 2, 3, 4};
4079 p.arcTo(oval, 0, 0, true);
4081 p.arcTo(oval, 0, 0, false);
4083 p.arcTo(oval, 360, 0, true);
4085 p.arcTo(oval, 360, 0, false);
4087
4088 for (float sweep = 359, delta = 0.5f; sweep != (float) (sweep + delta); ) {
4089 p.arcTo(oval, 0, sweep, false);
4090 REPORTER_ASSERT(reporter, nearly_equal(p.getBounds(), oval));
4091 sweep += delta;
4092 delta /= 2;
4093 }
4094 for (float sweep = 361, delta = 0.5f; sweep != (float) (sweep - delta);) {
4095 p.arcTo(oval, 0, sweep, false);
4096 REPORTER_ASSERT(reporter, nearly_equal(p.getBounds(), oval));
4097 sweep -= delta;
4098 delta /= 2;
4099 }
4100 SkRect noOvalWidth = {1, 2, 0, 3};
4101 p.reset();
4102 p.arcTo(noOvalWidth, 0, 360, false);
4103 REPORTER_ASSERT(reporter, p.isEmpty());
4104
4105 SkRect noOvalHeight = {1, 2, 3, 1};
4106 p.reset();
4107 p.arcTo(noOvalHeight, 0, 360, false);
4108 REPORTER_ASSERT(reporter, p.isEmpty());
4109
4110 // Inspired by http://code.google.com/p/chromium/issues/detail?id=1001768
4111 {
4112 p.reset();
4113 p.moveTo(216, 216);
4114 p.arcTo(216, 108, 0, SkPath::ArcSize::kLarge_ArcSize, SkPathDirection::kCW, 216, 0);
4115 p.arcTo(270, 135, 0, SkPath::ArcSize::kLarge_ArcSize, SkPathDirection::kCCW, 216, 216);
4116
4117 // The 'arcTo' call should end up exactly at the starting location.
4118 int n = p.countPoints();
4119 REPORTER_ASSERT(reporter, p.getPoint(0) == p.getPoint(n - 1));
4120 }
4121
4122 // This test, if improperly handled, can create an infinite loop in angles_to_unit_vectors
4123 p.reset();
4124 p.arcTo(SkRect::MakeXYWH(0, 0, 10, 10), -2.61488527e+33f, 359.992157f, false);
4125}
static void check_path_is_move_and_reset(skiatest::Reporter *reporter, SkPath *p, SkScalar x0, SkScalar y0)
static void check_path_is_line_and_reset(skiatest::Reporter *reporter, SkPath *p, SkScalar x1, SkScalar y1)
@ kLarge_ArcSize
larger of arc pair
Definition SkPath.h:925
constexpr float centerY() const
Definition SkRect.h:785

◆ test_bad_cubic_crbug229478()

static void test_bad_cubic_crbug229478 ( )
static

Definition at line 467 of file PathTest.cpp.

467 {
468 const SkPoint pts[] = {
469 { 4595.91064f, -11596.9873f },
470 { 4597.2168f, -11595.9414f },
471 { 4598.52344f, -11594.8955f },
472 { 4599.83008f, -11593.8496f },
473 };
474
475 SkPath path;
476 path.moveTo(pts[0]);
477 path.cubicTo(pts[1], pts[2], pts[3]);
478
481 paint.setStrokeWidth(20);
482
483 SkPath dst;
484 // Before the fix, this would infinite-recurse, and run out of stack
485 // because we would keep trying to subdivide a degenerate cubic segment.
486 skpathutils::FillPathWithPaint(path, paint, &dst, nullptr);
487}
dst
Definition cp.py:12

◆ test_bad_cubic_crbug234190()

static void test_bad_cubic_crbug234190 ( )
static

Definition at line 458 of file PathTest.cpp.

458 {
459 SkPath path;
460 path.moveTo(13.8509f, 3.16858f);
461 path.cubicTo(-2.35893e+08f, -4.21044e+08f,
462 -2.38991e+08f, -4.26573e+08f,
463 -2.41016e+08f, -4.30188e+08f);
464 test_draw_AA_path(84, 88, path);
465}
static void test_draw_AA_path(int width, int height, const SkPath &path)
Definition PathTest.cpp:180

◆ test_bounds()

static void test_bounds ( skiatest::Reporter reporter)
static

Definition at line 1208 of file PathTest.cpp.

1208 {
1209 static const SkRect rects[] = {
1210 { SkIntToScalar(10), SkIntToScalar(160), SkIntToScalar(610), SkIntToScalar(160) },
1211 { SkIntToScalar(610), SkIntToScalar(160), SkIntToScalar(610), SkIntToScalar(199) },
1212 { SkIntToScalar(10), SkIntToScalar(198), SkIntToScalar(610), SkIntToScalar(199) },
1213 { SkIntToScalar(10), SkIntToScalar(160), SkIntToScalar(10), SkIntToScalar(199) },
1214 };
1215
1216 SkPath path0, path1;
1217 for (size_t i = 0; i < std::size(rects); ++i) {
1218 path0.addRect(rects[i]);
1219 add_rect(&path1, rects[i]);
1220 }
1221
1223}
static void add_rect(SkPath *path, const SkRect &r)

◆ test_bounds_crbug_513799()

static void test_bounds_crbug_513799 ( skiatest::Reporter reporter)
static

Definition at line 754 of file PathTest.cpp.

754 {
755 SkPath path;
756#if 0
757 // As written these tests were failing on LLVM 4.2 MacMini Release mysteriously, so we've
758 // rewritten them to avoid this (compiler-bug?).
759 REPORTER_ASSERT(reporter, SkRect::MakeLTRB(0, 0, 0, 0) == path.getBounds());
760
761 path.moveTo(-5, -8);
762 REPORTER_ASSERT(reporter, SkRect::MakeLTRB(-5, -8, -5, -8) == path.getBounds());
763
764 path.addRect(SkRect::MakeLTRB(1, 2, 3, 4));
765 REPORTER_ASSERT(reporter, SkRect::MakeLTRB(-5, -8, 3, 4) == path.getBounds());
766
767 path.moveTo(1, 2);
768 REPORTER_ASSERT(reporter, SkRect::MakeLTRB(-5, -8, 3, 4) == path.getBounds());
769#else
770 dump_if_ne(reporter, SkRect::MakeLTRB(0, 0, 0, 0), path.getBounds());
771
772 path.moveTo(-5, -8); // should set the bounds
773 dump_if_ne(reporter, SkRect::MakeLTRB(-5, -8, -5, -8), path.getBounds());
774
775 path.addRect(SkRect::MakeLTRB(1, 2, 3, 4)); // should extend the bounds
776 dump_if_ne(reporter, SkRect::MakeLTRB(-5, -8, 3, 4), path.getBounds());
777
778 path.moveTo(1, 2); // don't expect this to have changed the bounds
779 dump_if_ne(reporter, SkRect::MakeLTRB(-5, -8, 3, 4), path.getBounds());
780#endif
781}
static void dump_if_ne(skiatest::Reporter *reporter, const SkRect &expected, const SkRect &bounds)
Definition PathTest.cpp:746

◆ test_circle()

static void test_circle ( skiatest::Reporter reporter)
static

Definition at line 3657 of file PathTest.cpp.

3657 {
3660
3661 // multiple addCircle()
3662 SkPath path;
3663 path.addCircle(0, 0, SkIntToScalar(10), SkPathDirection::kCW);
3664 path.addCircle(0, 0, SkIntToScalar(20), SkPathDirection::kCW);
3666
3667 // some extra lineTo() would make isOval() fail
3668 path.reset();
3669 path.addCircle(0, 0, SkIntToScalar(10), SkPathDirection::kCW);
3670 path.lineTo(0, 0);
3672
3673 // not back to the original point
3674 path.reset();
3675 path.addCircle(0, 0, SkIntToScalar(10), SkPathDirection::kCW);
3676 path.setLastPt(SkIntToScalar(5), SkIntToScalar(5));
3678
3680
3681 // test negative radius
3682 path.reset();
3683 path.addCircle(0, 0, -1, SkPathDirection::kCW);
3684 REPORTER_ASSERT(reporter, path.isEmpty());
3685}
static void test_circle_with_add_paths(skiatest::Reporter *reporter)
static void check_for_circle(skiatest::Reporter *reporter, const SkPath &path, bool expectedCircle, SkPathFirstDirection expectedDir)
static void test_circle_with_direction(skiatest::Reporter *reporter, SkPathDirection inDir)

◆ test_circle_mirror_x()

static void test_circle_mirror_x ( skiatest::Reporter reporter,
const SkPath path,
SkPathFirstDirection  dir 
)
static

Definition at line 3530 of file PathTest.cpp.

3532 {
3533 SkPath tmp;
3534 SkMatrix m;
3535 m.reset();
3536 m.setScaleX(-SK_Scalar1);
3537 path.transform(m, &tmp);
3538 if (SkPathFirstDirection::kCW == dir) {
3540 } else {
3543 }
3544 check_for_circle(reporter, tmp, true, dir);
3545}

◆ test_circle_mirror_xy()

static void test_circle_mirror_xy ( skiatest::Reporter reporter,
const SkPath path,
SkPathFirstDirection  dir 
)
static

Definition at line 3566 of file PathTest.cpp.

3568 {
3569 SkPath tmp;
3570 SkMatrix m;
3571 m.reset();
3572 m.setScaleX(-SK_Scalar1);
3573 m.setScaleY(-SK_Scalar1);
3574 path.transform(m, &tmp);
3575
3576 check_for_circle(reporter, tmp, true, dir);
3577}

◆ test_circle_mirror_y()

static void test_circle_mirror_y ( skiatest::Reporter reporter,
const SkPath path,
SkPathFirstDirection  dir 
)
static

Definition at line 3547 of file PathTest.cpp.

3549 {
3550 SkPath tmp;
3551 SkMatrix m;
3552 m.reset();
3553 m.setScaleY(-SK_Scalar1);
3554 path.transform(m, &tmp);
3555
3556 if (SkPathFirstDirection::kCW == dir) {
3558 } else {
3561 }
3562
3563 check_for_circle(reporter, tmp, true, dir);
3564}

◆ test_circle_rotate()

static void test_circle_rotate ( skiatest::Reporter reporter,
const SkPath path,
SkPathFirstDirection  dir 
)
static

Definition at line 3510 of file PathTest.cpp.

3512 {
3513 for (int angle = 0; angle < 360; ++angle) {
3514 SkPath tmp;
3515 SkMatrix m;
3516 m.setRotate(SkIntToScalar(angle));
3517 path.transform(m, &tmp);
3518
3519 // TODO: a rotated circle whose rotated angle is not a multiple of 90
3520 // degrees is not an oval anymore, this can be improved. we made this
3521 // for the simplicity of our implementation.
3522 if (angle % 90 == 0) {
3523 check_for_circle(reporter, tmp, true, dir);
3524 } else {
3525 check_for_circle(reporter, tmp, false, dir);
3526 }
3527 }
3528}

◆ test_circle_skew()

static void test_circle_skew ( skiatest::Reporter reporter,
const SkPath path,
SkPathFirstDirection  dir 
)
static

Definition at line 3472 of file PathTest.cpp.

3474 {
3475 SkPath tmp;
3476
3477 SkMatrix m;
3478 m.setSkew(SkIntToScalar(3), SkIntToScalar(5));
3479 path.transform(m, &tmp);
3480 // this matrix reverses the direction.
3481 if (SkPathFirstDirection::kCCW == dir) {
3483 } else {
3486 }
3487 check_for_circle(reporter, tmp, false, dir);
3488}

◆ test_circle_translate()

static void test_circle_translate ( skiatest::Reporter reporter,
const SkPath path,
SkPathFirstDirection  dir 
)
static

Definition at line 3490 of file PathTest.cpp.

3492 {
3493 SkPath tmp;
3494
3495 // translate at small offset
3496 SkMatrix m;
3497 m.setTranslate(SkIntToScalar(15), SkIntToScalar(15));
3498 path.transform(m, &tmp);
3499 check_for_circle(reporter, tmp, true, dir);
3500
3501 tmp.reset();
3502 m.reset();
3503
3504 // translate at a relatively big offset
3505 m.setTranslate(SkIntToScalar(1000), SkIntToScalar(1000));
3506 path.transform(m, &tmp);
3507 check_for_circle(reporter, tmp, true, dir);
3508}

◆ test_circle_with_add_paths()

static void test_circle_with_add_paths ( skiatest::Reporter reporter)
static

Definition at line 3621 of file PathTest.cpp.

3621 {
3622 SkPath path;
3623 SkPath circle;
3624 SkPath rect;
3625 SkPath empty;
3626
3627 const SkPathDirection kCircleDir = SkPathDirection::kCW;
3628 const SkPathDirection kCircleDirOpposite = SkPathDirection::kCCW;
3629
3630 circle.addCircle(0, 0, SkIntToScalar(10), kCircleDir);
3631 rect.addRect(SkIntToScalar(5), SkIntToScalar(5),
3633
3634 SkMatrix translate;
3635 translate.setTranslate(SkIntToScalar(12), SkIntToScalar(12));
3636
3637 // Although all the path concatenation related operations leave
3638 // the path a circle, most mark it as a non-circle for simplicity
3639
3640 // empty + circle (translate)
3641 path = empty;
3642 path.addPath(circle, translate);
3643 check_for_circle(reporter, path, false, SkPathPriv::AsFirstDirection(kCircleDir));
3644
3645 // circle + empty (translate)
3646 path = circle;
3647 path.addPath(empty, translate);
3648
3649 check_for_circle(reporter, path, true, SkPathPriv::AsFirstDirection(kCircleDir));
3650
3651 // test reverseAddPath
3652 path = circle;
3653 path.reverseAddPath(rect);
3654 check_for_circle(reporter, path, false, SkPathPriv::AsFirstDirection(kCircleDirOpposite));
3655}
SkMatrix & setTranslate(SkScalar dx, SkScalar dy)
Definition SkMatrix.cpp:254
SkPath & addCircle(SkScalar x, SkScalar y, SkScalar radius, SkPathDirection dir=SkPathDirection::kCW)
Definition SkPath.cpp:1149

◆ test_circle_with_direction()

static void test_circle_with_direction ( skiatest::Reporter reporter,
SkPathDirection  inDir 
)
static

Definition at line 3579 of file PathTest.cpp.

3580 {
3582 SkPath path;
3583
3584 // circle at origin
3585 path.addCircle(0, 0, SkIntToScalar(20), inDir);
3586
3587 check_for_circle(reporter, path, true, dir);
3588 test_circle_rotate(reporter, path, dir);
3589 test_circle_translate(reporter, path, dir);
3590 test_circle_skew(reporter, path, dir);
3591 test_circle_mirror_x(reporter, path, dir);
3592 test_circle_mirror_y(reporter, path, dir);
3593 test_circle_mirror_xy(reporter, path, dir);
3594
3595 // circle at an offset at (10, 10)
3596 path.reset();
3597 path.addCircle(SkIntToScalar(10), SkIntToScalar(10),
3598 SkIntToScalar(20), inDir);
3599
3600 check_for_circle(reporter, path, true, dir);
3601 test_circle_rotate(reporter, path, dir);
3602 test_circle_translate(reporter, path, dir);
3603 test_circle_skew(reporter, path, dir);
3604 test_circle_mirror_x(reporter, path, dir);
3605 test_circle_mirror_y(reporter, path, dir);
3606 test_circle_mirror_xy(reporter, path, dir);
3607
3608 // Try different starting points for the contour.
3609 for (unsigned start = 0; start < 4; ++start) {
3610 path.reset();
3611 path.addOval(SkRect::MakeXYWH(20, 10, 5, 5), inDir, start);
3612 test_circle_rotate(reporter, path, dir);
3613 test_circle_translate(reporter, path, dir);
3614 test_circle_skew(reporter, path, dir);
3615 test_circle_mirror_x(reporter, path, dir);
3616 test_circle_mirror_y(reporter, path, dir);
3617 test_circle_mirror_xy(reporter, path, dir);
3618 }
3619}
static void test_circle_translate(skiatest::Reporter *reporter, const SkPath &path, SkPathFirstDirection dir)
static void test_circle_rotate(skiatest::Reporter *reporter, const SkPath &path, SkPathFirstDirection dir)
static void test_circle_mirror_x(skiatest::Reporter *reporter, const SkPath &path, SkPathFirstDirection dir)
static void test_circle_mirror_xy(skiatest::Reporter *reporter, const SkPath &path, SkPathFirstDirection dir)
static void test_circle_mirror_y(skiatest::Reporter *reporter, const SkPath &path, SkPathFirstDirection dir)
static void test_circle_skew(skiatest::Reporter *reporter, const SkPath &path, SkPathFirstDirection dir)

◆ test_clipped_cubic()

static void test_clipped_cubic ( )
static

Definition at line 728 of file PathTest.cpp.

728 {
730
731 // This path used to assert, because our cubic-chopping code incorrectly
732 // moved control points after the chop. This test should be run in SK_DEBUG
733 // mode to ensure that we no long assert.
734 SkPath path;
735 for (int doReducedCase = 0; doReducedCase <= 1; ++doReducedCase) {
736 build_big_path(&path, SkToBool(doReducedCase));
737
739 for (int doAA = 0; doAA <= 1; ++doAA) {
740 paint.setAntiAlias(SkToBool(doAA));
741 surface->getCanvas()->drawPath(path, paint);
742 }
743 }
744}
static void build_big_path(SkPath *path, bool reducedCase)
Definition PathTest.cpp:707

◆ test_close()

static void test_close ( skiatest::Reporter reporter)
static

Definition at line 1290 of file PathTest.cpp.

1290 {
1291 SkPath closePt;
1292 closePt.moveTo(0, 0);
1293 closePt.close();
1294 check_close(reporter, closePt);
1295
1296 SkPath openPt;
1297 openPt.moveTo(0, 0);
1298 check_close(reporter, openPt);
1299
1300 SkPath empty;
1302 empty.close();
1304
1305 SkPath rect;
1306 rect.addRect(SK_Scalar1, SK_Scalar1, 10 * SK_Scalar1, 10*SK_Scalar1);
1307 check_close(reporter, rect);
1308 rect.close();
1309 check_close(reporter, rect);
1310
1311 SkPath quad;
1313 check_close(reporter, quad);
1314 quad.close();
1315 check_close(reporter, quad);
1316
1317 SkPath cubic;
1319 10*SK_Scalar1, 20 * SK_Scalar1, 20*SK_Scalar1);
1320 check_close(reporter, cubic);
1321 cubic.close();
1322 check_close(reporter, cubic);
1323
1324 SkPath line;
1325 line.moveTo(SK_Scalar1, SK_Scalar1);
1326 line.lineTo(10 * SK_Scalar1, 10*SK_Scalar1);
1327 check_close(reporter, line);
1328 line.close();
1329 check_close(reporter, line);
1330
1331 SkPath rect2;
1333 rect2.close();
1335 check_close(reporter, rect2);
1336 rect2.close();
1337 check_close(reporter, rect2);
1338
1339 SkPath oval3;
1341 oval3.close();
1343 check_close(reporter, oval3);
1344 oval3.close();
1345 check_close(reporter, oval3);
1346
1347 SkPath moves;
1349 moves.moveTo(5 * SK_Scalar1, SK_Scalar1);
1350 moves.moveTo(SK_Scalar1, 10 * SK_Scalar1);
1351 moves.moveTo(10 *SK_Scalar1, SK_Scalar1);
1352 check_close(reporter, moves);
1353
1355}
static void stroke_tiny_cubic()
static void check_close(skiatest::Reporter *reporter, const SkPath &path)
AI float cubic(float precision, const SkPoint pts[], const VectorXform &vectorXform=VectorXform())

◆ test_conicTo_special_case()

static void test_conicTo_special_case ( skiatest::Reporter reporter)
static

Definition at line 4207 of file PathTest.cpp.

4207 {
4208 SkPath p;
4209 p.conicTo(1, 2, 3, 4, -1);
4211 p.conicTo(1, 2, 3, 4, SK_ScalarInfinity);
4213 p.conicTo(1, 2, 3, 4, 1);
4214 check_path_is_quad_and_reset(reporter, &p, 1, 2, 3, 4);
4215}
static void check_path_is_line_pair_and_reset(skiatest::Reporter *reporter, SkPath *p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
static void check_path_is_quad_and_reset(skiatest::Reporter *reporter, SkPath *p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)

◆ test_conservativelyContains()

static void test_conservativelyContains ( skiatest::Reporter reporter)
static

Definition at line 1872 of file PathTest.cpp.

1872 {
1873 SkPath path;
1874
1875 // kBaseRect is used to construct most our test paths: a rect, a circle, and a round-rect.
1876 static const SkRect kBaseRect = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(100));
1877
1878 // A circle that bounds kBaseRect (with a significant amount of slop)
1879 SkScalar circleR = std::max(kBaseRect.width(), kBaseRect.height());
1880 circleR *= 1.75f / 2;
1881 static const SkPoint kCircleC = {kBaseRect.centerX(), kBaseRect.centerY()};
1882
1883 // round-rect radii
1884 static const SkScalar kRRRadii[] = {SkIntToScalar(5), SkIntToScalar(3)};
1885
1886 static const struct SUPPRESS_VISIBILITY_WARNING {
1887 SkRect fQueryRect;
1888 bool fInRect;
1889 bool fInCircle;
1890 bool fInRR;
1891 bool fInCubicRR;
1892 } kQueries[] = {
1893 {kBaseRect, true, true, false, false},
1894
1895 // rect well inside of kBaseRect
1896 {SkRect::MakeLTRB(kBaseRect.fLeft + 0.25f*kBaseRect.width(),
1897 kBaseRect.fTop + 0.25f*kBaseRect.height(),
1898 kBaseRect.fRight - 0.25f*kBaseRect.width(),
1899 kBaseRect.fBottom - 0.25f*kBaseRect.height()),
1900 true, true, true, true},
1901
1902 // rects with edges off by one from kBaseRect's edges
1903 {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fTop,
1904 kBaseRect.width(), kBaseRect.height() + 1),
1905 false, true, false, false},
1906 {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fTop,
1907 kBaseRect.width() + 1, kBaseRect.height()),
1908 false, true, false, false},
1909 {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fTop,
1910 kBaseRect.width() + 1, kBaseRect.height() + 1),
1911 false, true, false, false},
1912 {SkRect::MakeXYWH(kBaseRect.fLeft - 1, kBaseRect.fTop,
1913 kBaseRect.width(), kBaseRect.height()),
1914 false, true, false, false},
1915 {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fTop - 1,
1916 kBaseRect.width(), kBaseRect.height()),
1917 false, true, false, false},
1918 {SkRect::MakeXYWH(kBaseRect.fLeft - 1, kBaseRect.fTop,
1919 kBaseRect.width() + 2, kBaseRect.height()),
1920 false, true, false, false},
1921 {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fTop - 1,
1922 kBaseRect.width() + 2, kBaseRect.height()),
1923 false, true, false, false},
1924
1925 // zero-w/h rects at each corner of kBaseRect
1926 {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fTop, 0, 0), true, true, false, false},
1927 {SkRect::MakeXYWH(kBaseRect.fRight, kBaseRect.fTop, 0, 0), true, true, false, true},
1928 {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fBottom, 0, 0), true, true, false, true},
1929 {SkRect::MakeXYWH(kBaseRect.fRight, kBaseRect.fBottom, 0, 0), true, true, false, true},
1930
1931 // far away rect
1932 {SkRect::MakeXYWH(10 * kBaseRect.fRight, 10 * kBaseRect.fBottom,
1933 SkIntToScalar(10), SkIntToScalar(10)),
1934 false, false, false, false},
1935
1936 // very large rect containing kBaseRect
1937 {SkRect::MakeXYWH(kBaseRect.fLeft - 5 * kBaseRect.width(),
1938 kBaseRect.fTop - 5 * kBaseRect.height(),
1939 11 * kBaseRect.width(), 11 * kBaseRect.height()),
1940 false, false, false, false},
1941
1942 // skinny rect that spans same y-range as kBaseRect
1943 {SkRect::MakeXYWH(kBaseRect.centerX(), kBaseRect.fTop,
1944 SkIntToScalar(1), kBaseRect.height()),
1945 true, true, true, true},
1946
1947 // short rect that spans same x-range as kBaseRect
1948 {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.centerY(), kBaseRect.width(), SkScalar(1)),
1949 true, true, true, true},
1950
1951 // skinny rect that spans slightly larger y-range than kBaseRect
1952 {SkRect::MakeXYWH(kBaseRect.centerX(), kBaseRect.fTop,
1953 SkIntToScalar(1), kBaseRect.height() + 1),
1954 false, true, false, false},
1955
1956 // short rect that spans slightly larger x-range than kBaseRect
1957 {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.centerY(),
1958 kBaseRect.width() + 1, SkScalar(1)),
1959 false, true, false, false},
1960 };
1961
1962 for (int inv = 0; inv < 4; ++inv) {
1963 for (size_t q = 0; q < std::size(kQueries); ++q) {
1964 SkRect qRect = kQueries[q].fQueryRect;
1965 if (inv & 0x1) {
1966 using std::swap;
1967 swap(qRect.fLeft, qRect.fRight);
1968 }
1969 if (inv & 0x2) {
1970 using std::swap;
1971 swap(qRect.fTop, qRect.fBottom);
1972 }
1973 for (int d = 0; d < 2; ++d) {
1975 path.reset();
1976 path.addRect(kBaseRect, dir);
1977 REPORTER_ASSERT(reporter, kQueries[q].fInRect ==
1978 path.conservativelyContainsRect(qRect));
1979
1980 path.reset();
1981 path.addCircle(kCircleC.fX, kCircleC.fY, circleR, dir);
1982 REPORTER_ASSERT(reporter, kQueries[q].fInCircle ==
1983 path.conservativelyContainsRect(qRect));
1984
1985 path.reset();
1986 path.addRoundRect(kBaseRect, kRRRadii[0], kRRRadii[1], dir);
1987 REPORTER_ASSERT(reporter, kQueries[q].fInRR ==
1988 path.conservativelyContainsRect(qRect));
1989
1990 path.reset();
1991 path.moveTo(kBaseRect.fLeft + kRRRadii[0], kBaseRect.fTop);
1992 path.cubicTo(kBaseRect.fLeft + kRRRadii[0] / 2, kBaseRect.fTop,
1993 kBaseRect.fLeft, kBaseRect.fTop + kRRRadii[1] / 2,
1994 kBaseRect.fLeft, kBaseRect.fTop + kRRRadii[1]);
1995 path.lineTo(kBaseRect.fLeft, kBaseRect.fBottom);
1996 path.lineTo(kBaseRect.fRight, kBaseRect.fBottom);
1997 path.lineTo(kBaseRect.fRight, kBaseRect.fTop);
1998 path.close();
1999 REPORTER_ASSERT(reporter, kQueries[q].fInCubicRR ==
2000 path.conservativelyContainsRect(qRect));
2001
2002 }
2003 // Slightly non-convex shape, shouldn't contain any rects.
2004 path.reset();
2005 path.moveTo(0, 0);
2006 path.lineTo(SkIntToScalar(50), 0.05f);
2007 path.lineTo(SkIntToScalar(100), 0);
2008 path.lineTo(SkIntToScalar(100), SkIntToScalar(100));
2009 path.lineTo(0, SkIntToScalar(100));
2010 path.close();
2011 REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(qRect));
2012 }
2013 }
2014
2015 // make sure a minimal convex shape works, a right tri with edges along pos x and y axes.
2016 path.reset();
2017 path.moveTo(0, 0);
2018 path.lineTo(SkIntToScalar(100), 0);
2019 path.lineTo(0, SkIntToScalar(100));
2020
2021 // inside, on along top edge
2022 REPORTER_ASSERT(reporter, path.conservativelyContainsRect(SkRect::MakeXYWH(SkIntToScalar(50), 0,
2023 SkIntToScalar(10),
2024 SkIntToScalar(10))));
2025 // above
2026 REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(
2028 SkIntToScalar(-10),
2029 SkIntToScalar(10),
2030 SkIntToScalar(10))));
2031 // to the left
2032 REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeXYWH(SkIntToScalar(-10),
2033 SkIntToScalar(5),
2034 SkIntToScalar(5),
2035 SkIntToScalar(5))));
2036
2037 // outside the diagonal edge
2038 REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeXYWH(SkIntToScalar(10),
2039 SkIntToScalar(200),
2040 SkIntToScalar(20),
2041 SkIntToScalar(5))));
2042
2043
2044 // Test that multiple move commands do not cause asserts.
2045 path.moveTo(SkIntToScalar(100), SkIntToScalar(100));
2046 REPORTER_ASSERT(reporter, path.conservativelyContainsRect(SkRect::MakeXYWH(SkIntToScalar(50), 0,
2047 SkIntToScalar(10),
2048 SkIntToScalar(10))));
2049
2050 // Same as above path and first test but with an extra moveTo.
2051 path.reset();
2052 path.moveTo(100, 100);
2053 path.moveTo(0, 0);
2054 path.lineTo(SkIntToScalar(100), 0);
2055 path.lineTo(0, SkIntToScalar(100));
2056 // Convexity logic treats a path as filled and closed, so that multiple (non-trailing) moveTos
2057 // have no effect on convexity
2058 REPORTER_ASSERT(reporter, path.conservativelyContainsRect(
2060 SkIntToScalar(10),
2061 SkIntToScalar(10))));
2062
2063 // Same as above path and first test but with the extra moveTo making a degenerate sub-path
2064 // following the non-empty sub-path. Verifies that this does not trigger assertions.
2065 path.reset();
2066 path.moveTo(0, 0);
2067 path.lineTo(SkIntToScalar(100), 0);
2068 path.lineTo(0, SkIntToScalar(100));
2069 path.moveTo(100, 100);
2070
2071 REPORTER_ASSERT(reporter, path.conservativelyContainsRect(SkRect::MakeXYWH(SkIntToScalar(50), 0,
2072 SkIntToScalar(10),
2073 SkIntToScalar(10))));
2074
2075 // Test that multiple move commands do not cause asserts and that the function
2076 // is not confused by the multiple moves.
2077 path.reset();
2078 path.moveTo(0, 0);
2079 path.lineTo(SkIntToScalar(100), 0);
2080 path.lineTo(0, SkIntToScalar(100));
2081 path.moveTo(0, SkIntToScalar(200));
2082 path.lineTo(SkIntToScalar(100), SkIntToScalar(200));
2083 path.lineTo(0, SkIntToScalar(300));
2084
2085 REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(
2087 SkIntToScalar(10),
2088 SkIntToScalar(10))));
2089
2090 path.reset();
2091 path.lineTo(100, 100);
2092 REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeXYWH(0, 0, 1, 1)));
2093
2094 // An empty path should not contain any rectangle. It's questionable whether an empty path
2095 // contains an empty rectangle. However, since it is a conservative test it is ok to
2096 // return false.
2097 path.reset();
2098 REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeWH(1,1)));
2099 REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeWH(0,0)));
2100}
static SkM44 inv(const SkM44 &m)
Definition 3d.cpp:26
#define SUPPRESS_VISIBILITY_WARNING
Definition PathTest.cpp:356
void swap(sk_sp< T > &a, sk_sp< T > &b)
Definition SkRefCnt.h:341
constexpr float centerX() const
Definition SkRect.h:776

◆ test_contains()

static void test_contains ( skiatest::Reporter reporter)
static

Definition at line 4231 of file PathTest.cpp.

4231 {
4232 SkPath p;
4233 p.moveTo(SkBits2Float(0xe085e7b1), SkBits2Float(0x5f512c00)); // -7.7191e+19f, 1.50724e+19f
4234 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
4235 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
4236 p.lineTo(SkBits2Float(0x609b9872), SkBits2Float(0xdf730de8)); // 8.96947e+19f, -1.75139e+19f
4237 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
4238 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
4239 // this may return true or false, depending on the platform's numerics, but it should not crash
4240 (void) p.contains(-77.2027664f, 15.3066053f);
4241
4242 p.reset();
4244 REPORTER_ASSERT(reporter, p.contains(0, 0));
4245 p.setFillType(SkPathFillType::kWinding);
4246 REPORTER_ASSERT(reporter, !p.contains(0, 0));
4247 p.moveTo(4, 4);
4248 p.lineTo(6, 8);
4249 p.lineTo(8, 4);
4250 // test on edge
4251 REPORTER_ASSERT(reporter, p.contains(6, 4));
4252 REPORTER_ASSERT(reporter, p.contains(5, 6));
4253 REPORTER_ASSERT(reporter, p.contains(7, 6));
4254 // test quick reject
4255 REPORTER_ASSERT(reporter, !p.contains(4, 0));
4256 REPORTER_ASSERT(reporter, !p.contains(0, 4));
4257 REPORTER_ASSERT(reporter, !p.contains(4, 10));
4258 REPORTER_ASSERT(reporter, !p.contains(10, 4));
4259 // test various crossings in x
4260 REPORTER_ASSERT(reporter, !p.contains(5, 7));
4261 REPORTER_ASSERT(reporter, p.contains(6, 7));
4262 REPORTER_ASSERT(reporter, !p.contains(7, 7));
4263 p.reset();
4264 p.moveTo(4, 4);
4265 p.lineTo(8, 6);
4266 p.lineTo(4, 8);
4267 // test on edge
4268 REPORTER_ASSERT(reporter, p.contains(4, 6));
4269 REPORTER_ASSERT(reporter, p.contains(6, 5));
4270 REPORTER_ASSERT(reporter, p.contains(6, 7));
4271 // test various crossings in y
4272 REPORTER_ASSERT(reporter, !p.contains(7, 5));
4273 REPORTER_ASSERT(reporter, p.contains(7, 6));
4274 REPORTER_ASSERT(reporter, !p.contains(7, 7));
4275 p.reset();
4276 p.moveTo(4, 4);
4277 p.lineTo(8, 4);
4278 p.lineTo(8, 8);
4279 p.lineTo(4, 8);
4280 // test on vertices
4281 REPORTER_ASSERT(reporter, p.contains(4, 4));
4282 REPORTER_ASSERT(reporter, p.contains(8, 4));
4283 REPORTER_ASSERT(reporter, p.contains(8, 8));
4284 REPORTER_ASSERT(reporter, p.contains(4, 8));
4285 p.reset();
4286 p.moveTo(4, 4);
4287 p.lineTo(6, 8);
4288 p.lineTo(2, 8);
4289 // test on edge
4290 REPORTER_ASSERT(reporter, p.contains(5, 6));
4291 REPORTER_ASSERT(reporter, p.contains(4, 8));
4292 REPORTER_ASSERT(reporter, p.contains(3, 6));
4293 p.reset();
4294 p.moveTo(4, 4);
4295 p.lineTo(0, 6);
4296 p.lineTo(4, 8);
4297 // test on edge
4298 REPORTER_ASSERT(reporter, p.contains(2, 5));
4299 REPORTER_ASSERT(reporter, p.contains(2, 7));
4300 REPORTER_ASSERT(reporter, p.contains(4, 6));
4301 // test canceling coincident edge (a smaller triangle is coincident with a larger one)
4302 p.reset();
4303 p.moveTo(4, 0);
4304 p.lineTo(6, 4);
4305 p.lineTo(2, 4);
4306 p.moveTo(4, 0);
4307 p.lineTo(0, 8);
4308 p.lineTo(8, 8);
4309 REPORTER_ASSERT(reporter, !p.contains(1, 2));
4310 REPORTER_ASSERT(reporter, !p.contains(3, 2));
4311 REPORTER_ASSERT(reporter, !p.contains(4, 0));
4312 REPORTER_ASSERT(reporter, p.contains(4, 4));
4313
4314 // test quads
4315 p.reset();
4316 p.moveTo(4, 4);
4317 p.quadTo(6, 6, 8, 8);
4318 p.quadTo(6, 8, 4, 8);
4319 p.quadTo(4, 6, 4, 4);
4320 REPORTER_ASSERT(reporter, p.contains(5, 6));
4321 REPORTER_ASSERT(reporter, !p.contains(6, 5));
4322 // test quad edge
4323 REPORTER_ASSERT(reporter, p.contains(5, 5));
4324 REPORTER_ASSERT(reporter, p.contains(5, 8));
4325 REPORTER_ASSERT(reporter, p.contains(4, 5));
4326 // test quad endpoints
4327 REPORTER_ASSERT(reporter, p.contains(4, 4));
4328 REPORTER_ASSERT(reporter, p.contains(8, 8));
4329 REPORTER_ASSERT(reporter, p.contains(4, 8));
4330
4331 p.reset();
4332 const SkPoint qPts[] = {{6, 6}, {8, 8}, {6, 8}, {4, 8}, {4, 6}, {4, 4}, {6, 6}};
4333 p.moveTo(qPts[0]);
4334 for (int index = 1; index < (int) std::size(qPts); index += 2) {
4335 p.quadTo(qPts[index], qPts[index + 1]);
4336 }
4337 REPORTER_ASSERT(reporter, p.contains(5, 6));
4338 REPORTER_ASSERT(reporter, !p.contains(6, 5));
4339 // test quad edge
4340 SkPoint halfway;
4341 for (int index = 0; index < (int) std::size(qPts) - 2; index += 2) {
4342 SkEvalQuadAt(&qPts[index], 0.5f, &halfway, nullptr);
4343 REPORTER_ASSERT(reporter, p.contains(halfway.fX, halfway.fY));
4344 }
4345
4346 // test conics
4347 p.reset();
4348 const SkPoint kPts[] = {{4, 4}, {6, 6}, {8, 8}, {6, 8}, {4, 8}, {4, 6}, {4, 4}};
4349 p.moveTo(kPts[0]);
4350 for (int index = 1; index < (int) std::size(kPts); index += 2) {
4351 p.conicTo(kPts[index], kPts[index + 1], 0.5f);
4352 }
4353 REPORTER_ASSERT(reporter, p.contains(5, 6));
4354 REPORTER_ASSERT(reporter, !p.contains(6, 5));
4355 // test conic edge
4356 for (int index = 0; index < (int) std::size(kPts) - 2; index += 2) {
4357 SkConic conic(&kPts[index], 0.5f);
4358 halfway = conic.evalAt(0.5f);
4359 REPORTER_ASSERT(reporter, p.contains(halfway.fX, halfway.fY));
4360 }
4361 // test conic end points
4362 REPORTER_ASSERT(reporter, p.contains(4, 4));
4363 REPORTER_ASSERT(reporter, p.contains(8, 8));
4364 REPORTER_ASSERT(reporter, p.contains(4, 8));
4365
4366 // test cubics
4367 SkPoint pts[] = {{5, 4}, {6, 5}, {7, 6}, {6, 6}, {4, 6}, {5, 7}, {5, 5}, {5, 4}, {6, 5}, {7, 6}};
4368 for (int i = 0; i < 3; ++i) {
4369 p.reset();
4370 p.setFillType(SkPathFillType::kEvenOdd);
4371 p.moveTo(pts[i].fX, pts[i].fY);
4372 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);
4373 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);
4374 p.close();
4375 REPORTER_ASSERT(reporter, p.contains(5.5f, 5.5f));
4376 REPORTER_ASSERT(reporter, !p.contains(4.5f, 5.5f));
4377 // test cubic edge
4378 SkEvalCubicAt(&pts[i], 0.5f, &halfway, nullptr, nullptr);
4379 REPORTER_ASSERT(reporter, p.contains(halfway.fX, halfway.fY));
4380 SkEvalCubicAt(&pts[i + 3], 0.5f, &halfway, nullptr, nullptr);
4381 REPORTER_ASSERT(reporter, p.contains(halfway.fX, halfway.fY));
4382 // test cubic end points
4383 REPORTER_ASSERT(reporter, p.contains(pts[i].fX, pts[i].fY));
4384 REPORTER_ASSERT(reporter, p.contains(pts[i + 3].fX, pts[i + 3].fY));
4385 REPORTER_ASSERT(reporter, p.contains(pts[i + 6].fX, pts[i + 6].fY));
4386 }
4387}
void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint *loc, SkVector *tangent, SkVector *curvature)
void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint *pt, SkVector *tangent)
Type::kYUV Type::kRGBA() int(0.7 *637)
AI float conic(float tolerance, const SkPoint pts[], float w, const VectorXform &vectorXform=VectorXform())

◆ test_convexity()

static void test_convexity ( skiatest::Reporter reporter)
static

Definition at line 1641 of file PathTest.cpp.

1641 {
1642 SkPath path;
1643
1644 check_convexity(reporter, path, true);
1645 path.addCircle(0, 0, SkIntToScalar(10));
1646 check_convexity(reporter, path, true);
1647 path.addCircle(0, 0, SkIntToScalar(10)); // 2nd circle
1648 check_convexity(reporter, path, false);
1649
1650 path.reset();
1651 path.addRect(0, 0, SkIntToScalar(10), SkIntToScalar(10), SkPathDirection::kCCW);
1652 check_convexity(reporter, path, true);
1654
1655 path.reset();
1656 path.addRect(0, 0, SkIntToScalar(10), SkIntToScalar(10), SkPathDirection::kCW);
1657 check_convexity(reporter, path, true);
1659
1660 path.reset();
1661 path.quadTo(100, 100, 50, 50); // This from GM:convexpaths
1662 check_convexity(reporter, path, true);
1663
1664 static const struct {
1665 const char* fPathStr;
1666 bool fExpectedIsConvex;
1667 SkPathFirstDirection fExpectedDirection;
1668 } gRec[] = {
1669 { "", true, SkPathFirstDirection::kUnknown },
1670 { "0 0", true, SkPathFirstDirection::kUnknown },
1671 { "0 0 10 10", true, SkPathFirstDirection::kUnknown },
1672 { "0 0 10 10 20 20 0 0 10 10", false, SkPathFirstDirection::kUnknown },
1673 { "0 0 10 10 10 20", true, SkPathFirstDirection::kCW },
1674 { "0 0 10 10 10 0", true, SkPathFirstDirection::kCCW },
1675 { "0 0 10 10 10 0 0 10", false, kDontCheckDir },
1676 { "0 0 10 0 0 10 -10 -10", false, SkPathFirstDirection::kCW },
1677 };
1678
1679 for (size_t i = 0; i < std::size(gRec); ++i) {
1680 path.reset();
1681 setFromString(&path, gRec[i].fPathStr);
1682 check_convexity(reporter, path, gRec[i].fExpectedIsConvex);
1683 check_direction(reporter, path, gRec[i].fExpectedDirection);
1684 // check after setting the initial convex and direction
1685 if (kDontCheckDir != gRec[i].fExpectedDirection) {
1686 // We make a copy so that we don't cache the result on the passed in path.
1687 SkPath copy(path); // NOLINT(performance-unnecessary-copy-initialization)
1689 bool foundDir = dir != SkPathFirstDirection::kUnknown;
1691 ^ foundDir);
1692 REPORTER_ASSERT(reporter, !foundDir || gRec[i].fExpectedDirection == dir);
1693 check_convexity(reporter, copy, gRec[i].fExpectedIsConvex);
1694 }
1695 REPORTER_ASSERT(reporter, gRec[i].fExpectedIsConvex == path.isConvex());
1696 check_direction(reporter, path, gRec[i].fExpectedDirection);
1697 }
1698
1699 static const SkPoint nonFinitePts[] = {
1700 { SK_ScalarInfinity, 0 },
1701 { 0, SK_ScalarInfinity },
1708 { SK_ScalarNaN, 0 },
1709 { 0, SK_ScalarNaN },
1711 };
1712
1713 const size_t nonFinitePtsCount = sizeof(nonFinitePts) / sizeof(nonFinitePts[0]);
1714
1715 static const SkPoint axisAlignedPts[] = {
1716 { SK_ScalarMax, 0 },
1717 { 0, SK_ScalarMax },
1718 { SK_ScalarMin, 0 },
1719 { 0, SK_ScalarMin },
1720 };
1721
1722 const size_t axisAlignedPtsCount = sizeof(axisAlignedPts) / sizeof(axisAlignedPts[0]);
1723
1724 for (int index = 0; index < (int) (13 * nonFinitePtsCount * axisAlignedPtsCount); ++index) {
1725 int i = (int) (index % nonFinitePtsCount);
1726 int f = (int) (index % axisAlignedPtsCount);
1727 int g = (int) ((f + 1) % axisAlignedPtsCount);
1728 path.reset();
1729 switch (index % 13) {
1730 case 0: path.lineTo(nonFinitePts[i]); break;
1731 case 1: path.quadTo(nonFinitePts[i], nonFinitePts[i]); break;
1732 case 2: path.quadTo(nonFinitePts[i], axisAlignedPts[f]); break;
1733 case 3: path.quadTo(axisAlignedPts[f], nonFinitePts[i]); break;
1734 case 4: path.cubicTo(nonFinitePts[i], axisAlignedPts[f], axisAlignedPts[f]); break;
1735 case 5: path.cubicTo(axisAlignedPts[f], nonFinitePts[i], axisAlignedPts[f]); break;
1736 case 6: path.cubicTo(axisAlignedPts[f], axisAlignedPts[f], nonFinitePts[i]); break;
1737 case 7: path.cubicTo(nonFinitePts[i], nonFinitePts[i], axisAlignedPts[f]); break;
1738 case 8: path.cubicTo(nonFinitePts[i], axisAlignedPts[f], nonFinitePts[i]); break;
1739 case 9: path.cubicTo(axisAlignedPts[f], nonFinitePts[i], nonFinitePts[i]); break;
1740 case 10: path.cubicTo(nonFinitePts[i], nonFinitePts[i], nonFinitePts[i]); break;
1741 case 11: path.cubicTo(nonFinitePts[i], axisAlignedPts[f], axisAlignedPts[g]); break;
1742 case 12: path.moveTo(nonFinitePts[i]); break;
1743 }
1746 }
1747
1748 for (int index = 0; index < (int) (11 * axisAlignedPtsCount); ++index) {
1749 int f = (int) (index % axisAlignedPtsCount);
1750 int g = (int) ((f + 1) % axisAlignedPtsCount);
1751 path.reset();
1752 int curveSelect = index % 11;
1753 switch (curveSelect) {
1754 case 0: path.moveTo(axisAlignedPts[f]); break;
1755 case 1: path.lineTo(axisAlignedPts[f]); break;
1756 case 2: path.quadTo(axisAlignedPts[f], axisAlignedPts[f]); break;
1757 case 3: path.quadTo(axisAlignedPts[f], axisAlignedPts[g]); break;
1758 case 4: path.quadTo(axisAlignedPts[g], axisAlignedPts[f]); break;
1759 case 5: path.cubicTo(axisAlignedPts[f], axisAlignedPts[f], axisAlignedPts[f]); break;
1760 case 6: path.cubicTo(axisAlignedPts[f], axisAlignedPts[f], axisAlignedPts[g]); break;
1761 case 7: path.cubicTo(axisAlignedPts[f], axisAlignedPts[g], axisAlignedPts[f]); break;
1762 case 8: path.cubicTo(axisAlignedPts[f], axisAlignedPts[g], axisAlignedPts[g]); break;
1763 case 9: path.cubicTo(axisAlignedPts[g], axisAlignedPts[f], axisAlignedPts[f]); break;
1764 case 10: path.cubicTo(axisAlignedPts[g], axisAlignedPts[f], axisAlignedPts[g]); break;
1765 }
1766 if (curveSelect == 0 || curveSelect == 1 || curveSelect == 2 || curveSelect == 5) {
1767 check_convexity(reporter, path, true);
1768 } else {
1769 // We make a copy so that we don't cache the result on the passed in path.
1770 SkPath copy(path); // NOLINT(performance-unnecessary-copy-initialization)
1771 REPORTER_ASSERT(reporter, !copy.isConvex());
1772 }
1773 }
1774
1775 static const SkPoint diagonalPts[] = {
1778 };
1779
1780 const size_t diagonalPtsCount = sizeof(diagonalPts) / sizeof(diagonalPts[0]);
1781
1782 for (int index = 0; index < (int) (7 * diagonalPtsCount); ++index) {
1783 int f = (int) (index % diagonalPtsCount);
1784 int g = (int) ((f + 1) % diagonalPtsCount);
1785 path.reset();
1786 int curveSelect = index % 11;
1787 switch (curveSelect) {
1788 case 0: path.moveTo(diagonalPts[f]); break;
1789 case 1: path.lineTo(diagonalPts[f]); break;
1790 case 2: path.quadTo(diagonalPts[f], diagonalPts[f]); break;
1791 case 3: path.quadTo(axisAlignedPts[f], diagonalPts[g]); break;
1792 case 4: path.quadTo(diagonalPts[g], axisAlignedPts[f]); break;
1793 case 5: path.cubicTo(diagonalPts[f], diagonalPts[f], diagonalPts[f]); break;
1794 case 6: path.cubicTo(diagonalPts[f], diagonalPts[f], axisAlignedPts[g]); break;
1795 case 7: path.cubicTo(diagonalPts[f], axisAlignedPts[g], diagonalPts[f]); break;
1796 case 8: path.cubicTo(axisAlignedPts[f], diagonalPts[g], diagonalPts[g]); break;
1797 case 9: path.cubicTo(diagonalPts[g], diagonalPts[f], axisAlignedPts[f]); break;
1798 case 10: path.cubicTo(diagonalPts[g], axisAlignedPts[f], diagonalPts[g]); break;
1799 }
1800 if (curveSelect == 0) {
1801 check_convexity(reporter, path, true);
1802 } else {
1803 // We make a copy so that we don't cache the result on the passed in path.
1804 SkPath copy(path); // NOLINT(performance-unnecessary-copy-initialization)
1805 REPORTER_ASSERT(reporter, !copy.isConvex());
1806 }
1807 }
1808
1809
1810 path.reset();
1811 path.moveTo(SkBits2Float(0xbe9171db), SkBits2Float(0xbd7eeb5d)); // -0.284072f, -0.0622362f
1812 path.lineTo(SkBits2Float(0xbe9171db), SkBits2Float(0xbd7eea38)); // -0.284072f, -0.0622351f
1813 path.lineTo(SkBits2Float(0xbe9171a0), SkBits2Float(0xbd7ee5a7)); // -0.28407f, -0.0622307f
1814 path.lineTo(SkBits2Float(0xbe917147), SkBits2Float(0xbd7ed886)); // -0.284067f, -0.0622182f
1815 path.lineTo(SkBits2Float(0xbe917378), SkBits2Float(0xbd7ee1a9)); // -0.284084f, -0.0622269f
1816 path.lineTo(SkBits2Float(0xbe9171db), SkBits2Float(0xbd7eeb5d)); // -0.284072f, -0.0622362f
1817 path.close();
1818 check_convexity(reporter, path, false);
1819
1820}
static const struct @223 gRec[]
static const SkPoint nonFinitePts[]
const size_t nonFinitePtsCount
static void check_convexity(skiatest::Reporter *reporter, const SkPath &path, bool expectedConvexity)
static void check_direction(skiatest::Reporter *reporter, const SkPath &path, SkPathFirstDirection expected)
static void setFromString(SkPath *path, const char str[])
#define SK_ScalarMin
Definition SkScalar.h:25
#define SK_ScalarNegativeInfinity
Definition SkScalar.h:27

◆ test_convexity2()

static void test_convexity2 ( skiatest::Reporter reporter)
static

Definition at line 1392 of file PathTest.cpp.

1392 {
1393 SkPath pt;
1394 pt.moveTo(0, 0);
1395 pt.close();
1396 check_convexity(reporter, pt, true);
1398
1399 SkPath line;
1400 line.moveTo(12*SK_Scalar1, 20*SK_Scalar1);
1401 line.lineTo(-12*SK_Scalar1, -20*SK_Scalar1);
1402 line.close();
1403 check_convexity(reporter, line, true);
1405
1406 SkPath triLeft;
1407 triLeft.moveTo(0, 0);
1408 triLeft.lineTo(SK_Scalar1, 0);
1409 triLeft.lineTo(SK_Scalar1, SK_Scalar1);
1410 triLeft.close();
1411 check_convexity(reporter, triLeft, true);
1413
1414 SkPath triRight;
1415 triRight.moveTo(0, 0);
1416 triRight.lineTo(-SK_Scalar1, 0);
1417 triRight.lineTo(SK_Scalar1, SK_Scalar1);
1418 triRight.close();
1419 check_convexity(reporter, triRight, true);
1421
1422 SkPath square;
1423 square.moveTo(0, 0);
1427 square.close();
1430
1431 SkPath redundantSquare;
1432 redundantSquare.moveTo(0, 0);
1433 redundantSquare.lineTo(0, 0);
1434 redundantSquare.lineTo(0, 0);
1435 redundantSquare.lineTo(SK_Scalar1, 0);
1436 redundantSquare.lineTo(SK_Scalar1, 0);
1437 redundantSquare.lineTo(SK_Scalar1, 0);
1438 redundantSquare.lineTo(SK_Scalar1, SK_Scalar1);
1439 redundantSquare.lineTo(SK_Scalar1, SK_Scalar1);
1440 redundantSquare.lineTo(SK_Scalar1, SK_Scalar1);
1441 redundantSquare.lineTo(0, SK_Scalar1);
1442 redundantSquare.lineTo(0, SK_Scalar1);
1443 redundantSquare.lineTo(0, SK_Scalar1);
1444 redundantSquare.close();
1445 check_convexity(reporter, redundantSquare, true);
1447
1448 SkPath bowTie;
1449 bowTie.moveTo(0, 0);
1450 bowTie.lineTo(0, 0);
1451 bowTie.lineTo(0, 0);
1452 bowTie.lineTo(SK_Scalar1, SK_Scalar1);
1453 bowTie.lineTo(SK_Scalar1, SK_Scalar1);
1454 bowTie.lineTo(SK_Scalar1, SK_Scalar1);
1455 bowTie.lineTo(SK_Scalar1, 0);
1456 bowTie.lineTo(SK_Scalar1, 0);
1457 bowTie.lineTo(SK_Scalar1, 0);
1458 bowTie.lineTo(0, SK_Scalar1);
1459 bowTie.lineTo(0, SK_Scalar1);
1460 bowTie.lineTo(0, SK_Scalar1);
1461 bowTie.close();
1462 check_convexity(reporter, bowTie, false);
1464
1465 SkPath spiral;
1466 spiral.moveTo(0, 0);
1467 spiral.lineTo(100*SK_Scalar1, 0);
1468 spiral.lineTo(100*SK_Scalar1, 100*SK_Scalar1);
1469 spiral.lineTo(0, 100*SK_Scalar1);
1470 spiral.lineTo(0, 50*SK_Scalar1);
1471 spiral.lineTo(50*SK_Scalar1, 50*SK_Scalar1);
1472 spiral.lineTo(50*SK_Scalar1, 75*SK_Scalar1);
1473 spiral.close();
1474 check_convexity(reporter, spiral, false);
1476
1477 SkPath dent;
1478 dent.moveTo(0, 0);
1479 dent.lineTo(100*SK_Scalar1, 100*SK_Scalar1);
1480 dent.lineTo(0, 100*SK_Scalar1);
1481 dent.lineTo(-50*SK_Scalar1, 200*SK_Scalar1);
1482 dent.lineTo(-200*SK_Scalar1, 100*SK_Scalar1);
1483 dent.close();
1484 check_convexity(reporter, dent, false);
1486
1487 // https://bug.skia.org/2235
1488 SkPath strokedSin;
1489 for (int i = 0; i < 2000; i++) {
1490 SkScalar x = SkIntToScalar(i) / 2;
1491 SkScalar y = 500 - (x + SkScalarSin(x / 100) * 40) / 3;
1492 if (0 == i) {
1493 strokedSin.moveTo(x, y);
1494 } else {
1495 strokedSin.lineTo(x, y);
1496 }
1497 }
1499 stroke.setStrokeStyle(2 * SK_Scalar1);
1500 stroke.applyToPath(&strokedSin, strokedSin);
1501 check_convexity(reporter, strokedSin, false);
1503
1504 // http://crbug.com/412640
1505 SkPath degenerateConcave;
1506 degenerateConcave.moveTo(148.67912f, 191.875f);
1507 degenerateConcave.lineTo(470.37695f, 7.5f);
1508 degenerateConcave.lineTo(148.67912f, 191.875f);
1509 degenerateConcave.lineTo(41.446522f, 376.25f);
1510 degenerateConcave.lineTo(-55.971577f, 460.0f);
1511 degenerateConcave.lineTo(41.446522f, 376.25f);
1512 check_convexity(reporter, degenerateConcave, false);
1514
1515 // http://crbug.com/433683
1516 SkPath badFirstVector;
1517 badFirstVector.moveTo(501.087708f, 319.610352f);
1518 badFirstVector.lineTo(501.087708f, 319.610352f);
1519 badFirstVector.cubicTo(501.087677f, 319.610321f, 449.271606f, 258.078674f, 395.084564f, 198.711182f);
1520 badFirstVector.cubicTo(358.967072f, 159.140717f, 321.910553f, 120.650436f, 298.442322f, 101.955399f);
1521 badFirstVector.lineTo(301.557678f, 98.044601f);
1522 badFirstVector.cubicTo(325.283844f, 116.945084f, 362.615204f, 155.720825f, 398.777557f, 195.340454f);
1523 badFirstVector.cubicTo(453.031860f, 254.781662f, 504.912262f, 316.389618f, 504.912292f, 316.389648f);
1524 badFirstVector.lineTo(504.912292f, 316.389648f);
1525 badFirstVector.lineTo(501.087708f, 319.610352f);
1526 badFirstVector.close();
1527 check_convexity(reporter, badFirstVector, false);
1528
1529 // http://crbug.com/993330
1530 SkPath falseBackEdge;
1531 falseBackEdge.moveTo(-217.83430557928145f, -382.14948768484857f);
1532 falseBackEdge.lineTo(-227.73867866614847f, -399.52485512718323f);
1533 falseBackEdge.cubicTo(-158.3541047666846f, -439.0757140459542f,
1534 -79.8654464485281f, -459.875f,
1535 -1.1368683772161603e-13f, -459.875f);
1536 falseBackEdge.lineTo(-8.08037266162413e-14f, -439.875f);
1537 falseBackEdge.lineTo(-8.526512829121202e-14f, -439.87499999999994f);
1538 falseBackEdge.cubicTo(-76.39209188702645f, -439.87499999999994f,
1539 -151.46727226799754f, -419.98027663161537f,
1540 -217.83430557928145f, -382.14948768484857f);
1541 falseBackEdge.close();
1542 check_convexity(reporter, falseBackEdge, false);
1543}
#define SkScalarSin(radians)
Definition SkScalar.h:45
static int square(int x)
Definition etc1.cpp:302

◆ test_convexity_doubleback()

static void test_convexity_doubleback ( skiatest::Reporter reporter)
static

Definition at line 1545 of file PathTest.cpp.

1545 {
1546 SkPath doubleback;
1547 doubleback.lineTo(1, 1);
1548 check_convexity(reporter, doubleback, true);
1549 doubleback.lineTo(2, 2);
1550 check_convexity(reporter, doubleback, true);
1551 doubleback.reset();
1552 doubleback.lineTo(1, 0);
1553 check_convexity(reporter, doubleback, true);
1554 doubleback.lineTo(2, 0);
1555 check_convexity(reporter, doubleback, true);
1556 doubleback.lineTo(1, 0);
1557 check_convexity(reporter, doubleback, true);
1558 doubleback.reset();
1559 doubleback.quadTo(1, 1, 2, 2);
1560 check_convexity(reporter, doubleback, true);
1561 doubleback.reset();
1562 doubleback.quadTo(1, 0, 2, 0);
1563 check_convexity(reporter, doubleback, true);
1564 doubleback.quadTo(1, 0, 0, 0);
1565 check_convexity(reporter, doubleback, true);
1566
1567 doubleback.reset();
1568 doubleback.lineTo(1, 0);
1569 doubleback.lineTo(1, 0);
1570 doubleback.lineTo(1, 1);
1571 doubleback.lineTo(1, 1);
1572 doubleback.lineTo(1, 0);
1573 check_convexity(reporter, doubleback, false);
1574
1575 doubleback.reset();
1576 doubleback.lineTo(-1, 0);
1577 doubleback.lineTo(-1, 1);
1578 doubleback.lineTo(-1, 0);
1579 check_convexity(reporter, doubleback, false);
1580
1581 for (int i = 0; i < 4; ++i) {
1582 doubleback.reset();
1583 doubleback.moveTo(0, 0);
1584 if (i == 0) {
1585 doubleback.lineTo(-1, -1);
1586 doubleback.lineTo(0, 0);
1587 }
1588 doubleback.lineTo(0, 1);
1589 if (i == 1) {
1590 doubleback.lineTo(0, 2);
1591 doubleback.lineTo(0, 1);
1592 }
1593 doubleback.lineTo(1, 1);
1594 if (i == 2) {
1595 doubleback.lineTo(2, 2);
1596 doubleback.lineTo(1, 1);
1597 }
1598 doubleback.lineTo(0, 0);
1599 if (i == 3) {
1600 doubleback.lineTo(-1, -1);
1601 doubleback.lineTo(0, 0);
1602 }
1603 check_convexity(reporter, doubleback, false);
1604 }
1605}

◆ test_crbug_170666()

static void test_crbug_170666 ( )
static

Definition at line 577 of file PathTest.cpp.

577 {
578 SkPath path;
580 test_draw_AA_path(1000, 1000, path);
581
582 build_path_170666(path);
583 test_draw_AA_path(1000, 1000, path);
584}
static void build_path_170666(SkPath &path)
Definition PathTest.cpp:489
static void build_path_simple_170666(SkPath &path)
Definition PathTest.cpp:569

◆ test_crbug_493450()

static void test_crbug_493450 ( skiatest::Reporter reporter)
static

Definition at line 603 of file PathTest.cpp.

603 {
604 const char reducedCase[] =
605 "M0,0"
606 "L0.0002, 0"
607 "L0.0002, 0.0002"
608 "L0.0001, 0.0001"
609 "L0,0.0002"
610 "Z";
611 test_tiny_path_convexity(reporter, reducedCase, 100, 100, 100000);
612 const char originalFiddleData[] =
613 "M-0.3383152268862998,-0.11217565719203619L-0.33846085183212765,-0.11212264406895281"
614 "L-0.338509393480737,-0.11210607966681395L-0.33857792286700894,-0.1121889121487573"
615 "L-0.3383866116636664,-0.11228834570924921L-0.33842087635680235,-0.11246078673250548"
616 "L-0.33809536177201055,-0.11245415228342878L-0.33797257995493996,-0.11216571641452182"
617 "L-0.33802112160354925,-0.11201996164188659L-0.33819815585141844,-0.11218559834671019Z";
618 test_tiny_path_convexity(reporter, originalFiddleData, 280081.4116670522f, 93268.04618493588f,
619 826357.3384828606f);
620}
static void test_tiny_path_convexity(skiatest::Reporter *reporter, const char *pathBug, SkScalar tx, SkScalar ty, SkScalar scale)
Definition PathTest.cpp:587

◆ test_crbug_495894()

static void test_crbug_495894 ( skiatest::Reporter reporter)
static

Definition at line 622 of file PathTest.cpp.

622 {
623 const char originalFiddleData[] =
624 "M-0.34004273849857214,-0.11332803232216355L-0.34008271397389744,-0.11324483772714951"
625 "L-0.3401940742265893,-0.11324483772714951L-0.34017694188002134,-0.11329807920275889"
626 "L-0.3402026403998733,-0.11333468903941245L-0.34029972369709194,-0.11334134592705701"
627 "L-0.3403054344792813,-0.11344121970007795L-0.3403140006525653,-0.11351115418399343"
628 "L-0.34024261587519866,-0.11353446986281181L-0.3402197727464413,-0.11360442946144192"
629 "L-0.34013696640469604,-0.11359110237029302L-0.34009128014718143,-0.1135877707043939"
630 "L-0.3400598708451401,-0.11360776134112742L-0.34004273849857214,-0.11355112520064405"
631 "L-0.3400113291965308,-0.11355112520064405L-0.3399970522410575,-0.11359110237029302"
632 "L-0.33997135372120546,-0.11355112520064405L-0.3399627875479215,-0.11353780084493197"
633 "L-0.3399485105924481,-0.11350782354357004L-0.3400027630232468,-0.11346452910331437"
634 "L-0.3399485105924481,-0.11340126558629839L-0.33993994441916414,-0.11340126558629839"
635 "L-0.33988283659727087,-0.11331804756574679L-0.33989140277055485,-0.11324483772714951"
636 "L-0.33997991989448945,-0.11324483772714951L-0.3399856306766788,-0.11324483772714951"
637 "L-0.34002560615200417,-0.11334467443478255ZM-0.3400684370184241,-0.11338461985124307"
638 "L-0.340154098751264,-0.11341791238732665L-0.340162664924548,-0.1134378899559977"
639 "L-0.34017979727111597,-0.11340126558629839L-0.3401655203156427,-0.11338129083212668"
640 "L-0.34012268944922275,-0.11332137577529414L-0.34007414780061346,-0.11334467443478255Z"
641 "M-0.3400027630232468,-0.11290567901106024L-0.3400113291965308,-0.11298876531245433"
642 "L-0.33997991989448945,-0.11301535852306784L-0.33990282433493346,-0.11296217481488612"
643 "L-0.33993994441916414,-0.11288906492739594Z";
644 test_tiny_path_convexity(reporter, originalFiddleData, 22682.240000000005f,7819.72220766405f,
645 65536);
646}

◆ test_crbug_613918()

static void test_crbug_613918 ( )
static

Definition at line 648 of file PathTest.cpp.

648 {
649 SkPath path;
650 path.conicTo(-6.62478e-08f, 4.13885e-08f, -6.36935e-08f, 3.97927e-08f, 0.729058f);
651 path.quadTo(2.28206e-09f, -1.42572e-09f, 3.91919e-09f, -2.44852e-09f);
652 path.cubicTo(-16752.2f, -26792.9f, -21.4673f, 10.9347f, -8.57322f, -7.22739f);
653
654 // This call could lead to an assert or uninitialized read due to a failure
655 // to check the return value from SkCubicClipper::ChopMonoAtY.
656 path.contains(-1.84817e-08f, 1.15465e-08f);
657}

◆ test_crbug_629455()

static void test_crbug_629455 ( skiatest::Reporter reporter)
static

Definition at line 4637 of file PathTest.cpp.

4637 {
4638 SkPath path;
4639 path.moveTo(0, 0);
4640 path.cubicTo(SkBits2Float(0xcdcdcd00), SkBits2Float(0xcdcdcdcd),
4641 SkBits2Float(0xcdcdcdcd), SkBits2Float(0xcdcdcdcd),
4642 SkBits2Float(0x423fcdcd), SkBits2Float(0x40ed9341));
4643// AKA: cubicTo(-4.31596e+08f, -4.31602e+08f, -4.31602e+08f, -4.31602e+08f, 47.951f, 7.42423f);
4644 path.lineTo(0, 0);
4645 test_draw_AA_path(100, 100, path);
4646}

◆ test_direction()

static void test_direction ( skiatest::Reporter reporter)
static

Definition at line 1113 of file PathTest.cpp.

1113 {
1114 size_t i;
1115 SkPath path;
1118
1119 static const char* gDegen[] = {
1120 "M 10 10",
1121 "M 10 10 M 20 20",
1122 "M 10 10 L 20 20",
1123 "M 10 10 L 10 10 L 10 10",
1124 "M 10 10 Q 10 10 10 10",
1125 "M 10 10 C 10 10 10 10 10 10",
1126 };
1127 for (i = 0; i < std::size(gDegen); ++i) {
1128 path.reset();
1129 bool valid = SkParsePath::FromSVGString(gDegen[i], &path);
1130 REPORTER_ASSERT(reporter, valid);
1133 }
1134
1135 static const char* gCW[] = {
1136 "M 10 10 L 10 10 Q 20 10 20 20",
1137 "M 10 10 C 20 10 20 20 20 20",
1138 "M 20 10 Q 20 20 30 20 L 10 20", // test double-back at y-max
1139 // rect with top two corners replaced by cubics with identical middle
1140 // control points
1141 "M 10 10 C 10 0 10 0 20 0 L 40 0 C 50 0 50 0 50 10",
1142 "M 20 10 L 0 10 Q 10 10 20 0", // left, degenerate serif
1143 };
1144 for (i = 0; i < std::size(gCW); ++i) {
1145 path.reset();
1146 bool valid = SkParsePath::FromSVGString(gCW[i], &path);
1147 REPORTER_ASSERT(reporter, valid);
1149 }
1150
1151 static const char* gCCW[] = {
1152 "M 10 10 L 10 10 Q 20 10 20 -20",
1153 "M 10 10 C 20 10 20 -20 20 -20",
1154 "M 20 10 Q 20 20 10 20 L 30 20", // test double-back at y-max
1155 // rect with top two corners replaced by cubics with identical middle
1156 // control points
1157 "M 50 10 C 50 0 50 0 40 0 L 20 0 C 10 0 10 0 10 10",
1158 "M 10 10 L 30 10 Q 20 10 10 0", // right, degenerate serif
1159 };
1160 for (i = 0; i < std::size(gCCW); ++i) {
1161 path.reset();
1162 bool valid = SkParsePath::FromSVGString(gCCW[i], &path);
1163 REPORTER_ASSERT(reporter, valid);
1165 }
1166
1167 // Test two donuts, each wound a different direction. Only the outer contour
1168 // determines the cheap direction
1169 path.reset();
1170 path.addCircle(0, 0, SkIntToScalar(2), SkPathDirection::kCW);
1171 path.addCircle(0, 0, SkIntToScalar(1), SkPathDirection::kCCW);
1173
1174 path.reset();
1175 path.addCircle(0, 0, SkIntToScalar(1), SkPathDirection::kCW);
1176 path.addCircle(0, 0, SkIntToScalar(2), SkPathDirection::kCCW);
1178
1179 // triangle with one point really far from the origin.
1180 path.reset();
1181 // the first point is roughly 1.05e10, 1.05e10
1182 path.moveTo(SkBits2Float(0x501c7652), SkBits2Float(0x501c7652));
1183 path.lineTo(110 * SK_Scalar1, -10 * SK_Scalar1);
1184 path.lineTo(-10 * SK_Scalar1, 60 * SK_Scalar1);
1186
1187 path.reset();
1188 path.conicTo(20, 0, 20, 20, 0.5f);
1189 path.close();
1191
1192 path.reset();
1193 path.lineTo(1, 1e7f);
1194 path.lineTo(1e7f, 2e7f);
1195 path.close();
1196 REPORTER_ASSERT(reporter, path.isConvex());
1198}

◆ test_draw_AA_path()

static void test_draw_AA_path ( int  width,
int  height,
const SkPath path 
)
static

Definition at line 180 of file PathTest.cpp.

180 {
182 SkCanvas* canvas = surface->getCanvas();
184 paint.setAntiAlias(true);
185 canvas->drawPath(path, paint);
186}
int32_t height

◆ test_dump()

static void test_dump ( skiatest::Reporter reporter)
static

Definition at line 4497 of file PathTest.cpp.

4497 {
4498 SkPath p;
4499 compare_dump(reporter, p, false, "path.setFillType(SkPathFillType::kWinding);\n");
4500 p.moveTo(1, 2);
4501 p.lineTo(3, 4);
4502 compare_dump(reporter, p, false, "path.setFillType(SkPathFillType::kWinding);\n"
4503 "path.moveTo(1, 2);\n"
4504 "path.lineTo(3, 4);\n");
4505 p.reset();
4506 p.setFillType(SkPathFillType::kEvenOdd);
4507 p.moveTo(1, 2);
4508 p.quadTo(3, 4, 5, 6);
4509 compare_dump(reporter, p, false, "path.setFillType(SkPathFillType::kEvenOdd);\n"
4510 "path.moveTo(1, 2);\n"
4511 "path.quadTo(3, 4, 5, 6);\n");
4512 p.reset();
4514 p.moveTo(1, 2);
4515 p.conicTo(3, 4, 5, 6, 0.5f);
4516 compare_dump(reporter, p, false, "path.setFillType(SkPathFillType::kInverseWinding);\n"
4517 "path.moveTo(1, 2);\n"
4518 "path.conicTo(3, 4, 5, 6, 0.5f);\n");
4519 p.reset();
4521 p.moveTo(1, 2);
4522 p.cubicTo(3, 4, 5, 6, 7, 8);
4523 compare_dump(reporter, p, false, "path.setFillType(SkPathFillType::kInverseEvenOdd);\n"
4524 "path.moveTo(1, 2);\n"
4525 "path.cubicTo(3, 4, 5, 6, 7, 8);\n");
4526 p.reset();
4527 p.setFillType(SkPathFillType::kWinding);
4528 p.moveTo(1, 2);
4529 p.lineTo(3, 4);
4530 compare_dump(reporter, p, true,
4531 "path.setFillType(SkPathFillType::kWinding);\n"
4532 "path.moveTo(SkBits2Float(0x3f800000), SkBits2Float(0x40000000)); // 1, 2\n"
4533 "path.lineTo(SkBits2Float(0x40400000), SkBits2Float(0x40800000)); // 3, 4\n");
4534 p.reset();
4535 p.moveTo(SkBits2Float(0x3f800000), SkBits2Float(0x40000000));
4536 p.lineTo(SkBits2Float(0x40400000), SkBits2Float(0x40800000));
4537 compare_dump(reporter, p, false, "path.setFillType(SkPathFillType::kWinding);\n"
4538 "path.moveTo(1, 2);\n"
4539 "path.lineTo(3, 4);\n");
4540}
static void compare_dump(skiatest::Reporter *reporter, const SkPath &path, bool dumpAsHex, const char *str)

◆ test_edger()

static void test_edger ( skiatest::Reporter r,
const std::initializer_list< SkPath::Verb > &  in,
const std::initializer_list< SkPath::Verb > &  expected 
)
static

Definition at line 5800 of file PathTest.cpp.

5802 {
5803 SkPath path;
5804 SkScalar x = 0, y = 0;
5805 for (auto v : in) {
5806 switch (v) {
5807 case SkPath::kMove_Verb: path.moveTo(x++, y++); break;
5808 case SkPath::kLine_Verb: path.lineTo(x++, y++); break;
5809 case SkPath::kClose_Verb: path.close(); break;
5810 default: SkASSERT(false);
5811 }
5812 }
5813
5814 SkPathEdgeIter iter(path);
5815 for (auto v : expected) {
5816 auto e = iter.next();
5817 REPORTER_ASSERT(r, e);
5819 }
5820 REPORTER_ASSERT(r, !iter.next());
5821}
static SkPath::Verb EdgeToVerb(Edge e)
Definition SkPathPriv.h:472

◆ test_empty()

static void test_empty ( skiatest::Reporter reporter,
const SkPath p 
)
static

Definition at line 3750 of file PathTest.cpp.

3750 {
3751 SkPath empty;
3752
3753 REPORTER_ASSERT(reporter, p.isEmpty());
3754 REPORTER_ASSERT(reporter, 0 == p.countPoints());
3755 REPORTER_ASSERT(reporter, 0 == p.countVerbs());
3756 REPORTER_ASSERT(reporter, 0 == p.getSegmentMasks());
3757 REPORTER_ASSERT(reporter, p.isConvex());
3759 REPORTER_ASSERT(reporter, !p.isInverseFillType());
3761 REPORTER_ASSERT(reporter, !(p != empty));
3762}

◆ test_extendClosedPath()

static void test_extendClosedPath ( skiatest::Reporter reporter)
static

Definition at line 4165 of file PathTest.cpp.

4165 {
4166 SkPath p, q;
4167 p.moveTo(1, 1);
4168 p.lineTo(1, 2);
4169 p.lineTo(2, 2);
4170 p.close();
4171 q.moveTo(2, 1);
4172 q.lineTo(2, 3);
4173 p.addPath(q, SkPath::kExtend_AddPathMode);
4174 uint8_t verbs[7];
4175 int verbcount = p.getVerbs(verbs, 7);
4176 REPORTER_ASSERT(reporter, verbcount == 7);
4184
4185 SkPoint pt;
4186 REPORTER_ASSERT(reporter, p.getLastPt(&pt));
4188 REPORTER_ASSERT(reporter, p.getPoint(3) == SkPoint::Make(1, 1));
4189}

◆ test_flattening()

static void test_flattening ( skiatest::Reporter reporter)
static

Definition at line 2784 of file PathTest.cpp.

2784 {
2785 SkPath p;
2786
2787 static const SkPoint pts[] = {
2788 { 0, 0 },
2789 { SkIntToScalar(10), SkIntToScalar(10) },
2790 { SkIntToScalar(20), SkIntToScalar(10) }, { SkIntToScalar(20), 0 },
2791 { 0, 0 }, { 0, SkIntToScalar(10) }, { SkIntToScalar(1), SkIntToScalar(10) }
2792 };
2793 p.moveTo(pts[0]);
2794 p.lineTo(pts[1]);
2795 p.quadTo(pts[2], pts[3]);
2796 p.cubicTo(pts[4], pts[5], pts[6]);
2797
2799
2800 // create a buffer that should be much larger than the path so we don't
2801 // kill our stack if writer goes too far.
2802 char buffer[1024];
2803 size_t size1 = p.writeToMemory(nullptr);
2804 size_t size2 = p.writeToMemory(buffer);
2805 REPORTER_ASSERT(reporter, size1 == size2);
2806
2807 SkPath p2;
2808 size_t size3 = p2.readFromMemory(buffer, 1024);
2809 REPORTER_ASSERT(reporter, size1 == size3);
2810 REPORTER_ASSERT(reporter, p == p2);
2811
2812 size3 = p2.readFromMemory(buffer, 0);
2813 REPORTER_ASSERT(reporter, !size3);
2814
2815 SkPath tooShort;
2816 size3 = tooShort.readFromMemory(buffer, size1 - 1);
2817 REPORTER_ASSERT(reporter, tooShort.isEmpty());
2818
2819 char buffer2[1024];
2820 size3 = p2.writeToMemory(buffer2);
2821 REPORTER_ASSERT(reporter, size1 == size3);
2822 REPORTER_ASSERT(reporter, memcmp(buffer, buffer2, size1) == 0);
2823
2824 // test persistence of the oval flag & convexity
2825 {
2826 SkPath oval;
2827 SkRect rect = SkRect::MakeWH(10, 10);
2828 oval.addOval(rect);
2829
2831 }
2832}
static void write_and_read_back(skiatest::Reporter *reporter, const SkPath &p)
size_t writeToMemory(void *buffer) const
static const uint8_t buffer[]

◆ test_fuzz_crbug_627414()

static void test_fuzz_crbug_627414 ( skiatest::Reporter reporter)
static

Definition at line 783 of file PathTest.cpp.

783 {
784 SkPath path;
785 path.moveTo(0, 0);
786 path.conicTo(3.58732e-43f, 2.72084f, 3.00392f, 3.00392f, 8.46e+37f);
787 test_draw_AA_path(100, 100, path);
788}

◆ test_fuzz_crbug_638223()

static void test_fuzz_crbug_638223 ( )
static

Definition at line 189 of file PathTest.cpp.

189 {
190 SkPath path;
191 path.moveTo(SkBits2Float(0x47452a00), SkBits2Float(0x43211d01)); // 50474, 161.113f
192 path.conicTo(SkBits2Float(0x401c0000), SkBits2Float(0x40680000),
193 SkBits2Float(0x02c25a81), SkBits2Float(0x981a1fa0),
194 SkBits2Float(0x6bf9abea)); // 2.4375f, 3.625f, 2.85577e-37f, -1.992e-24f, 6.03669e+26f
195 test_draw_AA_path(250, 250, path);
196}

◆ test_fuzz_crbug_643933()

static void test_fuzz_crbug_643933 ( )
static

Definition at line 198 of file PathTest.cpp.

198 {
199 SkPath path;
200 path.moveTo(0, 0);
201 path.conicTo(SkBits2Float(0x002001f2), SkBits2Float(0x4161ffff), // 2.93943e-39f, 14.125f
202 SkBits2Float(0x49f7224d), SkBits2Float(0x45eec8df), // 2.02452e+06f, 7641.11f
203 SkBits2Float(0x721aee0c)); // 3.0687e+30f
204 test_draw_AA_path(250, 250, path);
205 path.reset();
206 path.moveTo(0, 0);
207 path.conicTo(SkBits2Float(0x00007ff2), SkBits2Float(0x4169ffff), // 4.58981e-41f, 14.625f
208 SkBits2Float(0x43ff2261), SkBits2Float(0x41eeea04), // 510.269f, 29.8643f
209 SkBits2Float(0x5d06eff8)); // 6.07704e+17f
210 test_draw_AA_path(250, 250, path);
211}

◆ test_fuzz_crbug_647922()

static void test_fuzz_crbug_647922 ( )
static

Definition at line 213 of file PathTest.cpp.

213 {
214 SkPath path;
215 path.moveTo(0, 0);
216 path.conicTo(SkBits2Float(0x00003939), SkBits2Float(0x42487fff), // 2.05276e-41f, 50.125f
217 SkBits2Float(0x48082361), SkBits2Float(0x4408e8e9), // 139406, 547.639f
218 SkBits2Float(0x4d1ade0f)); // 1.6239e+08f
219 test_draw_AA_path(250, 250, path);
220}

◆ test_fuzz_crbug_662730()

static void test_fuzz_crbug_662730 ( skiatest::Reporter reporter)
static

Definition at line 4687 of file PathTest.cpp.

4687 {
4688 SkPath path;
4689 path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0
4690 path.lineTo(SkBits2Float(0xd5394437), SkBits2Float(0x37373737)); // -1.2731e+13f, 1.09205e-05f
4691 path.lineTo(SkBits2Float(0x37373737), SkBits2Float(0x37373737)); // 1.09205e-05f, 1.09205e-05f
4692 path.lineTo(SkBits2Float(0x37373745), SkBits2Float(0x0001b800)); // 1.09205e-05f, 1.57842e-40f
4693 path.close();
4694 test_draw_AA_path(100, 100, path);
4695}

◆ test_fuzz_crbug_662780()

static void test_fuzz_crbug_662780 ( )
static

Definition at line 222 of file PathTest.cpp.

222 {
224 SkCanvas* canvas = surface->getCanvas();
226 paint.setAntiAlias(true);
227 SkPath path;
228 path.moveTo(SkBits2Float(0x41000000), SkBits2Float(0x431e0000)); // 8, 158
229 path.lineTo(SkBits2Float(0x41000000), SkBits2Float(0x42f00000)); // 8, 120
230 // 8, 8, 8.00002f, 8, 0.707107f
231 path.conicTo(SkBits2Float(0x41000000), SkBits2Float(0x41000000),
232 SkBits2Float(0x41000010), SkBits2Float(0x41000000), SkBits2Float(0x3f3504f3));
233 path.lineTo(SkBits2Float(0x439a0000), SkBits2Float(0x41000000)); // 308, 8
234 // 308, 8, 308, 8, 0.707107f
235 path.conicTo(SkBits2Float(0x439a0000), SkBits2Float(0x41000000),
236 SkBits2Float(0x439a0000), SkBits2Float(0x41000000), SkBits2Float(0x3f3504f3));
237 path.lineTo(SkBits2Float(0x439a0000), SkBits2Float(0x431e0000)); // 308, 158
238 // 308, 158, 308, 158, 0.707107f
239 path.conicTo(SkBits2Float(0x439a0000), SkBits2Float(0x431e0000),
240 SkBits2Float(0x439a0000), SkBits2Float(0x431e0000), SkBits2Float(0x3f3504f3));
241 path.lineTo(SkBits2Float(0x41000000), SkBits2Float(0x431e0000)); // 8, 158
242 // 8, 158, 8, 158, 0.707107f
243 path.conicTo(SkBits2Float(0x41000000), SkBits2Float(0x431e0000),
244 SkBits2Float(0x41000000), SkBits2Float(0x431e0000), SkBits2Float(0x3f3504f3));
245 path.close();
246 canvas->clipPath(path, true);
247 canvas->drawRect(SkRect::MakeWH(250, 250), paint);
248}
void drawRect(const SkRect &rect, const SkPaint &paint)

◆ test_fuzz_crbug_662952()

static void test_fuzz_crbug_662952 ( skiatest::Reporter reporter)
static

Definition at line 4648 of file PathTest.cpp.

4648 {
4649 SkPath path;
4650 path.moveTo(SkBits2Float(0x4109999a), SkBits2Float(0x411c0000)); // 8.6f, 9.75f
4651 path.lineTo(SkBits2Float(0x410a6666), SkBits2Float(0x411c0000)); // 8.65f, 9.75f
4652 path.lineTo(SkBits2Float(0x410a6666), SkBits2Float(0x411e6666)); // 8.65f, 9.9f
4653 path.lineTo(SkBits2Float(0x4109999a), SkBits2Float(0x411e6666)); // 8.6f, 9.9f
4654 path.lineTo(SkBits2Float(0x4109999a), SkBits2Float(0x411c0000)); // 8.6f, 9.75f
4655 path.close();
4656
4658 SkPaint paint;
4659 paint.setAntiAlias(true);
4660 surface->getCanvas()->clipPath(path, true);
4661 surface->getCanvas()->drawRect(SkRect::MakeWH(100, 100), paint);
4662}

◆ test_fuzz_crbug_668907()

static void test_fuzz_crbug_668907 ( )
static

Definition at line 264 of file PathTest.cpp.

264 {
265 SkPath path;
266 path.moveTo(SkBits2Float(0x46313741), SkBits2Float(0x3b00e540)); // 11341.8f, 0.00196679f
267 path.quadTo(SkBits2Float(0x41410041), SkBits2Float(0xc1414141), SkBits2Float(0x41414141),
268 SkBits2Float(0x414100ff)); // 12.0626f, -12.0784f, 12.0784f, 12.0627f
269 path.lineTo(SkBits2Float(0x46313741), SkBits2Float(0x3b00e540)); // 11341.8f, 0.00196679f
270 path.close();
271 test_draw_AA_path(400, 500, path);
272}

◆ test_gen_id()

static void test_gen_id ( skiatest::Reporter reporter)
static

Definition at line 409 of file PathTest.cpp.

409 {
410 SkPath a, b;
411 REPORTER_ASSERT(reporter, a.getGenerationID() == b.getGenerationID());
412
413 a.moveTo(0, 0);
414 const uint32_t z = a.getGenerationID();
415 REPORTER_ASSERT(reporter, z != b.getGenerationID());
416
417 a.reset();
418 REPORTER_ASSERT(reporter, a.getGenerationID() == b.getGenerationID());
419
420 a.moveTo(1, 1);
421 const uint32_t y = a.getGenerationID();
423
424 b.moveTo(2, 2);
425 const uint32_t x = b.getGenerationID();
426 REPORTER_ASSERT(reporter, x != y && x != z);
427
428 a.swap(b);
429 REPORTER_ASSERT(reporter, b.getGenerationID() == y && a.getGenerationID() == x);
430
431 b = a;
432 REPORTER_ASSERT(reporter, b.getGenerationID() == x);
433
434 SkPath c(a);
435 REPORTER_ASSERT(reporter, c.getGenerationID() == x);
436
437 c.lineTo(3, 3);
438 const uint32_t w = c.getGenerationID();
439 REPORTER_ASSERT(reporter, b.getGenerationID() == x);
440 REPORTER_ASSERT(reporter, a.getGenerationID() == x);
442
443#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
444 static bool kExpectGenIDToIgnoreFill = false;
445#else
446 static bool kExpectGenIDToIgnoreFill = true;
447#endif
448
449 c.toggleInverseFillType();
450 const uint32_t v = c.getGenerationID();
451 REPORTER_ASSERT(reporter, (v == w) == kExpectGenIDToIgnoreFill);
452
453 c.rewind();
454 REPORTER_ASSERT(reporter, v != c.getGenerationID());
455}

◆ test_get_point()

static void test_get_point ( skiatest::Reporter reporter)
static

Definition at line 4217 of file PathTest.cpp.

4217 {
4218 SkPath p;
4219 SkPoint pt = p.getPoint(0);
4221 REPORTER_ASSERT(reporter, !p.getLastPt(nullptr));
4222 REPORTER_ASSERT(reporter, !p.getLastPt(&pt) && pt == SkPoint::Make(0, 0));
4223 p.setLastPt(10, 10);
4224 pt = p.getPoint(0);
4225 REPORTER_ASSERT(reporter, pt == SkPoint::Make(10, 10));
4226 REPORTER_ASSERT(reporter, p.getLastPt(nullptr));
4227 p.rMoveTo(10, 10);
4228 REPORTER_ASSERT(reporter, p.getLastPt(&pt) && pt == SkPoint::Make(20, 20));
4229}

◆ test_interp()

static void test_interp ( skiatest::Reporter reporter)
static

Definition at line 4922 of file PathTest.cpp.

4922 {
4923 SkPath p1, p2, out;
4925 REPORTER_ASSERT(reporter, p1.interpolate(p2, 0, &out));
4926 REPORTER_ASSERT(reporter, p1 == out);
4927 REPORTER_ASSERT(reporter, p1.interpolate(p2, 1, &out));
4928 REPORTER_ASSERT(reporter, p1 == out);
4929 p1.moveTo(0, 2);
4930 p1.lineTo(0, 4);
4932 REPORTER_ASSERT(reporter, !p1.interpolate(p2, 1, &out));
4933 p2.moveTo(6, 0);
4934 p2.lineTo(8, 0);
4936 REPORTER_ASSERT(reporter, p1.interpolate(p2, 0, &out));
4937 REPORTER_ASSERT(reporter, p2 == out);
4938 REPORTER_ASSERT(reporter, p1.interpolate(p2, 1, &out));
4939 REPORTER_ASSERT(reporter, p1 == out);
4940 REPORTER_ASSERT(reporter, p1.interpolate(p2, 0.5f, &out));
4941 REPORTER_ASSERT(reporter, out.getBounds() == SkRect::MakeLTRB(3, 1, 4, 2));
4942 p1.reset();
4943 p1.moveTo(4, 4);
4944 p1.conicTo(5, 4, 5, 5, 1 / SkScalarSqrt(2));
4945 p2.reset();
4946 p2.moveTo(4, 2);
4947 p2.conicTo(7, 2, 7, 5, 1 / SkScalarSqrt(2));
4949 REPORTER_ASSERT(reporter, p1.interpolate(p2, 0.5f, &out));
4950 REPORTER_ASSERT(reporter, out.getBounds() == SkRect::MakeLTRB(4, 3, 6, 5));
4951 p2.reset();
4952 p2.moveTo(4, 2);
4953 p2.conicTo(6, 3, 6, 5, 1);
4955 p2.reset();
4956 p2.moveTo(4, 4);
4957 p2.conicTo(5, 4, 5, 5, 0.5f);
4959}
#define SkScalarSqrt(x)
Definition SkScalar.h:42
bool isInterpolatable(const SkPath &compare) const
Definition SkPath.cpp:241
bool interpolate(const SkPath &ending, SkScalar weight, SkPath *out) const
Definition SkPath.cpp:248

◆ test_is_closed_rect()

static void test_is_closed_rect ( skiatest::Reporter reporter)
static

Definition at line 2312 of file PathTest.cpp.

2312 {
2313 using std::swap;
2316 unsigned s = ~0U;
2317
2318 const SkRect testRect = SkRect::MakeXYWH(10, 10, 50, 70);
2319 const SkRect emptyRect = SkRect::MakeEmpty();
2320 for (int start = 0; start < 4; ++start) {
2321 for (auto dir : {SkPathDirection::kCCW, SkPathDirection::kCW}) {
2322 SkPath path;
2323 path.addRect(testRect, dir, start);
2324 check_simple_rect(reporter, path, true, testRect, dir, start);
2325 path.close();
2326 check_simple_rect(reporter, path, true, testRect, dir, start);
2327 SkPath path2 = path;
2328 path2.lineTo(10, 10);
2331 path2 = path;
2332 path2.moveTo(10, 10);
2335 path2 = path;
2336 path2.addRect(testRect, dir, start);
2339 // Make the path by hand, manually closing it.
2340 path2.reset();
2341 SkPoint firstPt = {0.f, 0.f};
2342 for (auto [v, verbPts, w] : SkPathPriv::Iterate(path)) {
2343 switch(v) {
2344 case SkPathVerb::kMove:
2345 firstPt = verbPts[0];
2346 path2.moveTo(verbPts[0]);
2347 break;
2348 case SkPathVerb::kLine:
2349 path2.lineTo(verbPts[1]);
2350 break;
2351 default:
2352 break;
2353 }
2354 }
2355 // We haven't closed it yet...
2358 // ... now we do and test again.
2359 path2.lineTo(firstPt);
2360 check_simple_rect(reporter, path2, false, testRect, dir, start);
2361 // A redundant close shouldn't cause a failure.
2362 path2.close();
2363 check_simple_rect(reporter, path2, true, testRect, dir, start);
2364 // Degenerate point and line rects are not allowed
2365 path2.reset();
2366 path2.addRect(emptyRect, dir, start);
2369 SkRect degenRect = testRect;
2370 degenRect.fLeft = degenRect.fRight;
2371 path2.reset();
2372 path2.addRect(degenRect, dir, start);
2375 degenRect = testRect;
2376 degenRect.fTop = degenRect.fBottom;
2377 path2.reset();
2378 path2.addRect(degenRect, dir, start);
2381 // An inverted rect makes a rect path, but changes the winding dir and start point.
2385 static constexpr unsigned kXSwapStarts[] = { 1, 0, 3, 2 };
2386 static constexpr unsigned kYSwapStarts[] = { 3, 2, 1, 0 };
2387 SkRect swapRect = testRect;
2388 swap(swapRect.fLeft, swapRect.fRight);
2389 path2.reset();
2390 path2.addRect(swapRect, dir, start);
2391 check_simple_rect(reporter, path2, true, testRect, swapDir, kXSwapStarts[start]);
2392 swapRect = testRect;
2393 swap(swapRect.fTop, swapRect.fBottom);
2394 path2.reset();
2395 path2.addRect(swapRect, dir, start);
2396 check_simple_rect(reporter, path2, true, testRect, swapDir, kYSwapStarts[start]);
2397 }
2398 }
2399 // down, up, left, close
2400 SkPath path;
2401 path.moveTo(1, 1);
2402 path.lineTo(1, 2);
2403 path.lineTo(1, 1);
2404 path.lineTo(0, 1);
2405 SkRect rect;
2407 unsigned start;
2408 path.close();
2409 REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path, false, &rect, &dir, &start));
2410 REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path, true, &rect, &dir, &start));
2411 // right, left, up, close
2412 path.reset();
2413 path.moveTo(1, 1);
2414 path.lineTo(2, 1);
2415 path.lineTo(1, 1);
2416 path.lineTo(1, 0);
2417 path.close();
2418 REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path, false, &rect, &dir, &start));
2419 REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path, true, &rect, &dir, &start));
2420 // parallelogram with horizontal edges
2421 path.reset();
2422 path.moveTo(1, 0);
2423 path.lineTo(3, 0);
2424 path.lineTo(2, 1);
2425 path.lineTo(0, 1);
2426 path.close();
2427 REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path, false, &rect, &dir, &start));
2428 REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path, true, &rect, &dir, &start));
2429 // parallelogram with vertical edges
2430 path.reset();
2431 path.moveTo(0, 1);
2432 path.lineTo(0, 3);
2433 path.lineTo(1, 2);
2434 path.lineTo(1, 0);
2435 path.close();
2436 REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path, false, &rect, &dir, &start));
2437 REPORTER_ASSERT(reporter, !SkPathPriv::IsSimpleRect(path, true, &rect, &dir, &start));
2438
2439}
static void check_simple_rect(skiatest::Reporter *reporter, const SkPath &path, bool isClosed, const SkRect &rect, SkPathDirection dir, unsigned start)

◆ test_isArc()

static void test_isArc ( skiatest::Reporter reporter)
static

Definition at line 2441 of file PathTest.cpp.

2441 {
2442 SkPath path;
2443 REPORTER_ASSERT(reporter, !path.isArc(nullptr));
2444
2445 // One circle, one oval:
2446 const SkRect kOvals[] = { SkRect::MakeWH(100, 100), SkRect::MakeWH(100, 200)};
2447
2448 // Various start and sweep angles. Note that we can't test with more than a full revolution,
2449 // those cases are automatically converted to ovals by SkPath.
2450 const SkScalar kStartAngles[] = { -270, -135, -45, 0, 10, 70, 180, 350 };
2451 const SkScalar kSweepAngles[] = { -350, -190, -90, -5, 5, 89, 180, 270, 350 };
2452
2453 int mutator = 0;
2454
2455 for (SkRect oval : kOvals) {
2456 for (SkScalar startAngle : kStartAngles) {
2457 for (SkScalar sweepAngle : kSweepAngles) {
2458 // For now, isArc only works for arcs where useCenter is false!
2459 // TODO: When that's fixed, add more tests cases here.
2460 path.rewind();
2461 // Include an extra moveTo at the start - this should not interfere with isArc
2462 path.moveTo(oval.center());
2463 path.addArc(oval, startAngle, sweepAngle);
2464
2465 SkArc arc;
2466 REPORTER_ASSERT(reporter, path.isArc(&arc));
2468 oval == arc.fOval &&
2469 startAngle == arc.fStartAngle &&
2470 sweepAngle == arc.fSweepAngle &&
2471 !arc.fUseCenter);
2472
2473 // Apply some mutation. All of these should cause the path to no longer be an arc:
2474 switch (mutator) {
2475 case 0:
2476 path.addArc(oval, startAngle, sweepAngle);
2477 break;
2478 case 1:
2479 path.lineTo(oval.center());
2480 break;
2481 case 2:
2482 path.lineTo(path.getPoint(0));
2483 break;
2484 case 3:
2485 path.close();
2486 break;
2487 case 4:
2488 path.moveTo(oval.center());
2489 break;
2490 default:
2492 }
2493 mutator = (mutator + 1) % 5;
2494 REPORTER_ASSERT(reporter, !path.isArc(nullptr));
2495 }
2496 }
2497 }
2498
2499 // Having any non-move verb before the arc should cause isArc to return false:
2500 path.rewind();
2501 path.lineTo(kOvals[0].center());
2502 path.addArc(kOvals[0], kStartAngles[0], kSweepAngles[0]);
2503 REPORTER_ASSERT(reporter, !path.isArc(nullptr));
2504
2505 // Finally, transforming an arc path by a non-identity should always result in a non-arc path:
2506 // TODO: We could clearly preserve arcs for translation, and for scale/rotation with extra work.
2507 for (SkMatrix m :
2509 path.rewind();
2510 path.addArc(kOvals[0], kStartAngles[0], kSweepAngles[0]);
2511 REPORTER_ASSERT(reporter, path.isArc(nullptr));
2512 path.transform(SkMatrix::I());
2513 REPORTER_ASSERT(reporter, path.isArc(nullptr));
2514 path.transform(m);
2515 REPORTER_ASSERT(reporter, !path.isArc(nullptr));
2516 }
2517}
#define SkUNREACHABLE
Definition SkAssert.h:135
static SkScalar center(float pos0, float pos1)
static SkMatrix RotateDeg(SkScalar deg)
Definition SkMatrix.h:104
static SkMatrix Translate(SkScalar dx, SkScalar dy)
Definition SkMatrix.h:91
static const SkMatrix & I()
Definition SkArc.h:15
bool fUseCenter
Definition SkArc.h:26
SkScalar fSweepAngle
Definition SkArc.h:22
SkScalar fStartAngle
Definition SkArc.h:20
SkRect fOval
Definition SkArc.h:17
constexpr SkPoint center() const
Definition SkRect.h:792

◆ test_isfinite()

static void test_isfinite ( skiatest::Reporter reporter)
static

Definition at line 990 of file PathTest.cpp.

990 {
993}
static void test_rect_isfinite(skiatest::Reporter *reporter)
Definition PathTest.cpp:932
static void test_path_isfinite(skiatest::Reporter *reporter)
Definition PathTest.cpp:966

◆ test_isfinite_after_transform()

static void test_isfinite_after_transform ( skiatest::Reporter reporter)
static

Definition at line 810 of file PathTest.cpp.

810 {
811 SkPath path;
812 path.quadTo(157, 366, 286, 208);
813 path.arcTo(37, 442, 315, 163, 957494590897113.0f);
814
816 matrix.setScale(1000*1000, 1000*1000);
817
818 // Be sure that path::transform correctly updates isFinite and the bounds
819 // if the transformation overflows. The previous bug was that isFinite was
820 // set to true in this case, but the bounds were not set to empty (which
821 // they should be).
822 while (path.isFinite()) {
823 REPORTER_ASSERT(reporter, path.getBounds().isFinite());
824 REPORTER_ASSERT(reporter, !path.getBounds().isEmpty());
825 path.transform(matrix);
826 }
827 REPORTER_ASSERT(reporter, path.getBounds().isEmpty());
828
829 matrix.setTranslate(SK_Scalar1, SK_Scalar1);
830 path.transform(matrix);
831 // we need to still be non-finite
832 REPORTER_ASSERT(reporter, !path.isFinite());
833 REPORTER_ASSERT(reporter, path.getBounds().isEmpty());
834}

◆ test_islastcontourclosed()

static void test_islastcontourclosed ( skiatest::Reporter reporter)
static

Definition at line 995 of file PathTest.cpp.

995 {
996 SkPath path;
997 REPORTER_ASSERT(reporter, !path.isLastContourClosed());
998 path.moveTo(0, 0);
999 REPORTER_ASSERT(reporter, !path.isLastContourClosed());
1000 path.close();
1001 REPORTER_ASSERT(reporter, path.isLastContourClosed());
1002 path.lineTo(100, 100);
1003 REPORTER_ASSERT(reporter, !path.isLastContourClosed());
1004 path.moveTo(200, 200);
1005 REPORTER_ASSERT(reporter, !path.isLastContourClosed());
1006 path.close();
1007 REPORTER_ASSERT(reporter, path.isLastContourClosed());
1008 path.moveTo(0, 0);
1009 REPORTER_ASSERT(reporter, !path.isLastContourClosed());
1010}

◆ test_isLine()

static void test_isLine ( skiatest::Reporter reporter)
static

Definition at line 1822 of file PathTest.cpp.

1822 {
1823 SkPath path;
1824 SkPoint pts[2];
1825 const SkScalar value = SkIntToScalar(5);
1826
1827 REPORTER_ASSERT(reporter, !path.isLine(nullptr));
1828
1829 // set some non-zero values
1830 pts[0].set(value, value);
1831 pts[1].set(value, value);
1832 REPORTER_ASSERT(reporter, !path.isLine(pts));
1833 // check that pts was untouched
1834 REPORTER_ASSERT(reporter, pts[0].equals(value, value));
1835 REPORTER_ASSERT(reporter, pts[1].equals(value, value));
1836
1837 const SkScalar moveX = SkIntToScalar(1);
1838 const SkScalar moveY = SkIntToScalar(2);
1839 REPORTER_ASSERT(reporter, value != moveX && value != moveY);
1840
1841 path.moveTo(moveX, moveY);
1842 REPORTER_ASSERT(reporter, !path.isLine(nullptr));
1843 REPORTER_ASSERT(reporter, !path.isLine(pts));
1844 // check that pts was untouched
1845 REPORTER_ASSERT(reporter, pts[0].equals(value, value));
1846 REPORTER_ASSERT(reporter, pts[1].equals(value, value));
1847
1848 const SkScalar lineX = SkIntToScalar(2);
1849 const SkScalar lineY = SkIntToScalar(2);
1850 REPORTER_ASSERT(reporter, value != lineX && value != lineY);
1851
1852 path.lineTo(lineX, lineY);
1853 REPORTER_ASSERT(reporter, path.isLine(nullptr));
1854
1855 REPORTER_ASSERT(reporter, !pts[0].equals(moveX, moveY));
1856 REPORTER_ASSERT(reporter, !pts[1].equals(lineX, lineY));
1857 REPORTER_ASSERT(reporter, path.isLine(pts));
1858 REPORTER_ASSERT(reporter, pts[0].equals(moveX, moveY));
1859 REPORTER_ASSERT(reporter, pts[1].equals(lineX, lineY));
1860
1861 path.lineTo(0, 0); // too many points/verbs
1862 REPORTER_ASSERT(reporter, !path.isLine(nullptr));
1863 REPORTER_ASSERT(reporter, !path.isLine(pts));
1864 REPORTER_ASSERT(reporter, pts[0].equals(moveX, moveY));
1865 REPORTER_ASSERT(reporter, pts[1].equals(lineX, lineY));
1866
1867 path.reset();
1868 path.quadTo(1, 1, 2, 2);
1869 REPORTER_ASSERT(reporter, !path.isLine(nullptr));
1870}
static bool equals(T *a, T *b)
uint8_t value

◆ test_isNestedFillRects()

static void test_isNestedFillRects ( skiatest::Reporter reporter)
static

Definition at line 2519 of file PathTest.cpp.

2519 {
2520 // passing tests (all moveTo / lineTo...
2521 SkPoint r1[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; // CW
2522 SkPoint r2[] = {{1, 0}, {1, 1}, {0, 1}, {0, 0}};
2523 SkPoint r3[] = {{1, 1}, {0, 1}, {0, 0}, {1, 0}};
2524 SkPoint r4[] = {{0, 1}, {0, 0}, {1, 0}, {1, 1}};
2525 SkPoint r5[] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}}; // CCW
2526 SkPoint r6[] = {{0, 1}, {1, 1}, {1, 0}, {0, 0}};
2527 SkPoint r7[] = {{1, 1}, {1, 0}, {0, 0}, {0, 1}};
2528 SkPoint r8[] = {{1, 0}, {0, 0}, {0, 1}, {1, 1}};
2529 SkPoint r9[] = {{0, 1}, {1, 1}, {1, 0}, {0, 0}};
2530 SkPoint ra[] = {{0, 0}, {0, .5f}, {0, 1}, {.5f, 1}, {1, 1}, {1, .5f}, {1, 0}, {.5f, 0}}; // CCW
2531 SkPoint rb[] = {{0, 0}, {.5f, 0}, {1, 0}, {1, .5f}, {1, 1}, {.5f, 1}, {0, 1}, {0, .5f}}; // CW
2532 SkPoint rc[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}}; // CW
2533 SkPoint rd[] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}}; // CCW
2534 SkPoint re[] = {{0, 0}, {1, 0}, {1, 0}, {1, 1}, {0, 1}}; // CW
2535
2536 // failing tests
2537 SkPoint f1[] = {{0, 0}, {1, 0}, {1, 1}}; // too few points
2538 SkPoint f2[] = {{0, 0}, {1, 1}, {0, 1}, {1, 0}}; // diagonal
2539 SkPoint f3[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}, {1, 0}}; // wraps
2540 SkPoint f4[] = {{0, 0}, {1, 0}, {0, 0}, {1, 0}, {1, 1}, {0, 1}}; // backs up
2541 SkPoint f5[] = {{0, 0}, {1, 0}, {1, 1}, {2, 0}}; // end overshoots
2542 SkPoint f6[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 2}}; // end overshoots
2543 SkPoint f7[] = {{0, 0}, {1, 0}, {1, 1}, {0, 2}}; // end overshoots
2544 SkPoint f8[] = {{0, 0}, {1, 0}, {1, 1}, {1, 0}}; // 'L'
2545
2546 // success, no close is OK
2547 SkPoint c1[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; // close doesn't match
2548 SkPoint c2[] = {{0, 0}, {1, 0}, {1, 2}, {0, 2}, {0, 1}}; // ditto
2549
2550 struct IsNestedRectTest {
2551 SkPoint *fPoints;
2552 int fPointCount;
2553 SkPathFirstDirection fDirection;
2554 bool fClose;
2555 bool fIsNestedRect; // nests with path.addRect(-1, -1, 2, 2);
2556 } tests[] = {
2557 { r1, std::size(r1), SkPathFirstDirection::kCW , true, true },
2558 { r2, std::size(r2), SkPathFirstDirection::kCW , true, true },
2559 { r3, std::size(r3), SkPathFirstDirection::kCW , true, true },
2560 { r4, std::size(r4), SkPathFirstDirection::kCW , true, true },
2561 { r5, std::size(r5), SkPathFirstDirection::kCCW, true, true },
2562 { r6, std::size(r6), SkPathFirstDirection::kCCW, true, true },
2563 { r7, std::size(r7), SkPathFirstDirection::kCCW, true, true },
2564 { r8, std::size(r8), SkPathFirstDirection::kCCW, true, true },
2565 { r9, std::size(r9), SkPathFirstDirection::kCCW, true, true },
2566 { ra, std::size(ra), SkPathFirstDirection::kCCW, true, true },
2567 { rb, std::size(rb), SkPathFirstDirection::kCW, true, true },
2568 { rc, std::size(rc), SkPathFirstDirection::kCW, true, true },
2569 { rd, std::size(rd), SkPathFirstDirection::kCCW, true, true },
2570 { re, std::size(re), SkPathFirstDirection::kCW, true, true },
2571
2572 { f1, std::size(f1), SkPathFirstDirection::kUnknown, true, false },
2573 { f2, std::size(f2), SkPathFirstDirection::kUnknown, true, false },
2574 { f3, std::size(f3), SkPathFirstDirection::kUnknown, true, false },
2575 { f4, std::size(f4), SkPathFirstDirection::kUnknown, true, false },
2576 { f5, std::size(f5), SkPathFirstDirection::kUnknown, true, false },
2577 { f6, std::size(f6), SkPathFirstDirection::kUnknown, true, false },
2578 { f7, std::size(f7), SkPathFirstDirection::kUnknown, true, false },
2579 { f8, std::size(f8), SkPathFirstDirection::kUnknown, true, false },
2580
2581 { c1, std::size(c1), SkPathFirstDirection::kCW, false, true },
2582 { c2, std::size(c2), SkPathFirstDirection::kCW, false, true },
2583 };
2584
2585 const size_t testCount = std::size(tests);
2586 int index;
2587 for (int rectFirst = 0; rectFirst <= 1; ++rectFirst) {
2588 for (size_t testIndex = 0; testIndex < testCount; ++testIndex) {
2589 SkPath path;
2590 if (rectFirst) {
2591 path.addRect(-1, -1, 2, 2, SkPathDirection::kCW);
2592 }
2593 path.moveTo(tests[testIndex].fPoints[0].fX, tests[testIndex].fPoints[0].fY);
2594 for (index = 1; index < tests[testIndex].fPointCount; ++index) {
2595 path.lineTo(tests[testIndex].fPoints[index].fX, tests[testIndex].fPoints[index].fY);
2596 }
2597 if (tests[testIndex].fClose) {
2598 path.close();
2599 }
2600 if (!rectFirst) {
2601 path.addRect(-1, -1, 2, 2, SkPathDirection::kCCW);
2602 }
2604 tests[testIndex].fIsNestedRect == SkPathPriv::IsNestedFillRects(path, nullptr));
2605 if (tests[testIndex].fIsNestedRect) {
2606 SkRect expected[2], computed[2];
2607 SkPathFirstDirection expectedDirs[2];
2608 SkPathDirection computedDirs[2];
2609 SkRect testBounds;
2610 testBounds.setBounds(tests[testIndex].fPoints, tests[testIndex].fPointCount);
2611 expected[0] = SkRect::MakeLTRB(-1, -1, 2, 2);
2612 expected[1] = testBounds;
2613 if (rectFirst) {
2614 expectedDirs[0] = SkPathFirstDirection::kCW;
2615 } else {
2616 expectedDirs[0] = SkPathFirstDirection::kCCW;
2617 }
2618 expectedDirs[1] = tests[testIndex].fDirection;
2619 REPORTER_ASSERT(reporter, SkPathPriv::IsNestedFillRects(path, computed, computedDirs));
2620 REPORTER_ASSERT(reporter, expected[0] == computed[0]);
2621 REPORTER_ASSERT(reporter, expected[1] == computed[1]);
2622 REPORTER_ASSERT(reporter, expectedDirs[0] == SkPathPriv::AsFirstDirection(computedDirs[0]));
2623 REPORTER_ASSERT(reporter, expectedDirs[1] == SkPathPriv::AsFirstDirection(computedDirs[1]));
2624 }
2625 }
2626
2627 // fail, close then line
2628 SkPath path1;
2629 if (rectFirst) {
2630 path1.addRect(-1, -1, 2, 2, SkPathDirection::kCW);
2631 }
2632 path1.moveTo(r1[0].fX, r1[0].fY);
2633 for (index = 1; index < SkToInt(std::size(r1)); ++index) {
2634 path1.lineTo(r1[index].fX, r1[index].fY);
2635 }
2636 path1.close();
2637 path1.lineTo(1, 0);
2638 if (!rectFirst) {
2639 path1.addRect(-1, -1, 2, 2, SkPathDirection::kCCW);
2640 }
2642
2643 // fail, move in the middle
2644 path1.reset();
2645 if (rectFirst) {
2646 path1.addRect(-1, -1, 2, 2, SkPathDirection::kCW);
2647 }
2648 path1.moveTo(r1[0].fX, r1[0].fY);
2649 for (index = 1; index < SkToInt(std::size(r1)); ++index) {
2650 if (index == 2) {
2651 path1.moveTo(1, .5f);
2652 }
2653 path1.lineTo(r1[index].fX, r1[index].fY);
2654 }
2655 path1.close();
2656 if (!rectFirst) {
2657 path1.addRect(-1, -1, 2, 2, SkPathDirection::kCCW);
2658 }
2660
2661 // fail, move on the edge
2662 path1.reset();
2663 if (rectFirst) {
2664 path1.addRect(-1, -1, 2, 2, SkPathDirection::kCW);
2665 }
2666 for (index = 1; index < SkToInt(std::size(r1)); ++index) {
2667 path1.moveTo(r1[index - 1].fX, r1[index - 1].fY);
2668 path1.lineTo(r1[index].fX, r1[index].fY);
2669 }
2670 path1.close();
2671 if (!rectFirst) {
2672 path1.addRect(-1, -1, 2, 2, SkPathDirection::kCCW);
2673 }
2675
2676 // fail, quad
2677 path1.reset();
2678 if (rectFirst) {
2679 path1.addRect(-1, -1, 2, 2, SkPathDirection::kCW);
2680 }
2681 path1.moveTo(r1[0].fX, r1[0].fY);
2682 for (index = 1; index < SkToInt(std::size(r1)); ++index) {
2683 if (index == 2) {
2684 path1.quadTo(1, .5f, 1, .5f);
2685 }
2686 path1.lineTo(r1[index].fX, r1[index].fY);
2687 }
2688 path1.close();
2689 if (!rectFirst) {
2690 path1.addRect(-1, -1, 2, 2, SkPathDirection::kCCW);
2691 }
2693
2694 // fail, cubic
2695 path1.reset();
2696 if (rectFirst) {
2697 path1.addRect(-1, -1, 2, 2, SkPathDirection::kCW);
2698 }
2699 path1.moveTo(r1[0].fX, r1[0].fY);
2700 for (index = 1; index < SkToInt(std::size(r1)); ++index) {
2701 if (index == 2) {
2702 path1.cubicTo(1, .5f, 1, .5f, 1, .5f);
2703 }
2704 path1.lineTo(r1[index].fX, r1[index].fY);
2705 }
2706 path1.close();
2707 if (!rectFirst) {
2708 path1.addRect(-1, -1, 2, 2, SkPathDirection::kCCW);
2709 }
2711
2712 // fail, not nested
2713 path1.reset();
2714 path1.addRect(1, 1, 3, 3, SkPathDirection::kCW);
2715 path1.addRect(2, 2, 4, 4, SkPathDirection::kCW);
2717 }
2718
2719 // pass, constructed explicitly from manually closed rects specified as moves/lines.
2720 SkPath path;
2721 path.moveTo(0, 0);
2722 path.lineTo(10, 0);
2723 path.lineTo(10, 10);
2724 path.lineTo(0, 10);
2725 path.lineTo(0, 0);
2726 path.moveTo(1, 1);
2727 path.lineTo(9, 1);
2728 path.lineTo(9, 9);
2729 path.lineTo(1, 9);
2730 path.lineTo(1, 1);
2732
2733 // pass, stroke rect
2734 SkPath src, dst;
2735 src.addRect(1, 1, 7, 7, SkPathDirection::kCW);
2736 SkPaint strokePaint;
2737 strokePaint.setStyle(SkPaint::kStroke_Style);
2738 strokePaint.setStrokeWidth(2);
2739 skpathutils::FillPathWithPaint(src, strokePaint, &dst);
2741}
static const size_t testCount
void setStyle(Style style)
Definition SkPaint.cpp:105
void setStrokeWidth(SkScalar width)
Definition SkPaint.cpp:159
static bool IsNestedFillRects(const SkPath &, SkRect rect[2], SkPathDirection dirs[2]=nullptr)
Definition SkPath.cpp:3712

◆ test_isRect()

static void test_isRect ( skiatest::Reporter reporter)
static

Definition at line 2115 of file PathTest.cpp.

2115 {
2117
2118 // passing tests (all moveTo / lineTo...
2119 SkPoint r1[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
2120 SkPoint r2[] = {{1, 0}, {1, 1}, {0, 1}, {0, 0}};
2121 SkPoint r3[] = {{1, 1}, {0, 1}, {0, 0}, {1, 0}};
2122 SkPoint r4[] = {{0, 1}, {0, 0}, {1, 0}, {1, 1}};
2123 SkPoint r5[] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}};
2124 SkPoint r6[] = {{0, 1}, {1, 1}, {1, 0}, {0, 0}};
2125 SkPoint r7[] = {{1, 1}, {1, 0}, {0, 0}, {0, 1}};
2126 SkPoint r8[] = {{1, 0}, {0, 0}, {0, 1}, {1, 1}};
2127 SkPoint r9[] = {{0, 1}, {1, 1}, {1, 0}, {0, 0}};
2128 SkPoint ra[] = {{0, 0}, {0, .5f}, {0, 1}, {.5f, 1}, {1, 1}, {1, .5f}, {1, 0}, {.5f, 0}};
2129 SkPoint rb[] = {{0, 0}, {.5f, 0}, {1, 0}, {1, .5f}, {1, 1}, {.5f, 1}, {0, 1}, {0, .5f}};
2130 SkPoint rc[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}};
2131 SkPoint rd[] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}};
2132 SkPoint re[] = {{0, 0}, {1, 0}, {1, 0}, {1, 1}, {0, 1}};
2133 SkPoint rf[] = {{1, 0}, {8, 0}, {8, 8}, {0, 8}, {0, 0}};
2134
2135 // failing tests
2136 SkPoint f1[] = {{0, 0}, {1, 0}, {1, 1}}; // too few points
2137 SkPoint f2[] = {{0, 0}, {1, 1}, {0, 1}, {1, 0}}; // diagonal
2138 SkPoint f3[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}, {1, 0}}; // wraps
2139 SkPoint f4[] = {{0, 0}, {1, 0}, {0, 0}, {1, 0}, {1, 1}, {0, 1}}; // backs up
2140 SkPoint f5[] = {{0, 0}, {1, 0}, {1, 1}, {2, 0}}; // end overshoots
2141 SkPoint f6[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 2}}; // end overshoots
2142 SkPoint f7[] = {{0, 0}, {1, 0}, {1, 1}, {0, 2}}; // end overshoots
2143 SkPoint f8[] = {{0, 0}, {1, 0}, {1, 1}, {1, 0}}; // 'L'
2144 SkPoint f9[] = {{1, 0}, {8, 0}, {8, 8}, {0, 8}, {0, 0}, {2, 0}}; // overlaps
2145 SkPoint fa[] = {{1, 0}, {8, 0}, {8, 8}, {0, 8}, {0, -1}, {1, -1}}; // non colinear gap
2146 SkPoint fb[] = {{1, 0}, {8, 0}, {8, 8}, {0, 8}, {0, 1}}; // falls short
2147
2148 // no close, but we should detect them as fillably the same as a rect
2149 SkPoint c1[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
2150 SkPoint c2[] = {{0, 0}, {1, 0}, {1, 2}, {0, 2}, {0, 1}};
2151 SkPoint c3[] = {{0, 0}, {1, 0}, {1, 2}, {0, 2}, {0, 1}, {0, 0}}; // hit the start
2152
2153 // like c2, but we double-back on ourselves
2154 SkPoint d1[] = {{0, 0}, {1, 0}, {1, 2}, {0, 2}, {0, 1}, {0, 2}};
2155 // like c2, but we overshoot the start point
2156 SkPoint d2[] = {{0, 0}, {1, 0}, {1, 2}, {0, 2}, {0, -1}};
2157 SkPoint d3[] = {{0, 0}, {1, 0}, {1, 2}, {0, 2}, {0, -1}, {0, 0}};
2158
2159 struct IsRectTest {
2160 SkPoint *fPoints;
2161 int fPointCount;
2162 bool fClose;
2163 bool fIsRect;
2164 } tests[] = {
2165 { r1, std::size(r1), true, true },
2166 { r2, std::size(r2), true, true },
2167 { r3, std::size(r3), true, true },
2168 { r4, std::size(r4), true, true },
2169 { r5, std::size(r5), true, true },
2170 { r6, std::size(r6), true, true },
2171 { r7, std::size(r7), true, true },
2172 { r8, std::size(r8), true, true },
2173 { r9, std::size(r9), true, true },
2174 { ra, std::size(ra), true, true },
2175 { rb, std::size(rb), true, true },
2176 { rc, std::size(rc), true, true },
2177 { rd, std::size(rd), true, true },
2178 { re, std::size(re), true, true },
2179 { rf, std::size(rf), true, true },
2180
2181 { f1, std::size(f1), true, false },
2182 { f2, std::size(f2), true, false },
2183 { f3, std::size(f3), true, false },
2184 { f4, std::size(f4), true, false },
2185 { f5, std::size(f5), true, false },
2186 { f6, std::size(f6), true, false },
2187 { f7, std::size(f7), true, false },
2188 { f8, std::size(f8), true, false },
2189 { f9, std::size(f9), true, false },
2190 { fa, std::size(fa), true, false },
2191 { fb, std::size(fb), true, false },
2192
2193 { c1, std::size(c1), false, true },
2194 { c2, std::size(c2), false, true },
2195 { c3, std::size(c3), false, true },
2196
2197 { d1, std::size(d1), false, false },
2198 { d2, std::size(d2), false, true },
2199 { d3, std::size(d3), false, false },
2200 };
2201
2202 const size_t testCount = std::size(tests);
2203 int index;
2204 for (size_t testIndex = 0; testIndex < testCount; ++testIndex) {
2205 SkPath path;
2206 path.moveTo(tests[testIndex].fPoints[0].fX, tests[testIndex].fPoints[0].fY);
2207 for (index = 1; index < tests[testIndex].fPointCount; ++index) {
2208 path.lineTo(tests[testIndex].fPoints[index].fX, tests[testIndex].fPoints[index].fY);
2209 }
2210 if (tests[testIndex].fClose) {
2211 path.close();
2212 }
2213 REPORTER_ASSERT(reporter, tests[testIndex].fIsRect == path.isRect(nullptr));
2214
2215 if (tests[testIndex].fIsRect) {
2216 SkRect computed, expected;
2217 bool isClosed;
2218 SkPathDirection direction;
2219 int pointCount = tests[testIndex].fPointCount - (d2 == tests[testIndex].fPoints);
2220 expected.setBounds(tests[testIndex].fPoints, pointCount);
2223 REPORTER_ASSERT(reporter, path.isRect(&computed, &isClosed, &direction));
2224 REPORTER_ASSERT(reporter, expected == computed);
2225 REPORTER_ASSERT(reporter, isClosed == tests[testIndex].fClose);
2226 REPORTER_ASSERT(reporter, SkPathPriv::AsFirstDirection(direction) == cheapDirection);
2227 } else {
2228 SkRect computed;
2229 computed.setLTRB(123, 456, 789, 1011);
2230 for (auto c : {true, false})
2232 bool isClosed = c;
2233 SkPathDirection direction = d;
2234 REPORTER_ASSERT(reporter, !path.isRect(&computed, &isClosed, &direction));
2235 REPORTER_ASSERT(reporter, computed.fLeft == 123 && computed.fTop == 456);
2236 REPORTER_ASSERT(reporter, computed.fRight == 789 && computed.fBottom == 1011);
2237 REPORTER_ASSERT(reporter, isClosed == c);
2238 REPORTER_ASSERT(reporter, direction == d);
2239 }
2240 }
2241 }
2242
2243 // fail, close then line
2244 SkPath path1;
2245 path1.moveTo(r1[0].fX, r1[0].fY);
2246 for (index = 1; index < SkToInt(std::size(r1)); ++index) {
2247 path1.lineTo(r1[index].fX, r1[index].fY);
2248 }
2249 path1.close();
2250 path1.lineTo(1, 0);
2252
2253 // fail, move in the middle
2254 path1.reset();
2255 path1.moveTo(r1[0].fX, r1[0].fY);
2256 for (index = 1; index < SkToInt(std::size(r1)); ++index) {
2257 if (index == 2) {
2258 path1.moveTo(1, .5f);
2259 }
2260 path1.lineTo(r1[index].fX, r1[index].fY);
2261 }
2262 path1.close();
2264
2265 // fail, move on the edge
2266 path1.reset();
2267 for (index = 1; index < SkToInt(std::size(r1)); ++index) {
2268 path1.moveTo(r1[index - 1].fX, r1[index - 1].fY);
2269 path1.lineTo(r1[index].fX, r1[index].fY);
2270 }
2271 path1.close();
2273
2274 // fail, quad
2275 path1.reset();
2276 path1.moveTo(r1[0].fX, r1[0].fY);
2277 for (index = 1; index < SkToInt(std::size(r1)); ++index) {
2278 if (index == 2) {
2279 path1.quadTo(1, .5f, 1, .5f);
2280 }
2281 path1.lineTo(r1[index].fX, r1[index].fY);
2282 }
2283 path1.close();
2285
2286 // fail, cubic
2287 path1.reset();
2288 path1.moveTo(r1[0].fX, r1[0].fY);
2289 for (index = 1; index < SkToInt(std::size(r1)); ++index) {
2290 if (index == 2) {
2291 path1.cubicTo(1, .5f, 1, .5f, 1, .5f);
2292 }
2293 path1.lineTo(r1[index].fX, r1[index].fY);
2294 }
2295 path1.close();
2297}
static void test_isRect_open_close(skiatest::Reporter *reporter)

◆ test_isRect_open_close()

static void test_isRect_open_close ( skiatest::Reporter reporter)
static

Definition at line 2102 of file PathTest.cpp.

2102 {
2103 SkPath path;
2104 bool isClosed;
2105
2106 path.moveTo(0, 0); path.lineTo(1, 0); path.lineTo(1, 1); path.lineTo(0, 1);
2107 path.close();
2108
2109 REPORTER_ASSERT(reporter, path.isRect(nullptr, &isClosed, nullptr));
2110 REPORTER_ASSERT(reporter, isClosed);
2111}

◆ test_iter()

static void test_iter ( skiatest::Reporter reporter)
static

Definition at line 3058 of file PathTest.cpp.

3058 {
3059 SkPath p;
3060 SkPoint pts[4];
3061
3062 // Test an iterator with no path
3063 SkPath::Iter noPathIter;
3064 REPORTER_ASSERT(reporter, noPathIter.next(pts) == SkPath::kDone_Verb);
3065
3066 // Test that setting an empty path works
3067 noPathIter.setPath(p, false);
3068 REPORTER_ASSERT(reporter, noPathIter.next(pts) == SkPath::kDone_Verb);
3069
3070 // Test that close path makes no difference for an empty path
3071 noPathIter.setPath(p, true);
3072 REPORTER_ASSERT(reporter, noPathIter.next(pts) == SkPath::kDone_Verb);
3073
3074 // Test an iterator with an initial empty path
3075 SkPath::Iter iter(p, false);
3076 REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kDone_Verb);
3077
3078 // Test that close path makes no difference
3079 iter.setPath(p, true);
3080 REPORTER_ASSERT(reporter, iter.next(pts) == SkPath::kDone_Verb);
3081
3082
3083 struct iterTestData {
3084 const char* testPath;
3085 const bool forceClose;
3086 const size_t* numResultPtsPerVerb;
3087 const SkPoint* resultPts;
3088 const SkPath::Verb* resultVerbs;
3089 const size_t numResultVerbs;
3090 };
3091
3092 static const SkPath::Verb resultVerbs1[] = { SkPath::kDone_Verb };
3093 static const SkPath::Verb resultVerbs2[] = {
3095 };
3096 static const SkPath::Verb resultVerbs3[] = {
3098 };
3099 static const size_t resultPtsSizes1[] = { 0 };
3100 static const size_t resultPtsSizes2[] = { 1, 2, 1, 1, 0 };
3101 static const size_t resultPtsSizes3[] = { 1, 2, 1, 1, 1, 0 };
3102 static const SkPoint* resultPts1 = nullptr;
3103 static const SkPoint resultPts2[] = {
3104 { SK_Scalar1, 0 }, { SK_Scalar1, 0 }, { SK_Scalar1, 0 }, { 0, 0 }, { 0, 0 }
3105 };
3106 static const SkPoint resultPts3[] = {
3107 { SK_Scalar1, 0 }, { SK_Scalar1, 0 }, { SK_Scalar1, 0 }, { SK_Scalar1, 0 }, { 0, 0 }, { 0, 0 }
3108 };
3109 static const struct iterTestData gIterTests[] = {
3110 { "M 1 0", false, resultPtsSizes1, resultPts1, resultVerbs1, std::size(resultVerbs1) },
3111 { "z", false, resultPtsSizes1, resultPts1, resultVerbs1, std::size(resultVerbs1) },
3112 { "z", true, resultPtsSizes1, resultPts1, resultVerbs1, std::size(resultVerbs1) },
3113 { "M 1 0 L 1 0 M 0 0 z", false, resultPtsSizes2, resultPts2, resultVerbs2, std::size(resultVerbs2) },
3114 { "M 1 0 L 1 0 M 0 0 z", true, resultPtsSizes3, resultPts3, resultVerbs3, std::size(resultVerbs3) }
3115 };
3116
3117 for (size_t i = 0; i < std::size(gIterTests); ++i) {
3118 p.reset();
3119 bool valid = SkParsePath::FromSVGString(gIterTests[i].testPath, &p);
3120 REPORTER_ASSERT(reporter, valid);
3121 iter.setPath(p, gIterTests[i].forceClose);
3122 int j = 0, l = 0;
3123 do {
3124 REPORTER_ASSERT(reporter, iter.next(pts) == gIterTests[i].resultVerbs[j]);
3125 for (int k = 0; k < (int)gIterTests[i].numResultPtsPerVerb[j]; ++k) {
3126 REPORTER_ASSERT(reporter, pts[k] == gIterTests[i].resultPts[l++]);
3127 }
3128 } while (gIterTests[i].resultVerbs[j++] != SkPath::kDone_Verb);
3129 REPORTER_ASSERT(reporter, j == (int)gIterTests[i].numResultVerbs);
3130 }
3131
3132 p.reset();
3133 iter.setPath(p, false);
3134 REPORTER_ASSERT(reporter, !iter.isClosedContour());
3135 p.lineTo(1, 1);
3136 p.close();
3137 iter.setPath(p, false);
3138 REPORTER_ASSERT(reporter, iter.isClosedContour());
3139 p.reset();
3140 iter.setPath(p, true);
3141 REPORTER_ASSERT(reporter, !iter.isClosedContour());
3142 p.lineTo(1, 1);
3143 iter.setPath(p, true);
3144 REPORTER_ASSERT(reporter, iter.isClosedContour());
3145 p.moveTo(0, 0);
3146 p.lineTo(2, 2);
3147 iter.setPath(p, false);
3148 REPORTER_ASSERT(reporter, !iter.isClosedContour());
3149
3150 // this checks to see if the NaN logic is executed in SkPath::autoClose(), but does not
3151 // check to see if the result is correct.
3152 for (int setNaN = 0; setNaN < 4; ++setNaN) {
3153 p.reset();
3154 p.moveTo(setNaN == 0 ? SK_ScalarNaN : 0, setNaN == 1 ? SK_ScalarNaN : 0);
3155 p.lineTo(setNaN == 2 ? SK_ScalarNaN : 1, setNaN == 3 ? SK_ScalarNaN : 1);
3156 iter.setPath(p, true);
3157 iter.next(pts);
3158 iter.next(pts);
3159 REPORTER_ASSERT(reporter, SkPath::kClose_Verb == iter.next(pts));
3160 }
3161
3162 p.reset();
3163 p.quadTo(0, 0, 0, 0);
3164 iter.setPath(p, false);
3165 iter.next(pts);
3166 REPORTER_ASSERT(reporter, SkPath::kQuad_Verb == iter.next(pts));
3167
3168 p.reset();
3169 p.conicTo(0, 0, 0, 0, 0.5f);
3170 iter.setPath(p, false);
3171 iter.next(pts);
3172 REPORTER_ASSERT(reporter, SkPath::kConic_Verb == iter.next(pts));
3173
3174 p.reset();
3175 p.cubicTo(0, 0, 0, 0, 0, 0);
3176 iter.setPath(p, false);
3177 iter.next(pts);
3178 REPORTER_ASSERT(reporter, SkPath::kCubic_Verb == iter.next(pts));
3179
3180 p.moveTo(1, 1); // add a trailing moveto
3181 iter.setPath(p, false);
3182 iter.next(pts);
3183 REPORTER_ASSERT(reporter, SkPath::kCubic_Verb == iter.next(pts));
3184
3185 // The GM degeneratesegments.cpp test is more extensive
3186
3187 // Test out mixed degenerate and non-degenerate geometry with Conics
3188 const SkVector radii[4] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 100, 100 } };
3189 SkRect r = SkRect::MakeWH(100, 100);
3190 SkRRect rr;
3191 rr.setRectRadii(r, radii);
3192 p.reset();
3193 p.addRRect(rr);
3194 iter.setPath(p, false);
3195 REPORTER_ASSERT(reporter, SkPath::kMove_Verb == iter.next(pts));
3196 REPORTER_ASSERT(reporter, SkPath::kLine_Verb == iter.next(pts));
3197 return;
3198 REPORTER_ASSERT(reporter, SkPath::kLine_Verb == iter.next(pts));
3199 REPORTER_ASSERT(reporter, SkPath::kConic_Verb == iter.next(pts));
3200 REPORTER_ASSERT(reporter, SK_ScalarRoot2Over2 == iter.conicWeight());
3201}
#define SK_ScalarRoot2Over2
Definition SkScalar.h:23
void setPath(const SkPath &path, bool forceClose)
Definition SkPath.cpp:1773
Verb next(SkPoint pts[4])
Definition SkPath.cpp:1837

◆ test_iterative_intersect_line()

static void test_iterative_intersect_line ( )
static

Definition at line 149 of file PathTest.cpp.

149 {
150 // crbug.com/1320467
151 // SkLineClipper::IntersectLine used to clip against the horizontal segment. Then, if it still
152 // needed clipping, would clip against the vertical segment, but start over from the un-clipped
153 // endpoints. With that version, this draw would trigger an assert.
154 // With the fix (iteratively clipping the intermediate results after the first operation),
155 // this shouldn't assert:
156 SkPath path;
157 path.moveTo(-478.805145f, 153.862549f);
158 path.lineTo(6.27216804e+19f, 6.27216804e+19f);
159 path.lineTo(-666.754272f, 155.086304f);
160 path.close();
161
165}

◆ test_mask_overflow()

static void test_mask_overflow ( )
static

Definition at line 250 of file PathTest.cpp.

250 {
251 SkPath path;
252 path.moveTo(SkBits2Float(0x43e28000), SkBits2Float(0x43aa8000)); // 453, 341
253 path.lineTo(SkBits2Float(0x43de6000), SkBits2Float(0x43aa8000)); // 444.75f, 341
254 // 440.47f, 341, 437, 344.47f, 437, 348.75f
255 path.cubicTo(SkBits2Float(0x43dc3c29), SkBits2Float(0x43aa8000),
256 SkBits2Float(0x43da8000), SkBits2Float(0x43ac3c29),
257 SkBits2Float(0x43da8000), SkBits2Float(0x43ae6000));
258 path.lineTo(SkBits2Float(0x43da8000), SkBits2Float(0x43b18000)); // 437, 355
259 path.lineTo(SkBits2Float(0x43e28000), SkBits2Float(0x43b18000)); // 453, 355
260 path.lineTo(SkBits2Float(0x43e28000), SkBits2Float(0x43aa8000)); // 453, 341
261 test_draw_AA_path(500, 500, path);
262}

◆ test_operatorEqual()

static void test_operatorEqual ( skiatest::Reporter reporter)
static

Definition at line 4463 of file PathTest.cpp.

4463 {
4464 SkPath a;
4465 SkPath b;
4470 a.reset();
4472 a.lineTo(1, 1);
4474 a.reset();
4476 a.lineTo(1, 1);
4477 b.lineTo(1, 2);
4479 a.reset();
4480 a.lineTo(1, 2);
4482}

◆ test_oval()

static void test_oval ( skiatest::Reporter reporter)
static

Definition at line 3687 of file PathTest.cpp.

3687 {
3688 SkRect rect;
3689 SkMatrix m;
3690 SkPath path;
3691 unsigned start = 0;
3693
3695 path.addOval(rect);
3696
3697 // Defaults to dir = CW and start = 1
3698 REPORTER_ASSERT(reporter, path.isOval(nullptr));
3699
3700 m.setRotate(SkIntToScalar(90));
3701 SkPath tmp;
3702 path.transform(m, &tmp);
3703 // an oval rotated 90 degrees is still an oval. The start index changes from 1 to 2. Direction
3704 // is unchanged.
3705 REPORTER_ASSERT(reporter, SkPathPriv::IsOval(tmp, nullptr, &dir, &start));
3708
3709 m.reset();
3710 m.setRotate(SkIntToScalar(30));
3711 tmp.reset();
3712 path.transform(m, &tmp);
3713 // an oval rotated 30 degrees is not an oval anymore.
3714 REPORTER_ASSERT(reporter, !tmp.isOval(nullptr));
3715
3716 // since empty path being transformed.
3717 path.reset();
3718 tmp.reset();
3719 m.reset();
3720 path.transform(m, &tmp);
3721 REPORTER_ASSERT(reporter, !tmp.isOval(nullptr));
3722
3723 // empty path is not an oval
3724 tmp.reset();
3725 REPORTER_ASSERT(reporter, !tmp.isOval(nullptr));
3726
3727 // only has moveTo()s
3728 tmp.reset();
3729 tmp.moveTo(0, 0);
3730 tmp.moveTo(SkIntToScalar(10), SkIntToScalar(10));
3731 REPORTER_ASSERT(reporter, !tmp.isOval(nullptr));
3732
3733 // mimic WebKit's calling convention,
3734 // call moveTo() first and then call addOval()
3735 path.reset();
3736 path.moveTo(0, 0);
3737 path.addOval(rect);
3738 REPORTER_ASSERT(reporter, path.isOval(nullptr));
3739
3740 // copy path
3741 path.reset();
3742 tmp.reset();
3743 tmp.addOval(rect);
3744 path = tmp;
3745 REPORTER_ASSERT(reporter, SkPathPriv::IsOval(path, nullptr, &dir, &start));
3748}
bool isOval(SkRect *bounds) const
Definition SkPath.cpp:513

◆ test_path_close_issue1474()

static void test_path_close_issue1474 ( skiatest::Reporter reporter)
static

Definition at line 359 of file PathTest.cpp.

359 {
360 // This test checks that r{Line,Quad,Conic,Cubic}To following a close()
361 // are relative to the point we close to, not relative to the point we close from.
362 SkPath path;
363 SkPoint last;
364
365 // Test rLineTo().
366 path.rLineTo(0, 100);
367 path.rLineTo(100, 0);
368 path.close(); // Returns us back to 0,0.
369 path.rLineTo(50, 50); // This should go to 50,50.
370
371 path.getLastPt(&last);
372 REPORTER_ASSERT(reporter, 50 == last.fX);
373 REPORTER_ASSERT(reporter, 50 == last.fY);
374
375 // Test rQuadTo().
376 path.rewind();
377 path.rLineTo(0, 100);
378 path.rLineTo(100, 0);
379 path.close();
380 path.rQuadTo(50, 50, 75, 75);
381
382 path.getLastPt(&last);
383 REPORTER_ASSERT(reporter, 75 == last.fX);
384 REPORTER_ASSERT(reporter, 75 == last.fY);
385
386 // Test rConicTo().
387 path.rewind();
388 path.rLineTo(0, 100);
389 path.rLineTo(100, 0);
390 path.close();
391 path.rConicTo(50, 50, 85, 85, 2);
392
393 path.getLastPt(&last);
394 REPORTER_ASSERT(reporter, 85 == last.fX);
395 REPORTER_ASSERT(reporter, 85 == last.fY);
396
397 // Test rCubicTo().
398 path.rewind();
399 path.rLineTo(0, 100);
400 path.rLineTo(100, 0);
401 path.close();
402 path.rCubicTo(50, 50, 85, 85, 95, 95);
403
404 path.getLastPt(&last);
405 REPORTER_ASSERT(reporter, 95 == last.fX);
406 REPORTER_ASSERT(reporter, 95 == last.fY);
407}

◆ test_path_crbug364224()

static void test_path_crbug364224 ( )
static

Definition at line 167 of file PathTest.cpp.

167 {
168 SkPath path;
171 SkCanvas* canvas = surface->getCanvas();
172
174 canvas->drawPath(path, paint);
175
177 canvas->drawPath(path, paint);
178}
static void make_path_crbug364224(SkPath *path)
Definition PathTest.cpp:105
static void make_path_crbug364224_simplified(SkPath *path)
Definition PathTest.cpp:129

◆ test_path_crbug389050()

static void test_path_crbug389050 ( skiatest::Reporter reporter)
static

Definition at line 1365 of file PathTest.cpp.

1365 {
1366 SkPath tinyConvexPolygon;
1367 tinyConvexPolygon.moveTo(600.131559f, 800.112512f);
1368 tinyConvexPolygon.lineTo(600.161735f, 800.118627f);
1369 tinyConvexPolygon.lineTo(600.148962f, 800.142338f);
1370 tinyConvexPolygon.lineTo(600.134891f, 800.137724f);
1371 tinyConvexPolygon.close();
1372 tinyConvexPolygon.isConvex();
1374
1375 SkPath platTriangle;
1376 platTriangle.moveTo(0, 0);
1377 platTriangle.lineTo(200, 0);
1378 platTriangle.lineTo(100, 0.04f);
1379 platTriangle.close();
1380 platTriangle.isConvex();
1382
1383 platTriangle.reset();
1384 platTriangle.moveTo(0, 0);
1385 platTriangle.lineTo(200, 0);
1386 platTriangle.lineTo(100, 0.03f);
1387 platTriangle.close();
1388 platTriangle.isConvex();
1390}

◆ test_path_crbugskia2820()

static void test_path_crbugskia2820 ( skiatest::Reporter reporter)
static

Definition at line 291 of file PathTest.cpp.

291 {
292 SkPath path;
294
296 stroke.setStrokeStyle(2 * SK_Scalar1);
297 stroke.applyToPath(&path, path);
298}
static void make_path_crbugskia2820(SkPath *path, skiatest::Reporter *reporter)
Definition PathTest.cpp:278

◆ test_path_crbugskia5995()

static void test_path_crbugskia5995 ( )
static

Definition at line 300 of file PathTest.cpp.

300 {
301 SkPath path;
302 path.moveTo(SkBits2Float(0x40303030), SkBits2Float(0x3e303030)); // 2.75294f, 0.172059f
303 path.quadTo(SkBits2Float(0x41d63030), SkBits2Float(0x30303030), SkBits2Float(0x41013030),
304 SkBits2Float(0x00000000)); // 26.7735f, 6.40969e-10f, 8.07426f, 0
305 path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0
306 test_draw_AA_path(500, 500, path);
307}

◆ test_path_crbugskia6003()

static void test_path_crbugskia6003 ( )
static

Definition at line 4664 of file PathTest.cpp.

4664 {
4666 SkCanvas* canvas = surface->getCanvas();
4667 SkPaint paint;
4668 paint.setAntiAlias(true);
4669 SkPath path;
4670 path.moveTo(SkBits2Float(0x4325e666), SkBits2Float(0x42a1999a)); // 165.9f, 80.8f
4671 path.lineTo(SkBits2Float(0x4325e666), SkBits2Float(0x42a2999a)); // 165.9f, 81.3f
4672 path.lineTo(SkBits2Float(0x4325b333), SkBits2Float(0x42a2999a)); // 165.7f, 81.3f
4673 path.lineTo(SkBits2Float(0x4325b333), SkBits2Float(0x42a16666)); // 165.7f, 80.7f
4674 path.lineTo(SkBits2Float(0x4325b333), SkBits2Float(0x429f6666)); // 165.7f, 79.7f
4675 // 165.7f, 79.7f, 165.8f, 79.7f, 165.8f, 79.7f
4676 path.cubicTo(SkBits2Float(0x4325b333), SkBits2Float(0x429f6666), SkBits2Float(0x4325cccc),
4677 SkBits2Float(0x429f6666), SkBits2Float(0x4325cccc), SkBits2Float(0x429f6666));
4678 // 165.8f, 79.7f, 165.8f, 79.7f, 165.9f, 79.7f
4679 path.cubicTo(SkBits2Float(0x4325cccc), SkBits2Float(0x429f6666), SkBits2Float(0x4325cccc),
4680 SkBits2Float(0x429f6666), SkBits2Float(0x4325e666), SkBits2Float(0x429f6666));
4681 path.lineTo(SkBits2Float(0x4325e666), SkBits2Float(0x42a1999a)); // 165.9f, 80.8f
4682 path.close();
4683 canvas->clipPath(path, true);
4684 canvas->drawRect(SkRect::MakeWH(500, 500), paint);
4685}

◆ test_path_isfinite()

static void test_path_isfinite ( skiatest::Reporter reporter)
static

Definition at line 966 of file PathTest.cpp.

966 {
967 const SkScalar inf = SK_ScalarInfinity;
968 const SkScalar negInf = SK_ScalarNegativeInfinity;
969 const SkScalar nan = SK_ScalarNaN;
970
971 SkPath path;
972 REPORTER_ASSERT(reporter, path.isFinite());
973
974 path.reset();
975 REPORTER_ASSERT(reporter, path.isFinite());
976
977 path.reset();
978 path.moveTo(SK_Scalar1, 0);
979 REPORTER_ASSERT(reporter, path.isFinite());
980
981 path.reset();
982 path.moveTo(inf, negInf);
983 REPORTER_ASSERT(reporter, !path.isFinite());
984
985 path.reset();
986 path.moveTo(nan, 0);
987 REPORTER_ASSERT(reporter, !path.isFinite());
988}

◆ test_path_to_region()

static void test_path_to_region ( skiatest::Reporter reporter)
static

Definition at line 333 of file PathTest.cpp.

333 {
334 PathProc procs[] = {
337 };
338
340 clip.setRect({0, 0, 1255, 1925});
341
342 for (size_t i = 0; i < std::size(procs); ++i) {
343 SkPath path;
344 procs[i](&path);
345
346 SkRegion rgn;
347 rgn.setPath(path, clip);
348 path.toggleInverseFillType();
349 rgn.setPath(path, clip);
350 }
351}
static void make_path0(SkPath *path)
Definition PathTest.cpp:309
static void make_path1(SkPath *path)
Definition PathTest.cpp:320
void(* PathProc)(SkPath *)
Definition PathTest.cpp:324
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition SkPath.cpp:3824
bool setPath(const SkPath &path, const SkRegion &clip)

◆ test_poly()

static void test_poly ( skiatest::Reporter reporter,
const SkPath path,
const SkPoint  srcPts[],
bool  expectClose 
)
static

Definition at line 1019 of file PathTest.cpp.

1020 {
1021 bool firstTime = true;
1022 bool foundClose = false;
1023 for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
1024 switch (verb) {
1025 case SkPathVerb::kMove:
1026 REPORTER_ASSERT(reporter, firstTime);
1027 REPORTER_ASSERT(reporter, pts[0] == srcPts[0]);
1028 srcPts++;
1029 firstTime = false;
1030 break;
1031 case SkPathVerb::kLine:
1032 REPORTER_ASSERT(reporter, !firstTime);
1033 REPORTER_ASSERT(reporter, pts[1] == srcPts[0]);
1034 srcPts++;
1035 break;
1036 case SkPathVerb::kQuad:
1037 REPORTER_ASSERT(reporter, false, "unexpected quad verb");
1038 break;
1039 case SkPathVerb::kConic:
1040 REPORTER_ASSERT(reporter, false, "unexpected conic verb");
1041 break;
1042 case SkPathVerb::kCubic:
1043 REPORTER_ASSERT(reporter, false, "unexpected cubic verb");
1044 break;
1045 case SkPathVerb::kClose:
1046 REPORTER_ASSERT(reporter, !firstTime);
1047 REPORTER_ASSERT(reporter, !foundClose);
1048 REPORTER_ASSERT(reporter, expectClose);
1049 foundClose = true;
1050 break;
1051 }
1052 }
1053 REPORTER_ASSERT(reporter, foundClose == expectClose);
1054}
@ kCubic
SkPath::RawIter returns 4 points.
@ kConic
SkPath::RawIter returns 3 points + 1 weight.

◆ test_range_iter()

static void test_range_iter ( skiatest::Reporter reporter)
static

Definition at line 3203 of file PathTest.cpp.

3203 {
3204 SkPath path;
3205
3206 // Test an iterator with an initial empty path
3207 SkPathPriv::Iterate iterate(path);
3208 REPORTER_ASSERT(reporter, iterate.begin() == iterate.end());
3209
3210 // Test that a move-only path returns the move.
3211 path.moveTo(SK_Scalar1, 0);
3212 iterate = SkPathPriv::Iterate(path);
3213 SkPathPriv::RangeIter iter = iterate.begin();
3214 {
3215 auto [verb, pts, w] = *iter++;
3217 REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1);
3218 REPORTER_ASSERT(reporter, pts[0].fY == 0);
3219 }
3220 REPORTER_ASSERT(reporter, iter == iterate.end());
3221
3222 // No matter how many moves we add, we should get them all back
3223 path.moveTo(SK_Scalar1*2, SK_Scalar1);
3224 path.moveTo(SK_Scalar1*3, SK_Scalar1*2);
3225 iterate = SkPathPriv::Iterate(path);
3226 iter = iterate.begin();
3227 {
3228 auto [verb, pts, w] = *iter++;
3230 REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1);
3231 REPORTER_ASSERT(reporter, pts[0].fY == 0);
3232 }
3233 {
3234 auto [verb, pts, w] = *iter++;
3236 REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*2);
3237 REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1);
3238 }
3239 {
3240 auto [verb, pts, w] = *iter++;
3242 REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*3);
3243 REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1*2);
3244 }
3245 REPORTER_ASSERT(reporter, iter == iterate.end());
3246
3247 // Initial close is never ever stored
3248 path.reset();
3249 path.close();
3250 iterate = SkPathPriv::Iterate(path);
3251 REPORTER_ASSERT(reporter, iterate.begin() == iterate.end());
3252
3253 // Move/close sequences
3254 path.reset();
3255 path.close(); // Not stored, no purpose
3256 path.moveTo(SK_Scalar1, 0);
3257 path.close();
3258 path.close(); // Not stored, no purpose
3259 path.moveTo(SK_Scalar1*2, SK_Scalar1);
3260 path.close();
3261 path.moveTo(SK_Scalar1*3, SK_Scalar1*2);
3262 path.moveTo(SK_Scalar1*4, SK_Scalar1*3);
3263 path.close();
3264 iterate = SkPathPriv::Iterate(path);
3265 iter = iterate.begin();
3266 {
3267 auto [verb, pts, w] = *iter++;
3269 REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1);
3270 REPORTER_ASSERT(reporter, pts[0].fY == 0);
3271 }
3272 {
3273 auto [verb, pts, w] = *iter++;
3275 }
3276 {
3277 auto [verb, pts, w] = *iter++;
3279 REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*2);
3280 REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1);
3281 }
3282 {
3283 auto [verb, pts, w] = *iter++;
3285 }
3286 {
3287 auto [verb, pts, w] = *iter++;
3289 REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*3);
3290 REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1*2);
3291 }
3292 {
3293 auto [verb, pts, w] = *iter++;
3295 REPORTER_ASSERT(reporter, pts[0].fX == SK_Scalar1*4);
3296 REPORTER_ASSERT(reporter, pts[0].fY == SK_Scalar1*3);
3297 }
3298 {
3299 auto [verb, pts, w] = *iter++;
3301 }
3302 REPORTER_ASSERT(reporter, iter == iterate.end());
3303
3304 // Generate random paths and verify
3305 SkPoint randomPts[25];
3306 for (int i = 0; i < 5; ++i) {
3307 for (int j = 0; j < 5; ++j) {
3308 randomPts[i*5+j].set(SK_Scalar1*i, SK_Scalar1*j);
3309 }
3310 }
3311
3312 // Max of 10 segments, max 3 points per segment
3313 SkRandom rand(9876543);
3314 SkPoint expectedPts[31]; // May have leading moveTo
3315 SkPathVerb expectedVerbs[22]; // May have leading moveTo
3316 SkPathVerb nextVerb;
3317
3318 for (int i = 0; i < 500; ++i) {
3319 path.reset();
3320 bool lastWasClose = true;
3321 bool haveMoveTo = false;
3322 SkPoint lastMoveToPt = { 0, 0 };
3323 int numPoints = 0;
3324 int numVerbs = (rand.nextU() >> 16) % 10;
3325 int numIterVerbs = 0;
3326 for (int j = 0; j < numVerbs; ++j) {
3327 do {
3328 nextVerb = static_cast<SkPathVerb>((rand.nextU() >> 16) % SkPath::kDone_Verb);
3329 } while (lastWasClose && nextVerb == SkPathVerb::kClose);
3330 switch (nextVerb) {
3331 case SkPathVerb::kMove:
3332 expectedPts[numPoints] = randomPts[(rand.nextU() >> 16) % 25];
3333 path.moveTo(expectedPts[numPoints]);
3334 lastMoveToPt = expectedPts[numPoints];
3335 numPoints += 1;
3336 lastWasClose = false;
3337 haveMoveTo = true;
3338 break;
3339 case SkPathVerb::kLine:
3340 if (!haveMoveTo) {
3341 expectedPts[numPoints++] = lastMoveToPt;
3342 expectedVerbs[numIterVerbs++] = SkPathVerb::kMove;
3343 haveMoveTo = true;
3344 }
3345 expectedPts[numPoints] = randomPts[(rand.nextU() >> 16) % 25];
3346 path.lineTo(expectedPts[numPoints]);
3347 numPoints += 1;
3348 lastWasClose = false;
3349 break;
3350 case SkPathVerb::kQuad:
3351 if (!haveMoveTo) {
3352 expectedPts[numPoints++] = lastMoveToPt;
3353 expectedVerbs[numIterVerbs++] = SkPathVerb::kMove;
3354 haveMoveTo = true;
3355 }
3356 expectedPts[numPoints] = randomPts[(rand.nextU() >> 16) % 25];
3357 expectedPts[numPoints + 1] = randomPts[(rand.nextU() >> 16) % 25];
3358 path.quadTo(expectedPts[numPoints], expectedPts[numPoints + 1]);
3359 numPoints += 2;
3360 lastWasClose = false;
3361 break;
3362 case SkPathVerb::kConic:
3363 if (!haveMoveTo) {
3364 expectedPts[numPoints++] = lastMoveToPt;
3365 expectedVerbs[numIterVerbs++] = SkPathVerb::kMove;
3366 haveMoveTo = true;
3367 }
3368 expectedPts[numPoints] = randomPts[(rand.nextU() >> 16) % 25];
3369 expectedPts[numPoints + 1] = randomPts[(rand.nextU() >> 16) % 25];
3370 path.conicTo(expectedPts[numPoints], expectedPts[numPoints + 1],
3371 rand.nextUScalar1() * 4);
3372 numPoints += 2;
3373 lastWasClose = false;
3374 break;
3375 case SkPathVerb::kCubic:
3376 if (!haveMoveTo) {
3377 expectedPts[numPoints++] = lastMoveToPt;
3378 expectedVerbs[numIterVerbs++] = SkPathVerb::kMove;
3379 haveMoveTo = true;
3380 }
3381 expectedPts[numPoints] = randomPts[(rand.nextU() >> 16) % 25];
3382 expectedPts[numPoints + 1] = randomPts[(rand.nextU() >> 16) % 25];
3383 expectedPts[numPoints + 2] = randomPts[(rand.nextU() >> 16) % 25];
3384 path.cubicTo(expectedPts[numPoints], expectedPts[numPoints + 1],
3385 expectedPts[numPoints + 2]);
3386 numPoints += 3;
3387 lastWasClose = false;
3388 break;
3389 case SkPathVerb::kClose:
3390 path.close();
3391 haveMoveTo = false;
3392 lastWasClose = true;
3393 break;
3394 default:
3395 SkDEBUGFAIL("unexpected verb");
3396 }
3397 expectedVerbs[numIterVerbs++] = nextVerb;
3398 }
3399
3400 numVerbs = numIterVerbs;
3401 numIterVerbs = 0;
3402 int numIterPts = 0;
3403 SkPoint lastMoveTo;
3404 SkPoint lastPt;
3405 lastMoveTo.set(0, 0);
3406 lastPt.set(0, 0);
3407 for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
3408 REPORTER_ASSERT(reporter, verb == expectedVerbs[numIterVerbs]);
3409 numIterVerbs++;
3410 switch (verb) {
3411 case SkPathVerb::kMove:
3412 REPORTER_ASSERT(reporter, numIterPts < numPoints);
3413 REPORTER_ASSERT(reporter, pts[0] == expectedPts[numIterPts]);
3414 lastPt = lastMoveTo = pts[0];
3415 numIterPts += 1;
3416 break;
3417 case SkPathVerb::kLine:
3418 REPORTER_ASSERT(reporter, numIterPts < numPoints + 1);
3419 REPORTER_ASSERT(reporter, pts[0] == lastPt);
3420 REPORTER_ASSERT(reporter, pts[1] == expectedPts[numIterPts]);
3421 lastPt = pts[1];
3422 numIterPts += 1;
3423 break;
3424 case SkPathVerb::kQuad:
3425 case SkPathVerb::kConic:
3426 REPORTER_ASSERT(reporter, numIterPts < numPoints + 2);
3427 REPORTER_ASSERT(reporter, pts[0] == lastPt);
3428 REPORTER_ASSERT(reporter, pts[1] == expectedPts[numIterPts]);
3429 REPORTER_ASSERT(reporter, pts[2] == expectedPts[numIterPts + 1]);
3430 lastPt = pts[2];
3431 numIterPts += 2;
3432 break;
3433 case SkPathVerb::kCubic:
3434 REPORTER_ASSERT(reporter, numIterPts < numPoints + 3);
3435 REPORTER_ASSERT(reporter, pts[0] == lastPt);
3436 REPORTER_ASSERT(reporter, pts[1] == expectedPts[numIterPts]);
3437 REPORTER_ASSERT(reporter, pts[2] == expectedPts[numIterPts + 1]);
3438 REPORTER_ASSERT(reporter, pts[3] == expectedPts[numIterPts + 2]);
3439 lastPt = pts[3];
3440 numIterPts += 3;
3441 break;
3442 case SkPathVerb::kClose:
3443 lastPt = lastMoveTo;
3444 break;
3445 default:
3446 SkDEBUGFAIL("unexpected verb");
3447 }
3448 }
3449 REPORTER_ASSERT(reporter, numIterPts == numPoints);
3450 REPORTER_ASSERT(reporter, numIterVerbs == numVerbs);
3451 }
3452}
#define SkDEBUGFAIL(message)
Definition SkAssert.h:118
SkPathVerb
Definition SkPathTypes.h:48

◆ test_rect_isfinite()

static void test_rect_isfinite ( skiatest::Reporter reporter)
static

Definition at line 932 of file PathTest.cpp.

932 {
933 const SkScalar inf = SK_ScalarInfinity;
934 const SkScalar negInf = SK_ScalarNegativeInfinity;
935 const SkScalar nan = SK_ScalarNaN;
936
937 SkRect r;
938 r.setEmpty();
940 r.setLTRB(0, 0, inf, negInf);
942 r.setLTRB(0, 0, nan, 0);
944
945 SkPoint pts[] = {
946 { 0, 0 },
947 { SK_Scalar1, 0 },
948 { 0, SK_Scalar1 },
949 };
950
951 bool isFine = r.setBoundsCheck(pts, 3);
952 REPORTER_ASSERT(reporter, isFine);
954
955 pts[1].set(inf, 0);
956 isFine = r.setBoundsCheck(pts, 3);
957 REPORTER_ASSERT(reporter, !isFine);
959
960 pts[1].set(nan, 0);
961 isFine = r.setBoundsCheck(pts, 3);
962 REPORTER_ASSERT(reporter, !isFine);
964}
bool isFinite() const
Definition SkRect.h:711
bool setBoundsCheck(const SkPoint pts[], int count)
Definition SkRect.cpp:61

◆ test_rMoveTo()

static void test_rMoveTo ( skiatest::Reporter reporter)
static

Definition at line 4033 of file PathTest.cpp.

4033 {
4034 SkPath p;
4035 p.moveTo(10, 11);
4036 p.lineTo(20, 21);
4037 p.close();
4038 p.rMoveTo(30, 31);
4040 check_move(reporter, &iter, 10, 11);
4041 check_line(reporter, &iter, 20, 21);
4042 check_close(reporter, &iter);
4043 check_move(reporter, &iter, 10 + 30, 11 + 31);
4044 check_done_and_reset(reporter, &p, &iter);
4045
4046 p.moveTo(10, 11);
4047 p.lineTo(20, 21);
4048 p.rMoveTo(30, 31);
4049 iter = SkPathPriv::Iterate(p).begin();
4050 check_move(reporter, &iter, 10, 11);
4051 check_line(reporter, &iter, 20, 21);
4052 check_move(reporter, &iter, 20 + 30, 21 + 31);
4053 check_done_and_reset(reporter, &p, &iter);
4054
4055 p.rMoveTo(30, 31);
4056 iter = SkPathPriv::Iterate(p).begin();
4057 check_move(reporter, &iter, 30, 31);
4058 check_done_and_reset(reporter, &p, &iter);
4059}

◆ test_rrect()

static void test_rrect ( skiatest::Reporter reporter)
static

Definition at line 3784 of file PathTest.cpp.

3784 {
3785 SkPath p;
3786 SkRRect rr;
3787 SkVector radii[] = {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
3788 SkRect r = {10, 20, 30, 40};
3789 rr.setRectRadii(r, radii);
3790 p.addRRect(rr);
3792 p.addRRect(rr, SkPathDirection::kCCW);
3794 p.addRoundRect(r, &radii[0].fX);
3796 p.addRoundRect(r, &radii[0].fX, SkPathDirection::kCCW);
3798 p.addRoundRect(r, radii[1].fX, radii[1].fY);
3800 p.addRoundRect(r, radii[1].fX, radii[1].fY, SkPathDirection::kCCW);
3802 for (size_t i = 0; i < std::size(radii); ++i) {
3803 SkVector save = radii[i];
3804 radii[i].set(0, 0);
3805 rr.setRectRadii(r, radii);
3806 p.addRRect(rr);
3808 radii[i] = save;
3809 }
3810 p.addRoundRect(r, 0, 0);
3811 SkRect returnedRect;
3812 REPORTER_ASSERT(reporter, p.isRect(&returnedRect));
3813 REPORTER_ASSERT(reporter, returnedRect == r);
3815 SkVector zeroRadii[] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
3816 rr.setRectRadii(r, zeroRadii);
3817 p.addRRect(rr);
3818 bool closed;
3820 REPORTER_ASSERT(reporter, p.isRect(nullptr, &closed, &dir));
3821 REPORTER_ASSERT(reporter, closed);
3824 p.addRRect(rr, SkPathDirection::kCW);
3825 p.addRRect(rr, SkPathDirection::kCW);
3826 REPORTER_ASSERT(reporter, !p.isConvex());
3827 p.reset();
3828 p.addRRect(rr, SkPathDirection::kCCW);
3829 p.addRRect(rr, SkPathDirection::kCCW);
3830 REPORTER_ASSERT(reporter, !p.isConvex());
3831 p.reset();
3832 SkRect emptyR = {10, 20, 10, 30};
3833 rr.setRectRadii(emptyR, radii);
3834 p.addRRect(rr);
3835 // The round rect is "empty" in that it has no fill area. However,
3836 // the path isn't "empty" in that it should have verbs and points.
3837 REPORTER_ASSERT(reporter, !p.isEmpty());
3838 p.reset();
3839 SkRect largeR = {0, 0, SK_ScalarMax, SK_ScalarMax};
3840 rr.setRectRadii(largeR, radii);
3841 p.addRRect(rr);
3843
3844 // we check for non-finites
3845 SkRect infR = {0, 0, SK_ScalarMax, SK_ScalarInfinity};
3846 rr.setRectRadii(infR, radii);
3848}
static void test_rrect_convexity_is_unknown(skiatest::Reporter *reporter, SkPath *path, SkPathDirection dir)
static void test_rrect_is_convex(skiatest::Reporter *reporter, SkPath *path, SkPathDirection dir)
bool isEmpty() const
Definition SkRRect.h:83

◆ test_rrect_convexity_is_unknown()

static void test_rrect_convexity_is_unknown ( skiatest::Reporter reporter,
SkPath path,
SkPathDirection  dir 
)
static

Definition at line 3774 of file PathTest.cpp.

3775 {
3776 REPORTER_ASSERT(reporter, path->isConvex());
3780 REPORTER_ASSERT(reporter, !path->isConvex());
3781 path->reset();
3782}

◆ test_rrect_is_convex()

static void test_rrect_is_convex ( skiatest::Reporter reporter,
SkPath path,
SkPathDirection  dir 
)
static

Definition at line 3764 of file PathTest.cpp.

3765 {
3766 REPORTER_ASSERT(reporter, path->isConvex());
3770 REPORTER_ASSERT(reporter, path->isConvex());
3771 path->reset();
3772}

◆ test_sect_with_horizontal_needs_pinning()

static void test_sect_with_horizontal_needs_pinning ( )
static

Definition at line 135 of file PathTest.cpp.

135 {
136 // Test that sect_with_horizontal in SkLineClipper.cpp needs to pin after computing the
137 // intersection.
138 SkPath path;
139 path.reset();
140 path.moveTo(-540000, -720000);
141 path.lineTo(-9.10000017e-05f, 9.99999996e-13f);
142 path.lineTo(1, 1);
143
144 // Without the pinning code in sect_with_horizontal(), this would assert in the lineclipper
147}

◆ test_segment_masks()

static void test_segment_masks ( skiatest::Reporter reporter)
static

Definition at line 3033 of file PathTest.cpp.

3033 {
3034 SkPath p, p2;
3035
3036 p.moveTo(0, 0);
3037 p.quadTo(100, 100, 200, 200);
3038 REPORTER_ASSERT(reporter, SkPath::kQuad_SegmentMask == p.getSegmentMasks());
3039 REPORTER_ASSERT(reporter, !p.isEmpty());
3040 p2 = p;
3041 REPORTER_ASSERT(reporter, p2.getSegmentMasks() == p.getSegmentMasks());
3042 p.cubicTo(100, 100, 200, 200, 300, 300);
3043 REPORTER_ASSERT(reporter, kCurveSegmentMask == p.getSegmentMasks());
3044 REPORTER_ASSERT(reporter, !p.isEmpty());
3045 p2 = p;
3046 REPORTER_ASSERT(reporter, p2.getSegmentMasks() == p.getSegmentMasks());
3047
3048 p.reset();
3049 p.moveTo(0, 0);
3050 p.cubicTo(100, 100, 200, 200, 300, 300);
3052 p2 = p;
3053 REPORTER_ASSERT(reporter, p2.getSegmentMasks() == p.getSegmentMasks());
3054
3055 REPORTER_ASSERT(reporter, !p.isEmpty());
3056}
@ kQuad_SegmentMask
Definition SkPath.h:1438
@ kCubic_SegmentMask
Definition SkPath.h:1440
uint32_t getSegmentMasks() const
Definition SkPath.cpp:424

◆ test_skbug_3239()

static void test_skbug_3239 ( skiatest::Reporter reporter)
static

Definition at line 87 of file PathTest.cpp.

87 {
88 const float min = SkBits2Float(0xcb7f16c8); /* -16717512.000000 */
89 const float max = SkBits2Float(0x4b7f1c1d); /* 16718877.000000 */
90 const float big = SkBits2Float(0x4b7f1bd7); /* 16718807.000000 */
91
92 const float rad = 33436320;
93
94 const SkRect rectx = SkRect::MakeLTRB(min, min, max, big);
95 const SkRect recty = SkRect::MakeLTRB(min, min, big, max);
96
97 SkVector radii[4];
98 for (int i = 0; i < 4; ++i) {
99 set_radii(radii, i, rad);
100 test_add_rrect(reporter, rectx, radii);
101 test_add_rrect(reporter, recty, radii);
102 }
103}
static void test_add_rrect(skiatest::Reporter *reporter, const SkRect &bounds, const SkVector radii[4])
Definition PathTest.cpp:67
static void set_radii(SkVector radii[4], int index, float rad)
Definition PathTest.cpp:62
static float max(float r, float g, float b)
Definition hsl.cpp:49
static float min(float r, float g, float b)
Definition hsl.cpp:48

◆ test_skbug_3469()

static void test_skbug_3469 ( skiatest::Reporter reporter)
static

Definition at line 79 of file PathTest.cpp.

79 {
81 path.moveTo(20, 20);
82 path.quadTo(20, 50, 80, 50);
83 path.quadTo(20, 50, 20, 80);
84 REPORTER_ASSERT(reporter, !path.isConvex());
85}

◆ test_skbug_6947()

static void test_skbug_6947 ( )
static

Definition at line 4697 of file PathTest.cpp.

4697 {
4698 SkPath path;
4699 SkPoint points[] =
4700 {{125.126022f, -0.499872506f}, {125.288895f, -0.499338806f},
4701 {125.299316f, -0.499290764f}, {126.294594f, 0.505449712f},
4702 {125.999992f, 62.5047531f}, {124.0f, 62.4980202f},
4703 {124.122749f, 0.498142242f}, {125.126022f, -0.499872506f},
4704 {125.119476f, 1.50011659f}, {125.122749f, 0.50012207f},
4705 {126.122749f, 0.502101898f}, {126.0f, 62.5019798f},
4706 {125.0f, 62.5f}, {124.000008f, 62.4952469f},
4707 {124.294609f, 0.495946467f}, {125.294601f, 0.50069809f},
4708 {125.289886f, 1.50068688f}, {125.282349f, 1.50065041f},
4709 {125.119476f, 1.50011659f}};
4715 int pointIndex = 0;
4716 for(auto verb : verbs) {
4717 switch (verb) {
4718 case kMove:
4719 path.moveTo(points[pointIndex++]);
4720 break;
4721 case kLine:
4722 path.lineTo(points[pointIndex++]);
4723 break;
4724 case kClose:
4725 default:
4726 path.close();
4727 break;
4728 }
4729 }
4730 test_draw_AA_path(250, 125, path);
4731}
static constexpr SkScalar kClose
@ kMove
Definition embedder.h:983

◆ test_skbug_7015()

static void test_skbug_7015 ( )
static

Definition at line 4733 of file PathTest.cpp.

4733 {
4734 SkPath path;
4735 path.setFillType(SkPathFillType::kWinding);
4736 path.moveTo(SkBits2Float(0x4388c000), SkBits2Float(0x43947c08)); // 273.5f, 296.969f
4737 path.lineTo(SkBits2Float(0x4386c000), SkBits2Float(0x43947c08)); // 269.5f, 296.969f
4738 // 269.297f, 292.172f, 273.695f, 292.172f, 273.5f, 296.969f
4739 path.cubicTo(SkBits2Float(0x4386a604), SkBits2Float(0x43921604),
4740 SkBits2Float(0x4388d8f6), SkBits2Float(0x43921604),
4741 SkBits2Float(0x4388c000), SkBits2Float(0x43947c08));
4742 path.close();
4743 test_draw_AA_path(500, 500, path);
4744}

◆ test_skbug_7051()

static void test_skbug_7051 ( )
static

Definition at line 4746 of file PathTest.cpp.

4746 {
4747 SkPath path;
4748 path.moveTo(10, 10);
4749 path.cubicTo(10, 20, 10, 30, 30, 30);
4750 path.lineTo(50, 20);
4751 path.lineTo(50, 10);
4752 path.close();
4753 test_draw_AA_path(100, 100, path);
4754}

◆ test_skbug_7435()

static void test_skbug_7435 ( )
static

Definition at line 4756 of file PathTest.cpp.

4756 {
4757 SkPaint paint;
4758 SkPath path;
4759 path.setFillType(SkPathFillType::kWinding);
4760 path.moveTo(SkBits2Float(0x7f07a5af), SkBits2Float(0xff07ff1d)); // 1.80306e+38f, -1.8077e+38f
4761 path.lineTo(SkBits2Float(0x7edf4b2d), SkBits2Float(0xfedffe0a)); // 1.48404e+38f, -1.48868e+38f
4762 path.lineTo(SkBits2Float(0x7edf4585), SkBits2Float(0xfee003b2)); // 1.48389e+38f, -1.48883e+38f
4763 path.lineTo(SkBits2Float(0x7ef348e9), SkBits2Float(0xfef403c6)); // 1.6169e+38f, -1.62176e+38f
4764 path.lineTo(SkBits2Float(0x7ef74c4e), SkBits2Float(0xfef803cb)); // 1.64358e+38f, -1.64834e+38f
4765 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
4766 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
4767 path.lineTo(SkBits2Float(0x7edb57a9), SkBits2Float(0xfedbfe06)); // 1.45778e+38f, -1.4621e+38f
4768 path.lineTo(SkBits2Float(0x7e875976), SkBits2Float(0xfe87fdb3)); // 8.99551e+37f, -9.03815e+37f
4769 path.lineTo(SkBits2Float(0x7ded5c2b), SkBits2Float(0xfdeff59e)); // 3.94382e+37f, -3.98701e+37f
4770 path.lineTo(SkBits2Float(0x7d7a78a7), SkBits2Float(0xfd7fda0f)); // 2.08083e+37f, -2.12553e+37f
4771 path.lineTo(SkBits2Float(0x7d7a6403), SkBits2Float(0xfd7fe461)); // 2.08016e+37f, -2.12587e+37f
4772 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
4773 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
4774 path.lineTo(SkBits2Float(0x7d8d2067), SkBits2Float(0xfd900bdb)); // 2.34487e+37f, -2.39338e+37f
4775 path.lineTo(SkBits2Float(0x7ddd137a), SkBits2Float(0xfde00c2d)); // 3.67326e+37f, -3.72263e+37f
4776 path.lineTo(SkBits2Float(0x7ddd2a1b), SkBits2Float(0xfddff58e)); // 3.67473e+37f, -3.72116e+37f
4777 path.lineTo(SkBits2Float(0x7c694ae5), SkBits2Float(0xfc7fa67c)); // 4.8453e+36f, -5.30965e+36f
4778 path.lineTo(SkBits2Float(0xfc164a8b), SkBits2Float(0x7c005af5)); // -3.12143e+36f, 2.66584e+36f
4779 path.lineTo(SkBits2Float(0xfc8ae983), SkBits2Float(0x7c802da7)); // -5.77019e+36f, 5.32432e+36f
4780 path.lineTo(SkBits2Float(0xfc8b16d9), SkBits2Float(0x7c80007b)); // -5.77754e+36f, 5.31699e+36f
4781 path.lineTo(SkBits2Float(0xfc8b029c), SkBits2Float(0x7c7f8788)); // -5.77426e+36f, 5.30714e+36f
4782 path.lineTo(SkBits2Float(0xfc8b0290), SkBits2Float(0x7c7f8790)); // -5.77425e+36f, 5.30714e+36f
4783 path.lineTo(SkBits2Float(0xfc8b16cd), SkBits2Float(0x7c80007f)); // -5.77753e+36f, 5.31699e+36f
4784 path.lineTo(SkBits2Float(0xfc8b4409), SkBits2Float(0x7c7fa672)); // -5.78487e+36f, 5.30965e+36f
4785 path.lineTo(SkBits2Float(0x7d7aa2ba), SkBits2Float(0xfd800bd1)); // 2.0822e+37f, -2.12753e+37f
4786 path.lineTo(SkBits2Float(0x7e8757ee), SkBits2Float(0xfe88035b)); // 8.99512e+37f, -9.03962e+37f
4787 path.lineTo(SkBits2Float(0x7ef7552d), SkBits2Float(0xfef803ca)); // 1.64381e+38f, -1.64834e+38f
4788 path.lineTo(SkBits2Float(0x7f0fa653), SkBits2Float(0xff1001f9)); // 1.90943e+38f, -1.91419e+38f
4789 path.lineTo(SkBits2Float(0x7f0fa926), SkBits2Float(0xff0fff24)); // 1.90958e+38f, -1.91404e+38f
4790 path.lineTo(SkBits2Float(0x7f0da75c), SkBits2Float(0xff0dff22)); // 1.8829e+38f, -1.88746e+38f
4791 path.lineTo(SkBits2Float(0x7f07a5af), SkBits2Float(0xff07ff1d)); // 1.80306e+38f, -1.8077e+38f
4792 path.close();
4793 path.moveTo(SkBits2Float(0x7f07a2db), SkBits2Float(0xff0801f1)); // 1.80291e+38f, -1.80785e+38f
4794 path.lineTo(SkBits2Float(0x7f0da48a), SkBits2Float(0xff0e01f8)); // 1.88275e+38f, -1.88761e+38f
4795 path.lineTo(SkBits2Float(0x7f0fa654), SkBits2Float(0xff1001fa)); // 1.90943e+38f, -1.91419e+38f
4796 path.lineTo(SkBits2Float(0x7f0fa7bd), SkBits2Float(0xff10008f)); // 1.90951e+38f, -1.91412e+38f
4797 path.lineTo(SkBits2Float(0x7f0fa927), SkBits2Float(0xff0fff25)); // 1.90958e+38f, -1.91404e+38f
4798 path.lineTo(SkBits2Float(0x7ef75ad5), SkBits2Float(0xfef7fe22)); // 1.64395e+38f, -1.64819e+38f
4799 path.lineTo(SkBits2Float(0x7e875d96), SkBits2Float(0xfe87fdb3)); // 8.99659e+37f, -9.03815e+37f
4800 path.lineTo(SkBits2Float(0x7d7acff6), SkBits2Float(0xfd7fea5b)); // 2.08367e+37f, -2.12606e+37f
4801 path.lineTo(SkBits2Float(0xfc8b0588), SkBits2Float(0x7c8049b7)); // -5.77473e+36f, 5.32887e+36f
4802 path.lineTo(SkBits2Float(0xfc8b2b16), SkBits2Float(0x7c803d32)); // -5.78083e+36f, 5.32684e+36f
4803 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
4804 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
4805 path.lineTo(SkBits2Float(0xfc16ffaa), SkBits2Float(0x7bff4c12)); // -3.13612e+36f, 2.65116e+36f
4806 path.lineTo(SkBits2Float(0x7c6895e0), SkBits2Float(0xfc802dc0)); // 4.83061e+36f, -5.32434e+36f
4807 path.lineTo(SkBits2Float(0x7ddd137b), SkBits2Float(0xfde00c2e)); // 3.67326e+37f, -3.72263e+37f
4808 path.lineTo(SkBits2Float(0x7ddd1ecb), SkBits2Float(0xfde000de)); // 3.67399e+37f, -3.72189e+37f
4809 path.lineTo(SkBits2Float(0x7ddd2a1c), SkBits2Float(0xfddff58f)); // 3.67473e+37f, -3.72116e+37f
4810 path.lineTo(SkBits2Float(0x7d8d3711), SkBits2Float(0xfd8ff543)); // 2.34634e+37f, -2.39191e+37f
4811 path.lineTo(SkBits2Float(0x7d7a88fe), SkBits2Float(0xfd7fea69)); // 2.08136e+37f, -2.12606e+37f
4812 path.lineTo(SkBits2Float(0x7d7a7254), SkBits2Float(0xfd800080)); // 2.08063e+37f, -2.1268e+37f
4813 path.lineTo(SkBits2Float(0x7d7a80a4), SkBits2Float(0xfd800ed0)); // 2.08109e+37f, -2.12773e+37f
4814 path.lineTo(SkBits2Float(0x7d7a80a8), SkBits2Float(0xfd800ecf)); // 2.08109e+37f, -2.12773e+37f
4815 path.lineTo(SkBits2Float(0x7d7a7258), SkBits2Float(0xfd80007f)); // 2.08063e+37f, -2.1268e+37f
4816 path.lineTo(SkBits2Float(0x7d7a5bb9), SkBits2Float(0xfd800bd0)); // 2.0799e+37f, -2.12753e+37f
4817 path.lineTo(SkBits2Float(0x7ded458b), SkBits2Float(0xfdf00c3e)); // 3.94235e+37f, -3.98848e+37f
4818 path.lineTo(SkBits2Float(0x7e8753ce), SkBits2Float(0xfe88035b)); // 8.99405e+37f, -9.03962e+37f
4819 path.lineTo(SkBits2Float(0x7edb5201), SkBits2Float(0xfedc03ae)); // 1.45763e+38f, -1.46225e+38f
4820 path.lineTo(SkBits2Float(0x7ef74c4d), SkBits2Float(0xfef803ca)); // 1.64358e+38f, -1.64834e+38f
4821 path.lineTo(SkBits2Float(0x7ef74f21), SkBits2Float(0xfef800f6)); // 1.64365e+38f, -1.64827e+38f
4822 path.lineTo(SkBits2Float(0x7ef751f4), SkBits2Float(0xfef7fe21)); // 1.64372e+38f, -1.64819e+38f
4823 path.lineTo(SkBits2Float(0x7ef34e91), SkBits2Float(0xfef3fe1e)); // 1.61705e+38f, -1.62161e+38f
4824 path.lineTo(SkBits2Float(0x7edf4b2d), SkBits2Float(0xfedffe0a)); // 1.48404e+38f, -1.48868e+38f
4825 path.lineTo(SkBits2Float(0x7edf4859), SkBits2Float(0xfee000de)); // 1.48397e+38f, -1.48876e+38f
4826 path.lineTo(SkBits2Float(0x7edf4585), SkBits2Float(0xfee003b2)); // 1.48389e+38f, -1.48883e+38f
4827 path.lineTo(SkBits2Float(0x7f07a2db), SkBits2Float(0xff0801f1)); // 1.80291e+38f, -1.80785e+38f
4828 path.close();
4829 path.moveTo(SkBits2Float(0xfab120db), SkBits2Float(0x77b50b4f)); // -4.59851e+35f, 7.34402e+33f
4830 path.lineTo(SkBits2Float(0xfd6597e5), SkBits2Float(0x7d60177f)); // -1.90739e+37f, 1.86168e+37f
4831 path.lineTo(SkBits2Float(0xfde2cea1), SkBits2Float(0x7de00c2e)); // -3.76848e+37f, 3.72263e+37f
4832 path.lineTo(SkBits2Float(0xfe316511), SkBits2Float(0x7e300657)); // -5.89495e+37f, 5.84943e+37f
4833 path.lineTo(SkBits2Float(0xfe415da1), SkBits2Float(0x7e400666)); // -6.42568e+37f, 6.38112e+37f
4834 path.lineTo(SkBits2Float(0xfe41634a), SkBits2Float(0x7e4000be)); // -6.42641e+37f, 6.38039e+37f
4835 path.lineTo(SkBits2Float(0xfe41634a), SkBits2Float(0x7e3ff8be)); // -6.42641e+37f, 6.37935e+37f
4836 path.lineTo(SkBits2Float(0xfe416349), SkBits2Float(0x7e3ff8be)); // -6.42641e+37f, 6.37935e+37f
4837 path.lineTo(SkBits2Float(0xfe415f69), SkBits2Float(0x7e3ff8be)); // -6.42591e+37f, 6.37935e+37f
4838 path.lineTo(SkBits2Float(0xfe415bc9), SkBits2Float(0x7e3ff8be)); // -6.42544e+37f, 6.37935e+37f
4839 path.lineTo(SkBits2Float(0xfe415bc9), SkBits2Float(0x7e4000be)); // -6.42544e+37f, 6.38039e+37f
4840 path.lineTo(SkBits2Float(0xfe416171), SkBits2Float(0x7e3ffb16)); // -6.42617e+37f, 6.37966e+37f
4841 path.lineTo(SkBits2Float(0xfe016131), SkBits2Float(0x7dfff5ae)); // -4.29938e+37f, 4.25286e+37f
4842 path.lineTo(SkBits2Float(0xfe0155e2), SkBits2Float(0x7e000628)); // -4.29791e+37f, 4.25433e+37f
4843 path.lineTo(SkBits2Float(0xfe0958ea), SkBits2Float(0x7e080630)); // -4.56415e+37f, 4.52018e+37f
4844 path.lineTo(SkBits2Float(0xfe115c92), SkBits2Float(0x7e100638)); // -4.83047e+37f, 4.78603e+37f
4845 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
4846 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
4847 path.lineTo(SkBits2Float(0xfe016b92), SkBits2Float(0x7dfff5af)); // -4.30072e+37f, 4.25286e+37f
4848 path.lineTo(SkBits2Float(0xfdc2d963), SkBits2Float(0x7dbff56e)); // -3.23749e+37f, 3.18946e+37f
4849 path.lineTo(SkBits2Float(0xfd65ae25), SkBits2Float(0x7d5fea3d)); // -1.90811e+37f, 1.86021e+37f
4850 path.lineTo(SkBits2Float(0xfab448de), SkBits2Float(0xf7b50a19)); // -4.68046e+35f, -7.34383e+33f
4851 path.lineTo(SkBits2Float(0xfab174d9), SkBits2Float(0x43480000)); // -4.60703e+35f, 200
4852 path.lineTo(SkBits2Float(0xfab174d9), SkBits2Float(0x7800007f)); // -4.60703e+35f, 1.03848e+34f
4853 path.lineTo(SkBits2Float(0xfab3f4db), SkBits2Float(0x7800007f)); // -4.67194e+35f, 1.03848e+34f
4854 path.lineTo(SkBits2Float(0xfab3f4db), SkBits2Float(0x43480000)); // -4.67194e+35f, 200
4855 path.lineTo(SkBits2Float(0xfab120db), SkBits2Float(0x77b50b4f)); // -4.59851e+35f, 7.34402e+33f
4856 path.close();
4857 path.moveTo(SkBits2Float(0xfab59cf2), SkBits2Float(0xf800007e)); // -4.71494e+35f, -1.03847e+34f
4858 path.lineTo(SkBits2Float(0xfaa7cc52), SkBits2Float(0xf800007f)); // -4.35629e+35f, -1.03848e+34f
4859 path.lineTo(SkBits2Float(0xfd6580e5), SkBits2Float(0x7d60177f)); // -1.90664e+37f, 1.86168e+37f
4860 path.lineTo(SkBits2Float(0xfdc2c2c1), SkBits2Float(0x7dc00c0f)); // -3.23602e+37f, 3.19093e+37f
4861 path.lineTo(SkBits2Float(0xfe016040), SkBits2Float(0x7e000626)); // -4.29925e+37f, 4.25433e+37f
4862 path.lineTo(SkBits2Float(0xfe115c90), SkBits2Float(0x7e100636)); // -4.83047e+37f, 4.78603e+37f
4863 path.lineTo(SkBits2Float(0xfe116239), SkBits2Float(0x7e10008f)); // -4.8312e+37f, 4.78529e+37f
4864 path.lineTo(SkBits2Float(0xfe1167e0), SkBits2Float(0x7e0ffae6)); // -4.83194e+37f, 4.78456e+37f
4865 path.lineTo(SkBits2Float(0xfe096438), SkBits2Float(0x7e07fade)); // -4.56562e+37f, 4.51871e+37f
4866 path.lineTo(SkBits2Float(0xfe016130), SkBits2Float(0x7dfff5ac)); // -4.29938e+37f, 4.25286e+37f
4867 path.lineTo(SkBits2Float(0xfe015b89), SkBits2Float(0x7e00007f)); // -4.29864e+37f, 4.25359e+37f
4868 path.lineTo(SkBits2Float(0xfe0155e1), SkBits2Float(0x7e000627)); // -4.29791e+37f, 4.25433e+37f
4869 path.lineTo(SkBits2Float(0xfe415879), SkBits2Float(0x7e4008bf)); // -6.42501e+37f, 6.38143e+37f
4870 path.lineTo(SkBits2Float(0xfe415f69), SkBits2Float(0x7e4008bf)); // -6.42591e+37f, 6.38143e+37f
4871 path.lineTo(SkBits2Float(0xfe416349), SkBits2Float(0x7e4008bf)); // -6.42641e+37f, 6.38143e+37f
4872 path.lineTo(SkBits2Float(0xfe41634a), SkBits2Float(0x7e4008bf)); // -6.42641e+37f, 6.38143e+37f
4873 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
4874 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
4875 path.lineTo(SkBits2Float(0xfe317061), SkBits2Float(0x7e2ffb07)); // -5.89642e+37f, 5.84796e+37f
4876 path.lineTo(SkBits2Float(0xfde2e542), SkBits2Float(0x7ddff58e)); // -3.76995e+37f, 3.72116e+37f
4877 path.lineTo(SkBits2Float(0xfd65c525), SkBits2Float(0x7d5fea3d)); // -1.90886e+37f, 1.86021e+37f
4878 path.lineTo(SkBits2Float(0xfab6c8db), SkBits2Float(0xf7b50b4f)); // -4.74536e+35f, -7.34402e+33f
4879 path.lineTo(SkBits2Float(0xfab59cf2), SkBits2Float(0xf800007e)); // -4.71494e+35f, -1.03847e+34f
4880 path.close();
4881 path.moveTo(SkBits2Float(0xfab3f4db), SkBits2Float(0x43480000)); // -4.67194e+35f, 200
4882 path.lineTo(SkBits2Float(0xfab174d9), SkBits2Float(0x43480000)); // -4.60703e+35f, 200
4883 path.quadTo(SkBits2Float(0xfd0593a5), SkBits2Float(0x7d00007f), SkBits2Float(0xfd659785), SkBits2Float(0x7d6000de)); // -1.10971e+37f, 1.0634e+37f, -1.90737e+37f, 1.86095e+37f
4884 path.quadTo(SkBits2Float(0xfda2cdf2), SkBits2Float(0x7da0009f), SkBits2Float(0xfdc2ce12), SkBits2Float(0x7dc000be)); // -2.70505e+37f, 2.6585e+37f, -3.23675e+37f, 3.1902e+37f
4885 path.quadTo(SkBits2Float(0xfde2ce31), SkBits2Float(0x7de000de), SkBits2Float(0xfe0165e9), SkBits2Float(0x7e00007f)); // -3.76845e+37f, 3.72189e+37f, -4.29999e+37f, 4.25359e+37f
4886 path.quadTo(SkBits2Float(0xfe1164b9), SkBits2Float(0x7e10008f), SkBits2Float(0xfe116239), SkBits2Float(0x7e10008f)); // -4.83153e+37f, 4.78529e+37f, -4.8312e+37f, 4.78529e+37f
4887 path.quadTo(SkBits2Float(0xfe116039), SkBits2Float(0x7e10008f), SkBits2Float(0xfe095e91), SkBits2Float(0x7e080087)); // -4.83094e+37f, 4.78529e+37f, -4.56488e+37f, 4.51944e+37f
4888 path.quadTo(SkBits2Float(0xfe015d09), SkBits2Float(0x7e00007f), SkBits2Float(0xfe015b89), SkBits2Float(0x7e00007f)); // -4.29884e+37f, 4.25359e+37f, -4.29864e+37f, 4.25359e+37f
4889 path.lineTo(SkBits2Float(0xfe415bc9), SkBits2Float(0x7e4000be)); // -6.42544e+37f, 6.38039e+37f
4890 path.quadTo(SkBits2Float(0xfe415da9), SkBits2Float(0x7e4000be), SkBits2Float(0xfe415f69), SkBits2Float(0x7e4000be)); // -6.42568e+37f, 6.38039e+37f, -6.42591e+37f, 6.38039e+37f
4891 path.quadTo(SkBits2Float(0xfe416149), SkBits2Float(0x7e4000be), SkBits2Float(0xfe416349), SkBits2Float(0x7e4000be)); // -6.42615e+37f, 6.38039e+37f, -6.42641e+37f, 6.38039e+37f
4892 path.quadTo(SkBits2Float(0xfe416849), SkBits2Float(0x7e4000be), SkBits2Float(0xfe316ab9), SkBits2Float(0x7e3000af)); // -6.42706e+37f, 6.38039e+37f, -5.89569e+37f, 5.84869e+37f
4893 path.quadTo(SkBits2Float(0xfe216d29), SkBits2Float(0x7e20009f), SkBits2Float(0xfde2d9f2), SkBits2Float(0x7de000de)); // -5.36431e+37f, 5.31699e+37f, -3.76921e+37f, 3.72189e+37f
4894 path.quadTo(SkBits2Float(0xfda2d9b2), SkBits2Float(0x7da0009f), SkBits2Float(0xfd65ae85), SkBits2Float(0x7d6000de)); // -2.70582e+37f, 2.6585e+37f, -1.90812e+37f, 1.86095e+37f
4895 path.quadTo(SkBits2Float(0xfd05a9a6), SkBits2Float(0x7d00007f), SkBits2Float(0xfab3f4db), SkBits2Float(0x43480000)); // -1.11043e+37f, 1.0634e+37f, -4.67194e+35f, 200
4896 path.close();
4897 path.moveTo(SkBits2Float(0x7f07a445), SkBits2Float(0xff080087)); // 1.80299e+38f, -1.80778e+38f
4898 path.quadTo(SkBits2Float(0x7f0ba519), SkBits2Float(0xff0c008b), SkBits2Float(0x7f0da5f3), SkBits2Float(0xff0e008d)); // 1.8562e+38f, -1.86095e+38f, 1.88283e+38f, -1.88753e+38f
4899 path.quadTo(SkBits2Float(0x7f0fa6d5), SkBits2Float(0xff10008f), SkBits2Float(0x7f0fa7bd), SkBits2Float(0xff10008f)); // 1.90946e+38f, -1.91412e+38f, 1.90951e+38f, -1.91412e+38f
4900 path.quadTo(SkBits2Float(0x7f0faa7d), SkBits2Float(0xff10008f), SkBits2Float(0x7ef75801), SkBits2Float(0xfef800f6)); // 1.90965e+38f, -1.91412e+38f, 1.64388e+38f, -1.64827e+38f
4901 path.quadTo(SkBits2Float(0x7ecf5b09), SkBits2Float(0xfed000ce), SkBits2Float(0x7e875ac2), SkBits2Float(0xfe880087)); // 1.37811e+38f, -1.38242e+38f, 8.99585e+37f, -9.03889e+37f
4902 path.quadTo(SkBits2Float(0x7e0eb505), SkBits2Float(0xfe10008f), SkBits2Float(0x7d7ab958), SkBits2Float(0xfd80007f)); // 4.74226e+37f, -4.78529e+37f, 2.08293e+37f, -2.1268e+37f
4903 path.quadTo(SkBits2Float(0xfc8ac1cd), SkBits2Float(0x7c80007f), SkBits2Float(0xfc8b16cd), SkBits2Float(0x7c80007f)); // -5.76374e+36f, 5.31699e+36f, -5.77753e+36f, 5.31699e+36f
4904 path.quadTo(SkBits2Float(0xfc8b36cd), SkBits2Float(0x7c80007f), SkBits2Float(0xfc16a51a), SkBits2Float(0x7c00007f)); // -5.78273e+36f, 5.31699e+36f, -3.12877e+36f, 2.6585e+36f
4905 path.quadTo(SkBits2Float(0xfab6e4de), SkBits2Float(0x43480000), SkBits2Float(0x7c68f062), SkBits2Float(0xfc80007f)); // -4.7482e+35f, 200, 4.83795e+36f, -5.31699e+36f
4906 path.lineTo(SkBits2Float(0x7ddd1ecb), SkBits2Float(0xfde000de)); // 3.67399e+37f, -3.72189e+37f
4907 path.quadTo(SkBits2Float(0x7d9d254b), SkBits2Float(0xfda0009f), SkBits2Float(0x7d8d2bbc), SkBits2Float(0xfd90008f)); // 2.61103e+37f, -2.6585e+37f, 2.3456e+37f, -2.39265e+37f
4908 path.quadTo(SkBits2Float(0x7d7a64d8), SkBits2Float(0xfd80007f), SkBits2Float(0x7d7a7258), SkBits2Float(0xfd80007f)); // 2.08019e+37f, -2.1268e+37f, 2.08063e+37f, -2.1268e+37f
4909 path.quadTo(SkBits2Float(0x7d7a9058), SkBits2Float(0xfd80007f), SkBits2Float(0x7ded50db), SkBits2Float(0xfdf000ee)); // 2.0816e+37f, -2.1268e+37f, 3.94309e+37f, -3.98774e+37f
4910 path.quadTo(SkBits2Float(0x7e2eace5), SkBits2Float(0xfe3000af), SkBits2Float(0x7e8756a2), SkBits2Float(0xfe880087)); // 5.80458e+37f, -5.84869e+37f, 8.99478e+37f, -9.03889e+37f
4911 path.quadTo(SkBits2Float(0x7ebf56d9), SkBits2Float(0xfec000be), SkBits2Float(0x7edb54d5), SkBits2Float(0xfedc00da)); // 1.27167e+38f, -1.27608e+38f, 1.45771e+38f, -1.46217e+38f
4912 path.quadTo(SkBits2Float(0x7ef752e1), SkBits2Float(0xfef800f6), SkBits2Float(0x7ef74f21), SkBits2Float(0xfef800f6)); // 1.64375e+38f, -1.64827e+38f, 1.64365e+38f, -1.64827e+38f
4913 path.quadTo(SkBits2Float(0x7ef74d71), SkBits2Float(0xfef800f6), SkBits2Float(0x7ef34bbd), SkBits2Float(0xfef400f2)); // 1.64361e+38f, -1.64827e+38f, 1.61698e+38f, -1.62168e+38f
4914 path.quadTo(SkBits2Float(0x7eef4a19), SkBits2Float(0xfef000ee), SkBits2Float(0x7edf4859), SkBits2Float(0xfee000de)); // 1.59035e+38f, -1.5951e+38f, 1.48397e+38f, -1.48876e+38f
4915 path.lineTo(SkBits2Float(0x7f07a445), SkBits2Float(0xff080087)); // 1.80299e+38f, -1.80778e+38f
4916 path.close();
4918 ->getCanvas()
4919 ->drawPath(path, paint);
4920}

◆ test_strokerec()

static void test_strokerec ( skiatest::Reporter reporter)
static

Definition at line 1074 of file PathTest.cpp.

1074 {
1076 REPORTER_ASSERT(reporter, rec.isFillStyle());
1077
1078 rec.setHairlineStyle();
1079 REPORTER_ASSERT(reporter, rec.isHairlineStyle());
1080
1081 rec.setStrokeStyle(SK_Scalar1, false);
1083
1084 rec.setStrokeStyle(SK_Scalar1, true);
1086
1087 rec.setStrokeStyle(0, false);
1089
1090 rec.setStrokeStyle(0, true);
1092}
@ kStrokeAndFill_Style
Definition SkStrokeRec.h:36

◆ test_tiny_path_convexity()

static void test_tiny_path_convexity ( skiatest::Reporter reporter,
const char *  pathBug,
SkScalar  tx,
SkScalar  ty,
SkScalar  scale 
)
static

Definition at line 587 of file PathTest.cpp.

588 {
589 SkPath smallPath;
590 SkAssertResult(SkParsePath::FromSVGString(pathBug, &smallPath));
591 bool smallConvex = smallPath.isConvex();
592 SkPath largePath;
593 SkAssertResult(SkParsePath::FromSVGString(pathBug, &largePath));
595 matrix.reset();
596 matrix.preTranslate(100, 100);
597 matrix.preScale(scale, scale);
598 largePath.transform(matrix);
599 bool largeConvex = largePath.isConvex();
600 REPORTER_ASSERT(reporter, smallConvex == largeConvex);
601}

◆ test_transform()

static void test_transform ( skiatest::Reporter reporter)
static

Definition at line 2834 of file PathTest.cpp.

2834 {
2835 SkPath p;
2836
2837#define CONIC_PERSPECTIVE_BUG_FIXED 0
2838 static const SkPoint pts[] = {
2839 { 0, 0 }, // move
2840 { SkIntToScalar(10), SkIntToScalar(10) }, // line
2841 { SkIntToScalar(20), SkIntToScalar(10) }, { SkIntToScalar(20), 0 }, // quad
2842 { 0, 0 }, { 0, SkIntToScalar(10) }, { SkIntToScalar(1), SkIntToScalar(10) }, // cubic
2843#if CONIC_PERSPECTIVE_BUG_FIXED
2844 { 0, 0 }, { SkIntToScalar(20), SkIntToScalar(10) }, // conic
2845#endif
2846 };
2847 const int kPtCount = std::size(pts);
2848
2849 p.moveTo(pts[0]);
2850 p.lineTo(pts[1]);
2851 p.quadTo(pts[2], pts[3]);
2852 p.cubicTo(pts[4], pts[5], pts[6]);
2853#if CONIC_PERSPECTIVE_BUG_FIXED
2854 p.conicTo(pts[4], pts[5], 0.5f);
2855#endif
2856 p.close();
2857
2858 {
2860 matrix.reset();
2861 SkPath p1;
2862 p.transform(matrix, &p1);
2863 REPORTER_ASSERT(reporter, p == p1);
2864 }
2865
2866
2867 {
2869 matrix.setScale(SK_Scalar1 * 2, SK_Scalar1 * 3);
2870
2871 SkPath p1; // Leave p1 non-unique (i.e., the empty path)
2872
2873 p.transform(matrix, &p1);
2874 SkPoint pts1[kPtCount];
2875 int count = p1.getPoints(pts1, kPtCount);
2877 for (int i = 0; i < count; ++i) {
2878 SkPoint newPt = SkPoint::Make(pts[i].fX * 2, pts[i].fY * 3);
2879 REPORTER_ASSERT(reporter, newPt == pts1[i]);
2880 }
2881 }
2882
2883 {
2885 matrix.reset();
2886 matrix.setPerspX(4);
2887
2888 SkPath p1;
2889 p1.moveTo(SkPoint::Make(0, 0));
2890
2891 p.transform(matrix, &p1, SkApplyPerspectiveClip::kNo);
2892 REPORTER_ASSERT(reporter, matrix.invert(&matrix));
2893 p1.transform(matrix, nullptr, SkApplyPerspectiveClip::kNo);
2894 SkRect pBounds = p.getBounds();
2895 SkRect p1Bounds = p1.getBounds();
2900 }
2901
2902 p.reset();
2903 p.addCircle(0, 0, 1, SkPathDirection::kCW);
2904
2905 {
2907 matrix.reset();
2908 SkPath p1;
2909 p1.moveTo(SkPoint::Make(0, 0));
2910
2911 p.transform(matrix, &p1);
2913 }
2914
2915
2916 {
2918 matrix.reset();
2919 matrix.setScaleX(-1);
2920 SkPath p1;
2921 p1.moveTo(SkPoint::Make(0, 0)); // Make p1 unique (i.e., not empty path)
2922
2923 p.transform(matrix, &p1);
2925 }
2926
2927 {
2929 matrix.setAll(1, 1, 0, 1, 1, 0, 0, 0, 1);
2930 SkPath p1;
2931 p1.moveTo(SkPoint::Make(0, 0)); // Make p1 unique (i.e., not empty path)
2932
2933 p.transform(matrix, &p1);
2935 }
2936
2937 {
2938 SkPath p1;
2939 p1.addRect({ 10, 20, 30, 40 });
2940 SkPath p2;
2941 p2.addRect({ 10, 20, 30, 40 });
2942 uint32_t id1 = p1.getGenerationID();
2943 uint32_t id2 = p2.getGenerationID();
2944 REPORTER_ASSERT(reporter, id1 != id2);
2946 matrix.setScale(2, 2);
2947 p1.transform(matrix, &p2);
2950 p1.transform(matrix);
2952 }
2953}
@ kNo
Don't pre-clip the geometry before applying the (perspective) matrix.
static const int kPtCount[]
int getPoints(SkPoint points[], int max) const
Definition SkPath.cpp:529

◆ test_tricky_cubic()

static void test_tricky_cubic ( )
static

Definition at line 794 of file PathTest.cpp.

794 {
795 const SkPoint pts[] = {
796 { SkDoubleToScalar(18.8943768), SkDoubleToScalar(129.121277) },
797 { SkDoubleToScalar(18.8937435), SkDoubleToScalar(129.121689) },
798 { SkDoubleToScalar(18.8950119), SkDoubleToScalar(129.120422) },
799 { SkDoubleToScalar(18.5030727), SkDoubleToScalar(129.13121) },
800 };
801
802 SkPath path;
803 path.moveTo(pts[0]);
804 path.cubicTo(pts[1], pts[2], pts[3]);
805 test_draw_AA_path(19, 130, path);
806}
#define SkDoubleToScalar(x)
Definition SkScalar.h:64

◆ test_zero_length_paths()

static void test_zero_length_paths ( skiatest::Reporter reporter)
static

Definition at line 2955 of file PathTest.cpp.

2955 {
2956 SkPath p;
2957 uint8_t verbs[32];
2958
2959 struct SUPPRESS_VISIBILITY_WARNING zeroPathTestData {
2960 const char* testPath;
2961 const size_t numResultPts;
2962 const SkRect resultBound;
2963 const SkPath::Verb* resultVerbs;
2964 const size_t numResultVerbs;
2965 };
2966
2967 static const SkPath::Verb resultVerbs1[] = { SkPath::kMove_Verb };
2968 static const SkPath::Verb resultVerbs2[] = { SkPath::kMove_Verb, SkPath::kMove_Verb };
2969 static const SkPath::Verb resultVerbs3[] = { SkPath::kMove_Verb, SkPath::kClose_Verb };
2971 static const SkPath::Verb resultVerbs5[] = { SkPath::kMove_Verb, SkPath::kLine_Verb };
2973 static const SkPath::Verb resultVerbs7[] = { SkPath::kMove_Verb, SkPath::kLine_Verb, SkPath::kClose_Verb };
2974 static const SkPath::Verb resultVerbs8[] = {
2976 };
2977 static const SkPath::Verb resultVerbs9[] = { SkPath::kMove_Verb, SkPath::kQuad_Verb };
2979 static const SkPath::Verb resultVerbs11[] = { SkPath::kMove_Verb, SkPath::kQuad_Verb, SkPath::kClose_Verb };
2980 static const SkPath::Verb resultVerbs12[] = {
2982 };
2983 static const SkPath::Verb resultVerbs13[] = { SkPath::kMove_Verb, SkPath::kCubic_Verb };
2985 static const SkPath::Verb resultVerbs15[] = { SkPath::kMove_Verb, SkPath::kCubic_Verb, SkPath::kClose_Verb };
2986 static const SkPath::Verb resultVerbs16[] = {
2988 };
2989 static const struct zeroPathTestData gZeroLengthTests[] = {
2990 { "M 1 1", 1, {1, 1, 1, 1}, resultVerbs1, std::size(resultVerbs1) },
2991 { "M 1 1 M 2 1", 2, {SK_Scalar1, SK_Scalar1, 2*SK_Scalar1, SK_Scalar1}, resultVerbs2, std::size(resultVerbs2) },
2992 { "M 1 1 z", 1, {1, 1, 1, 1}, resultVerbs3, std::size(resultVerbs3) },
2993 { "M 1 1 z M 2 1 z", 2, {SK_Scalar1, SK_Scalar1, 2*SK_Scalar1, SK_Scalar1}, resultVerbs4, std::size(resultVerbs4) },
2994 { "M 1 1 L 1 1", 2, {SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1}, resultVerbs5, std::size(resultVerbs5) },
2995 { "M 1 1 L 1 1 M 2 1 L 2 1", 4, {SK_Scalar1, SK_Scalar1, 2*SK_Scalar1, SK_Scalar1}, resultVerbs6, std::size(resultVerbs6) },
2996 { "M 1 1 L 1 1 z", 2, {SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1}, resultVerbs7, std::size(resultVerbs7) },
2997 { "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, std::size(resultVerbs8) },
2998 { "M 1 1 Q 1 1 1 1", 3, {SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1}, resultVerbs9, std::size(resultVerbs9) },
2999 { "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, std::size(resultVerbs10) },
3000 { "M 1 1 Q 1 1 1 1 z", 3, {SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1}, resultVerbs11, std::size(resultVerbs11) },
3001 { "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, std::size(resultVerbs12) },
3002 { "M 1 1 C 1 1 1 1 1 1", 4, {SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1}, resultVerbs13, std::size(resultVerbs13) },
3003 { "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,
3004 std::size(resultVerbs14)
3005 },
3006 { "M 1 1 C 1 1 1 1 1 1 z", 4, {SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1}, resultVerbs15, std::size(resultVerbs15) },
3007 { "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,
3008 std::size(resultVerbs16)
3009 }
3010 };
3011
3012 for (size_t i = 0; i < std::size(gZeroLengthTests); ++i) {
3013 p.reset();
3014 bool valid = SkParsePath::FromSVGString(gZeroLengthTests[i].testPath, &p);
3015 REPORTER_ASSERT(reporter, valid);
3016 REPORTER_ASSERT(reporter, !p.isEmpty());
3017 REPORTER_ASSERT(reporter, gZeroLengthTests[i].numResultPts == (size_t)p.countPoints());
3018 REPORTER_ASSERT(reporter, gZeroLengthTests[i].resultBound == p.getBounds());
3019 REPORTER_ASSERT(reporter, gZeroLengthTests[i].numResultVerbs == (size_t)p.getVerbs(verbs, std::size(verbs)));
3020 for (size_t j = 0; j < gZeroLengthTests[i].numResultVerbs; ++j) {
3021 REPORTER_ASSERT(reporter, gZeroLengthTests[i].resultVerbs[j] == verbs[j]);
3022 }
3023 }
3024}

◆ write_and_read_back()

static void write_and_read_back ( skiatest::Reporter reporter,
const SkPath p 
)
static

Definition at line 2743 of file PathTest.cpp.

2744 {
2745 SkBinaryWriteBuffer writer({});
2746 writer.writePath(p);
2747 size_t size = writer.bytesWritten();
2748 SkAutoMalloc storage(size);
2749 writer.writeToMemory(storage.get());
2750 SkReadBuffer reader(storage.get(), size);
2751
2752 SkPath readBack;
2753 REPORTER_ASSERT(reporter, readBack != p);
2754 reader.readPath(&readBack);
2755 REPORTER_ASSERT(reporter, readBack == p);
2756
2759
2760 SkRect oval0, oval1;
2761 SkPathDirection dir0, dir1;
2762 unsigned start0, start1;
2763 REPORTER_ASSERT(reporter, readBack.isOval(nullptr) == p.isOval(nullptr));
2764 if (SkPathPriv::IsOval(p, &oval0, &dir0, &start0) &&
2765 SkPathPriv::IsOval(readBack, &oval1, &dir1, &start1)) {
2766 REPORTER_ASSERT(reporter, oval0 == oval1);
2767 REPORTER_ASSERT(reporter, dir0 == dir1);
2768 REPORTER_ASSERT(reporter, start0 == start1);
2769 }
2770 REPORTER_ASSERT(reporter, readBack.isRRect(nullptr) == p.isRRect(nullptr));
2771 SkRRect rrect0, rrect1;
2772 if (SkPathPriv::IsRRect(p, &rrect0, &dir0, &start0) &&
2773 SkPathPriv::IsRRect(readBack, &rrect1, &dir1, &start1)) {
2774 REPORTER_ASSERT(reporter, rrect0 == rrect1);
2775 REPORTER_ASSERT(reporter, dir0 == dir1);
2776 REPORTER_ASSERT(reporter, start0 == start1);
2777 }
2778 const SkRect& origBounds = p.getBounds();
2779 const SkRect& readBackBounds = readBack.getBounds();
2780
2781 REPORTER_ASSERT(reporter, origBounds == readBackBounds);
2782}
void writePath(const SkPath &path) override
static bool IsRRect(const SkPath &path, SkRRect *rrect, SkPathDirection *dir, unsigned *start)
Definition SkPathPriv.h:272
bool isRRect(SkRRect *rrect) const
Definition SkPath.cpp:517

Variable Documentation

◆ kDontCheckDir

const SkPathFirstDirection kDontCheckDir = static_cast<SkPathFirstDirection>(3)

Definition at line 1097 of file PathTest.cpp.