Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Macros | Enumerations | Functions
SkPath.cpp File Reference
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkRRect.h"
#include "include/core/SkStream.h"
#include "include/core/SkString.h"
#include "include/private/SkPathRef.h"
#include "include/private/base/SkFloatingPoint.h"
#include "include/private/base/SkMalloc.h"
#include "include/private/base/SkTArray.h"
#include "include/private/base/SkTDArray.h"
#include "include/private/base/SkTo.h"
#include "src/base/SkFloatBits.h"
#include "src/base/SkTLazy.h"
#include "src/base/SkVx.h"
#include "src/core/SkCubicClipper.h"
#include "src/core/SkEdgeClipper.h"
#include "src/core/SkGeometry.h"
#include "src/core/SkMatrixPriv.h"
#include "src/core/SkPathEnums.h"
#include "src/core/SkPathMakers.h"
#include "src/core/SkPathPriv.h"
#include "src/core/SkPointPriv.h"
#include "src/core/SkStringUtils.h"
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iterator>
#include <limits.h>
#include <utility>

Go to the source code of this file.

Classes

struct  SkPath_Storage_Equivalent
 
class  SkAutoDisableDirectionCheck
 
class  SkAutoPathBoundsUpdate
 
struct  Convexicator
 
class  ContourIter
 
struct  SkHalfPlane
 

Macros

#define INITIAL_LASTMOVETOINDEX_VALUE   ~0
 
#define kValueNeverReturnedBySign   2
 

Enumerations

enum  DirChange {
  kUnknown_DirChange , kLeft_DirChange , kRight_DirChange , kStraight_DirChange ,
  kBackwards_DirChange , kInvalid_DirChange
}
 

Functions

static float poly_eval (float A, float B, float C, float t)
 
static float poly_eval (float A, float B, float C, float D, float t)
 
static void joinNoEmptyChecks (SkRect *dst, const SkRect &src)
 
static bool is_degenerate (const SkPath &path)
 
bool operator== (const SkPath &a, const SkPath &b)
 
static bool check_edge_against_rect (const SkPoint &p0, const SkPoint &p1, const SkRect &rect, SkPathFirstDirection dir)
 
static int rect_make_dir (SkScalar dx, SkScalar dy)
 
static void assert_known_direction (SkPathDirection dir)
 
static bool arc_is_lone_point (const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, SkPoint *pt)
 
static void angles_to_unit_vectors (SkScalar startAngle, SkScalar sweepAngle, SkVector *startV, SkVector *stopV, SkRotationDirection *dir)
 
static int build_arc_conics (const SkRect &oval, const SkVector &start, const SkVector &stop, SkRotationDirection dir, SkConic conics[SkConic::kMaxConicsForArc], SkPoint *singlePt)
 
static void subdivide_cubic_to (SkPath *path, const SkPoint pts[4], int level=2)
 
static void append_params (SkString *str, const char label[], const SkPoint pts[], int count, SkScalarAsStringType strType, SkScalar conicWeight=-12345)
 
static int sign (SkScalar x)
 
static SkScalar cross_prod (const SkPoint &p0, const SkPoint &p1, const SkPoint &p2)
 
static int find_max_y (const SkPoint pts[], int count)
 
static int find_diff_pt (const SkPoint pts[], int index, int n, int inc)
 
static int find_min_max_x_at_y (const SkPoint pts[], int index, int n, int *maxIndexPtr)
 
static SkPathFirstDirection crossToDir (SkScalar cross)
 
static bool between (SkScalar a, SkScalar b, SkScalar c)
 
static SkScalar eval_cubic_pts (SkScalar c0, SkScalar c1, SkScalar c2, SkScalar c3, SkScalar t)
 
template<size_t N>
static void find_minmax (const SkPoint pts[], SkScalar *minPtr, SkScalar *maxPtr)
 
static bool checkOnCurve (SkScalar x, SkScalar y, const SkPoint &start, const SkPoint &end)
 
static int winding_mono_cubic (const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
 
static int winding_cubic (const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
 
static double conic_eval_numerator (const SkScalar src[], SkScalar w, SkScalar t)
 
static double conic_eval_denominator (SkScalar w, SkScalar t)
 
static int winding_mono_conic (const SkConic &conic, SkScalar x, SkScalar y, int *onCurveCount)
 
static bool is_mono_quad (SkScalar y0, SkScalar y1, SkScalar y2)
 
static int winding_conic (const SkPoint pts[], SkScalar x, SkScalar y, SkScalar weight, int *onCurveCount)
 
static int winding_mono_quad (const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
 
static int winding_quad (const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
 
static int winding_line (const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
 
static void tangent_cubic (const SkPoint pts[], SkScalar x, SkScalar y, SkTDArray< SkVector > *tangents)
 
static void tangent_conic (const SkPoint pts[], SkScalar x, SkScalar y, SkScalar w, SkTDArray< SkVector > *tangents)
 
static void tangent_quad (const SkPoint pts[], SkScalar x, SkScalar y, SkTDArray< SkVector > *tangents)
 
static void tangent_line (const SkPoint pts[], SkScalar x, SkScalar y, SkTDArray< SkVector > *tangents)
 
static bool contains_inclusive (const SkRect &r, SkScalar x, SkScalar y)
 
static int compute_quad_extremas (const SkPoint src[3], SkPoint extremas[3])
 
static int compute_conic_extremas (const SkPoint src[3], SkScalar w, SkPoint extremas[3])
 
static int compute_cubic_extremas (const SkPoint src[4], SkPoint extremas[5])
 
SkPathVerbAnalysis sk_path_analyze_verbs (const uint8_t vbs[], int verbCount)
 
static SkPath clip (const SkPath &path, const SkHalfPlane &plane)
 

Macro Definition Documentation

◆ INITIAL_LASTMOVETOINDEX_VALUE

#define INITIAL_LASTMOVETOINDEX_VALUE   ~0

Definition at line 152 of file SkPath.cpp.

◆ kValueNeverReturnedBySign

#define kValueNeverReturnedBySign   2

Definition at line 2142 of file SkPath.cpp.

Enumeration Type Documentation

◆ DirChange

enum DirChange
Enumerator
kUnknown_DirChange 
kLeft_DirChange 
kRight_DirChange 
kStraight_DirChange 
kBackwards_DirChange 
kInvalid_DirChange 

Definition at line 2144 of file SkPath.cpp.

2144 {
2149 kBackwards_DirChange, // if double back, allow simple lines to be convex
2151};
@ kBackwards_DirChange
Definition SkPath.cpp:2149
@ kStraight_DirChange
Definition SkPath.cpp:2148
@ kInvalid_DirChange
Definition SkPath.cpp:2150
@ kLeft_DirChange
Definition SkPath.cpp:2146
@ kRight_DirChange
Definition SkPath.cpp:2147
@ kUnknown_DirChange
Definition SkPath.cpp:2145

Function Documentation

◆ angles_to_unit_vectors()

static void angles_to_unit_vectors ( SkScalar  startAngle,
SkScalar  sweepAngle,
SkVector startV,
SkVector stopV,
SkRotationDirection dir 
)
static

Definition at line 930 of file SkPath.cpp.

931 {
932 SkScalar startRad = SkDegreesToRadians(startAngle),
933 stopRad = SkDegreesToRadians(startAngle + sweepAngle);
934
935 startV->fY = SkScalarSinSnapToZero(startRad);
936 startV->fX = SkScalarCosSnapToZero(startRad);
937 stopV->fY = SkScalarSinSnapToZero(stopRad);
938 stopV->fX = SkScalarCosSnapToZero(stopRad);
939
940 /* If the sweep angle is nearly (but less than) 360, then due to precision
941 loss in radians-conversion and/or sin/cos, we may end up with coincident
942 vectors, which will fool SkBuildQuadArc into doing nothing (bad) instead
943 of drawing a nearly complete circle (good).
944 e.g. canvas.drawArc(0, 359.99, ...)
945 -vs- canvas.drawArc(0, 359.9, ...)
946 We try to detect this edge case, and tweak the stop vector
947 */
948 if (*startV == *stopV) {
949 SkScalar sw = SkScalarAbs(sweepAngle);
950 if (sw < SkIntToScalar(360) && sw > SkIntToScalar(359)) {
951 // make a guess at a tiny angle (in radians) to tweak by
952 SkScalar deltaRad = SkScalarCopySign(SK_Scalar1/512, sweepAngle);
953 // not sure how much will be enough, so we use a loop
954 do {
955 stopRad -= deltaRad;
956 stopV->fY = SkScalarSinSnapToZero(stopRad);
957 stopV->fX = SkScalarCosSnapToZero(stopRad);
958 } while (*startV == *stopV);
959 }
960 }
962}
@ kCW_SkRotationDirection
Definition SkGeometry.h:322
@ kCCW_SkRotationDirection
Definition SkGeometry.h:323
#define SkDegreesToRadians(degrees)
Definition SkScalar.h:77
#define SkScalarCopySign(x, y)
Definition SkScalar.h:40
static float SkScalarSinSnapToZero(SkScalar radians)
Definition SkScalar.h:115
#define SK_Scalar1
Definition SkScalar.h:18
#define SkIntToScalar(x)
Definition SkScalar.h:57
#define SkScalarAbs(x)
Definition SkScalar.h:39
static float SkScalarCosSnapToZero(SkScalar radians)
Definition SkScalar.h:120
float SkScalar
Definition extension.cpp:12
SkScalar sweepAngle
Definition SkRecords.h:251
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
float fX
x-axis value
float fY
y-axis value

◆ append_params()

static void append_params ( SkString str,
const char  label[],
const SkPoint  pts[],
int  count,
SkScalarAsStringType  strType,
SkScalar  conicWeight = -12345 
)
static

Definition at line 1941 of file SkPath.cpp.

1942 {
1943 str->append(label);
1944 str->append("(");
1945
1946 const SkScalar* values = &pts[0].fX;
1947 count *= 2;
1948
1949 for (int i = 0; i < count; ++i) {
1950 SkAppendScalar(str, values[i], strType);
1951 if (i < count - 1) {
1952 str->append(", ");
1953 }
1954 }
1955 if (conicWeight != -12345) {
1956 str->append(", ");
1957 SkAppendScalar(str, conicWeight, strType);
1958 }
1959 str->append(");");
1960 if (kHex_SkScalarAsStringType == strType) {
1961 str->append(" // ");
1962 for (int i = 0; i < count; ++i) {
1963 SkAppendScalarDec(str, values[i]);
1964 if (i < count - 1) {
1965 str->append(", ");
1966 }
1967 }
1968 if (conicWeight >= 0) {
1969 str->append(", ");
1970 SkAppendScalarDec(str, conicWeight);
1971 }
1972 }
1973 str->append("\n");
1974}
int count
void SkAppendScalar(SkString *str, SkScalar value, SkScalarAsStringType asType)
@ kHex_SkScalarAsStringType
static void SkAppendScalarDec(SkString *str, SkScalar value)
void append(const char text[])
Definition SkString.h:203

◆ arc_is_lone_point()

static bool arc_is_lone_point ( const SkRect oval,
SkScalar  startAngle,
SkScalar  sweepAngle,
SkPoint pt 
)
static

Definition at line 907 of file SkPath.cpp.

908 {
909 if (0 == sweepAngle && (0 == startAngle || SkIntToScalar(360) == startAngle)) {
910 // Chrome uses this path to move into and out of ovals. If not
911 // treated as a special case the moves can distort the oval's
912 // bounding box (and break the circle special case).
913 pt->set(oval.fRight, oval.centerY());
914 return true;
915 } else if (0 == oval.width() && 0 == oval.height()) {
916 // Chrome will sometimes create 0 radius round rects. Having degenerate
917 // quad segments in the path prevents the path from being recognized as
918 // a rect.
919 // TODO: optimizing the case where only one of width or height is zero
920 // should also be considered. This case, however, doesn't seem to be
921 // as common as the single point case.
922 pt->set(oval.fRight, oval.fTop);
923 return true;
924 }
925 return false;
926}
SkRect oval
Definition SkRecords.h:249
void set(float x, float y)
SkScalar fRight
larger x-axis bounds
Definition extension.cpp:16
constexpr float height() const
Definition SkRect.h:769
constexpr float centerY() const
Definition SkRect.h:785
constexpr float width() const
Definition SkRect.h:762
SkScalar fTop
smaller y-axis bounds
Definition extension.cpp:15

◆ assert_known_direction()

static void assert_known_direction ( SkPathDirection  dir)
static

Definition at line 850 of file SkPath.cpp.

850 {
852}
#define SkASSERT(cond)
Definition SkAssert.h:116

◆ between()

static bool between ( SkScalar  a,
SkScalar  b,
SkScalar  c 
)
static

Definition at line 2652 of file SkPath.cpp.

2652 {
2653 SkASSERT(((a <= b && b <= c) || (a >= b && b >= c)) == ((a - b) * (c - b) <= 0)
2655 return (a - b) * (c - b) <= 0;
2656}
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
Definition SkScalar.h:101
static bool b
struct MyStruct a[10]

◆ build_arc_conics()

static int build_arc_conics ( const SkRect oval,
const SkVector start,
const SkVector stop,
SkRotationDirection  dir,
SkConic  conics[SkConic::kMaxConicsForArc],
SkPoint singlePt 
)
static

If this returns 0, then the caller should just line-to the singlePt, else it should ignore singlePt and append the specified number of conics.

Definition at line 968 of file SkPath.cpp.

970 {
972
974 matrix.postTranslate(oval.centerX(), oval.centerY());
975
976 int count = SkConic::BuildUnitArc(start, stop, dir, &matrix, conics);
977 if (0 == count) {
978 matrix.mapXY(stop.x(), stop.y(), singlePt);
979 }
980 return count;
981}
#define SkScalarHalf(a)
Definition SkScalar.h:75
unsigned useCenter Optional< SkMatrix > matrix
Definition SkRecords.h:258
static int BuildUnitArc(const SkVector &start, const SkVector &stop, SkRotationDirection, const SkMatrix *, SkConic conics[kMaxConicsForArc])
constexpr float y() const
constexpr float x() const
constexpr float centerX() const
Definition SkRect.h:776

◆ check_edge_against_rect()

static bool check_edge_against_rect ( const SkPoint p0,
const SkPoint p1,
const SkRect rect,
SkPathFirstDirection  dir 
)
inlinestatic

Definition at line 263 of file SkPath.cpp.

266 {
267 const SkPoint* edgeBegin;
268 SkVector v;
269 if (SkPathFirstDirection::kCW == dir) {
270 v = p1 - p0;
271 edgeBegin = &p0;
272 } else {
273 v = p0 - p1;
274 edgeBegin = &p1;
275 }
276 if (v.fX || v.fY) {
277 // check the cross product of v with the vec from edgeBegin to each rect corner
278 SkScalar yL = v.fY * (rect.fLeft - edgeBegin->fX);
279 SkScalar xT = v.fX * (rect.fTop - edgeBegin->fY);
280 SkScalar yR = v.fY * (rect.fRight - edgeBegin->fX);
281 SkScalar xB = v.fX * (rect.fBottom - edgeBegin->fY);
282 if ((xT < yL) || (xT < yR) || (xB < yL) || (xB < yR)) {
283 return false;
284 }
285 }
286 return true;
287}
sk_sp< SkBlender > blender SkRect rect
Definition SkRecords.h:350

◆ checkOnCurve()

static bool checkOnCurve ( SkScalar  x,
SkScalar  y,
const SkPoint start,
const SkPoint end 
)
static

Definition at line 2679 of file SkPath.cpp.

2679 {
2680 if (start.fY == end.fY) {
2681 return between(start.fX, x, end.fX) && x != end.fX;
2682 } else {
2683 return x == start.fX && y == start.fY;
2684 }
2685}
static bool between(SkScalar a, SkScalar b, SkScalar c)
Definition SkPath.cpp:2652
glong glong end
double y
double x

◆ clip()

static SkPath clip ( const SkPath path,
const SkHalfPlane plane 
)
static

Definition at line 3824 of file SkPath.cpp.

3824 {
3825 SkMatrix mx, inv;
3826 SkPoint p0 = { -plane.fA*plane.fC, -plane.fB*plane.fC };
3827 mx.setAll( plane.fB, plane.fA, p0.fX,
3828 -plane.fA, plane.fB, p0.fY,
3829 0, 0, 1);
3830 if (!mx.invert(&inv)) {
3831 return SkPath();
3832 }
3833
3834 SkPath rotated;
3835 path.transform(inv, &rotated);
3836 if (!rotated.isFinite()) {
3837 return SkPath();
3838 }
3839
3840 SkScalar big = SK_ScalarMax;
3841 SkRect clip = {-big, 0, big, big };
3842
3843 struct Rec {
3844 SkPathBuilder fResult;
3845 SkPoint fPrev = {0,0};
3846 } rec;
3847
3848 SkEdgeClipper::ClipPath(rotated, clip, false,
3849 [](SkEdgeClipper* clipper, bool newCtr, void* ctx) {
3850 Rec* rec = (Rec*)ctx;
3851
3852 bool addLineTo = false;
3853 SkPoint pts[4];
3854 SkPath::Verb verb;
3855 while ((verb = clipper->next(pts)) != SkPath::kDone_Verb) {
3856 if (newCtr) {
3857 rec->fResult.moveTo(pts[0]);
3858 rec->fPrev = pts[0];
3859 newCtr = false;
3860 }
3861
3862 if (addLineTo || pts[0] != rec->fPrev) {
3863 rec->fResult.lineTo(pts[0]);
3864 }
3865
3866 switch (verb) {
3867 case SkPath::kLine_Verb:
3868 rec->fResult.lineTo(pts[1]);
3869 rec->fPrev = pts[1];
3870 break;
3871 case SkPath::kQuad_Verb:
3872 rec->fResult.quadTo(pts[1], pts[2]);
3873 rec->fPrev = pts[2];
3874 break;
3876 rec->fResult.cubicTo(pts[1], pts[2], pts[3]);
3877 rec->fPrev = pts[3];
3878 break;
3879 default: break;
3880 }
3881 addLineTo = true;
3882 }
3883 }, &rec);
3884
3885 rec.fResult.setFillType(path.getFillType());
3886 SkPath result = rec.fResult.detach().makeTransform(mx);
3887 if (!result.isFinite()) {
3888 result = SkPath();
3889 }
3890 return result;
3891}
static SkM44 inv(const SkM44 &m)
Definition 3d.cpp:26
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition SkPath.cpp:3824
#define SK_ScalarMax
Definition SkScalar.h:24
static void ClipPath(const SkPath &path, const SkRect &clip, bool canCullToTheRight, void(*consume)(SkEdgeClipper *, bool newCtr, void *ctx), void *ctx)
SkPath::Verb next(SkPoint pts[])
SkMatrix & setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar persp0, SkScalar persp1, SkScalar persp2)
Definition SkMatrix.h:562
bool invert(SkMatrix *inverse) const
Definition SkMatrix.h:1206
bool isFinite() const
Definition SkPath.cpp:411
@ kDone_Verb
Definition SkPath.h:1464
@ kCubic_Verb
Definition SkPath.h:1462
@ kQuad_Verb
Definition SkPath.h:1460
@ kLine_Verb
Definition SkPath.h:1459
GAsyncResult * result
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 fC
Definition SkPath.cpp:3751
SkScalar fB
Definition SkPath.cpp:3751
SkScalar fA
Definition SkPath.cpp:3751

◆ compute_conic_extremas()

static int compute_conic_extremas ( const SkPoint  src[3],
SkScalar  w,
SkPoint  extremas[3] 
)
static

Definition at line 3353 of file SkPath.cpp.

3353 {
3354 SkConic conic(src[0], src[1], src[2], w);
3355 SkScalar ts[2];
3356 int n = conic.findXExtrema(ts);
3357 n += conic.findYExtrema(&ts[n]);
3358 SkASSERT(n >= 0 && n <= 2);
3359 for (int i = 0; i < n; ++i) {
3360 extremas[i] = conic.evalAt(ts[i]);
3361 }
3362 extremas[n] = src[2];
3363 return n + 1;
3364}
AI float conic(float tolerance, const SkPoint pts[], float w, const VectorXform &vectorXform=VectorXform())
SkScalar w

◆ compute_cubic_extremas()

static int compute_cubic_extremas ( const SkPoint  src[4],
SkPoint  extremas[5] 
)
static

Definition at line 3366 of file SkPath.cpp.

3366 {
3367 SkScalar ts[4];
3368 int n = SkFindCubicExtrema(src[0].fX, src[1].fX, src[2].fX, src[3].fX, ts);
3369 n += SkFindCubicExtrema(src[0].fY, src[1].fY, src[2].fY, src[3].fY, &ts[n]);
3370 SkASSERT(n >= 0 && n <= 4);
3371 for (int i = 0; i < n; ++i) {
3372 SkEvalCubicAt(src, ts[i], &extremas[i], nullptr, nullptr);
3373 }
3374 extremas[n] = src[3];
3375 return n + 1;
3376}
void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint *loc, SkVector *tangent, SkVector *curvature)
int SkFindCubicExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar d, SkScalar tValues[2])

◆ compute_quad_extremas()

static int compute_quad_extremas ( const SkPoint  src[3],
SkPoint  extremas[3] 
)
static

Definition at line 3341 of file SkPath.cpp.

3341 {
3342 SkScalar ts[2];
3343 int n = SkFindQuadExtrema(src[0].fX, src[1].fX, src[2].fX, ts);
3344 n += SkFindQuadExtrema(src[0].fY, src[1].fY, src[2].fY, &ts[n]);
3345 SkASSERT(n >= 0 && n <= 2);
3346 for (int i = 0; i < n; ++i) {
3347 extremas[i] = SkEvalQuadAt(src, ts[i]);
3348 }
3349 extremas[n] = src[2];
3350 return n + 1;
3351}
void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint *pt, SkVector *tangent)
int SkFindQuadExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar tValue[1])

◆ conic_eval_denominator()

static double conic_eval_denominator ( SkScalar  w,
SkScalar  t 
)
static

Definition at line 2754 of file SkPath.cpp.

2754 {
2755 SkScalar B = 2 * (w - 1);
2756 SkScalar C = 1;
2757 SkScalar A = -B;
2758 return poly_eval(A, B, C, t);
2759}
static float poly_eval(float A, float B, float C, float t)
Definition SkPath.cpp:49
#define B

◆ conic_eval_numerator()

static double conic_eval_numerator ( const SkScalar  src[],
SkScalar  w,
SkScalar  t 
)
static

Definition at line 2743 of file SkPath.cpp.

2743 {
2744 SkASSERT(src);
2745 SkASSERT(t >= 0 && t <= 1);
2746 SkScalar src2w = src[2] * w;
2747 SkScalar C = src[0];
2748 SkScalar A = src[4] - 2 * src2w + C;
2749 SkScalar B = 2 * (src2w - C);
2750 return poly_eval(A, B, C, t);
2751}
#define C(TEST_CATEGORY)
Definition colrv1.cpp:247

◆ contains_inclusive()

static bool contains_inclusive ( const SkRect r,
SkScalar  x,
SkScalar  y 
)
static

Definition at line 3050 of file SkPath.cpp.

3050 {
3051 return r.fLeft <= x && x <= r.fRight && r.fTop <= y && y <= r.fBottom;
3052}
SkScalar fBottom
larger y-axis bounds
Definition extension.cpp:17
SkScalar fLeft
smaller x-axis bounds
Definition extension.cpp:14

◆ cross_prod()

static SkScalar cross_prod ( const SkPoint p0,
const SkPoint p1,
const SkPoint p2 
)
static

Definition at line 2473 of file SkPath.cpp.

2473 {
2474 SkScalar cross = SkPoint::CrossProduct(p1 - p0, p2 - p0);
2475 // We may get 0 when the above subtracts underflow. We expect this to be
2476 // very rare and lazily promote to double.
2477 if (0 == cross) {
2478 double p0x = SkScalarToDouble(p0.fX);
2479 double p0y = SkScalarToDouble(p0.fY);
2480
2481 double p1x = SkScalarToDouble(p1.fX);
2482 double p1y = SkScalarToDouble(p1.fY);
2483
2484 double p2x = SkScalarToDouble(p2.fX);
2485 double p2y = SkScalarToDouble(p2.fY);
2486
2487 cross = SkDoubleToScalar((p1x - p0x) * (p2y - p0y) -
2488 (p1y - p0y) * (p2x - p0x));
2489
2490 }
2491 return cross;
2492}
#define SkScalarToDouble(x)
Definition SkScalar.h:63
#define SkDoubleToScalar(x)
Definition SkScalar.h:64
int64_t cross(Point d0, Point d1)
Definition Myers.cpp:55
static float CrossProduct(const SkVector &a, const SkVector &b)

◆ crossToDir()

static SkPathFirstDirection crossToDir ( SkScalar  cross)
static

Definition at line 2551 of file SkPath.cpp.

◆ eval_cubic_pts()

static SkScalar eval_cubic_pts ( SkScalar  c0,
SkScalar  c1,
SkScalar  c2,
SkScalar  c3,
SkScalar  t 
)
static

Definition at line 2658 of file SkPath.cpp.

2659 {
2660 SkScalar A = c3 + 3*(c1 - c2) - c0;
2661 SkScalar B = 3*(c2 - c1 - c1 + c0);
2662 SkScalar C = 3*(c1 - c0);
2663 SkScalar D = c0;
2664 return poly_eval(A, B, C, D, t);
2665}

◆ find_diff_pt()

static int find_diff_pt ( const SkPoint  pts[],
int  index,
int  n,
int  inc 
)
static

Definition at line 2509 of file SkPath.cpp.

2509 {
2510 int i = index;
2511 for (;;) {
2512 i = (i + inc) % n;
2513 if (i == index) { // we wrapped around, so abort
2514 break;
2515 }
2516 if (pts[index] != pts[i]) { // found a different point, success!
2517 break;
2518 }
2519 }
2520 return i;
2521}

◆ find_max_y()

static int find_max_y ( const SkPoint  pts[],
int  count 
)
static

Definition at line 2495 of file SkPath.cpp.

2495 {
2496 SkASSERT(count > 0);
2497 SkScalar max = pts[0].fY;
2498 int firstIndex = 0;
2499 for (int i = 1; i < count; ++i) {
2500 SkScalar y = pts[i].fY;
2501 if (y > max) {
2502 max = y;
2503 firstIndex = i;
2504 }
2505 }
2506 return firstIndex;
2507}
static float max(float r, float g, float b)
Definition hsl.cpp:49

◆ find_min_max_x_at_y()

static int find_min_max_x_at_y ( const SkPoint  pts[],
int  index,
int  n,
int maxIndexPtr 
)
static

Starting at index, and moving forward (incrementing), find the xmin and xmax of the contiguous points that have the same Y.

Definition at line 2527 of file SkPath.cpp.

2528 {
2529 const SkScalar y = pts[index].fY;
2530 SkScalar min = pts[index].fX;
2531 SkScalar max = min;
2532 int minIndex = index;
2533 int maxIndex = index;
2534 for (int i = index + 1; i < n; ++i) {
2535 if (pts[i].fY != y) {
2536 break;
2537 }
2538 SkScalar x = pts[i].fX;
2539 if (x < min) {
2540 min = x;
2541 minIndex = i;
2542 } else if (x > max) {
2543 max = x;
2544 maxIndex = i;
2545 }
2546 }
2547 *maxIndexPtr = maxIndex;
2548 return minIndex;
2549}
static float min(float r, float g, float b)
Definition hsl.cpp:48

◆ find_minmax()

template<size_t N>
static void find_minmax ( const SkPoint  pts[],
SkScalar minPtr,
SkScalar maxPtr 
)
static

Definition at line 2667 of file SkPath.cpp.

2668 {
2669 SkScalar min, max;
2670 min = max = pts[0].fX;
2671 for (size_t i = 1; i < N; ++i) {
2672 min = std::min(min, pts[i].fX);
2673 max = std::max(max, pts[i].fX);
2674 }
2675 *minPtr = min;
2676 *maxPtr = max;
2677}
#define N
Definition beziers.cpp:19

◆ is_degenerate()

static bool is_degenerate ( const SkPath path)
static

Definition at line 71 of file SkPath.cpp.

71 {
72 return (path.countVerbs() - SkPathPriv::LeadingMoveToCount(path)) == 0;
73}
static int LeadingMoveToCount(const SkPath &path)
Definition SkPathPriv.h:94

◆ is_mono_quad()

static bool is_mono_quad ( SkScalar  y0,
SkScalar  y1,
SkScalar  y2 
)
static

Definition at line 2811 of file SkPath.cpp.

2811 {
2812 // return SkScalarSignAsInt(y0 - y1) + SkScalarSignAsInt(y1 - y2) != 0;
2813 if (y0 == y1) {
2814 return true;
2815 }
2816 if (y0 < y1) {
2817 return y1 <= y2;
2818 } else {
2819 return y1 >= y2;
2820 }
2821}

◆ joinNoEmptyChecks()

static void joinNoEmptyChecks ( SkRect dst,
const SkRect src 
)
static

Path.bounds is defined to be the bounds of all the control points. If we called bounds.join(r) we would skip r if r was empty, which breaks our promise. Hence we have a custom joiner that doesn't look at emptiness

Definition at line 64 of file SkPath.cpp.

64 {
65 dst->fLeft = std::min(dst->fLeft, src.fLeft);
66 dst->fTop = std::min(dst->fTop, src.fTop);
67 dst->fRight = std::max(dst->fRight, src.fRight);
68 dst->fBottom = std::max(dst->fBottom, src.fBottom);
69}
dst
Definition cp.py:12

◆ operator==()

bool operator== ( const SkPath a,
const SkPath b 
)

Compares a and b; returns true if SkPath::FillType, verb array, SkPoint array, and weights are equivalent.

Parameters
aSkPath to compare
bSkPath to compare
Returns
true if SkPath pair are equivalent

Definition at line 210 of file SkPath.cpp.

210 {
211 // note: don't need to look at isConvex or bounds, since just comparing the
212 // raw data is sufficient.
213 return &a == &b ||
214 (a.fFillType == b.fFillType && *a.fPathRef == *b.fPathRef);
215}

◆ poly_eval() [1/2]

static float poly_eval ( float  A,
float  B,
float  C,
float  D,
float  t 
)
static

Definition at line 53 of file SkPath.cpp.

53 {
54 return ((A * t + B) * t + C) * t + D;
55}

◆ poly_eval() [2/2]

static float poly_eval ( float  A,
float  B,
float  C,
float  t 
)
static

Definition at line 49 of file SkPath.cpp.

49 {
50 return (A * t + B) * t + C;
51}

◆ rect_make_dir()

static int rect_make_dir ( SkScalar  dx,
SkScalar  dy 
)
static

Definition at line 502 of file SkPath.cpp.

502 {
503 return ((0 != dx) << 0) | ((dx > 0 || dy > 0) << 1);
504}
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
Definition SkRecords.h:208

◆ sign()

static int sign ( SkScalar  x)
static

Definition at line 2141 of file SkPath.cpp.

2141{ return x < 0; }

◆ sk_path_analyze_verbs()

SkPathVerbAnalysis sk_path_analyze_verbs ( const uint8_t  vbs[],
int  verbCount 
)

Definition at line 3447 of file SkPath.cpp.

3447 {
3448 SkPathVerbAnalysis info = {false, 0, 0, 0};
3449 bool needMove = true;
3450 bool invalid = false;
3451
3452 if (verbCount >= (INT_MAX / 3)) {
3453 // A path with an extremely high number of quad, conic or cubic verbs could cause
3454 // `info.points` to overflow. To prevent against this, we reject extremely large paths. This
3455 // check is conservative and assumes the worst case (in particular, it assumes that every
3456 // verb consumes 3 points, which would only happen for a path composed entirely of cubics).
3457 // This limits us to 700 million verbs, which is large enough for any reasonable use case.
3458 invalid = true;
3459 } else {
3460 for (int i = 0; i < verbCount; ++i) {
3461 switch ((SkPathVerb)vbs[i]) {
3462 case SkPathVerb::kMove:
3463 needMove = false;
3464 info.points += 1;
3465 break;
3466 case SkPathVerb::kLine:
3467 invalid |= needMove;
3468 info.segmentMask |= kLine_SkPathSegmentMask;
3469 info.points += 1;
3470 break;
3471 case SkPathVerb::kQuad:
3472 invalid |= needMove;
3473 info.segmentMask |= kQuad_SkPathSegmentMask;
3474 info.points += 2;
3475 break;
3476 case SkPathVerb::kConic:
3477 invalid |= needMove;
3478 info.segmentMask |= kConic_SkPathSegmentMask;
3479 info.points += 2;
3480 info.weights += 1;
3481 break;
3482 case SkPathVerb::kCubic:
3483 invalid |= needMove;
3484 info.segmentMask |= kCubic_SkPathSegmentMask;
3485 info.points += 3;
3486 break;
3487 case SkPathVerb::kClose:
3488 invalid |= needMove;
3489 needMove = true;
3490 break;
3491 default:
3492 invalid = true;
3493 break;
3494 }
3495 }
3496 }
3497 info.valid = !invalid;
3498 return info;
3499}
static bool invalid(const SkISize &size)
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
@ kCubic_SkPathSegmentMask
Definition SkPathTypes.h:45
@ kConic_SkPathSegmentMask
Definition SkPathTypes.h:44
@ kQuad_SkPathSegmentMask
Definition SkPathTypes.h:43
@ kLine_SkPathSegmentMask
Definition SkPathTypes.h:42
SkPathVerb
Definition SkPathTypes.h:48
@ kClose
SkPath::RawIter returns 0 points.
@ kCubic
SkPath::RawIter returns 4 points.
@ kConic
SkPath::RawIter returns 3 points + 1 weight.
@ kQuad
SkPath::RawIter returns 3 points.
@ kMove
SkPath::RawIter returns 1 point.
@ kLine
SkPath::RawIter returns 2 points.

◆ subdivide_cubic_to()

static void subdivide_cubic_to ( SkPath path,
const SkPoint  pts[4],
int  level = 2 
)
static

Definition at line 1634 of file SkPath.cpp.

1635 {
1636 if (--level >= 0) {
1637 SkPoint tmp[7];
1638
1639 SkChopCubicAtHalf(pts, tmp);
1640 subdivide_cubic_to(path, &tmp[0], level);
1641 subdivide_cubic_to(path, &tmp[3], level);
1642 } else {
1643 path->cubicTo(pts[1], pts[2], pts[3]);
1644 }
1645}
void SkChopCubicAtHalf(const SkPoint src[4], SkPoint dst[7])
static void subdivide_cubic_to(SkPath *path, const SkPoint pts[4], int level=2)
Definition SkPath.cpp:1634

◆ tangent_conic()

static void tangent_conic ( const SkPoint  pts[],
SkScalar  x,
SkScalar  y,
SkScalar  w,
SkTDArray< SkVector > *  tangents 
)
static

Definition at line 2975 of file SkPath.cpp.

2976 {
2977 if (!between(pts[0].fY, y, pts[1].fY) && !between(pts[1].fY, y, pts[2].fY)) {
2978 return;
2979 }
2980 if (!between(pts[0].fX, x, pts[1].fX) && !between(pts[1].fX, x, pts[2].fX)) {
2981 return;
2982 }
2983 SkScalar roots[2];
2984 SkScalar A = pts[2].fY;
2985 SkScalar B = pts[1].fY * w - y * w + y;
2986 SkScalar C = pts[0].fY;
2987 A += C - 2 * B; // A = a + c - 2*(b*w - yCept*w + yCept)
2988 B -= C; // B = b*w - w * yCept + yCept - a
2989 C -= y;
2990 int n = SkFindUnitQuadRoots(A, 2 * B, C, roots);
2991 for (int index = 0; index < n; ++index) {
2992 SkScalar t = roots[index];
2993 SkScalar xt = conic_eval_numerator(&pts[0].fX, w, t) / conic_eval_denominator(w, t);
2994 if (!SkScalarNearlyEqual(x, xt)) {
2995 continue;
2996 }
2997 SkConic conic(pts, w);
2998 tangents->push_back(conic.evalTangentAt(t));
2999 }
3000}
int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2])
static double conic_eval_numerator(const SkScalar src[], SkScalar w, SkScalar t)
Definition SkPath.cpp:2743
static double conic_eval_denominator(SkScalar w, SkScalar t)
Definition SkPath.cpp:2754
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
Definition SkScalar.h:107
void push_back(const T &v)
Definition SkTDArray.h:219

◆ tangent_cubic()

static void tangent_cubic ( const SkPoint  pts[],
SkScalar  x,
SkScalar  y,
SkTDArray< SkVector > *  tangents 
)
static

Definition at line 2947 of file SkPath.cpp.

2948 {
2949 if (!between(pts[0].fY, y, pts[1].fY) && !between(pts[1].fY, y, pts[2].fY)
2950 && !between(pts[2].fY, y, pts[3].fY)) {
2951 return;
2952 }
2953 if (!between(pts[0].fX, x, pts[1].fX) && !between(pts[1].fX, x, pts[2].fX)
2954 && !between(pts[2].fX, x, pts[3].fX)) {
2955 return;
2956 }
2957 SkPoint dst[10];
2958 int n = SkChopCubicAtYExtrema(pts, dst);
2959 for (int i = 0; i <= n; ++i) {
2960 SkPoint* c = &dst[i * 3];
2961 SkScalar t;
2962 if (!SkCubicClipper::ChopMonoAtY(c, y, &t)) {
2963 continue;
2964 }
2965 SkScalar xt = eval_cubic_pts(c[0].fX, c[1].fX, c[2].fX, c[3].fX, t);
2966 if (!SkScalarNearlyEqual(x, xt)) {
2967 continue;
2968 }
2969 SkVector tangent;
2970 SkEvalCubicAt(c, t, nullptr, &tangent, nullptr);
2971 tangents->push_back(tangent);
2972 }
2973}
int SkChopCubicAtYExtrema(const SkPoint src[4], SkPoint dst[10])
static SkScalar eval_cubic_pts(SkScalar c0, SkScalar c1, SkScalar c2, SkScalar c3, SkScalar t)
Definition SkPath.cpp:2658
static bool ChopMonoAtY(const SkPoint pts[4], SkScalar y, SkScalar *t)

◆ tangent_line()

static void tangent_line ( const SkPoint  pts[],
SkScalar  x,
SkScalar  y,
SkTDArray< SkVector > *  tangents 
)
static

Definition at line 3028 of file SkPath.cpp.

3029 {
3030 SkScalar y0 = pts[0].fY;
3031 SkScalar y1 = pts[1].fY;
3032 if (!between(y0, y, y1)) {
3033 return;
3034 }
3035 SkScalar x0 = pts[0].fX;
3036 SkScalar x1 = pts[1].fX;
3037 if (!between(x0, x, x1)) {
3038 return;
3039 }
3040 SkScalar dx = x1 - x0;
3041 SkScalar dy = y1 - y0;
3042 if (!SkScalarNearlyEqual((x - x0) * dy, dx * (y - y0))) {
3043 return;
3044 }
3045 SkVector v;
3046 v.set(dx, dy);
3047 tangents->push_back(v);
3048}

◆ tangent_quad()

static void tangent_quad ( const SkPoint  pts[],
SkScalar  x,
SkScalar  y,
SkTDArray< SkVector > *  tangents 
)
static

Definition at line 3002 of file SkPath.cpp.

3003 {
3004 if (!between(pts[0].fY, y, pts[1].fY) && !between(pts[1].fY, y, pts[2].fY)) {
3005 return;
3006 }
3007 if (!between(pts[0].fX, x, pts[1].fX) && !between(pts[1].fX, x, pts[2].fX)) {
3008 return;
3009 }
3010 SkScalar roots[2];
3011 int n = SkFindUnitQuadRoots(pts[0].fY - 2 * pts[1].fY + pts[2].fY,
3012 2 * (pts[1].fY - pts[0].fY),
3013 pts[0].fY - y,
3014 roots);
3015 for (int index = 0; index < n; ++index) {
3016 SkScalar t = roots[index];
3017 SkScalar C = pts[0].fX;
3018 SkScalar A = pts[2].fX - 2 * pts[1].fX + C;
3019 SkScalar B = 2 * (pts[1].fX - C);
3020 SkScalar xt = poly_eval(A, B, C, t);
3021 if (!SkScalarNearlyEqual(x, xt)) {
3022 continue;
3023 }
3024 tangents->push_back(SkEvalQuadTangentAt(pts, t));
3025 }
3026}
SkVector SkEvalQuadTangentAt(const SkPoint src[3], SkScalar t)

◆ winding_conic()

static int winding_conic ( const SkPoint  pts[],
SkScalar  x,
SkScalar  y,
SkScalar  weight,
int onCurveCount 
)
static

Definition at line 2823 of file SkPath.cpp.

2824 {
2825 SkConic conic(pts, weight);
2826 SkConic chopped[2];
2827 // If the data points are very large, the conic may not be monotonic but may also
2828 // fail to chop. Then, the chopper does not split the original conic in two.
2829 bool isMono = is_mono_quad(pts[0].fY, pts[1].fY, pts[2].fY) || !conic.chopAtYExtrema(chopped);
2830 int w = winding_mono_conic(isMono ? conic : chopped[0], x, y, onCurveCount);
2831 if (!isMono) {
2832 w += winding_mono_conic(chopped[1], x, y, onCurveCount);
2833 }
2834 return w;
2835}
static int winding_mono_conic(const SkConic &conic, SkScalar x, SkScalar y, int *onCurveCount)
Definition SkPath.cpp:2761
static bool is_mono_quad(SkScalar y0, SkScalar y1, SkScalar y2)
Definition SkPath.cpp:2811

◆ winding_cubic()

static int winding_cubic ( const SkPoint  pts[],
SkScalar  x,
SkScalar  y,
int onCurveCount 
)
static

Definition at line 2733 of file SkPath.cpp.

2733 {
2734 SkPoint dst[10];
2735 int n = SkChopCubicAtYExtrema(pts, dst);
2736 int w = 0;
2737 for (int i = 0; i <= n; ++i) {
2738 w += winding_mono_cubic(&dst[i * 3], x, y, onCurveCount);
2739 }
2740 return w;
2741}
static int winding_mono_cubic(const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
Definition SkPath.cpp:2687

◆ winding_line()

static int winding_line ( const SkPoint  pts[],
SkScalar  x,
SkScalar  y,
int onCurveCount 
)
static

Definition at line 2907 of file SkPath.cpp.

2907 {
2908 SkScalar x0 = pts[0].fX;
2909 SkScalar y0 = pts[0].fY;
2910 SkScalar x1 = pts[1].fX;
2911 SkScalar y1 = pts[1].fY;
2912
2913 SkScalar dy = y1 - y0;
2914
2915 int dir = 1;
2916 if (y0 > y1) {
2917 using std::swap;
2918 swap(y0, y1);
2919 dir = -1;
2920 }
2921 if (y < y0 || y > y1) {
2922 return 0;
2923 }
2924 if (checkOnCurve(x, y, pts[0], pts[1])) {
2925 *onCurveCount += 1;
2926 return 0;
2927 }
2928 if (y == y1) {
2929 return 0;
2930 }
2931 SkScalar cross = (x1 - x0) * (y - pts[0].fY) - dy * (x - x0);
2932
2933 if (!cross) {
2934 // zero cross means the point is on the line, and since the case where
2935 // y of the query point is at the end point is handled above, we can be
2936 // sure that we're on the line (excluding the end point) here
2937 if (x != x1 || y != pts[1].fY) {
2938 *onCurveCount += 1;
2939 }
2940 dir = 0;
2941 } else if (SkScalarSignAsInt(cross) == dir) {
2942 dir = 0;
2943 }
2944 return dir;
2945}
static bool checkOnCurve(SkScalar x, SkScalar y, const SkPoint &start, const SkPoint &end)
Definition SkPath.cpp:2679
void swap(sk_sp< T > &a, sk_sp< T > &b)
Definition SkRefCnt.h:341
static int SkScalarSignAsInt(SkScalar x)
Definition SkScalar.h:90

◆ winding_mono_conic()

static int winding_mono_conic ( const SkConic conic,
SkScalar  x,
SkScalar  y,
int onCurveCount 
)
static

Definition at line 2761 of file SkPath.cpp.

2761 {
2762 const SkPoint* pts = conic.fPts;
2763 SkScalar y0 = pts[0].fY;
2764 SkScalar y2 = pts[2].fY;
2765
2766 int dir = 1;
2767 if (y0 > y2) {
2768 using std::swap;
2769 swap(y0, y2);
2770 dir = -1;
2771 }
2772 if (y < y0 || y > y2) {
2773 return 0;
2774 }
2775 if (checkOnCurve(x, y, pts[0], pts[2])) {
2776 *onCurveCount += 1;
2777 return 0;
2778 }
2779 if (y == y2) {
2780 return 0;
2781 }
2782
2783 SkScalar roots[2];
2784 SkScalar A = pts[2].fY;
2785 SkScalar B = pts[1].fY * conic.fW - y * conic.fW + y;
2786 SkScalar C = pts[0].fY;
2787 A += C - 2 * B; // A = a + c - 2*(b*w - yCept*w + yCept)
2788 B -= C; // B = b*w - w * yCept + yCept - a
2789 C -= y;
2790 int n = SkFindUnitQuadRoots(A, 2 * B, C, roots);
2791 SkASSERT(n <= 1);
2792 SkScalar xt;
2793 if (0 == n) {
2794 // zero roots are returned only when y0 == y
2795 // Need [0] if dir == 1
2796 // and [2] if dir == -1
2797 xt = pts[1 - dir].fX;
2798 } else {
2799 SkScalar t = roots[0];
2800 xt = conic_eval_numerator(&pts[0].fX, conic.fW, t) / conic_eval_denominator(conic.fW, t);
2801 }
2802 if (SkScalarNearlyEqual(xt, x)) {
2803 if (x != pts[2].fX || y != pts[2].fY) { // don't test end points; they're start points
2804 *onCurveCount += 1;
2805 return 0;
2806 }
2807 }
2808 return xt < x ? dir : 0;
2809}

◆ winding_mono_cubic()

static int winding_mono_cubic ( const SkPoint  pts[],
SkScalar  x,
SkScalar  y,
int onCurveCount 
)
static

Definition at line 2687 of file SkPath.cpp.

2687 {
2688 SkScalar y0 = pts[0].fY;
2689 SkScalar y3 = pts[3].fY;
2690
2691 int dir = 1;
2692 if (y0 > y3) {
2693 using std::swap;
2694 swap(y0, y3);
2695 dir = -1;
2696 }
2697 if (y < y0 || y > y3) {
2698 return 0;
2699 }
2700 if (checkOnCurve(x, y, pts[0], pts[3])) {
2701 *onCurveCount += 1;
2702 return 0;
2703 }
2704 if (y == y3) {
2705 return 0;
2706 }
2707
2708 // quickreject or quickaccept
2709 SkScalar min, max;
2710 find_minmax<4>(pts, &min, &max);
2711 if (x < min) {
2712 return 0;
2713 }
2714 if (x > max) {
2715 return dir;
2716 }
2717
2718 // compute the actual x(t) value
2719 SkScalar t;
2720 if (!SkCubicClipper::ChopMonoAtY(pts, y, &t)) {
2721 return 0;
2722 }
2723 SkScalar xt = eval_cubic_pts(pts[0].fX, pts[1].fX, pts[2].fX, pts[3].fX, t);
2724 if (SkScalarNearlyEqual(xt, x)) {
2725 if (x != pts[3].fX || y != pts[3].fY) { // don't test end points; they're start points
2726 *onCurveCount += 1;
2727 return 0;
2728 }
2729 }
2730 return xt < x ? dir : 0;
2731}

◆ winding_mono_quad()

static int winding_mono_quad ( const SkPoint  pts[],
SkScalar  x,
SkScalar  y,
int onCurveCount 
)
static

Definition at line 2837 of file SkPath.cpp.

2837 {
2838 SkScalar y0 = pts[0].fY;
2839 SkScalar y2 = pts[2].fY;
2840
2841 int dir = 1;
2842 if (y0 > y2) {
2843 using std::swap;
2844 swap(y0, y2);
2845 dir = -1;
2846 }
2847 if (y < y0 || y > y2) {
2848 return 0;
2849 }
2850 if (checkOnCurve(x, y, pts[0], pts[2])) {
2851 *onCurveCount += 1;
2852 return 0;
2853 }
2854 if (y == y2) {
2855 return 0;
2856 }
2857 // bounds check on X (not required. is it faster?)
2858#if 0
2859 if (pts[0].fX > x && pts[1].fX > x && pts[2].fX > x) {
2860 return 0;
2861 }
2862#endif
2863
2864 SkScalar roots[2];
2865 int n = SkFindUnitQuadRoots(pts[0].fY - 2 * pts[1].fY + pts[2].fY,
2866 2 * (pts[1].fY - pts[0].fY),
2867 pts[0].fY - y,
2868 roots);
2869 SkASSERT(n <= 1);
2870 SkScalar xt;
2871 if (0 == n) {
2872 // zero roots are returned only when y0 == y
2873 // Need [0] if dir == 1
2874 // and [2] if dir == -1
2875 xt = pts[1 - dir].fX;
2876 } else {
2877 SkScalar t = roots[0];
2878 SkScalar C = pts[0].fX;
2879 SkScalar A = pts[2].fX - 2 * pts[1].fX + C;
2880 SkScalar B = 2 * (pts[1].fX - C);
2881 xt = poly_eval(A, B, C, t);
2882 }
2883 if (SkScalarNearlyEqual(xt, x)) {
2884 if (x != pts[2].fX || y != pts[2].fY) { // don't test end points; they're start points
2885 *onCurveCount += 1;
2886 return 0;
2887 }
2888 }
2889 return xt < x ? dir : 0;
2890}

◆ winding_quad()

static int winding_quad ( const SkPoint  pts[],
SkScalar  x,
SkScalar  y,
int onCurveCount 
)
static

Definition at line 2892 of file SkPath.cpp.

2892 {
2893 SkPoint dst[5];
2894 int n = 0;
2895
2896 if (!is_mono_quad(pts[0].fY, pts[1].fY, pts[2].fY)) {
2897 n = SkChopQuadAtYExtrema(pts, dst);
2898 pts = dst;
2899 }
2900 int w = winding_mono_quad(pts, x, y, onCurveCount);
2901 if (n > 0) {
2902 w += winding_mono_quad(&pts[2], x, y, onCurveCount);
2903 }
2904 return w;
2905}
int SkChopQuadAtYExtrema(const SkPoint src[3], SkPoint dst[5])
static int winding_mono_quad(const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
Definition SkPath.cpp:2837