Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
PathCoverageTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
12#include "src/base/SkMathPriv.h"
14#include "tests/Test.h"
15
16#include <algorithm>
17#include <array>
18#include <cstdint>
19
20/*
21 Duplicates lots of code from gpu/src/GrPathUtils.cpp
22 It'd be nice not to do so, but that code's set up currently to only have
23 a single implementation.
24*/
25
26// Sk uses 6, Gr (implicitly) used 10, both apparently arbitrarily.
27#define MAX_COEFF_SHIFT 6
28static const uint32_t MAX_POINTS_PER_CURVE = 1 << MAX_COEFF_SHIFT;
29
30// max + 0.5 min has error [0.0, 0.12]
31// max + 0.375 min has error [-.03, 0.07]
32// 0.96043387 max + 0.397824735 min has error [-.06, +.05]
33// For determining the maximum possible number of points to use in
34// drawing a quadratic, we want to err on the high side.
35static inline int cheap_distance(SkScalar dx, SkScalar dy) {
36 int idx = SkAbs32(SkScalarRoundToInt(dx));
37 int idy = SkAbs32(SkScalarRoundToInt(dy));
38 if (idx > idy) {
39 idx += idy >> 1;
40 } else {
41 idx = idy + (idx >> 1);
42 }
43 return idx;
44}
45
46static inline int estimate_distance(const SkPoint points[]) {
47 return cheap_distance(points[1].fX * 2 - points[2].fX - points[0].fX,
48 points[1].fY * 2 - points[2].fY - points[0].fY);
49}
50
54
55static inline uint32_t estimate_pointCount(int distance) {
56 // Includes -2 bias because this estimator runs 4x high?
57 int shift = 30 - SkCLZ(distance);
58 // Clamp to zero if above subtraction went negative.
59 shift &= ~(shift>>31);
60 if (shift > MAX_COEFF_SHIFT) {
61 shift = MAX_COEFF_SHIFT;
62 }
63 return 1 << shift;
64}
65
66static inline uint32_t compute_pointCount(SkScalar d, SkScalar tol) {
67 if (d < tol) {
68 return 1;
69 } else {
70 int temp = SkScalarCeilToInt(SkScalarSqrt(d / tol));
71 uint32_t count = std::min<uint32_t>(SkNextPow2(temp), MAX_POINTS_PER_CURVE);
72 return count;
73 }
74}
75
76static uint32_t quadraticPointCount_EE(const SkPoint points[]) {
77 int distance = estimate_distance(points);
78 return estimate_pointCount(distance);
79}
80
81static uint32_t quadraticPointCount_EC(const SkPoint points[], SkScalar tol) {
82 int distance = estimate_distance(points);
83 return compute_pointCount(SkIntToScalar(distance), tol);
84}
85
86static uint32_t quadraticPointCount_CE(const SkPoint points[]) {
89}
90
91static uint32_t quadraticPointCount_CC(const SkPoint points[], SkScalar tol) {
93 return compute_pointCount(distance, tol);
94}
95
96// Curve from samplecode/SampleSlides.cpp
97static const int gXY[] = {
98 4, 0, 0, -4, 8, -4, 12, 0, 8, 4, 0, 4
99};
100
101static const int gSawtooth[] = {
102 0, 0, 10, 10, 20, 20, 30, 10, 40, 0, 50, -10, 60, -20, 70, -10, 80, 0
103};
104
105static const int gOvalish[] = {
106 0, 0, 5, 15, 20, 20, 35, 15, 40, 0
107};
108
109static const int gSharpSawtooth[] = {
110 0, 0, 1, 10, 2, 0, 3, -10, 4, 0
111};
112
113// Curve crosses back over itself around 0,10
114static const int gRibbon[] = {
115 -4, 0, 4, 20, 0, 25, -4, 20, 4, 0
116};
117
118static bool one_d_pe(const int* array, const unsigned int count,
120 SkPoint path [3];
121 path[1] = SkPoint::Make(SkIntToScalar(array[0]), SkIntToScalar(array[1]));
122 path[2] = SkPoint::Make(SkIntToScalar(array[2]), SkIntToScalar(array[3]));
123 int numErrors = 0;
124 for (unsigned i = 4; i < count; i += 2) {
125 path[0] = path[1];
126 path[1] = path[2];
127 path[2] = SkPoint::Make(SkIntToScalar(array[i]),
128 SkIntToScalar(array[i+1]));
129 uint32_t computedCount =
131 uint32_t estimatedCount =
133
134 if ((false)) { // avoid bit rot, suppress warning
135 computedCount = quadraticPointCount_EC(path, SkIntToScalar(1));
136 estimatedCount = quadraticPointCount_CE(path);
137 }
138 // Allow estimated to be high by a factor of two, but no less than
139 // the computed value.
140 bool isAccurate = (estimatedCount >= computedCount) &&
141 (estimatedCount <= 2 * computedCount);
142
143 if (!isAccurate) {
144 ERRORF(reporter, "Curve from %.2f %.2f through %.2f %.2f to "
145 "%.2f %.2f computes %u, estimates %u\n",
146 path[0].fX, path[0].fY, path[1].fX, path[1].fY,
147 path[2].fX, path[2].fY, computedCount, estimatedCount);
148 numErrors++;
149 }
150 }
151
152 return (numErrors == 0);
153}
154
155
156
164
165DEF_TEST(PathCoverage, reporter) {
167
168}
reporter
int count
static const int points[]
static uint32_t quadraticPointCount_EC(const SkPoint points[], SkScalar tol)
static uint32_t quadraticPointCount_CC(const SkPoint points[], SkScalar tol)
static const int gOvalish[]
static const int gSawtooth[]
static const int gRibbon[]
static const uint32_t MAX_POINTS_PER_CURVE
static int estimate_distance(const SkPoint points[])
static int cheap_distance(SkScalar dx, SkScalar dy)
static uint32_t estimate_pointCount(int distance)
static uint32_t compute_pointCount(SkScalar d, SkScalar tol)
static uint32_t quadraticPointCount_EE(const SkPoint points[])
#define MAX_COEFF_SHIFT
static SkScalar compute_distance(const SkPoint points[])
static const int gXY[]
static uint32_t quadraticPointCount_CE(const SkPoint points[])
static void TestQuadPointCount(skiatest::Reporter *reporter)
static const int gSharpSawtooth[]
static bool one_d_pe(const int *array, const unsigned int count, skiatest::Reporter *reporter)
static int SkCLZ(uint32_t mask)
Definition SkMathPriv.h:186
static int SkNextPow2(int value)
Definition SkMathPriv.h:272
static int32_t SkAbs32(int32_t value)
Definition SkSafe32.h:41
#define SkScalarRoundToInt(x)
Definition SkScalar.h:37
#define SkScalarCeilToInt(x)
Definition SkScalar.h:36
#define SkIntToScalar(x)
Definition SkScalar.h:57
#define SkScalarSqrt(x)
Definition SkScalar.h:42
#define DEF_TEST(name, reporter)
Definition Test.h:312
#define ERRORF(r,...)
Definition Test.h:293
static SkScalar DistanceToLineSegmentBetween(const SkPoint &pt, const SkPoint &a, const SkPoint &b)
Definition SkPointPriv.h:43
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19
float SkScalar
Definition extension.cpp:12
static constexpr SkPoint Make(float x, float y)