Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | List of all members
SkConic Struct Reference

#include <SkGeometry.h>

Public Types

enum  { kMaxConicsForArc = 5 }
 

Public Member Functions

 SkConic ()
 
 SkConic (const SkPoint &p0, const SkPoint &p1, const SkPoint &p2, SkScalar w)
 
 SkConic (const SkPoint pts[3], SkScalar w)
 
void set (const SkPoint pts[3], SkScalar w)
 
void set (const SkPoint &p0, const SkPoint &p1, const SkPoint &p2, SkScalar w)
 
void setW (SkScalar w)
 
void evalAt (SkScalar t, SkPoint *pos, SkVector *tangent=nullptr) const
 
bool chopAt (SkScalar t, SkConic dst[2]) const
 
void chopAt (SkScalar t1, SkScalar t2, SkConic *dst) const
 
void chop (SkConic dst[2]) const
 
SkPoint evalAt (SkScalar t) const
 
SkVector evalTangentAt (SkScalar t) const
 
void computeAsQuadError (SkVector *err) const
 
bool asQuadTol (SkScalar tol) const
 
int SK_SPI computeQuadPOW2 (SkScalar tol) const
 
int SK_SPI chopIntoQuadsPOW2 (SkPoint pts[], int pow2) const
 
float findMidTangent () const
 
bool findXExtrema (SkScalar *t) const
 
bool findYExtrema (SkScalar *t) const
 
bool chopAtXExtrema (SkConic dst[2]) const
 
bool chopAtYExtrema (SkConic dst[2]) const
 
void computeTightBounds (SkRect *bounds) const
 
void computeFastBounds (SkRect *bounds) const
 

Static Public Member Functions

static SkScalar TransformW (const SkPoint[3], SkScalar w, const SkMatrix &)
 
static int BuildUnitArc (const SkVector &start, const SkVector &stop, SkRotationDirection, const SkMatrix *, SkConic conics[kMaxConicsForArc])
 

Public Attributes

SkPoint fPts [3]
 
SkScalar fW
 

Detailed Description

Definition at line 326 of file SkGeometry.h.

Member Enumeration Documentation

◆ anonymous enum

anonymous enum
Enumerator
kMaxConicsForArc 

Definition at line 410 of file SkGeometry.h.

410 {
412 };
@ kMaxConicsForArc
Definition SkGeometry.h:411

Constructor & Destructor Documentation

◆ SkConic() [1/3]

SkConic::SkConic ( )
inline

Definition at line 327 of file SkGeometry.h.

327{}

◆ SkConic() [2/3]

SkConic::SkConic ( const SkPoint p0,
const SkPoint p1,
const SkPoint p2,
SkScalar  w 
)
inline

Definition at line 328 of file SkGeometry.h.

328 {
329 this->set(p0, p1, p2, w);
330 }
SkScalar w
void set(const SkPoint pts[3], SkScalar w)
Definition SkGeometry.h:339

◆ SkConic() [3/3]

SkConic::SkConic ( const SkPoint  pts[3],
SkScalar  w 
)
inline

Definition at line 332 of file SkGeometry.h.

332 {
333 this->set(pts, w);
334 }

Member Function Documentation

◆ asQuadTol()

bool SkConic::asQuadTol ( SkScalar  tol) const

Definition at line 1480 of file SkGeometry.cpp.

1480 {
1482 return (x * x + y * y) <= tol * tol;
1483}
#define AS_QUAD_ERROR_SETUP
double y
double x

◆ BuildUnitArc()

int SkConic::BuildUnitArc ( const SkVector start,
const SkVector stop,
SkRotationDirection  dir,
const SkMatrix userMatrix,
SkConic  conics[kMaxConicsForArc] 
)
static

Definition at line 1729 of file SkGeometry.cpp.

1730 {
1731 // rotate by x,y so that uStart is (1.0)
1732 SkScalar x = SkPoint::DotProduct(uStart, uStop);
1733 SkScalar y = SkPoint::CrossProduct(uStart, uStop);
1734
1735 SkScalar absY = SkScalarAbs(y);
1736
1737 // check for (effectively) coincident vectors
1738 // this can happen if our angle is nearly 0 or nearly 180 (y == 0)
1739 // ... we use the dot-prod to distinguish between 0 and 180 (x > 0)
1740 if (absY <= SK_ScalarNearlyZero && x > 0 && ((y >= 0 && kCW_SkRotationDirection == dir) ||
1741 (y <= 0 && kCCW_SkRotationDirection == dir))) {
1742 return 0;
1743 }
1744
1745 if (dir == kCCW_SkRotationDirection) {
1746 y = -y;
1747 }
1748
1749 // We decide to use 1-conic per quadrant of a circle. What quadrant does [xy] lie in?
1750 // 0 == [0 .. 90)
1751 // 1 == [90 ..180)
1752 // 2 == [180..270)
1753 // 3 == [270..360)
1754 //
1755 int quadrant = 0;
1756 if (0 == y) {
1757 quadrant = 2; // 180
1759 } else if (0 == x) {
1761 quadrant = y > 0 ? 1 : 3; // 90 : 270
1762 } else {
1763 if (y < 0) {
1764 quadrant += 2;
1765 }
1766 if ((x < 0) != (y < 0)) {
1767 quadrant += 1;
1768 }
1769 }
1770
1771 const SkPoint quadrantPts[] = {
1772 { 1, 0 }, { 1, 1 }, { 0, 1 }, { -1, 1 }, { -1, 0 }, { -1, -1 }, { 0, -1 }, { 1, -1 }
1773 };
1774 const SkScalar quadrantWeight = SK_ScalarRoot2Over2;
1775
1776 int conicCount = quadrant;
1777 for (int i = 0; i < conicCount; ++i) {
1778 dst[i].set(&quadrantPts[i * 2], quadrantWeight);
1779 }
1780
1781 // Now compute any remaing (sub-90-degree) arc for the last conic
1782 const SkPoint finalP = { x, y };
1783 const SkPoint& lastQ = quadrantPts[quadrant * 2]; // will already be a unit-vector
1784 const SkScalar dot = SkVector::DotProduct(lastQ, finalP);
1785 if (SkIsNaN(dot)) {
1786 return 0;
1787 }
1788 SkASSERT(0 <= dot && dot <= SK_Scalar1 + SK_ScalarNearlyZero);
1789
1790 if (dot < 1) {
1791 SkVector offCurve = { lastQ.x() + x, lastQ.y() + y };
1792 // compute the bisector vector, and then rescale to be the off-curve point.
1793 // we compute its length from cos(theta/2) = length / 1, using half-angle identity we get
1794 // length = sqrt(2 / (1 + cos(theta)). We already have cos() when to computed the dot.
1795 // This is nice, since our computed weight is cos(theta/2) as well!
1796 //
1797 const SkScalar cosThetaOver2 = SkScalarSqrt((1 + dot) / 2);
1798 offCurve.setLength(SkScalarInvert(cosThetaOver2));
1799 if (!SkPointPriv::EqualsWithinTolerance(lastQ, offCurve)) {
1800 dst[conicCount].set(lastQ, offCurve, finalP, cosThetaOver2);
1801 conicCount += 1;
1802 }
1803 }
1804
1805 // now handle counter-clockwise and the initial unitStart rotation
1807 matrix.setSinCos(uStart.fY, uStart.fX);
1808 if (dir == kCCW_SkRotationDirection) {
1809 matrix.preScale(SK_Scalar1, -SK_Scalar1);
1810 }
1811 if (userMatrix) {
1812 matrix.postConcat(*userMatrix);
1813 }
1814 for (int i = 0; i < conicCount; ++i) {
1815 matrix.mapPoints(dst[i].fPts, 3);
1816 }
1817 return conicCount;
1818}
#define SkASSERT(cond)
Definition SkAssert.h:116
static bool SkIsNaN(T x)
@ kCW_SkRotationDirection
Definition SkGeometry.h:322
@ kCCW_SkRotationDirection
Definition SkGeometry.h:323
#define SkScalarInvert(x)
Definition SkScalar.h:73
#define SK_Scalar1
Definition SkScalar.h:18
#define SK_ScalarNearlyZero
Definition SkScalar.h:99
#define SkScalarSqrt(x)
Definition SkScalar.h:42
#define SK_ScalarRoot2Over2
Definition SkScalar.h:23
#define SkScalarAbs(x)
Definition SkScalar.h:39
static bool EqualsWithinTolerance(const SkPoint &p1, const SkPoint &p2)
Definition SkPointPriv.h:54
float SkScalar
Definition extension.cpp:12
unsigned useCenter Optional< SkMatrix > matrix
Definition SkRecords.h:258
dst
Definition cp.py:12
SINT T dot(const Vec< N, T > &a, const Vec< N, T > &b)
Definition SkVx.h:964
SkPoint fPts[3]
Definition SkGeometry.h:336
static float CrossProduct(const SkVector &a, const SkVector &b)
bool setLength(float length)
Definition SkPoint.cpp:30
static float DotProduct(const SkVector &a, const SkVector &b)
constexpr float y() const
constexpr float x() const

◆ chop()

void SkConic::chop ( SkConic  dst[2]) const

Definition at line 1430 of file SkGeometry.cpp.

1430 {
1431
1432 // Observe that scale will always be smaller than 1 because fW > 0.
1433 const float scale = SkScalarInvert(SK_Scalar1 + fW);
1434
1435 // The subdivided control points below are the sums of the following three terms. Because the
1436 // terms are multiplied by something <1, and the resulting control points lie within the
1437 // control points of the original then the terms and the sums below will not overflow. Note
1438 // that fW * scale approaches 1 as fW becomes very large.
1439 float2 t0 = from_point(fPts[0]) * scale;
1440 float2 t1 = from_point(fPts[1]) * (fW * scale);
1441 float2 t2 = from_point(fPts[2]) * scale;
1442
1443 // Calculate the subdivided control points
1444 const SkPoint p1 = to_point(t0 + t1);
1445 const SkPoint p3 = to_point(t1 + t2);
1446
1447 // p2 = (t0 + 2*t1 + t2) / 2. Divide the terms by 2 before the sum to keep the sum for p2
1448 // from overflowing.
1449 const SkPoint p2 = to_point(0.5f * t0 + t1 + 0.5f * t2);
1450
1451 SkASSERT(p1.isFinite() && p2.isFinite() && p3.isFinite());
1452
1453 dst[0].fPts[0] = fPts[0];
1454 dst[0].fPts[1] = p1;
1455 dst[0].fPts[2] = p2;
1456 dst[1].fPts[0] = p2;
1457 dst[1].fPts[1] = p3;
1458 dst[1].fPts[2] = fPts[2];
1459
1460 // Update w.
1461 dst[0].fW = dst[1].fW = subdivide_w_value(fW);
1462}
static SkScalar subdivide_w_value(SkScalar w)
static skvx::float2 from_point(const SkPoint &point)
Definition SkGeometry.h:22
static SkPoint to_point(const skvx::float2 &x)
Definition SkGeometry.h:26
const Scalar scale
SkScalar fW
Definition SkGeometry.h:337
bool isFinite() const

◆ chopAt() [1/2]

bool SkConic::chopAt ( SkScalar  t,
SkConic  dst[2] 
) const

Definition at line 1297 of file SkGeometry.cpp.

1297 {
1298 SkPoint3 tmp[3], tmp2[3];
1299
1300 ratquad_mapTo3D(fPts, fW, tmp);
1301
1302 p3d_interp(&tmp[0].fX, &tmp2[0].fX, t);
1303 p3d_interp(&tmp[0].fY, &tmp2[0].fY, t);
1304 p3d_interp(&tmp[0].fZ, &tmp2[0].fZ, t);
1305
1306 dst[0].fPts[0] = fPts[0];
1307 dst[0].fPts[1] = project_down(tmp2[0]);
1308 dst[0].fPts[2] = project_down(tmp2[1]); dst[1].fPts[0] = dst[0].fPts[2];
1309 dst[1].fPts[1] = project_down(tmp2[2]);
1310 dst[1].fPts[2] = fPts[2];
1311
1312 // to put in "standard form", where w0 and w2 are both 1, we compute the
1313 // new w1 as sqrt(w1*w1/w0*w2)
1314 // or
1315 // w1 /= sqrt(w0*w2)
1316 //
1317 // However, in our case, we know that for dst[0]:
1318 // w0 == 1, and for dst[1], w2 == 1
1319 //
1320 SkScalar root = SkScalarSqrt(tmp2[1].fZ);
1321 dst[0].fW = tmp2[0].fZ / root;
1322 dst[1].fW = tmp2[2].fZ / root;
1323 SkASSERT(sizeof(dst[0]) == sizeof(SkScalar) * 7);
1324 SkASSERT(0 == offsetof(SkConic, fPts[0].fX));
1325 return SkIsFinite(&dst[0].fPts[0].fX, 7 * 2);
1326}
static bool SkIsFinite(T x, Pack... values)
static SkPoint project_down(const SkPoint3 &src)
static void ratquad_mapTo3D(const SkPoint src[3], SkScalar w, SkPoint3 dst[3])
static void p3d_interp(const SkScalar src[7], SkScalar dst[7], SkScalar t)
SkScalar fZ
Definition SkPoint3.h:16

◆ chopAt() [2/2]

void SkConic::chopAt ( SkScalar  t1,
SkScalar  t2,
SkConic dst 
) const

Definition at line 1328 of file SkGeometry.cpp.

1328 {
1329 if (0 == t1 || 1 == t2) {
1330 if (0 == t1 && 1 == t2) {
1331 *dst = *this;
1332 return;
1333 } else {
1334 SkConic pair[2];
1335 if (this->chopAt(t1 ? t1 : t2, pair)) {
1336 *dst = pair[SkToBool(t1)];
1337 return;
1338 }
1339 }
1340 }
1341 SkConicCoeff coeff(*this);
1342 float2 tt1(t1);
1343 float2 aXY = coeff.fNumer.eval(tt1);
1344 float2 aZZ = coeff.fDenom.eval(tt1);
1345 float2 midTT((t1 + t2) / 2);
1346 float2 dXY = coeff.fNumer.eval(midTT);
1347 float2 dZZ = coeff.fDenom.eval(midTT);
1348 float2 tt2(t2);
1349 float2 cXY = coeff.fNumer.eval(tt2);
1350 float2 cZZ = coeff.fDenom.eval(tt2);
1351 float2 bXY = times_2(dXY) - (aXY + cXY) * 0.5f;
1352 float2 bZZ = times_2(dZZ) - (aZZ + cZZ) * 0.5f;
1353 dst->fPts[0] = to_point(aXY / aZZ);
1354 dst->fPts[1] = to_point(bXY / bZZ);
1355 dst->fPts[2] = to_point(cXY / cZZ);
1356 float2 ww = bZZ / sqrt(aZZ * cZZ);
1357 dst->fW = ww[0];
1358}
static skvx::float2 times_2(const skvx::float2 &value)
Definition SkGeometry.h:32
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35
SIN Vec< N, float > sqrt(const Vec< N, float > &x)
Definition SkVx.h:706
bool chopAt(SkScalar t, SkConic dst[2]) const

◆ chopAtXExtrema()

bool SkConic::chopAtXExtrema ( SkConic  dst[2]) const

Definition at line 1647 of file SkGeometry.cpp.

1647 {
1648 SkScalar t;
1649 if (this->findXExtrema(&t)) {
1650 if (!this->chopAt(t, dst)) {
1651 // if chop can't return finite values, don't chop
1652 return false;
1653 }
1654 // now clean-up the middle, since we know t was meant to be at
1655 // an X-extrema
1656 SkScalar value = dst[0].fPts[2].fX;
1657 dst[0].fPts[1].fX = value;
1658 dst[1].fPts[0].fX = value;
1659 dst[1].fPts[1].fX = value;
1660 return true;
1661 }
1662 return false;
1663}
uint8_t value
bool findXExtrema(SkScalar *t) const

◆ chopAtYExtrema()

bool SkConic::chopAtYExtrema ( SkConic  dst[2]) const

Definition at line 1665 of file SkGeometry.cpp.

1665 {
1666 SkScalar t;
1667 if (this->findYExtrema(&t)) {
1668 if (!this->chopAt(t, dst)) {
1669 // if chop can't return finite values, don't chop
1670 return false;
1671 }
1672 // now clean-up the middle, since we know t was meant to be at
1673 // an Y-extrema
1674 SkScalar value = dst[0].fPts[2].fY;
1675 dst[0].fPts[1].fY = value;
1676 dst[1].fPts[0].fY = value;
1677 dst[1].fPts[1].fY = value;
1678 return true;
1679 }
1680 return false;
1681}
bool findYExtrema(SkScalar *t) const

◆ chopIntoQuadsPOW2()

int SkConic::chopIntoQuadsPOW2 ( SkPoint  pts[],
int  pow2 
) const

Chop this conic into N quads, stored continguously in pts[], where N = 1 << pow2. The amount of storage needed is (1 + 2 * N)

Definition at line 1570 of file SkGeometry.cpp.

1570 {
1571 SkASSERT(pow2 >= 0);
1572 *pts = fPts[0];
1573 SkDEBUGCODE(SkPoint* endPts);
1574 if (pow2 == kMaxConicToQuadPOW2) { // If an extreme weight generates many quads ...
1575 SkConic dst[2];
1576 this->chop(dst);
1577 // check to see if the first chop generates a pair of lines
1578 if (SkPointPriv::EqualsWithinTolerance(dst[0].fPts[1], dst[0].fPts[2]) &&
1579 SkPointPriv::EqualsWithinTolerance(dst[1].fPts[0], dst[1].fPts[1])) {
1580 pts[1] = pts[2] = pts[3] = dst[0].fPts[1]; // set ctrl == end to make lines
1581 pts[4] = dst[1].fPts[2];
1582 pow2 = 1;
1583 SkDEBUGCODE(endPts = &pts[5]);
1584 goto commonFinitePtCheck;
1585 }
1586 }
1587 SkDEBUGCODE(endPts = ) subdivide(*this, pts + 1, pow2);
1588commonFinitePtCheck:
1589 const int quadCount = 1 << pow2;
1590 const int ptCount = 2 * quadCount + 1;
1591 SkASSERT(endPts - pts == ptCount);
1592 if (!SkPointPriv::AreFinite(pts, ptCount)) {
1593 // if we generated a non-finite, pin ourselves to the middle of the hull,
1594 // as our first and last are already on the first/last pts of the hull.
1595 for (int i = 1; i < ptCount - 1; ++i) {
1596 pts[i] = fPts[1];
1597 }
1598 }
1599 return 1 << pow2;
1600}
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
#define kMaxConicToQuadPOW2
static SkPoint * subdivide(const SkConic &src, SkPoint pts[], int level)
void chop(SkConic dst[2]) const

◆ computeAsQuadError()

void SkConic::computeAsQuadError ( SkVector err) const

Definition at line 1475 of file SkGeometry.cpp.

1475 {
1477 err->set(x, y);
1478}
void set(float x, float y)

◆ computeFastBounds()

void SkConic::computeFastBounds ( SkRect bounds) const

Definition at line 1699 of file SkGeometry.cpp.

1699 {
1700 bounds->setBounds(fPts, 3);
1701}
Optional< SkRect > bounds
Definition SkRecords.h:189

◆ computeQuadPOW2()

int SkConic::computeQuadPOW2 ( SkScalar  tol) const

return the power-of-2 number of quads needed to approximate this conic with a sequence of quads. Will be >= 0.

Definition at line 1488 of file SkGeometry.cpp.

1488 {
1489 if (tol < 0 || !SkIsFinite(tol) || !SkPointPriv::AreFinite(fPts, 3)) {
1490 return 0;
1491 }
1492
1494
1495 SkScalar error = SkScalarSqrt(x * x + y * y);
1496 int pow2;
1497 for (pow2 = 0; pow2 < kMaxConicToQuadPOW2; ++pow2) {
1498 if (error <= tol) {
1499 break;
1500 }
1501 error *= 0.25f;
1502 }
1503 // float version -- using ceil gives the same results as the above.
1504 if ((false)) {
1505 SkScalar err = SkScalarSqrt(x * x + y * y);
1506 if (err <= tol) {
1507 return 0;
1508 }
1509 SkScalar tol2 = tol * tol;
1510 if (tol2 == 0) {
1511 return kMaxConicToQuadPOW2;
1512 }
1513 SkScalar fpow2 = SkScalarLog2((x * x + y * y) / tol2) * 0.25f;
1514 int altPow2 = SkScalarCeilToInt(fpow2);
1515 if (altPow2 != pow2) {
1516 SkDebugf("pow2 %d altPow2 %d fbits %g err %g tol %g\n", pow2, altPow2, fpow2, err, tol);
1517 }
1518 pow2 = altPow2;
1519 }
1520 return pow2;
1521}
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
#define SkScalarCeilToInt(x)
Definition SkScalar.h:36
#define SkScalarLog2(x)
Definition SkScalar.h:53
static bool AreFinite(const SkPoint array[], int count)
Definition SkPointPriv.h:22
const uint8_t uint32_t uint32_t GError ** error

◆ computeTightBounds()

void SkConic::computeTightBounds ( SkRect bounds) const

Definition at line 1683 of file SkGeometry.cpp.

1683 {
1684 SkPoint pts[4];
1685 pts[0] = fPts[0];
1686 pts[1] = fPts[2];
1687 int count = 2;
1688
1689 SkScalar t;
1690 if (this->findXExtrema(&t)) {
1691 this->evalAt(t, &pts[count++]);
1692 }
1693 if (this->findYExtrema(&t)) {
1694 this->evalAt(t, &pts[count++]);
1695 }
1696 bounds->setBounds(pts, count);
1697}
int count
void evalAt(SkScalar t, SkPoint *pos, SkVector *tangent=nullptr) const

◆ evalAt() [1/2]

SkPoint SkConic::evalAt ( SkScalar  t) const

Definition at line 1360 of file SkGeometry.cpp.

1360 {
1361 return to_point(SkConicCoeff(*this).eval(t));
1362}

◆ evalAt() [2/2]

void SkConic::evalAt ( SkScalar  t,
SkPoint pos,
SkVector tangent = nullptr 
) const

Given a t-value [0...1] return its position and/or tangent. If pos is not null, return its position at the t-value. If tangent is not null, return its tangent at the t-value. NOTE the tangent value's length is arbitrary, and only its direction should be used.

Definition at line 1386 of file SkGeometry.cpp.

1386 {
1387 SkASSERT(t >= 0 && t <= SK_Scalar1);
1388
1389 if (pt) {
1390 *pt = this->evalAt(t);
1391 }
1392 if (tangent) {
1393 *tangent = this->evalTangentAt(t);
1394 }
1395}
SkVector evalTangentAt(SkScalar t) const

◆ evalTangentAt()

SkVector SkConic::evalTangentAt ( SkScalar  t) const

Definition at line 1364 of file SkGeometry.cpp.

1364 {
1365 // The derivative equation returns a zero tangent vector when t is 0 or 1,
1366 // and the control point is equal to the end point.
1367 // In this case, use the conic endpoints to compute the tangent.
1368 if ((t == 0 && fPts[0] == fPts[1]) || (t == 1 && fPts[1] == fPts[2])) {
1369 return fPts[2] - fPts[0];
1370 }
1371 float2 p0 = from_point(fPts[0]);
1372 float2 p1 = from_point(fPts[1]);
1373 float2 p2 = from_point(fPts[2]);
1374 float2 ww(fW);
1375
1376 float2 p20 = p2 - p0;
1377 float2 p10 = p1 - p0;
1378
1379 float2 C = ww * p10;
1380 float2 A = ww * p20 - p20;
1381 float2 B = p20 - C - C;
1382
1383 return to_vector(SkQuadCoeff(A, B, C).eval(t));
1384}
#define C(TEST_CATEGORY)
Definition colrv1.cpp:247

◆ findMidTangent()

float SkConic::findMidTangent ( ) const

Definition at line 1602 of file SkGeometry.cpp.

1602 {
1603 // Tangents point in the direction of increasing T, so tan0 and -tan1 both point toward the
1604 // midtangent. The bisector of tan0 and -tan1 is orthogonal to the midtangent:
1605 //
1606 // bisector dot midtangent = 0
1607 //
1608 SkVector tan0 = fPts[1] - fPts[0];
1609 SkVector tan1 = fPts[2] - fPts[1];
1610 SkVector bisector = SkFindBisector(tan0, -tan1);
1611
1612 // Start by finding the tangent function's power basis coefficients. These define a tangent
1613 // direction (scaled by some uniform value) as:
1614 // |T^2|
1615 // Tangent_Direction(T) = dx,dy = |A B C| * |T |
1616 // |. . .| |1 |
1617 //
1618 // The derivative of a conic has a cumbersome order-4 denominator. However, this isn't necessary
1619 // if we are only interested in a vector in the same *direction* as a given tangent line. Since
1620 // the denominator scales dx and dy uniformly, we can throw it out completely after evaluating
1621 // the derivative with the standard quotient rule. This leaves us with a simpler quadratic
1622 // function that we use to find a tangent.
1623 SkVector A = (fPts[2] - fPts[0]) * (fW - 1);
1624 SkVector B = (fPts[2] - fPts[0]) - (fPts[1] - fPts[0]) * (fW*2);
1625 SkVector C = (fPts[1] - fPts[0]) * fW;
1626
1627 // Now solve for "bisector dot midtangent = 0":
1628 //
1629 // |T^2|
1630 // bisector * |A B C| * |T | = 0
1631 // |. . .| |1 |
1632 //
1633 float a = bisector.dot(A);
1634 float b = bisector.dot(B);
1635 float c = bisector.dot(C);
1637}
static float solve_quadratic_equation_for_midtangent(float a, float b, float c, float discr)
SkVector SkFindBisector(SkVector, SkVector)
static bool b
struct MyStruct a[10]
float dot(const SkVector &vec) const

◆ findXExtrema()

bool SkConic::findXExtrema ( SkScalar t) const

Definition at line 1639 of file SkGeometry.cpp.

1639 {
1640 return conic_find_extrema(&fPts[0].fX, fW, t);
1641}
static bool conic_find_extrema(const SkScalar src[], SkScalar w, SkScalar *t)

◆ findYExtrema()

bool SkConic::findYExtrema ( SkScalar t) const

Definition at line 1643 of file SkGeometry.cpp.

1643 {
1644 return conic_find_extrema(&fPts[0].fY, fW, t);
1645}

◆ set() [1/2]

void SkConic::set ( const SkPoint p0,
const SkPoint p1,
const SkPoint p2,
SkScalar  w 
)
inline

Definition at line 344 of file SkGeometry.h.

344 {
345 fPts[0] = p0;
346 fPts[1] = p1;
347 fPts[2] = p2;
348 this->setW(w);
349 }
void setW(SkScalar w)
Definition SkGeometry.h:351

◆ set() [2/2]

void SkConic::set ( const SkPoint  pts[3],
SkScalar  w 
)
inline

Definition at line 339 of file SkGeometry.h.

339 {
340 memcpy(fPts, pts, 3 * sizeof(SkPoint));
341 this->setW(w);
342 }

◆ setW()

void SkConic::setW ( SkScalar  w)
inline

Definition at line 351 of file SkGeometry.h.

351 {
352 if (SkIsFinite(w)) {
353 SkASSERT(w > 0);
354 }
355
356 // Guard against bad weights by forcing them to 1.
357 fW = w > 0 && SkIsFinite(w) ? w : 1;
358 }

◆ TransformW()

SkScalar SkConic::TransformW ( const SkPoint  pts[3],
SkScalar  w,
const SkMatrix matrix 
)
static

Find the parameter value where the conic takes on its maximum curvature.

Parameters
toutput scalar for max curvature. Will be unchanged if max curvature outside 0..1 range.
Returns
true if max curvature found inside 0..1 range, false otherwise

Definition at line 1710 of file SkGeometry.cpp.

1710 {
1711 if (!matrix.hasPerspective()) {
1712 return w;
1713 }
1714
1715 SkPoint3 src[3], dst[3];
1716
1717 ratquad_mapTo3D(pts, w, src);
1718
1719 matrix.mapHomogeneousPoints(dst, src, 3);
1720
1721 // w' = sqrt(w1*w1/w0*w2)
1722 // use doubles temporarily, to handle small numer/denom
1723 double w0 = dst[0].fZ;
1724 double w1 = dst[1].fZ;
1725 double w2 = dst[2].fZ;
1726 return sk_double_to_float(sqrt(sk_ieee_double_divide(w1 * w1, w0 * w2)));
1727}
static constexpr float sk_double_to_float(double x)
static constexpr double sk_ieee_double_divide(double numer, double denom)

Member Data Documentation

◆ fPts

SkPoint SkConic::fPts[3]

Definition at line 336 of file SkGeometry.h.

◆ fW

SkScalar SkConic::fW

Definition at line 337 of file SkGeometry.h.


The documentation for this struct was generated from the following files: