Flutter Engine
The Flutter Engine
Functions | Variables
GeometryTest.cpp File Reference
#include "include/core/SkMatrix.h"
#include "include/core/SkPoint.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSpan.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkDebug.h"
#include "src/base/SkRandom.h"
#include "src/core/SkGeometry.h"
#include "src/core/SkPointPriv.h"
#include "tests/Test.h"
#include <array>
#include <cmath>
#include <cstdlib>
#include <limits>
#include <string>

Go to the source code of this file.

Functions

static bool nearly_equal (const SkPoint &a, const SkPoint &b)
 
static void testChopCubic (skiatest::Reporter *reporter)
 
static void check_pairs (skiatest::Reporter *reporter, int index, SkScalar t, const char name[], SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1)
 
static void test_evalquadat (skiatest::Reporter *reporter)
 
static void test_conic_eval_pos (skiatest::Reporter *reporter, const SkConic &conic, SkScalar t)
 
static void test_conic_eval_tan (skiatest::Reporter *reporter, const SkConic &conic, SkScalar t)
 
static void test_conic (skiatest::Reporter *reporter)
 
static void test_quad_tangents (skiatest::Reporter *reporter)
 
static void test_conic_tangents (skiatest::Reporter *reporter)
 
static void test_this_conic_to_quad (skiatest::Reporter *r, const SkPoint pts[3], SkScalar w)
 
static void test_conic_to_quads (skiatest::Reporter *reporter)
 
static void test_cubic_tangents (skiatest::Reporter *reporter)
 
static void check_cubic_type (skiatest::Reporter *reporter, const std::array< SkPoint, 4 > &bezierPoints, SkCubicType expectedType, bool undefined=false)
 
static void check_cubic_around_rect (std::string name, skiatest::Reporter *reporter, float x1, float y1, float x2, float y2, bool undefined=false)
 
static void test_classify_cubic (skiatest::Reporter *reporter)
 
static void test_cubic_cusps (skiatest::Reporter *reporter)
 
static void test_chop_quad_at_midtangent (skiatest::Reporter *reporter, const SkPoint pts[3])
 
static void test_chop_cubic_at_midtangent (skiatest::Reporter *reporter, const SkPoint pts[4], SkCubicType cubicType)
 
SkPoint lerp (const SkPoint &a, const SkPoint &b, float t)
 
static void test_measure_rotation (skiatest::Reporter *reporter)
 
static void test_chop_at_midtangent (skiatest::Reporter *reporter)
 
 DEF_TEST (Geometry, reporter)
 
static void testChopMonoCubicAtY (skiatest::Reporter *reporter, std::string name, SkSpan< const SkPoint > curveInputs, SkScalar yToChopAt, SkSpan< const SkPoint > expectedOutputs)
 
 DEF_TEST (GeometryChopMonoCubicAtY_Successful, reporter)
 
 DEF_TEST (GeometryChopMonoCubicAtY_OutOfRangeReturnFalse, reporter)
 
static void testChopMonoCubicAtX (skiatest::Reporter *reporter, std::string name, SkSpan< const SkPoint > curveInputs, SkScalar xToChopAt, SkSpan< const SkPoint > expectedOutputs)
 
 DEF_TEST (GeometryChopMonoCubicAtX_Successful, reporter)
 
 DEF_TEST (GeometryChopMonoCubicAtX_OutOfRangeReturnFalse, reporter)
 

Variables

static std::array< SkPoint, 4 > kSerpentines []
 
static std::array< SkPoint, 4 > kLoops []
 
static std::array< SkPoint, 4 > kLinearCubics []
 
static std::array< SkPoint, 4 > kCusps []
 
static SkMatrix kSkewMatrices []
 
static std::array< SkPoint, 3 > kQuads []
 

Function Documentation

◆ check_cubic_around_rect()

static void check_cubic_around_rect ( std::string  name,
skiatest::Reporter reporter,
float  x1,
float  y1,
float  x2,
float  y2,
bool  undefined = false 
)
static

Definition at line 307 of file GeometryTest.cpp.

309 {
311 static constexpr SkCubicType expectations[24] = {
336 };
337 SkPoint points[] = {{x1, y1}, {x2, y1}, {x2, y2}, {x1, y2}};
338 std::array<SkPoint, 4> bezier;
339 for (int i=0; i < 4; ++i) {
340 bezier[0] = points[i];
341 for (int j=0; j < 3; ++j) {
342 int jidx = (j < i) ? j : j+1;
343 bezier[1] = points[jidx];
344 for (int k=0, kidx=0; k < 2; ++k, ++kidx) {
345 for (int n = 0; n < 2; ++n) {
346 kidx = (kidx == i || kidx == jidx) ? kidx+1 : kidx;
347 }
348 bezier[2] = points[kidx];
349 for (int l = 0; l < 4; ++l) {
350 if (l != i && l != jidx && l != kidx) {
351 bezier[3] = points[l];
352 break;
353 }
354 }
355 check_cubic_type(reporter, bezier, expectations[i*6 + j*2 + k], undefined);
356 }
357 }
358 }
359 for (int i=0; i < 4; ++i) {
360 bezier[0] = points[i];
361 for (int j=0; j < 3; ++j) {
362 int jidx = (j < i) ? j : j+1;
363 bezier[1] = points[jidx];
364 bezier[2] = points[jidx];
365 for (int k=0, kidx=0; k < 2; ++k, ++kidx) {
366 for (int n = 0; n < 2; ++n) {
367 kidx = (kidx == i || kidx == jidx) ? kidx+1 : kidx;
368 }
369 bezier[3] = points[kidx];
371 }
372 }
373 }
374}
reporter
Definition: FontMgrTest.cpp:39
static void check_cubic_type(skiatest::Reporter *reporter, const std::array< SkPoint, 4 > &bezierPoints, SkCubicType expectedType, bool undefined=false)
static const int points[]
SkCubicType
Definition: SkGeometry.h:264
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32

◆ check_cubic_type()

static void check_cubic_type ( skiatest::Reporter reporter,
const std::array< SkPoint, 4 > &  bezierPoints,
SkCubicType  expectedType,
bool  undefined = false 
)
static

Definition at line 296 of file GeometryTest.cpp.

298 {
299 // Classify the cubic even if the results will be undefined: check for crashes and asserts.
300 SkCubicType actualType = SkClassifyCubic(bezierPoints.data());
301 if (!undefined) {
302 REPORTER_ASSERT(reporter, actualType == expectedType,
303 "%d != %d", (int)actualType, (int)expectedType);
304 }
305}
SkCubicType SkClassifyCubic(const SkPoint P[4], double t[2], double s[2], double d[4])
Definition: SkGeometry.cpp:809
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286

◆ check_pairs()

static void check_pairs ( skiatest::Reporter reporter,
int  index,
SkScalar  t,
const char  name[],
SkScalar  x0,
SkScalar  y0,
SkScalar  x1,
SkScalar  y1 
)
static

Definition at line 128 of file GeometryTest.cpp.

129 {
130 bool eq = SkScalarNearlyEqual(x0, x1) && SkScalarNearlyEqual(y0, y1);
131 if (!eq) {
132 SkDebugf("%s [%d %g] p0 [%10.8f %10.8f] p1 [%10.8f %10.8f]\n",
133 name, index, t, x0, y0, x1, y1);
135 }
136}
static bool eq(const SkM44 &a, const SkM44 &b, float tol)
Definition: M44Test.cpp:18
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
Definition: SkScalar.h:107

◆ DEF_TEST() [1/5]

DEF_TEST ( Geometry  ,
reporter   
)

Definition at line 630 of file GeometryTest.cpp.

630 {
631 SkPoint pts[5];
632
633 pts[0].set(0, 0);
634 pts[1].set(100, 50);
635 pts[2].set(0, 100);
636
637 int count = SkChopQuadAtMaxCurvature(pts, pts); // Ensure src and dst can be the same pointer.
638 REPORTER_ASSERT(reporter, count == 1 || count == 2);
639
640 // This previously crashed because the computed t of max curvature is NaN and SkChopQuadAt
641 // asserts that the passed t is in 0..1. Passes by not asserting.
642 pts[0].set(15.1213f, 7.77647f);
643 pts[1].set(6.2168e+19f, 1.51338e+20f);
644 pts[2].set(1.4579e+19f, 1.55558e+21f);
646
647 pts[0].set(0, 0);
648 pts[1].set(3, 0);
649 pts[2].set(3, 3);
650 SkConvertQuadToCubic(pts, pts);
651 const SkPoint cubic[] = {
652 { 0, 0, }, { 2, 0, }, { 3, 1, }, { 3, 3 },
653 };
654 for (int i = 0; i < 4; ++i) {
656 }
657
669}
int count
Definition: FontMgrTest.cpp:50
static void test_conic_to_quads(skiatest::Reporter *reporter)
static bool nearly_equal(const SkPoint &a, const SkPoint &b)
static void testChopCubic(skiatest::Reporter *reporter)
static void test_measure_rotation(skiatest::Reporter *reporter)
static void test_chop_at_midtangent(skiatest::Reporter *reporter)
static void test_classify_cubic(skiatest::Reporter *reporter)
static void test_conic_tangents(skiatest::Reporter *reporter)
static void test_conic(skiatest::Reporter *reporter)
static void test_cubic_cusps(skiatest::Reporter *reporter)
static void test_cubic_tangents(skiatest::Reporter *reporter)
static void test_evalquadat(skiatest::Reporter *reporter)
static void test_quad_tangents(skiatest::Reporter *reporter)
void SkConvertQuadToCubic(const SkPoint src[3], SkPoint dst[4])
Definition: SkGeometry.cpp:378
int SkChopQuadAtMaxCurvature(const SkPoint src[3], SkPoint dst[5])
Definition: SkGeometry.cpp:367
AI float cubic(float precision, const SkPoint pts[], const VectorXform &vectorXform=VectorXform())
Definition: WangsFormula.h:195
void set(float x, float y)
Definition: SkPoint_impl.h:200

◆ DEF_TEST() [2/5]

DEF_TEST ( GeometryChopMonoCubicAtX_OutOfRangeReturnFalse  ,
reporter   
)

Definition at line 966 of file GeometryTest.cpp.

966 {
967 SkPoint inputs[] = {{ 0, 0 }, { 0, 0 }, { 10, 10 }, { 10, 10 }};
968 SkPoint outputs[7];
969
970 // Too low
972 // Too high
974}
bool SkChopMonoCubicAtX(const SkPoint src[4], SkScalar x, SkPoint dst[7])
dictionary outputs
Definition: bazel_build.py:29

◆ DEF_TEST() [3/5]

DEF_TEST ( GeometryChopMonoCubicAtX_Successful  ,
reporter   
)

Definition at line 849 of file GeometryTest.cpp.

849 {
850 // These cubics are all arbitrary, picked using Desmos for something that looked "nice".
851
852 testChopMonoCubicAtX(reporter, "straight, positive slope @ 2.5",
853 {{ 0, 0 }, { 0, 0 }, { 10, 10 }, { 10, 10 }},
854 2.5f,
855 {{ 0.000000f, 0.000000f }, { 0.000000f, 0.000000f }, { 1.065055f, 1.065055f },
856 { 2.500000f, 2.500000f },
857 { 5.461981f, 5.461981f }, { 10.000000f, 10.000000f }, { 10.000000f, 10.000000f }}
858 );
859 testChopMonoCubicAtX(reporter, "straight, positive slope @ 5.0",
860 {{ 0, 0 }, { 0, 0 }, { 10, 10 }, { 10, 10 }},
861 5.0f,
862 {{ 0.000000f, 0.000000f }, { 0.000000f, 0.000000f }, { 2.500000f, 2.500000f },
863 { 5.000000f, 5.000000f },
864 { 7.500000f, 7.500000f }, { 10.000000f, 10.000000f }, { 10.000000f, 10.000000f }}
865 );
866 testChopMonoCubicAtX(reporter, "straight, positive slope @ 9.0",
867 {{ 0, 0 }, { 0, 0 }, { 10, 10 }, { 10, 10 }},
868 9.0f,
869 {{ 0.000000f, 0.000000f }, { 0.000000f, 0.000000f }, { 6.467375f, 6.467375f },
870 { 9.000000f, 9.000000f },
871 { 9.616623f, 9.616623f }, { 10.000000f, 10.000000f }, { 10.000000f, 10.000000f }}
872 );
873 testChopMonoCubicAtX(reporter, "straight, positive slope @ 10.0",
874 {{ 0, 0 }, { 0, 0 }, { 10, 10 }, { 10, 10 }},
875 10.0f,
876 {{ 0.000000f, 0.000000f }, { 0.000000f, 0.000000f }, { 10.000000f, 10.000000f },
877 { 10.000000f, 10.000000f },
878 { 10.000000f, 10.000000f }, { 10.000000f, 10.000000f }, { 10.000000f, 10.000000f }}
879 );
880
881 testChopMonoCubicAtX(reporter, "curve, positive slope @ 2.0",
882 {{ 1, 1 }, { 5, 2 }, { 7, 4 }, { 8, 7 }},
883 2.0f,
884 {{ 1.000000f, 1.000000f }, { 1.348275f, 1.087069f }, { 1.681389f, 1.181719f },
885 { 2.000000f, 1.283949f },
886 { 5.340694f, 2.355856f }, { 7.087069f, 4.261207f }, { 8.000000f, 7.000000f }}
887 );
888 testChopMonoCubicAtX(reporter, "curve, positive slope @ 5.0",
889 {{ 1, 1 }, { 5, 2 }, { 7, 4 }, { 8, 7 }},
890 5.0f,
891 {{ 1.000000f, 1.000000f }, { 2.650396f, 1.412599f }, { 3.960316f, 1.995436f },
892 { 5.000000f, 2.748511f },
893 { 6.480158f, 3.820634f }, { 7.412599f, 5.237797f }, { 8.000000f, 7.000000f }}
894 );
895
896 testChopMonoCubicAtX(reporter, "curve, negative slope @ 5.0",
897 {{ 2, 7 }, { 3, 2 }, { 6, 3 }, { 11, 2 }},
898 5.0f,
899 {{ 2.000000f, 7.000000f }, { 2.500000f, 4.500000f }, { 3.500000f, 3.500000f },
900 { 5.000000f, 3.000000f },
901 { 6.500000f, 2.500000f }, { 8.500000f, 2.500000f }, { 11.000000f, 2.000000f }}
902 );
903 testChopMonoCubicAtX(reporter, "curve, negative slope @ 3.0",
904 {{ 2, 7 }, { 3, 2 }, { 6, 3 }, { 11, 2 }},
905 3.0f,
906 {{ 2.000000f, 7.000000f }, { 2.228714f, 5.856432f }, { 2.562047f, 5.026724f },
907 { 3.000000f, 4.415163f },
908 { 4.476901f, 2.352807f }, { 7.143568f, 2.771286f }, { 11.000000f, 2.000000f }}
909 );
910 testChopMonoCubicAtX(reporter, "curve, negative slope @ 2.5",
911 {{ 2, 7 }, { 3, 2 }, { 6, 3 }, { 11, 2 }},
912 2.5f,
913 {{ 2.000000f, 7.000000f }, { 2.131881f, 6.340593f }, { 2.298548f, 5.785543f },
914 { 2.500000f, 5.316498f },
915 { 3.826073f, 2.228977f }, { 6.659407f, 2.868119f }, { 11.000000f, 2.000000f }}
916 );
917
918 // This is the same curve as above, just the 4 points given in the opposite order.
919 // We would expect the math to result in the same chop points, with the outputs
920 // in the opposite order too.
921 testChopMonoCubicAtX(reporter, "inverted curve, negative slope @ 5.0",
922 {{ 11, 2 }, { 6, 3 }, { 3, 2 }, { 2, 7 }},
923 5.0f,
924 {{ 11.000000f, 2.000000f }, { 8.500000f, 2.500000f }, { 6.500000f, 2.500000f },
925 { 5.000000f, 3.000000f },
926 { 3.500000f, 3.500000f }, { 2.500000f, 4.500000f }, { 2.000000f, 7.000000f }}
927 );
928 testChopMonoCubicAtX(reporter, "inverted curve, negative slope @ 3.0",
929 {{ 11, 2 }, { 6, 3 }, { 3, 2 }, { 2, 7 }},
930 3.0f,
931 {{ 11.000000f, 2.000000f }, { 7.143568f, 2.771286f }, { 4.476901f, 2.352807f },
932 { 3.000000f, 4.415163f },
933 { 2.562047f, 5.026724f }, { 2.228714f, 5.856432f }, { 2.000000f, 7.000000f }}
934 );
935 testChopMonoCubicAtX(reporter, "inverted curve, negative slope @ 2.5",
936 {{ 11, 2 }, { 6, 3 }, { 3, 2 }, { 2, 7 }},
937 2.5f,
938 {{ 11.000000f, 2.000000f }, { 6.659407f, 2.868119f }, { 3.826073f, 2.228977f },
939 { 2.500000f, 5.316498f },
940 { 2.298548f, 5.785543f }, { 2.131881f, 6.340593f }, { 2.000000f, 7.000000f }}
941 );
942
943 testChopMonoCubicAtX(reporter, "big curve, negative slope @ 90",
944 {{ -2, 100 }, { 0, 0 }, { 0, 0 }, { 100, -2 }},
945 90.f,
946 {{ -2.000000f,100.000000f }, { -0.069021f, 3.451032f }, { -0.002382f, 0.119096f },
947 { 90.000000f, -1.795892f },
948 { 93.217033f, -1.864341f }, { 96.548965f, -1.930979f }, {100.000000f, -2.000000f }}
949 );
950 testChopMonoCubicAtX(reporter, "big curve, negative slope @ 10",
951 {{ -2, 100 }, { 0, 0 }, { 0, 0 }, { 100, -2 }},
952 10.f,
953 {{ -2.000000f,100.000000f }, { -1.062495f, 53.124729f }, { -0.564447f, 28.222368f },
954 { 10.000000f, 14.787060f },
955 { 21.972910f, -0.439458f }, { 46.875271f, -0.937505f }, {100.000000f, -2.000000f }}
956 );
957 testChopMonoCubicAtX(reporter, "big curve, negative slope @ 0",
958 {{ -2, 100 }, { 0, 0 }, { 0, 0 }, { 100, -2 }},
959 0.f,
960 {{ -2.000000f,100.000000f }, { -1.573017f, 78.650871f }, { -1.237192f, 61.859592f },
961 { 0.000000f, 48.633648f },
962 { 4.557854f, -0.091157f }, { 21.349131f, -0.426983f }, {100.000000f, -2.000000f }}
963 );
964}
static void testChopMonoCubicAtX(skiatest::Reporter *reporter, std::string name, SkSpan< const SkPoint > curveInputs, SkScalar xToChopAt, SkSpan< const SkPoint > expectedOutputs)

◆ DEF_TEST() [4/5]

DEF_TEST ( GeometryChopMonoCubicAtY_OutOfRangeReturnFalse  ,
reporter   
)

Definition at line 816 of file GeometryTest.cpp.

816 {
817 SkPoint inputs[] = {{ 0, 0 }, { 0, 0 }, { 10, 10 }, { 10, 10 }};
818 SkPoint outputs[7];
819
820 // Too low
822 // Too high
824}
bool SkChopMonoCubicAtY(const SkPoint src[4], SkScalar y, SkPoint dst[7])

◆ DEF_TEST() [5/5]

DEF_TEST ( GeometryChopMonoCubicAtY_Successful  ,
reporter   
)

Definition at line 690 of file GeometryTest.cpp.

690 {
691 // These cubics are all arbitrary, picked using Desmos for something that looked "nice".
692
693 testChopMonoCubicAtY(reporter, "straight, positive slope @ 2.5",
694 {{ 0, 0 }, { 0, 0 }, { 10, 10 }, { 10, 10 }},
695 2.5f,
696 {{ 0.000000f, 0.000000f }, { 0.000000f, 0.000000f }, { 1.065055f, 1.065055f },
697 { 2.500000f, 2.500000f },
698 { 5.461981f, 5.461981f }, { 10.000000f, 10.000000f }, { 10.000000f, 10.000000f }}
699 );
700 testChopMonoCubicAtY(reporter, "straight, positive slope @ 5.0",
701 {{ 0, 0 }, { 0, 0 }, { 10, 10 }, { 10, 10 }},
702 5.0f,
703 {{ 0.000000f, 0.000000f }, { 0.000000f, 0.000000f }, { 2.500000f, 2.500000f },
704 { 5.000000f, 5.000000f },
705 { 7.500000f, 7.500000f }, { 10.000000f, 10.000000f }, { 10.000000f, 10.000000f }}
706 );
707 testChopMonoCubicAtY(reporter, "straight, positive slope @ 9.0",
708 {{ 0, 0 }, { 0, 0 }, { 10, 10 }, { 10, 10 }},
709 9.0f,
710 {{ 0.000000f, 0.000000f }, { 0.000000f, 0.000000f }, { 6.467375f, 6.467375f },
711 { 9.000000f, 9.000000f },
712 { 9.616623f, 9.616623f }, { 10.000000f, 10.000000f }, { 10.000000f, 10.000000f }}
713 );
714 testChopMonoCubicAtY(reporter, "straight, positive slope @ 10.0",
715 {{ 0, 0 }, { 0, 0 }, { 10, 10 }, { 10, 10 }},
716 10.0f,
717 {{ 0.000000f, 0.000000f }, { 0.000000f, 0.000000f }, { 10.000000f, 10.000000f },
718 { 10.000000f, 10.000000f },
719 { 10.000000f, 10.000000f }, { 10.000000f, 10.000000f }, { 10.000000f, 10.000000f }}
720 );
721
722 testChopMonoCubicAtY(reporter, "curve, positive slope @ 2.0",
723 {{ 1, 1 }, { 5, 2 }, { 7, 4 }, { 8, 7 }},
724 2.0f,
725 {{ 1.000000f, 1.000000f }, { 2.055050f, 1.263763f }, { 2.970959f, 1.597096f },
726 { 3.766077f, 2.000000f },
727 { 5.985480f, 3.124621f }, { 7.263762f, 4.791288f }, { 8.000000f, 7.000000f }}
728 );
729 testChopMonoCubicAtY(reporter, "curve, positive slope @ 5.0",
730 {{ 1, 1 }, { 5, 2 }, { 7, 4 }, { 8, 7 }},
731 5.0f,
732 {{ 1.000000f, 1.000000f }, { 4.033223f, 1.758306f }, { 5.916391f, 3.091639f },
733 { 7.085550f, 5.000000f },
734 { 7.458195f, 5.608251f }, { 7.758306f, 6.274917f }, { 8.000000f, 7.000000f }}
735 );
736
737 testChopMonoCubicAtY(reporter, "curve, negative slope @ 5.0",
738 {{ 2, 7 }, { 3, 2 }, { 6, 3 }, { 11, 2 }},
739 5.0f,
740 {{ 2.000000f, 7.000000f }, { 2.162856f, 6.185719f }, { 2.378757f, 5.530570f },
741 { 2.647702f, 5.000000f },
742 { 4.030182f, 2.272668f }, { 6.814281f, 2.837144f }, { 11.000000f, 2.000000f }}
743 );
744 testChopMonoCubicAtY(reporter, "curve, negative slope @ 3.0",
745 {{ 2, 7 }, { 3, 2 }, { 6, 3 }, { 11, 2 }},
746 3.0f,
747 {{ 2.000000f, 7.000000f }, { 2.500000f, 4.500000f }, { 3.500000f, 3.500000f },
748 { 5.000000f, 3.000000f },
749 { 6.500000f, 2.500000f }, { 8.500000f, 2.500000f }, { 11.000000f, 2.000000f }}
750 );
751 testChopMonoCubicAtY(reporter, "curve, negative slope @ 2.5",
752 {{ 2, 7 }, { 3, 2 }, { 6, 3 }, { 11, 2 }},
753 2.5f,
754 {{ 2.000000f, 7.000000f }, { 2.750000f, 3.250000f }, { 4.625000f, 2.875000f },
755 { 7.625000f, 2.500000f },
756 { 8.625000f, 2.375000f }, { 9.750000f, 2.250000f }, { 11.000000f, 2.000000f }}
757 );
758
759 // This is the same curve as above, just the 4 points given in the opposite order.
760 // We would expect the math to result in the same chop points, with the outputs
761 // in the opposite order too.
762 testChopMonoCubicAtY(reporter, "inverted curve, negative slope @ 5.0",
763 {{ 11, 2 }, { 6, 3 }, { 3, 2 }, { 2, 7 }},
764 5.0f,
765 {{ 11.000000f, 2.000000f }, { 6.814281f, 2.837144f }, { 4.030182f, 2.272668f },
766 { 2.647702f, 5.000000f },
767 { 2.378757f, 5.530570f }, { 2.162856f, 6.185719f }, { 2.000000f, 7.000000f }}
768 );
769 testChopMonoCubicAtY(reporter, "inverted curve, negative slope @ 3.0",
770 {{ 11, 2 }, { 6, 3 }, { 3, 2 }, { 2, 7 }},
771 3.0f,
772 {{ 11.000000f, 2.000000f }, { 8.500000f, 2.500000f }, { 6.500000f, 2.500000f },
773 { 5.000000f, 3.000000f },
774 { 3.500000f, 3.500000f }, { 2.500000f, 4.500000f }, { 2.000000f, 7.000000f }}
775 );
776 testChopMonoCubicAtY(reporter, "inverted curve, negative slope @ 2.5",
777 {{ 11, 2 }, { 6, 3 }, { 3, 2 }, { 2, 7 }},
778 2.5f,
779 {{ 11.000000f, 2.000000f }, { 9.750000f, 2.250000f }, { 8.625000f, 2.375000f },
780 { 7.625000f, 2.500000f },
781 { 4.625000f, 2.875000f }, { 2.750000f, 3.250000f }, { 2.000000f, 7.000000f }}
782 );
783
784 testChopMonoCubicAtY(reporter, "big curve, negative slope @ 90",
785 {{ -2, 100 }, { 0, 0 }, { 0, 0 }, { 100, -2 }},
786 90.f,
787 {{ -2.000000f,100.000000f }, { -1.930979f, 96.548965f }, { -1.864341f, 93.217033f },
788 { -1.795892f, 90.000000f },
789 { 0.119096f, -0.002382f }, { 3.451032f, -0.069021f }, {100.000000f, -2.000000f }}
790 );
791 testChopMonoCubicAtY(reporter, "big curve, negative slope @ 10",
792 {{ -2, 100 }, { 0, 0 }, { 0, 0 }, { 100, -2 }},
793 10.f,
794 {{ -2.000000f,100.000000f }, { -0.937505f, 46.875271f }, { -0.439458f, 21.972910f },
795 { 14.787060f, 10.000000f },
796 { 28.222368f, -0.564447f }, { 53.124729f, -1.062495f }, {100.000000f, -2.000000f }}
797 );
798 testChopMonoCubicAtY(reporter, "big curve, negative slope @ 0",
799 {{ -2, 100 }, { 0, 0 }, { 0, 0 }, { 100, -2 }},
800 0.f,
801 {{ -2.000000f,100.000000f }, { -0.426983f, 21.349131f }, { -0.091157f, 4.557854f },
802 { 48.633648f, 0.000000f },
803 { 61.859592f, -1.237192f }, { 78.650871f, -1.573017f }, {100.000000f, -2.000000f }}
804 );
805
806 testChopMonoCubicAtY(reporter, "ossfuzz:55680 curve barely crosses Y axis",
807 {{-250.121582f, -1180.09509f}, {10.007843f, -1180.09509f},
808 {20.015685f, -786.041259f}, {40.0313721f, 2.0664072f}},
809 0.f,
810 {{-250.121582f, -1180.095093f}, {9.780392f, -1180.095093f}, {19.997992f, -786.730042f},
811 {39.978889f, 0.000000f},
812 {39.996376f, 0.688501f}, {40.013870f, 1.377304f}, {40.031372f, 2.066407f}}
813 );
814}
static void testChopMonoCubicAtY(skiatest::Reporter *reporter, std::string name, SkSpan< const SkPoint > curveInputs, SkScalar yToChopAt, SkSpan< const SkPoint > expectedOutputs)

◆ lerp()

SkPoint lerp ( const SkPoint a,
const SkPoint b,
float  t 
)

Definition at line 536 of file GeometryTest.cpp.

536 {
537 return a * (1 - t) + b * t;
538}
static bool b
struct MyStruct a[10]

◆ nearly_equal()

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

Definition at line 25 of file GeometryTest.cpp.

25 {
26 return SkScalarNearlyEqual(a.fX, b.fX) && SkScalarNearlyEqual(a.fY, b.fY);
27}

◆ test_chop_at_midtangent()

static void test_chop_at_midtangent ( skiatest::Reporter reporter)
static

Definition at line 590 of file GeometryTest.cpp.

590 {
591 SkPoint chops[10];
592 for (const auto& serp : kSerpentines) {
594 int n = SkChopCubicAtInflections(serp.data(), chops);
595 for (int i = 0; i < n; ++i) {
597 }
598 }
599 for (const auto& loop : kLoops) {
602 }
603 for (const auto& line : kLinearCubics) {
606 }
607 for (const auto& cusp : kCusps) {
610 }
611 for (const auto& quad : kQuads) {
613 SkPoint asCubic[4] = {
614 quad[0], lerp(quad[0], quad[1], 2/3.f), lerp(quad[1], quad[2], 1/3.f), quad[2]};
616 }
617
618 static const SkPoint kExactQuad[4] = {{0,0}, {6,2}, {10,2}, {12,0}};
621
622 static const SkPoint kExactCuspAtInf[4] = {{0,0}, {1,0}, {0,1}, {1,1}};
624 int n = SkChopCubicAtInflections(kExactCuspAtInf, chops);
625 for (int i = 0; i < n; ++i) {
627 }
628}
static std::array< SkPoint, 4 > kCusps[]
static std::array< SkPoint, 4 > kLoops[]
static void test_chop_cubic_at_midtangent(skiatest::Reporter *reporter, const SkPoint pts[4], SkCubicType cubicType)
static std::array< SkPoint, 4 > kSerpentines[]
static std::array< SkPoint, 3 > kQuads[]
static std::array< SkPoint, 4 > kLinearCubics[]
SkPoint lerp(const SkPoint &a, const SkPoint &b, float t)
static void test_chop_quad_at_midtangent(skiatest::Reporter *reporter, const SkPoint pts[3])
int SkChopCubicAtInflections(const SkPoint src[4], SkPoint dst[10])
Definition: SkGeometry.cpp:755

◆ test_chop_cubic_at_midtangent()

static void test_chop_cubic_at_midtangent ( skiatest::Reporter reporter,
const SkPoint  pts[4],
SkCubicType  cubicType 
)
static

Definition at line 486 of file GeometryTest.cpp.

487 {
488 constexpr float kTolerance = 1e-3f;
489 int n = std::size(kSkewMatrices);
490 if (cubicType == SkCubicType::kLocalCusp || cubicType == SkCubicType::kLineOrPoint) {
491 // FP precision isn't always enough to get the exact correct T value of the mid-tangent on
492 // cusps and lines. Only test the identity matrix and the matrix with all 1's.
493 n = 2;
494 }
495 for (int i = 0; i < n; ++i) {
496 SkPoint mapped[4];
497 kSkewMatrices[i].mapPoints(mapped, pts, 4);
498 float fullRotation = SkMeasureNonInflectCubicRotation(mapped);
499 SkPoint chopped[7];
500 SkChopCubicAtMidTangent(mapped, chopped);
501 float leftRotation = SkMeasureNonInflectCubicRotation(chopped);
502 float rightRotation = SkMeasureNonInflectCubicRotation(chopped+3);
503 if (cubicType == SkCubicType::kLineOrPoint &&
504 (SkScalarNearlyEqual(fullRotation, 2*SK_ScalarPI, kTolerance) ||
505 SkScalarNearlyEqual(fullRotation, 0, kTolerance))) {
506 // 0- and 360-degree flat lines don't have single points of midtangent.
507 // (tangent == midtangent at every point on these curves except the cusp points.)
508 // Instead verify the promise from SkChopCubicAtMidTangent that neither side will rotate
509 // more than 180 degrees.
512 continue;
513 }
514 float expectedChoppedRotation = fullRotation/2;
515 if (cubicType == SkCubicType::kLocalCusp ||
516 (cubicType == SkCubicType::kLineOrPoint &&
517 SkScalarNearlyEqual(fullRotation, SK_ScalarPI, kTolerance))) {
518 // If we chop a cubic at a cusp, we lose 180 degrees of rotation.
519 expectedChoppedRotation = (fullRotation - SK_ScalarPI)/2;
520 }
521 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(leftRotation, expectedChoppedRotation,
522 kTolerance));
523 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rightRotation, expectedChoppedRotation,
524 kTolerance));
525 }
526}
static SkMatrix kSkewMatrices[]
static constexpr float kTolerance
Definition: GrQuadUtils.cpp:29
float SkMeasureNonInflectCubicRotation(const SkPoint pts[4])
Definition: SkGeometry.cpp:579
void SkChopCubicAtMidTangent(const SkPoint src[4], SkPoint dst[7])
Definition: SkGeometry.h:195
#define SK_ScalarPI
Definition: SkScalar.h:21
void mapPoints(SkPoint dst[], const SkPoint src[], int count) const
Definition: SkMatrix.cpp:770
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
SIN Vec< N, float > abs(const Vec< N, float > &x)
Definition: SkVx.h:707

◆ test_chop_quad_at_midtangent()

static void test_chop_quad_at_midtangent ( skiatest::Reporter reporter,
const SkPoint  pts[3] 
)
static

Definition at line 471 of file GeometryTest.cpp.

471 {
472 constexpr float kTolerance = 1e-3f;
473 for (const SkMatrix& m : kSkewMatrices) {
474 SkPoint mapped[3];
475 m.mapPoints(mapped, pts, 3);
476 float fullRotation = SkMeasureQuadRotation(pts);
477 SkPoint chopped[5];
478 SkChopQuadAtMidTangent(pts, chopped);
479 float leftRotation = SkMeasureQuadRotation(chopped);
480 float rightRotation = SkMeasureQuadRotation(chopped+2);
481 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(leftRotation, fullRotation/2, kTolerance));
482 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rightRotation, fullRotation/2, kTolerance));
483 }
484}
void SkChopQuadAtMidTangent(const SkPoint src[3], SkPoint dst[5])
Definition: SkGeometry.h:91
float SkMeasureQuadRotation(const SkPoint pts[3])
Definition: SkGeometry.h:79

◆ test_classify_cubic()

static void test_classify_cubic ( skiatest::Reporter reporter)
static

Definition at line 399 of file GeometryTest.cpp.

399 {
400 for (const auto& serp : kSerpentines) {
402 }
403 for (const auto& loop : kLoops) {
405 }
406 for (const auto& loop : kLinearCubics) {
408 }
409 check_cubic_around_rect("small box", reporter, 0, 0, 1, 1);
410 check_cubic_around_rect("biggest box", reporter,
415 check_cubic_around_rect("large quadrant", reporter, 1, 1,
418 check_cubic_around_rect("smallest box", reporter,
423 check_cubic_around_rect("slightly negative box",reporter,
424 +1, -std::numeric_limits<float>::min(), -1, -1);
425 check_cubic_around_rect("infinite box", reporter,
426 -std::numeric_limits<float>::infinity(),
427 -std::numeric_limits<float>::infinity(),
428 +std::numeric_limits<float>::infinity(),
429 +std::numeric_limits<float>::infinity(),
430 true);
431 check_cubic_around_rect("one sided infinite box", reporter,
432 0, 0, 1, +std::numeric_limits<float>::infinity(), true);
434 -std::numeric_limits<float>::quiet_NaN(),
435 -std::numeric_limits<float>::quiet_NaN(),
436 +std::numeric_limits<float>::quiet_NaN(),
437 +std::numeric_limits<float>::quiet_NaN(),
438 true);
439 check_cubic_around_rect("partial nan box", reporter,
440 0, 0, 1, +std::numeric_limits<float>::quiet_NaN(), true);
441}
static void check_cubic_around_rect(std::string name, skiatest::Reporter *reporter, float x1, float y1, float x2, float y2, bool undefined=false)
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_conic()

static void test_conic ( skiatest::Reporter reporter)
static

Definition at line 177 of file GeometryTest.cpp.

177 {
178 SkRandom rand;
179 for (int i = 0; i < 1000; ++i) {
180 SkPoint pts[3];
181 for (int j = 0; j < 3; ++j) {
182 pts[j].set(rand.nextSScalar1() * 100, rand.nextSScalar1() * 100);
183 }
184 for (int k = 0; k < 10; ++k) {
185 SkScalar w = rand.nextUScalar1() * 2;
186 SkConic conic(pts, w);
187
188 const SkScalar dt = SK_Scalar1 / 128;
189 SkScalar t = dt;
190 for (int j = 1; j < 128; ++j) {
193 t += dt;
194 }
195 }
196 }
197}
static void test_conic_eval_pos(skiatest::Reporter *reporter, const SkConic &conic, SkScalar t)
static void test_conic_eval_tan(skiatest::Reporter *reporter, const SkConic &conic, SkScalar t)
#define SK_Scalar1
Definition: SkScalar.h:18
SkScalar nextUScalar1()
Definition: SkRandom.h:101
SkScalar nextSScalar1()
Definition: SkRandom.h:113
float SkScalar
Definition: extension.cpp:12
AI float conic(float tolerance, const SkPoint pts[], float w, const VectorXform &vectorXform=VectorXform())
Definition: WangsFormula.h:287
SkScalar w

◆ test_conic_eval_pos()

static void test_conic_eval_pos ( skiatest::Reporter reporter,
const SkConic conic,
SkScalar  t 
)
static

Definition at line 163 of file GeometryTest.cpp.

163 {
164 SkPoint p0, p1;
165 conic.evalAt(t, &p0, nullptr);
166 p1 = conic.evalAt(t);
167 check_pairs(reporter, 0, t, "conic-pos", p0.fX, p0.fY, p1.fX, p1.fY);
168}
static void check_pairs(skiatest::Reporter *reporter, int index, SkScalar t, const char name[], SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1)
float fX
x-axis value
Definition: SkPoint_impl.h:164
float fY
y-axis value
Definition: SkPoint_impl.h:165

◆ test_conic_eval_tan()

static void test_conic_eval_tan ( skiatest::Reporter reporter,
const SkConic conic,
SkScalar  t 
)
static

Definition at line 170 of file GeometryTest.cpp.

170 {
171 SkVector v0, v1;
172 conic.evalAt(t, nullptr, &v0);
173 v1 = conic.evalTangentAt(t);
174 check_pairs(reporter, 0, t, "conic-tan", v0.fX, v0.fY, v1.fX, v1.fY);
175}

◆ test_conic_tangents()

static void test_conic_tangents ( skiatest::Reporter reporter)
static

Definition at line 219 of file GeometryTest.cpp.

219 {
220 SkPoint pts[] = {
221 { 10, 20}, {10, 20}, {20, 30},
222 { 10, 20}, {15, 25}, {20, 30},
223 { 10, 20}, {20, 30}, {20, 30}
224 };
225 int count = (int) std::size(pts) / 3;
226 for (int index = 0; index < count; ++index) {
227 SkConic conic(&pts[index * 3], 0.707f);
228 SkVector start = conic.evalTangentAt(0);
229 SkVector mid = conic.evalTangentAt(.5f);
230 SkVector end = conic.evalTangentAt(1);
232 REPORTER_ASSERT(reporter, mid.fX && mid.fY);
233 REPORTER_ASSERT(reporter, end.fX && end.fY);
236 }
237}
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
Definition: SkScalar.h:101
glong glong end
float cross(const SkVector &vec) const
Definition: SkPoint_impl.h:545

◆ test_conic_to_quads()

static void test_conic_to_quads ( skiatest::Reporter reporter)
static

We need to ensure that when a conic is approximated by quads, that we always return finite values in the quads.

Inspired by crbug_627414

Definition at line 254 of file GeometryTest.cpp.

254 {
255 const SkPoint triples[] = {
256 { 0, 0 }, { 1, 0 }, { 1, 1 },
257 { 0, 0 }, { 3.58732e-43f, 2.72084f }, { 3.00392f, 3.00392f },
258 { 0, 0 }, { 100000, 0 }, { 100000, 100000 },
259 { 0, 0 }, { 1e30f, 0 }, { 1e30f, 1e30f },
260 };
261 const int N = sizeof(triples) / sizeof(SkPoint);
262
263 for (int i = 0; i < N; i += 3) {
264 const SkPoint* pts = &triples[i];
265
266 SkScalar w = 1e30f;
267 do {
268 w *= 2;
270 } while (SkIsFinite(w));
272 }
273}
static void test_this_conic_to_quad(skiatest::Reporter *r, const SkPoint pts[3], SkScalar w)
static bool SkIsFinite(T x, Pack... values)
#define SK_ScalarNaN
Definition: SkScalar.h:28
#define N
Definition: beziers.cpp:19

◆ test_cubic_cusps()

static void test_cubic_cusps ( skiatest::Reporter reporter)
static

Definition at line 450 of file GeometryTest.cpp.

450 {
451 std::array<SkPoint, 4> noCusps[] = {
452 {{{0, 0}, {1, 1}, {2, 2}, {3, 3}}},
453 {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}},
454 {{{0, 0}, {1, 0}, {2, 1}, {2, 2}}},
455 {{{0, 0}, {1, 0}, {1, 1}, {2, 1}}},
456 };
457 for (auto noCusp : noCusps) {
458 REPORTER_ASSERT(reporter, SkFindCubicCusp(noCusp.data()) < 0);
459 }
460 for (auto cusp : kCusps) {
461 REPORTER_ASSERT(reporter, SkFindCubicCusp(cusp.data()) > 0);
462 }
463}
SkScalar SkFindCubicCusp(const SkPoint src[4])

◆ test_cubic_tangents()

static void test_cubic_tangents ( skiatest::Reporter reporter)
static

Definition at line 275 of file GeometryTest.cpp.

275 {
276 SkPoint pts[] = {
277 { 10, 20}, {10, 20}, {20, 30}, {30, 40},
278 { 10, 20}, {15, 25}, {20, 30}, {30, 40},
279 { 10, 20}, {20, 30}, {30, 40}, {30, 40},
280 };
281 int count = (int) std::size(pts) / 4;
282 for (int index = 0; index < count; ++index) {
283 SkConic conic(&pts[index * 3], 0.707f);
284 SkVector start, mid, end;
285 SkEvalCubicAt(&pts[index * 4], 0, nullptr, &start, nullptr);
286 SkEvalCubicAt(&pts[index * 4], .5f, nullptr, &mid, nullptr);
287 SkEvalCubicAt(&pts[index * 4], 1, nullptr, &end, nullptr);
289 REPORTER_ASSERT(reporter, mid.fX && mid.fY);
290 REPORTER_ASSERT(reporter, end.fX && end.fY);
293 }
294}
void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint *loc, SkVector *tangent, SkVector *curvature)
Definition: SkGeometry.cpp:418

◆ test_evalquadat()

static void test_evalquadat ( skiatest::Reporter reporter)
static

Definition at line 138 of file GeometryTest.cpp.

138 {
139 SkRandom rand;
140 for (int i = 0; i < 1000; ++i) {
141 SkPoint pts[3];
142 for (int j = 0; j < 3; ++j) {
143 pts[j].set(rand.nextSScalar1() * 100, rand.nextSScalar1() * 100);
144 }
145 const SkScalar dt = SK_Scalar1 / 128;
146 SkScalar t = dt;
147 for (int j = 1; j < 128; ++j) {
148 SkPoint r0;
149 SkEvalQuadAt(pts, t, &r0);
150 SkPoint r1 = SkEvalQuadAt(pts, t);
151 check_pairs(reporter, i, t, "quad-pos", r0.fX, r0.fY, r1.fX, r1.fY);
152
153 SkVector v0;
154 SkEvalQuadAt(pts, t, nullptr, &v0);
155 SkVector v1 = SkEvalQuadTangentAt(pts, t);
156 check_pairs(reporter, i, t, "quad-tan", v0.fX, v0.fY, v1.fX, v1.fY);
157
158 t += dt;
159 }
160 }
161}
SkVector SkEvalQuadTangentAt(const SkPoint src[3], SkScalar t)
Definition: SkGeometry.cpp:148
void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint *pt, SkVector *tangent)
Definition: SkGeometry.cpp:132

◆ test_measure_rotation()

static void test_measure_rotation ( skiatest::Reporter reporter)
static

Definition at line 540 of file GeometryTest.cpp.

540 {
541 static SkPoint kFlatCubic[4] = {{0, 0}, {0, 1}, {0, 2}, {0, 3}};
543
544 static SkPoint kFlatCubic180_1[4] = {{0, 0}, {1, 0}, {3, 0}, {2, 0}};
546 SK_ScalarPI));
547
548 static SkPoint kFlatCubic180_2[4] = {{0, 1}, {0, 0}, {0, 2}, {0, 3}};
550 SK_ScalarPI));
551
552 static SkPoint kFlatCubic360[4] = {{0, 1}, {0, 0}, {0, 3}, {0, 2}};
554 2*SK_ScalarPI));
555
556 static SkPoint kSquare180[4] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}};
558 SK_ScalarPI));
559
560 auto checkQuadRotation = [=](const SkPoint pts[3], float expectedRotation) {
561 float r = SkMeasureQuadRotation(pts);
562 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(r, expectedRotation));
563
564 SkPoint cubic1[4] = {pts[0], pts[0], pts[1], pts[2]};
566 expectedRotation));
567
568 SkPoint cubic2[4] = {pts[0], pts[1], pts[1], pts[2]};
570 expectedRotation));
571
572 SkPoint cubic3[4] = {pts[0], pts[1], pts[2], pts[2]};
574 expectedRotation));
575 };
576
577 static SkPoint kFlatQuad[4] = {{0, 0}, {0, 1}, {0, 2}};
578 checkQuadRotation(kFlatQuad, 0);
579
580 static SkPoint kFlatQuad180_1[4] = {{1, 0}, {0, 0}, {2, 0}};
581 checkQuadRotation(kFlatQuad180_1, SK_ScalarPI);
582
583 static SkPoint kFlatQuad180_2[4] = {{0, 0}, {0, 2}, {0, 1}};
584 checkQuadRotation(kFlatQuad180_2, SK_ScalarPI);
585
586 static SkPoint kTri120[3] = {{0, 0}, {.5f, std::sqrt(3.f)/2}, {1, 0}};
587 checkQuadRotation(kTri120, 2*SK_ScalarPI/3);
588}
SIN Vec< N, float > sqrt(const Vec< N, float > &x)
Definition: SkVx.h:706

◆ test_quad_tangents()

static void test_quad_tangents ( skiatest::Reporter reporter)
static

Definition at line 199 of file GeometryTest.cpp.

199 {
200 SkPoint pts[] = {
201 {10, 20}, {10, 20}, {20, 30},
202 {10, 20}, {15, 25}, {20, 30},
203 {10, 20}, {20, 30}, {20, 30},
204 };
205 int count = (int) std::size(pts) / 3;
206 for (int index = 0; index < count; ++index) {
207 SkConic conic(&pts[index * 3], 0.707f);
208 SkVector start = SkEvalQuadTangentAt(&pts[index * 3], 0);
209 SkVector mid = SkEvalQuadTangentAt(&pts[index * 3], .5f);
210 SkVector end = SkEvalQuadTangentAt(&pts[index * 3], 1);
212 REPORTER_ASSERT(reporter, mid.fX && mid.fY);
213 REPORTER_ASSERT(reporter, end.fX && end.fY);
216 }
217}

◆ test_this_conic_to_quad()

static void test_this_conic_to_quad ( skiatest::Reporter r,
const SkPoint  pts[3],
SkScalar  w 
)
static

Definition at line 239 of file GeometryTest.cpp.

239 {
240 SkAutoConicToQuads quadder;
241 const SkPoint* qpts = quadder.computeQuads(pts, w, 0.25);
242 const int qcount = quadder.countQuads();
243 const int pcount = qcount * 2 + 1;
244
245 REPORTER_ASSERT(r, SkPointPriv::AreFinite(qpts, pcount));
246}
const SkPoint * computeQuads(const SkConic &conic, SkScalar tol)
Definition: SkGeometry.h:524
int countQuads() const
Definition: SkGeometry.h:539
static bool AreFinite(const SkPoint array[], int count)
Definition: SkPointPriv.h:22

◆ testChopCubic()

static void testChopCubic ( skiatest::Reporter reporter)
static

Definition at line 29 of file GeometryTest.cpp.

29 {
30 /*
31 Inspired by this test, which used to assert that the tValues had dups
32
33 <path stroke="#202020" d="M0,0 C0,0 1,1 2190,5130 C2190,5070 2220,5010 2205,4980" />
34 */
35 const SkPoint src[] = {
36 { SkIntToScalar(2190), SkIntToScalar(5130) },
37 { SkIntToScalar(2190), SkIntToScalar(5070) },
38 { SkIntToScalar(2220), SkIntToScalar(5010) },
39 { SkIntToScalar(2205), SkIntToScalar(4980) },
40 };
41 SkPoint dst[13];
42 SkScalar tValues[3];
43 // make sure we don't assert internally
44 int count = SkChopCubicAtMaxCurvature(src, dst, tValues);
45 if ((false)) { // avoid bit rot, suppress warning
47 }
48 // Make sure src and dst can be the same pointer.
49 {
50 SkPoint pts[7];
51 for (int i = 0; i < 7; ++i) {
52 pts[i].set(i, i);
53 }
54 SkChopCubicAt(pts, pts, .5f);
55 for (int i = 0; i < 7; ++i) {
56 REPORTER_ASSERT(reporter, pts[i].fX == pts[i].fY);
57 REPORTER_ASSERT(reporter, pts[i].fX == i * .5f);
58 }
59 }
60
61 static const float chopTs[] = {
62 0, 3/83.f, 3/79.f, 3/73.f, 3/71.f, 3/67.f, 3/61.f, 3/59.f, 3/53.f, 3/47.f, 3/43.f, 3/41.f,
63 3/37.f, 3/31.f, 3/29.f, 3/23.f, 3/19.f, 3/17.f, 3/13.f, 3/11.f, 3/7.f, 3/5.f, 1,
64 };
65 float ones[] = {1,1,1,1,1};
66
67 // Ensure an odd number of T values so we exercise the single chop code at the end of
68 // SkChopCubicAt form multiple T.
69 static_assert(std::size(chopTs) % 2 == 1);
70 static_assert(std::size(ones) % 2 == 1);
71
72 SkRandom rand;
73 for (int iterIdx = 0; iterIdx < 5; ++iterIdx) {
74 SkPoint pts[4] = {{rand.nextF(), rand.nextF()}, {rand.nextF(), rand.nextF()},
75 {rand.nextF(), rand.nextF()}, {rand.nextF(), rand.nextF()}};
76
77 SkPoint allChops[4 + std::size(chopTs)*3];
78 SkChopCubicAt(pts, allChops, chopTs, std::size(chopTs));
79 int i = 3;
80 for (float chopT : chopTs) {
81 // Ensure we chop at approximately the correct points when we chop an entire list.
82 SkPoint expectedPt;
83 SkEvalCubicAt(pts, chopT, &expectedPt, nullptr, nullptr);
84 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(allChops[i].x(), expectedPt.x()));
85 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(allChops[i].y(), expectedPt.y()));
86 if (chopT == 0) {
87 REPORTER_ASSERT(reporter, allChops[i] == pts[0]);
88 }
89 if (chopT == 1) {
90 REPORTER_ASSERT(reporter, allChops[i] == pts[3]);
91 }
92 i += 3;
93
94 // Ensure the middle is exactly degenerate when we chop at two equal points.
95 SkPoint localChops[10];
96 SkChopCubicAt(pts, localChops, chopT, chopT);
97 REPORTER_ASSERT(reporter, localChops[3] == localChops[4]);
98 REPORTER_ASSERT(reporter, localChops[3] == localChops[5]);
99 REPORTER_ASSERT(reporter, localChops[3] == localChops[6]);
100 if (chopT == 0) {
101 // Also ensure the first curve is exactly p0 when we chop at T=0.
102 REPORTER_ASSERT(reporter, localChops[0] == pts[0]);
103 REPORTER_ASSERT(reporter, localChops[1] == pts[0]);
104 REPORTER_ASSERT(reporter, localChops[2] == pts[0]);
105 REPORTER_ASSERT(reporter, localChops[3] == pts[0]);
106 }
107 if (chopT == 1) {
108 // Also ensure the last curve is exactly p3 when we chop at T=1.
109 REPORTER_ASSERT(reporter, localChops[6] == pts[3]);
110 REPORTER_ASSERT(reporter, localChops[7] == pts[3]);
111 REPORTER_ASSERT(reporter, localChops[8] == pts[3]);
112 REPORTER_ASSERT(reporter, localChops[9] == pts[3]);
113 }
114 }
115
116 // Now test what happens when SkChopCubicAt does 0/0 and gets NaN values.
117 SkPoint oneChops[4 + std::size(ones)*3];
118 SkChopCubicAt(pts, oneChops, ones, std::size(ones));
119 REPORTER_ASSERT(reporter, oneChops[0] == pts[0]);
120 REPORTER_ASSERT(reporter, oneChops[1] == pts[1]);
121 REPORTER_ASSERT(reporter, oneChops[2] == pts[2]);
122 for (size_t index = 3; index < std::size(oneChops); ++index) {
123 REPORTER_ASSERT(reporter, oneChops[index] == pts[3]);
124 }
125 }
126}
void SkChopCubicAt(const SkPoint src[4], SkPoint dst[7], SkScalar t)
Definition: SkGeometry.cpp:473
int SkChopCubicAtMaxCurvature(const SkPoint src[4], SkPoint dst[13], SkScalar tValues[3])
#define SkIntToScalar(x)
Definition: SkScalar.h:57
float nextF()
Definition: SkRandom.h:55
double y
double x
dst
Definition: cp.py:12
constexpr float y() const
Definition: SkPoint_impl.h:187
constexpr float x() const
Definition: SkPoint_impl.h:181

◆ testChopMonoCubicAtX()

static void testChopMonoCubicAtX ( skiatest::Reporter reporter,
std::string  name,
SkSpan< const SkPoint curveInputs,
SkScalar  xToChopAt,
SkSpan< const SkPoint expectedOutputs 
)
static

Definition at line 826 of file GeometryTest.cpp.

828 {
830 REPORTER_ASSERT(reporter, curveInputs.size() == 4,
831 "Invalid test case. Input curve should have 4 points");
832 REPORTER_ASSERT(reporter, expectedOutputs.size() == 7,
833 "Invalid test case. Outputs should have 7 points");
834 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(expectedOutputs[3].x(), xToChopAt),
835 "Invalid test case. 4th point's X should be %f", xToChopAt);
836
837 SkPoint outputs[7];
838 // Make sure it actually chopped
839 REPORTER_ASSERT(reporter, SkChopMonoCubicAtX(curveInputs.begin(), xToChopAt, outputs));
840
841 for (int i = 0; i < 7; ++i) {
842 REPORTER_ASSERT(reporter, nearly_equal(expectedOutputs[i], outputs[i]),
843 "(%f, %f) != (%f, %f) at index %d",
844 expectedOutputs[i].x(), expectedOutputs[i].y(),
845 outputs[i].x(), outputs[i].y(), i);
846 }
847}
constexpr T * begin() const
Definition: SkSpan_impl.h:90
constexpr size_t size() const
Definition: SkSpan_impl.h:95

◆ testChopMonoCubicAtY()

static void testChopMonoCubicAtY ( skiatest::Reporter reporter,
std::string  name,
SkSpan< const SkPoint curveInputs,
SkScalar  yToChopAt,
SkSpan< const SkPoint expectedOutputs 
)
static

Definition at line 671 of file GeometryTest.cpp.

673 {
675 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(expectedOutputs[3].y(), yToChopAt),
676 "Invalid test case. 4th point's Y should be %f", yToChopAt);
677
678 SkPoint outputs[7];
679 // Make sure it actually chopped
680 REPORTER_ASSERT(reporter, SkChopMonoCubicAtY(curveInputs.begin(), yToChopAt, outputs));
681
682 for (int i = 0; i < 7; ++i) {
683 REPORTER_ASSERT(reporter, nearly_equal(expectedOutputs[i], outputs[i]),
684 "(%f, %f) != (%f, %f) at index %d",
685 expectedOutputs[i].x(), expectedOutputs[i].y(),
686 outputs[i].x(), outputs[i].y(), i);
687 }
688}

Variable Documentation

◆ kCusps

std::array<SkPoint, 4> kCusps[]
static
Initial value:
= {
{{{0, 0}, {1, 1}, {1, 0}, {0, 1}}},
{{{0, 0}, {1, 1}, {0, 1}, {1, 0}}},
{{{0, 1}, {1, 0}, {0, 0}, {1, 1}}},
{{{0, 1}, {1, 0}, {1, 1}, {0, 0}}},
}

Definition at line 443 of file GeometryTest.cpp.

◆ kLinearCubics

std::array<SkPoint, 4> kLinearCubics[]
static
Initial value:
= {
{{{0, 0}, {0, 1}, {0, 2}, {0, 3}}},
{{{0, 0}, {1, 0}, {1, 0}, {0, 0}}},
{{{0, 1}, {0, 0}, {0, 2}, {0, 3}}},
{{{0, 1}, {0, 0}, {0, 3}, {0, 2}}},
{{{0, 0}, {2, 0}, {1, 0}, {64, 0}}},
{{{1, 0}, {0, 0}, {3, 0}, {-64, 0}}}
}

Definition at line 390 of file GeometryTest.cpp.

◆ kLoops

std::array<SkPoint, 4> kLoops[]
static
Initial value:
= {
{{{635.625f, 614.687f}, {171.625f, 236.188f}, {1064.62f, 135.688f}, {516.625f, 570.187f}}},
{{{653.050f, 725.049f}, {663.000f, 176.000f}, {1189.000f, 508.000f}, {288.050f, 564.950f}}},
{{{631.050f, 478.049f}, {730.000f, 302.000f}, {870.000f, 350.000f}, {905.050f, 528.950f}}},
{{{631.050f, 478.0499f}, {221.000f, 230.000f}, {1265.000f, 451.000f}, {905.050f, 528.950f}}}
}

Definition at line 383 of file GeometryTest.cpp.

◆ kQuads

std::array<SkPoint, 3> kQuads[]
static
Initial value:
= {
{{{10, 20}, {15, 35}, {30, 40}}},
{{{176.324f, 392.705f}, {719.325f, 205.782f}, {297.263f, 347.735f}}},
{{{652.050f, 602.049f}, {481.000f, 533.000f}, {288.050f, 564.950f}}},
{{{460.625f, 557.187f}, {707.121f, 209.688f}, {779.628f, 577.687f}}},
{{{359.050f, 578.049f}, {759.000f, 274.000f}, {288.050f, 564.950f}}}
}

Definition at line 528 of file GeometryTest.cpp.

◆ kSerpentines

std::array<SkPoint, 4> kSerpentines[]
static
Initial value:
= {
{{{149.325f, 107.705f}, {149.325f, 103.783f}, {151.638f, 100.127f}, {156.263f, 96.736f}}},
{{{225.694f, 223.15f}, {209.831f, 224.837f}, {195.994f, 230.237f}, {184.181f, 239.35f}}},
{{{4.873f, 5.581f}, {5.083f, 5.2783f}, {5.182f, 4.8593f}, {5.177f, 4.3242f}}},
{{{285.625f, 499.687f}, {411.625f, 808.188f}, {1064.62f, 135.688f}, {1042.63f, 585.187f}}}
}

Definition at line 376 of file GeometryTest.cpp.

◆ kSkewMatrices

SkMatrix kSkewMatrices[]
static
Initial value:
= {
SkMatrix::MakeAll(1,0,0, 0,1,0, 0,0,1),
SkMatrix::MakeAll(1,-1,0, 1,1,0, 0,0,1),
SkMatrix::MakeAll(.889f,.553f,0, -.443f,.123f,0, 0,0,1),
}
static SkMatrix MakeAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar pers0, SkScalar pers1, SkScalar pers2)
Definition: SkMatrix.h:179

Definition at line 465 of file GeometryTest.cpp.