Flutter Engine
The Flutter Engine
Classes | Macros | Enumerations | Functions
SkPath.cpp File Reference
#include "include/core/SkPath.h"
#include "include/core/SkArc.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/SkSpan_impl.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 154 of file SkPath.cpp.

◆ kValueNeverReturnedBySign

#define kValueNeverReturnedBySign   2

Definition at line 2206 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 2208 of file SkPath.cpp.

2208 {
2213 kBackwards_DirChange, // if double back, allow simple lines to be convex
2215};
@ kBackwards_DirChange
Definition: SkPath.cpp:2213
@ kStraight_DirChange
Definition: SkPath.cpp:2212
@ kInvalid_DirChange
Definition: SkPath.cpp:2214
@ kLeft_DirChange
Definition: SkPath.cpp:2210
@ kRight_DirChange
Definition: SkPath.cpp:2211
@ kUnknown_DirChange
Definition: SkPath.cpp:2209

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 940 of file SkPath.cpp.

941 {
944
945 startV->fY = SkScalarSinSnapToZero(startRad);
946 startV->fX = SkScalarCosSnapToZero(startRad);
947 stopV->fY = SkScalarSinSnapToZero(stopRad);
948 stopV->fX = SkScalarCosSnapToZero(stopRad);
949
950 /* If the sweep angle is nearly (but less than) 360, then due to precision
951 loss in radians-conversion and/or sin/cos, we may end up with coincident
952 vectors, which will fool SkBuildQuadArc into doing nothing (bad) instead
953 of drawing a nearly complete circle (good).
954 e.g. canvas.drawArc(0, 359.99, ...)
955 -vs- canvas.drawArc(0, 359.9, ...)
956 We try to detect this edge case, and tweak the stop vector
957 */
958 if (*startV == *stopV) {
960 if (sw < SkIntToScalar(360) && sw > SkIntToScalar(359)) {
961 // make a guess at a tiny angle (in radians) to tweak by
963 // not sure how much will be enough, so we use a loop
964 do {
965 stopRad -= deltaRad;
966 stopV->fY = SkScalarSinSnapToZero(stopRad);
967 stopV->fX = SkScalarCosSnapToZero(stopRad);
968 } while (*startV == *stopV);
969 }
970 }
972}
@ 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 startAngle
Definition: SkRecords.h:250
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
Definition: SkPoint_impl.h:164
float fY
y-axis value
Definition: SkPoint_impl.h:165

◆ 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 2005 of file SkPath.cpp.

2006 {
2007 str->append(label);
2008 str->append("(");
2009
2010 const SkScalar* values = &pts[0].fX;
2011 count *= 2;
2012
2013 for (int i = 0; i < count; ++i) {
2014 SkAppendScalar(str, values[i], strType);
2015 if (i < count - 1) {
2016 str->append(", ");
2017 }
2018 }
2019 if (conicWeight != -12345) {
2020 str->append(", ");
2021 SkAppendScalar(str, conicWeight, strType);
2022 }
2023 str->append(");");
2024 if (kHex_SkScalarAsStringType == strType) {
2025 str->append(" // ");
2026 for (int i = 0; i < count; ++i) {
2027 SkAppendScalarDec(str, values[i]);
2028 if (i < count - 1) {
2029 str->append(", ");
2030 }
2031 }
2032 if (conicWeight >= 0) {
2033 str->append(", ");
2034 SkAppendScalarDec(str, conicWeight);
2035 }
2036 }
2037 str->append("\n");
2038}
int count
Definition: FontMgrTest.cpp:50
void SkAppendScalar(SkString *str, SkScalar value, SkScalarAsStringType asType)
@ kHex_SkScalarAsStringType
Definition: SkStringUtils.h:20
static void SkAppendScalarDec(SkString *str, SkScalar value)
Definition: SkStringUtils.h:25
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 917 of file SkPath.cpp.

918 {
919 if (0 == sweepAngle && (0 == startAngle || SkIntToScalar(360) == startAngle)) {
920 // Chrome uses this path to move into and out of ovals. If not
921 // treated as a special case the moves can distort the oval's
922 // bounding box (and break the circle special case).
923 pt->set(oval.fRight, oval.centerY());
924 return true;
925 } else if (0 == oval.width() && 0 == oval.height()) {
926 // Chrome will sometimes create 0 radius round rects. Having degenerate
927 // quad segments in the path prevents the path from being recognized as
928 // a rect.
929 // TODO: optimizing the case where only one of width or height is zero
930 // should also be considered. This case, however, doesn't seem to be
931 // as common as the single point case.
932 pt->set(oval.fRight, oval.fTop);
933 return true;
934 }
935 return false;
936}
SkRect oval
Definition: SkRecords.h:249
void set(float x, float y)
Definition: SkPoint_impl.h:200
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 860 of file SkPath.cpp.

860 {
862}
#define SkASSERT(cond)
Definition: SkAssert.h:116

◆ between()

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

Definition at line 2716 of file SkPath.cpp.

2716 {
2717 SkASSERT(((a <= b && b <= c) || (a >= b && b >= c)) == ((a - b) * (c - b) <= 0)
2719 return (a - b) * (c - b) <= 0;
2720}
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 978 of file SkPath.cpp.

980 {
982
984 matrix.postTranslate(oval.centerX(), oval.centerY());
985
986 int count = SkConic::BuildUnitArc(start, stop, dir, &matrix, conics);
987 if (0 == count) {
988 matrix.mapXY(stop.x(), stop.y(), singlePt);
989 }
990 return count;
991}
#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
Definition: SkPoint_impl.h:187
constexpr float x() const
Definition: SkPoint_impl.h:181
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 265 of file SkPath.cpp.

268 {
269 const SkPoint* edgeBegin;
270 SkVector v;
272 v = p1 - p0;
273 edgeBegin = &p0;
274 } else {
275 v = p0 - p1;
276 edgeBegin = &p1;
277 }
278 if (v.fX || v.fY) {
279 // check the cross product of v with the vec from edgeBegin to each rect corner
280 SkScalar yL = v.fY * (rect.fLeft - edgeBegin->fX);
281 SkScalar xT = v.fX * (rect.fTop - edgeBegin->fY);
282 SkScalar yR = v.fY * (rect.fRight - edgeBegin->fX);
283 SkScalar xB = v.fX * (rect.fBottom - edgeBegin->fY);
284 if ((xT < yL) || (xT < yR) || (xB < yL) || (xB < yR)) {
285 return false;
286 }
287 }
288 return true;
289}
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 2743 of file SkPath.cpp.

2743 {
2744 if (start.fY == end.fY) {
2745 return between(start.fX, x, end.fX) && x != end.fX;
2746 } else {
2747 return x == start.fX && y == start.fY;
2748 }
2749}
static bool between(SkScalar a, SkScalar b, SkScalar c)
Definition: SkPath.cpp:2716
glong glong end
double y
double x

◆ clip()

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

Definition at line 3892 of file SkPath.cpp.

3892 {
3893 SkMatrix mx, inv;
3894 SkPoint p0 = { -plane.fA*plane.fC, -plane.fB*plane.fC };
3895 mx.setAll( plane.fB, plane.fA, p0.fX,
3896 -plane.fA, plane.fB, p0.fY,
3897 0, 0, 1);
3898 if (!mx.invert(&inv)) {
3899 return SkPath();
3900 }
3901
3902 SkPath rotated;
3903 path.transform(inv, &rotated);
3904 if (!rotated.isFinite()) {
3905 return SkPath();
3906 }
3907
3908 SkScalar big = SK_ScalarMax;
3909 SkRect clip = {-big, 0, big, big };
3910
3911 struct Rec {
3913 SkPoint fPrev = {0,0};
3914 } rec;
3915
3916 SkEdgeClipper::ClipPath(rotated, clip, false,
3917 [](SkEdgeClipper* clipper, bool newCtr, void* ctx) {
3918 Rec* rec = (Rec*)ctx;
3919
3920 bool addLineTo = false;
3921 SkPoint pts[4];
3922 SkPath::Verb verb;
3923 while ((verb = clipper->next(pts)) != SkPath::kDone_Verb) {
3924 if (newCtr) {
3925 rec->fResult.moveTo(pts[0]);
3926 rec->fPrev = pts[0];
3927 newCtr = false;
3928 }
3929
3930 if (addLineTo || pts[0] != rec->fPrev) {
3931 rec->fResult.lineTo(pts[0]);
3932 }
3933
3934 switch (verb) {
3935 case SkPath::kLine_Verb:
3936 rec->fResult.lineTo(pts[1]);
3937 rec->fPrev = pts[1];
3938 break;
3939 case SkPath::kQuad_Verb:
3940 rec->fResult.quadTo(pts[1], pts[2]);
3941 rec->fPrev = pts[2];
3942 break;
3944 rec->fResult.cubicTo(pts[1], pts[2], pts[3]);
3945 rec->fPrev = pts[3];
3946 break;
3947 default: break;
3948 }
3949 addLineTo = true;
3950 }
3951 }, &rec);
3952
3953 rec.fResult.setFillType(path.getFillType());
3954 SkPath result = rec.fResult.detach().makeTransform(mx);
3955 if (!result.isFinite()) {
3956 result = SkPath();
3957 }
3958 return result;
3959}
static SkM44 inv(const SkM44 &m)
Definition: 3d.cpp:26
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition: SkPath.cpp:3892
LoopControlFlowInfo fResult
#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
Definition: SkPath.h:59
bool isFinite() const
Definition: SkPath.cpp:421
@ kDone_Verb
Definition: SkPath.h:1472
@ kCubic_Verb
Definition: SkPath.h:1470
@ kQuad_Verb
Definition: SkPath.h:1468
@ kLine_Verb
Definition: SkPath.h:1467
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:3819
SkScalar fB
Definition: SkPath.cpp:3819
SkScalar fA
Definition: SkPath.cpp:3819

◆ compute_conic_extremas()

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

Definition at line 3421 of file SkPath.cpp.

3421 {
3422 SkConic conic(src[0], src[1], src[2], w);
3423 SkScalar ts[2];
3424 int n = conic.findXExtrema(ts);
3425 n += conic.findYExtrema(&ts[n]);
3426 SkASSERT(n >= 0 && n <= 2);
3427 for (int i = 0; i < n; ++i) {
3428 extremas[i] = conic.evalAt(ts[i]);
3429 }
3430 extremas[n] = src[2];
3431 return n + 1;
3432}
AI float conic(float tolerance, const SkPoint pts[], float w, const VectorXform &vectorXform=VectorXform())
Definition: WangsFormula.h:287
SkScalar w

◆ compute_cubic_extremas()

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

Definition at line 3434 of file SkPath.cpp.

3434 {
3435 SkScalar ts[4];
3436 int n = SkFindCubicExtrema(src[0].fX, src[1].fX, src[2].fX, src[3].fX, ts);
3437 n += SkFindCubicExtrema(src[0].fY, src[1].fY, src[2].fY, src[3].fY, &ts[n]);
3438 SkASSERT(n >= 0 && n <= 4);
3439 for (int i = 0; i < n; ++i) {
3440 SkEvalCubicAt(src, ts[i], &extremas[i], nullptr, nullptr);
3441 }
3442 extremas[n] = src[3];
3443 return n + 1;
3444}
void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint *loc, SkVector *tangent, SkVector *curvature)
Definition: SkGeometry.cpp:418
int SkFindCubicExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar d, SkScalar tValues[2])
Definition: SkGeometry.cpp:454

◆ compute_quad_extremas()

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

Definition at line 3409 of file SkPath.cpp.

3409 {
3410 SkScalar ts[2];
3411 int n = SkFindQuadExtrema(src[0].fX, src[1].fX, src[2].fX, ts);
3412 n += SkFindQuadExtrema(src[0].fY, src[1].fY, src[2].fY, &ts[n]);
3413 SkASSERT(n >= 0 && n <= 2);
3414 for (int i = 0; i < n; ++i) {
3415 extremas[i] = SkEvalQuadAt(src, ts[i]);
3416 }
3417 extremas[n] = src[2];
3418 return n + 1;
3419}
void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint *pt, SkVector *tangent)
Definition: SkGeometry.cpp:132
int SkFindQuadExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar tValue[1])
Definition: SkGeometry.cpp:265

◆ conic_eval_denominator()

static double conic_eval_denominator ( SkScalar  w,
SkScalar  t 
)
static

Definition at line 2818 of file SkPath.cpp.

2818 {
2819 SkScalar B = 2 * (w - 1);
2820 SkScalar C = 1;
2821 SkScalar A = -B;
2822 return poly_eval(A, B, C, t);
2823}
static float poly_eval(float A, float B, float C, float t)
Definition: SkPath.cpp:51
#define B

◆ conic_eval_numerator()

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

Definition at line 2807 of file SkPath.cpp.

2807 {
2808 SkASSERT(src);
2809 SkASSERT(t >= 0 && t <= 1);
2810 SkScalar src2w = src[2] * w;
2811 SkScalar C = src[0];
2812 SkScalar A = src[4] - 2 * src2w + C;
2813 SkScalar B = 2 * (src2w - C);
2814 return poly_eval(A, B, C, t);
2815}
#define C(TEST_CATEGORY)
Definition: colrv1.cpp:248

◆ contains_inclusive()

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

Definition at line 3114 of file SkPath.cpp.

3114 {
3115 return r.fLeft <= x && x <= r.fRight && r.fTop <= y && y <= r.fBottom;
3116}
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 2537 of file SkPath.cpp.

2537 {
2538 SkScalar cross = SkPoint::CrossProduct(p1 - p0, p2 - p0);
2539 // We may get 0 when the above subtracts underflow. We expect this to be
2540 // very rare and lazily promote to double.
2541 if (0 == cross) {
2542 double p0x = SkScalarToDouble(p0.fX);
2543 double p0y = SkScalarToDouble(p0.fY);
2544
2545 double p1x = SkScalarToDouble(p1.fX);
2546 double p1y = SkScalarToDouble(p1.fY);
2547
2548 double p2x = SkScalarToDouble(p2.fX);
2549 double p2y = SkScalarToDouble(p2.fY);
2550
2551 cross = SkDoubleToScalar((p1x - p0x) * (p2y - p0y) -
2552 (p1y - p0y) * (p2x - p0x));
2553
2554 }
2555 return cross;
2556}
#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)
Definition: SkPoint_impl.h:532

◆ crossToDir()

static SkPathFirstDirection crossToDir ( SkScalar  cross)
static

Definition at line 2615 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 2722 of file SkPath.cpp.

2723 {
2724 SkScalar A = c3 + 3*(c1 - c2) - c0;
2725 SkScalar B = 3*(c2 - c1 - c1 + c0);
2726 SkScalar C = 3*(c1 - c0);
2727 SkScalar D = c0;
2728 return poly_eval(A, B, C, D, t);
2729}

◆ find_diff_pt()

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

Definition at line 2573 of file SkPath.cpp.

2573 {
2574 int i = index;
2575 for (;;) {
2576 i = (i + inc) % n;
2577 if (i == index) { // we wrapped around, so abort
2578 break;
2579 }
2580 if (pts[index] != pts[i]) { // found a different point, success!
2581 break;
2582 }
2583 }
2584 return i;
2585}

◆ find_max_y()

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

Definition at line 2559 of file SkPath.cpp.

2559 {
2560 SkASSERT(count > 0);
2561 SkScalar max = pts[0].fY;
2562 int firstIndex = 0;
2563 for (int i = 1; i < count; ++i) {
2564 SkScalar y = pts[i].fY;
2565 if (y > max) {
2566 max = y;
2567 firstIndex = i;
2568 }
2569 }
2570 return firstIndex;
2571}
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 2591 of file SkPath.cpp.

2592 {
2593 const SkScalar y = pts[index].fY;
2594 SkScalar min = pts[index].fX;
2595 SkScalar max = min;
2596 int minIndex = index;
2597 int maxIndex = index;
2598 for (int i = index + 1; i < n; ++i) {
2599 if (pts[i].fY != y) {
2600 break;
2601 }
2602 SkScalar x = pts[i].fX;
2603 if (x < min) {
2604 min = x;
2605 minIndex = i;
2606 } else if (x > max) {
2607 max = x;
2608 maxIndex = i;
2609 }
2610 }
2611 *maxIndexPtr = maxIndex;
2612 return minIndex;
2613}
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 2731 of file SkPath.cpp.

2732 {
2733 SkScalar min, max;
2734 min = max = pts[0].fX;
2735 for (size_t i = 1; i < N; ++i) {
2736 min = std::min(min, pts[i].fX);
2737 max = std::max(max, pts[i].fX);
2738 }
2739 *minPtr = min;
2740 *maxPtr = max;
2741}
#define N
Definition: beziers.cpp:19

◆ is_degenerate()

static bool is_degenerate ( const SkPath path)
static

Definition at line 73 of file SkPath.cpp.

73 {
74 return (path.countVerbs() - SkPathPriv::LeadingMoveToCount(path)) == 0;
75}
static int LeadingMoveToCount(const SkPath &path)
Definition: SkPathPriv.h:95

◆ is_mono_quad()

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

Definition at line 2875 of file SkPath.cpp.

2875 {
2876 // return SkScalarSignAsInt(y0 - y1) + SkScalarSignAsInt(y1 - y2) != 0;
2877 if (y0 == y1) {
2878 return true;
2879 }
2880 if (y0 < y1) {
2881 return y1 <= y2;
2882 } else {
2883 return y1 >= y2;
2884 }
2885}

◆ 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 66 of file SkPath.cpp.

66 {
67 dst->fLeft = std::min(dst->fLeft, src.fLeft);
68 dst->fTop = std::min(dst->fTop, src.fTop);
69 dst->fRight = std::max(dst->fRight, src.fRight);
70 dst->fBottom = std::max(dst->fBottom, src.fBottom);
71}
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 212 of file SkPath.cpp.

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

◆ poly_eval() [1/2]

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

Definition at line 55 of file SkPath.cpp.

55 {
56 return ((A * t + B) * t + C) * t + D;
57}

◆ poly_eval() [2/2]

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

Definition at line 51 of file SkPath.cpp.

51 {
52 return (A * t + B) * t + C;
53}

◆ rect_make_dir()

static int rect_make_dir ( SkScalar  dx,
SkScalar  dy 
)
static

Definition at line 512 of file SkPath.cpp.

512 {
513 return ((0 != dx) << 0) | ((dx > 0 || dy > 0) << 1);
514}
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 2205 of file SkPath.cpp.

2205{ return x < 0; }

◆ sk_path_analyze_verbs()

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

Definition at line 3515 of file SkPath.cpp.

3515 {
3516 SkPathVerbAnalysis info = {false, 0, 0, 0};
3517 bool needMove = true;
3518 bool invalid = false;
3519
3520 if (verbCount >= (INT_MAX / 3)) SK_UNLIKELY {
3521 // A path with an extremely high number of quad, conic or cubic verbs could cause
3522 // `info.points` to overflow. To prevent against this, we reject extremely large paths. This
3523 // check is conservative and assumes the worst case (in particular, it assumes that every
3524 // verb consumes 3 points, which would only happen for a path composed entirely of cubics).
3525 // This limits us to 700 million verbs, which is large enough for any reasonable use case.
3526 invalid = true;
3527 } else {
3528 for (int i = 0; i < verbCount; ++i) {
3529 switch ((SkPathVerb)vbs[i]) {
3530 case SkPathVerb::kMove:
3531 needMove = false;
3532 info.points += 1;
3533 break;
3534 case SkPathVerb::kLine:
3535 invalid |= needMove;
3536 info.segmentMask |= kLine_SkPathSegmentMask;
3537 info.points += 1;
3538 break;
3539 case SkPathVerb::kQuad:
3540 invalid |= needMove;
3541 info.segmentMask |= kQuad_SkPathSegmentMask;
3542 info.points += 2;
3543 break;
3544 case SkPathVerb::kConic:
3545 invalid |= needMove;
3546 info.segmentMask |= kConic_SkPathSegmentMask;
3547 info.points += 2;
3548 info.weights += 1;
3549 break;
3550 case SkPathVerb::kCubic:
3551 invalid |= needMove;
3552 info.segmentMask |= kCubic_SkPathSegmentMask;
3553 info.points += 3;
3554 break;
3555 case SkPathVerb::kClose:
3556 invalid |= needMove;
3557 needMove = true;
3558 break;
3559 default:
3560 invalid = true;
3561 break;
3562 }
3563 }
3564 }
3565 info.valid = !invalid;
3566 return info;
3567}
static bool invalid(const SkISize &size)
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
#define SK_UNLIKELY
Definition: SkAssert.h:28
@ 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 1698 of file SkPath.cpp.

1699 {
1700 if (--level >= 0) {
1701 SkPoint tmp[7];
1702
1703 SkChopCubicAtHalf(pts, tmp);
1704 subdivide_cubic_to(path, &tmp[0], level);
1705 subdivide_cubic_to(path, &tmp[3], level);
1706 } else {
1707 path->cubicTo(pts[1], pts[2], pts[3]);
1708 }
1709}
void SkChopCubicAtHalf(const SkPoint src[4], SkPoint dst[7])
Definition: SkGeometry.cpp:575
static void subdivide_cubic_to(SkPath *path, const SkPoint pts[4], int level=2)
Definition: SkPath.cpp:1698

◆ tangent_conic()

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

Definition at line 3039 of file SkPath.cpp.

3040 {
3041 if (!between(pts[0].fY, y, pts[1].fY) && !between(pts[1].fY, y, pts[2].fY)) {
3042 return;
3043 }
3044 if (!between(pts[0].fX, x, pts[1].fX) && !between(pts[1].fX, x, pts[2].fX)) {
3045 return;
3046 }
3047 SkScalar roots[2];
3048 SkScalar A = pts[2].fY;
3049 SkScalar B = pts[1].fY * w - y * w + y;
3050 SkScalar C = pts[0].fY;
3051 A += C - 2 * B; // A = a + c - 2*(b*w - yCept*w + yCept)
3052 B -= C; // B = b*w - w * yCept + yCept - a
3053 C -= y;
3054 int n = SkFindUnitQuadRoots(A, 2 * B, C, roots);
3055 for (int index = 0; index < n; ++index) {
3056 SkScalar t = roots[index];
3057 SkScalar xt = conic_eval_numerator(&pts[0].fX, w, t) / conic_eval_denominator(w, t);
3058 if (!SkScalarNearlyEqual(x, xt)) {
3059 continue;
3060 }
3061 SkConic conic(pts, w);
3062 tangents->push_back(conic.evalTangentAt(t));
3063 }
3064}
int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2])
Definition: SkGeometry.cpp:95
static double conic_eval_numerator(const SkScalar src[], SkScalar w, SkScalar t)
Definition: SkPath.cpp:2807
static double conic_eval_denominator(SkScalar w, SkScalar t)
Definition: SkPath.cpp:2818
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 3011 of file SkPath.cpp.

3012 {
3013 if (!between(pts[0].fY, y, pts[1].fY) && !between(pts[1].fY, y, pts[2].fY)
3014 && !between(pts[2].fY, y, pts[3].fY)) {
3015 return;
3016 }
3017 if (!between(pts[0].fX, x, pts[1].fX) && !between(pts[1].fX, x, pts[2].fX)
3018 && !between(pts[2].fX, x, pts[3].fX)) {
3019 return;
3020 }
3021 SkPoint dst[10];
3022 int n = SkChopCubicAtYExtrema(pts, dst);
3023 for (int i = 0; i <= n; ++i) {
3024 SkPoint* c = &dst[i * 3];
3025 SkScalar t;
3026 if (!SkCubicClipper::ChopMonoAtY(c, y, &t)) {
3027 continue;
3028 }
3029 SkScalar xt = eval_cubic_pts(c[0].fX, c[1].fX, c[2].fX, c[3].fX, t);
3030 if (!SkScalarNearlyEqual(x, xt)) {
3031 continue;
3032 }
3033 SkVector tangent;
3034 SkEvalCubicAt(c, t, nullptr, &tangent, nullptr);
3035 tangents->push_back(tangent);
3036 }
3037}
int SkChopCubicAtYExtrema(const SkPoint src[4], SkPoint dst[10])
Definition: SkGeometry.cpp:698
static SkScalar eval_cubic_pts(SkScalar c0, SkScalar c1, SkScalar c2, SkScalar c3, SkScalar t)
Definition: SkPath.cpp:2722
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 3092 of file SkPath.cpp.

3093 {
3094 SkScalar y0 = pts[0].fY;
3095 SkScalar y1 = pts[1].fY;
3096 if (!between(y0, y, y1)) {
3097 return;
3098 }
3099 SkScalar x0 = pts[0].fX;
3100 SkScalar x1 = pts[1].fX;
3101 if (!between(x0, x, x1)) {
3102 return;
3103 }
3104 SkScalar dx = x1 - x0;
3105 SkScalar dy = y1 - y0;
3106 if (!SkScalarNearlyEqual((x - x0) * dy, dx * (y - y0))) {
3107 return;
3108 }
3109 SkVector v;
3110 v.set(dx, dy);
3111 tangents->push_back(v);
3112}

◆ tangent_quad()

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

Definition at line 3066 of file SkPath.cpp.

3067 {
3068 if (!between(pts[0].fY, y, pts[1].fY) && !between(pts[1].fY, y, pts[2].fY)) {
3069 return;
3070 }
3071 if (!between(pts[0].fX, x, pts[1].fX) && !between(pts[1].fX, x, pts[2].fX)) {
3072 return;
3073 }
3074 SkScalar roots[2];
3075 int n = SkFindUnitQuadRoots(pts[0].fY - 2 * pts[1].fY + pts[2].fY,
3076 2 * (pts[1].fY - pts[0].fY),
3077 pts[0].fY - y,
3078 roots);
3079 for (int index = 0; index < n; ++index) {
3080 SkScalar t = roots[index];
3081 SkScalar C = pts[0].fX;
3082 SkScalar A = pts[2].fX - 2 * pts[1].fX + C;
3083 SkScalar B = 2 * (pts[1].fX - C);
3084 SkScalar xt = poly_eval(A, B, C, t);
3085 if (!SkScalarNearlyEqual(x, xt)) {
3086 continue;
3087 }
3088 tangents->push_back(SkEvalQuadTangentAt(pts, t));
3089 }
3090}
SkVector SkEvalQuadTangentAt(const SkPoint src[3], SkScalar t)
Definition: SkGeometry.cpp:148

◆ winding_conic()

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

Definition at line 2887 of file SkPath.cpp.

2888 {
2889 SkConic conic(pts, weight);
2890 SkConic chopped[2];
2891 // If the data points are very large, the conic may not be monotonic but may also
2892 // fail to chop. Then, the chopper does not split the original conic in two.
2893 bool isMono = is_mono_quad(pts[0].fY, pts[1].fY, pts[2].fY) || !conic.chopAtYExtrema(chopped);
2894 int w = winding_mono_conic(isMono ? conic : chopped[0], x, y, onCurveCount);
2895 if (!isMono) {
2896 w += winding_mono_conic(chopped[1], x, y, onCurveCount);
2897 }
2898 return w;
2899}
static int winding_mono_conic(const SkConic &conic, SkScalar x, SkScalar y, int *onCurveCount)
Definition: SkPath.cpp:2825
static bool is_mono_quad(SkScalar y0, SkScalar y1, SkScalar y2)
Definition: SkPath.cpp:2875

◆ winding_cubic()

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

Definition at line 2797 of file SkPath.cpp.

2797 {
2798 SkPoint dst[10];
2799 int n = SkChopCubicAtYExtrema(pts, dst);
2800 int w = 0;
2801 for (int i = 0; i <= n; ++i) {
2802 w += winding_mono_cubic(&dst[i * 3], x, y, onCurveCount);
2803 }
2804 return w;
2805}
static int winding_mono_cubic(const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
Definition: SkPath.cpp:2751

◆ winding_line()

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

Definition at line 2971 of file SkPath.cpp.

2971 {
2972 SkScalar x0 = pts[0].fX;
2973 SkScalar y0 = pts[0].fY;
2974 SkScalar x1 = pts[1].fX;
2975 SkScalar y1 = pts[1].fY;
2976
2977 SkScalar dy = y1 - y0;
2978
2979 int dir = 1;
2980 if (y0 > y1) {
2981 using std::swap;
2982 swap(y0, y1);
2983 dir = -1;
2984 }
2985 if (y < y0 || y > y1) {
2986 return 0;
2987 }
2988 if (checkOnCurve(x, y, pts[0], pts[1])) {
2989 *onCurveCount += 1;
2990 return 0;
2991 }
2992 if (y == y1) {
2993 return 0;
2994 }
2995 SkScalar cross = (x1 - x0) * (y - pts[0].fY) - dy * (x - x0);
2996
2997 if (!cross) {
2998 // zero cross means the point is on the line, and since the case where
2999 // y of the query point is at the end point is handled above, we can be
3000 // sure that we're on the line (excluding the end point) here
3001 if (x != x1 || y != pts[1].fY) {
3002 *onCurveCount += 1;
3003 }
3004 dir = 0;
3005 } else if (SkScalarSignAsInt(cross) == dir) {
3006 dir = 0;
3007 }
3008 return dir;
3009}
static bool checkOnCurve(SkScalar x, SkScalar y, const SkPoint &start, const SkPoint &end)
Definition: SkPath.cpp:2743
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 2825 of file SkPath.cpp.

2825 {
2826 const SkPoint* pts = conic.fPts;
2827 SkScalar y0 = pts[0].fY;
2828 SkScalar y2 = pts[2].fY;
2829
2830 int dir = 1;
2831 if (y0 > y2) {
2832 using std::swap;
2833 swap(y0, y2);
2834 dir = -1;
2835 }
2836 if (y < y0 || y > y2) {
2837 return 0;
2838 }
2839 if (checkOnCurve(x, y, pts[0], pts[2])) {
2840 *onCurveCount += 1;
2841 return 0;
2842 }
2843 if (y == y2) {
2844 return 0;
2845 }
2846
2847 SkScalar roots[2];
2848 SkScalar A = pts[2].fY;
2849 SkScalar B = pts[1].fY * conic.fW - y * conic.fW + y;
2850 SkScalar C = pts[0].fY;
2851 A += C - 2 * B; // A = a + c - 2*(b*w - yCept*w + yCept)
2852 B -= C; // B = b*w - w * yCept + yCept - a
2853 C -= y;
2854 int n = SkFindUnitQuadRoots(A, 2 * B, C, roots);
2855 SkASSERT(n <= 1);
2856 SkScalar xt;
2857 if (0 == n) {
2858 // zero roots are returned only when y0 == y
2859 // Need [0] if dir == 1
2860 // and [2] if dir == -1
2861 xt = pts[1 - dir].fX;
2862 } else {
2863 SkScalar t = roots[0];
2864 xt = conic_eval_numerator(&pts[0].fX, conic.fW, t) / conic_eval_denominator(conic.fW, t);
2865 }
2866 if (SkScalarNearlyEqual(xt, x)) {
2867 if (x != pts[2].fX || y != pts[2].fY) { // don't test end points; they're start points
2868 *onCurveCount += 1;
2869 return 0;
2870 }
2871 }
2872 return xt < x ? dir : 0;
2873}

◆ winding_mono_cubic()

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

Definition at line 2751 of file SkPath.cpp.

2751 {
2752 SkScalar y0 = pts[0].fY;
2753 SkScalar y3 = pts[3].fY;
2754
2755 int dir = 1;
2756 if (y0 > y3) {
2757 using std::swap;
2758 swap(y0, y3);
2759 dir = -1;
2760 }
2761 if (y < y0 || y > y3) {
2762 return 0;
2763 }
2764 if (checkOnCurve(x, y, pts[0], pts[3])) {
2765 *onCurveCount += 1;
2766 return 0;
2767 }
2768 if (y == y3) {
2769 return 0;
2770 }
2771
2772 // quickreject or quickaccept
2773 SkScalar min, max;
2774 find_minmax<4>(pts, &min, &max);
2775 if (x < min) {
2776 return 0;
2777 }
2778 if (x > max) {
2779 return dir;
2780 }
2781
2782 // compute the actual x(t) value
2783 SkScalar t;
2784 if (!SkCubicClipper::ChopMonoAtY(pts, y, &t)) {
2785 return 0;
2786 }
2787 SkScalar xt = eval_cubic_pts(pts[0].fX, pts[1].fX, pts[2].fX, pts[3].fX, t);
2788 if (SkScalarNearlyEqual(xt, x)) {
2789 if (x != pts[3].fX || y != pts[3].fY) { // don't test end points; they're start points
2790 *onCurveCount += 1;
2791 return 0;
2792 }
2793 }
2794 return xt < x ? dir : 0;
2795}

◆ winding_mono_quad()

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

Definition at line 2901 of file SkPath.cpp.

2901 {
2902 SkScalar y0 = pts[0].fY;
2903 SkScalar y2 = pts[2].fY;
2904
2905 int dir = 1;
2906 if (y0 > y2) {
2907 using std::swap;
2908 swap(y0, y2);
2909 dir = -1;
2910 }
2911 if (y < y0 || y > y2) {
2912 return 0;
2913 }
2914 if (checkOnCurve(x, y, pts[0], pts[2])) {
2915 *onCurveCount += 1;
2916 return 0;
2917 }
2918 if (y == y2) {
2919 return 0;
2920 }
2921 // bounds check on X (not required. is it faster?)
2922#if 0
2923 if (pts[0].fX > x && pts[1].fX > x && pts[2].fX > x) {
2924 return 0;
2925 }
2926#endif
2927
2928 SkScalar roots[2];
2929 int n = SkFindUnitQuadRoots(pts[0].fY - 2 * pts[1].fY + pts[2].fY,
2930 2 * (pts[1].fY - pts[0].fY),
2931 pts[0].fY - y,
2932 roots);
2933 SkASSERT(n <= 1);
2934 SkScalar xt;
2935 if (0 == n) {
2936 // zero roots are returned only when y0 == y
2937 // Need [0] if dir == 1
2938 // and [2] if dir == -1
2939 xt = pts[1 - dir].fX;
2940 } else {
2941 SkScalar t = roots[0];
2942 SkScalar C = pts[0].fX;
2943 SkScalar A = pts[2].fX - 2 * pts[1].fX + C;
2944 SkScalar B = 2 * (pts[1].fX - C);
2945 xt = poly_eval(A, B, C, t);
2946 }
2947 if (SkScalarNearlyEqual(xt, x)) {
2948 if (x != pts[2].fX || y != pts[2].fY) { // don't test end points; they're start points
2949 *onCurveCount += 1;
2950 return 0;
2951 }
2952 }
2953 return xt < x ? dir : 0;
2954}

◆ winding_quad()

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

Definition at line 2956 of file SkPath.cpp.

2956 {
2957 SkPoint dst[5];
2958 int n = 0;
2959
2960 if (!is_mono_quad(pts[0].fY, pts[1].fY, pts[2].fY)) {
2961 n = SkChopQuadAtYExtrema(pts, dst);
2962 pts = dst;
2963 }
2964 int w = winding_mono_quad(pts, x, y, onCurveCount);
2965 if (n > 0) {
2966 w += winding_mono_quad(&pts[2], x, y, onCurveCount);
2967 }
2968 return w;
2969}
int SkChopQuadAtYExtrema(const SkPoint src[3], SkPoint dst[5])
Definition: SkGeometry.cpp:279
static int winding_mono_quad(const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
Definition: SkPath.cpp:2901