21#if !defined(SK_ENABLE_OPTIMIZE_SIZE)
29 double distanceSquared(DPoint p)
const {
30 double dx = fX -
p.fX;
31 double dy = fY -
p.fY;
35 double distance(DPoint p)
const {
return sqrt(this->distanceSquared(p)); }
94 double m21,
double m22,
double m23) {
106 fMat[0] = fMat[4] = 1.0;
108 fMat[2] = fMat[5] = 0.0;
115 DPoint pt = {src.fX, src.fY};
120 return { fMat[0] * src.fX + fMat[1] * src.fY + fMat[2],
121 fMat[3] * src.fX + fMat[4] * src.fY + fMat[5] };
137 double tolerance = 0.0,
138 bool xformToleranceToX =
false) {
140 double tolB = tolerance;
141 double tolC = tolerance;
143 if (xformToleranceToX) {
151 tolB = tolerance / sqrt(4.0 *
b *
b + 1.0);
152 tolC = tolerance / sqrt(4.0 * c * c + 1.0);
154 return b < c ? (
a >=
b - tolB &&
a < c - tolC) :
155 (
a >= c - tolC &&
a <
b - tolB);
160 double tolerance = 0.0,
161 bool xformToleranceToX =
false) {
163 double tolB = tolerance;
164 double tolC = tolerance;
166 if (xformToleranceToX) {
167 tolB = tolerance / sqrt(4.0 *
b *
b + 1.0);
168 tolC = tolerance / sqrt(4.0 * c * c + 1.0);
170 return b < c ? (
a >=
b - tolB &&
a <= c + tolC) :
171 (
a >= c - tolC &&
a <=
b + tolB);
176 return fabs(
x) <= tolerance;
181 bool xformToleranceToX =
false) {
183 if (xformToleranceToX) {
184 tolerance = tolerance / sqrt(4.0 *
y *
y + 1.0);
186 return fabs(
x -
y) <= tolerance;
189static inline double sign_of(
const double &val) {
190 return std::copysign(1, val);
194 return nearly_zero((pts[1].fY - pts[0].fY) * (pts[1].fX - pts[2].fX) -
195 (pts[1].fY - pts[2].fY) * (pts[1].fX - pts[0].fX),
kCloseSqd);
235 const double p0x = p0.fX;
236 const double p0y = p0.fY;
237 const double p2x = p2.fX;
238 const double p2y = p2.fY;
244 double hypotenuse = p0.distance(p2);
245 if (
SkTAbs(hypotenuse) < 1.0e-100) {
248 const double cosTheta = (p2x - p0x) / hypotenuse;
249 const double sinTheta = (p2y - p0y) / hypotenuse;
253 cosTheta, sinTheta, -(cosTheta * p0x) - (sinTheta * p0y),
254 -sinTheta, cosTheta, (sinTheta * p0x) - (cosTheta * p0y)
264 const double p1x =
fPts[1].
fX;
265 const double p1y =
fPts[1].
fY;
267 const double p0xSqd = p0x * p0x;
268 const double p0ySqd = p0y * p0y;
269 const double p2xSqd = p2x * p2x;
270 const double p2ySqd = p2y * p2y;
271 const double p1xSqd = p1x * p1x;
272 const double p1ySqd = p1y * p1y;
274 const double p01xProd = p0x * p1x;
275 const double p02xProd = p0x * p2x;
276 const double b12xProd = p1x * p2x;
277 const double p01yProd = p0y * p1y;
278 const double p02yProd = p0y * p2y;
279 const double b12yProd = p1y * p2y;
282 const double sqrtA = p0y - (2.0 * p1y) + p2y;
283 const double a = sqrtA * sqrtA;
284 const double h = -1.0 * (p0y - (2.0 * p1y) + p2y) * (p0x - (2.0 * p1x) + p2x);
285 const double sqrtB = p0x - (2.0 * p1x) + p2x;
286 const double b = sqrtB * sqrtB;
287 const double c = (p0xSqd * p2ySqd) - (4.0 * p01xProd * b12yProd)
288 - (2.0 * p02xProd * p02yProd) + (4.0 * p02xProd * p1ySqd)
289 + (4.0 * p1xSqd * p02yProd) - (4.0 * b12xProd * p01yProd)
291 const double g = (p0x * p02yProd) - (2.0 * p0x * p1ySqd)
292 + (2.0 * p0x * b12yProd) - (p0x * p2ySqd)
293 + (2.0 * p1x * p01yProd) - (4.0 * p1x * p02yProd)
294 + (2.0 * p1x * b12yProd) - (p2x * p0ySqd)
295 + (2.0 * p2x * p01yProd) + (p2x * p02yProd)
296 - (2.0 * p2x * p1ySqd);
297 const double f = -((p0xSqd * p2y) - (2.0 * p01xProd * p1y)
298 - (2.0 * p01xProd * p2y) - (p02xProd * p0y)
299 + (4.0 * p02xProd * p1y) - (p02xProd * p2y)
300 + (2.0 * p1xSqd * p0y) + (2.0 * p1xSqd * p2y)
301 - (2.0 * b12xProd * p0y) - (2.0 * b12xProd * p1y)
304 const double cosTheta = sqrt(
a / (
a +
b));
305 const double sinTheta = -1.0 *
sign_of((
a +
b) *
h) * sqrt(
b / (
a +
b));
307 const double gDef = cosTheta * g - sinTheta * f;
308 const double fDef = sinTheta * g + cosTheta * f;
311 const double x0 = gDef / (
a +
b);
312 const double y0 = (1.0 / (2.0 * fDef)) * (c - (gDef * gDef / (
a +
b)));
315 const double lambda = -1.0 * ((
a +
b) / (2.0 * fDef));
319 const double lambda_cosTheta = lambda * cosTheta;
320 const double lambda_sinTheta = lambda * sinTheta;
324 lambda_cosTheta, -lambda_sinTheta, lambda * x0,
325 lambda_sinTheta, lambda_cosTheta, lambda * y0
339 for (
int i = 0; i < size; ++i) {
350 segments->
back().fPts[0] = pts[0];
351 segments->
back().fPts[1] = pts[1];
353 segments->
back().init();
360 if (pts[0] != pts[2]) {
362 line_pts[0] = pts[0];
363 line_pts[1] = pts[2];
369 segments->
back().fPts[0] = pts[0];
370 segments->
back().fPts[1] = pts[1];
371 segments->
back().fPts[2] = pts[2];
373 segments->
back().init();
382 for (
int q = 0; q <
count; q += 3) {
389 const DPoint &xFormPt) {
390 static const float kThird = 0.33333333333f;
391 static const float kTwentySeventh = 0.037037037f;
393 const float a = 0.5f - (float)xFormPt.fY;
394 const float b = -0.5f * (float)xFormPt.fX;
396 const float a3 =
a *
a *
a;
397 const float b2 =
b *
b;
399 const float c = (b2 * 0.25f) + (a3 * kTwentySeventh);
402 const float sqrtC = sqrt(c);
403 const float result = (float)cbrt((-
b * 0.5f) + sqrtC) + (
float)cbrt((-
b * 0.5f) - sqrtC);
406 const float cosPhi = (float)sqrt((b2 * 0.25f) * (-27.f / a3)) * ((
b > 0) ? -1.f : 1.f);
407 const float phi = (float)acos(cosPhi);
409 if (xFormPt.fX > 0.f) {
410 result = 2.f * (float)sqrt(-
a * kThird) * (float)cos(phi * kThird);
412 result = 2.f * (float)sqrt(-
a * kThird) * (float)cos((phi * kThird) + (
SK_ScalarPI * 2.f * kThird));
415 result = 2.f * (float)sqrt(-
a * kThird) * (float)cos((phi * kThird) + (
SK_ScalarPI * 2.f * kThird));
417 result = 2.f * (float)sqrt(-
a * kThird) * (float)cos(phi * kThird);
462 const double x1 = xFormPtLeft.fX;
463 const double y1 = xFormPtLeft.fY;
464 const double x2 = xFormPtRight.fX;
465 const double y2 = xFormPtRight.fY;
475 const double m = (y2 - y1) / (x2 - x1);
476 const double b = -m * x1 + y1;
478 const double m2 = m * m;
479 const double c = m2 + 4.0 *
b;
486 (segment.
fPts[0].
fY == pointLeft.
fY ||
487 segment.
fPts[2].
fY == pointLeft.
fY)) &&
492 }
else if (c <= 0.0) {
497 const double d = sqrt(c);
506 const DPoint& xFormPt,
518 bool includeP1 =
true;
519 bool includeP2 =
true;
554 if (segment.
fPts[0].
fY == point.
fY) {
556 }
else if (segment.
fPts[2].
fY == point.
fY) {
577 result = (float)(xformPt.fY * xformPt.fY);
578 }
else if (xformPt.fX < segment.
fP0T.fX) {
579 result = (float)(xformPt.fX * xformPt.fX + xformPt.fY * xformPt.fY);
581 result = (float)((xformPt.fX - segment.
fP2T.fX) * (xformPt.fX - segment.
fP2T.fX)
582 + xformPt.fY * xformPt.fY);
600 DPoint
x = { nearestPoint, nearestPoint * nearestPoint };
601 dist = (float)xformPt.distanceSquared(
x);
603 const float distToB0T = (float)xformPt.distanceSquared(segment.
fP0T);
604 const float distToB2T = (float)xformPt.distanceSquared(segment.
fP2T);
606 if (distToB0T < distToB2T) {
634 int startColumn = (
int)paddedBB.
fLeft;
637 int startRow = (
int)paddedBB.
fTop;
640 SkASSERT((startColumn >= 0) &&
"StartColumn < 0!");
642 SkASSERT((startRow >= 0) &&
"StartRow < 0!");
646 startColumn = std::max(startColumn, 0);
647 endColumn = std::min(endColumn,
width);
648 startRow = std::max(startRow, 0);
649 endRow = std::min(endRow,
height);
652 for (
int row = startRow; row < endRow; ++row) {
654 const float pY = row + 0.5f;
667 for (
int col = startColumn; col < endColumn; ++col) {
668 int idx = (row *
width) + col;
670 const float pX = col + 0.5f;
673 const float distSq = dataPtr[idx].
fDistSq;
676 int dilation = distSq < 1.5f * 1.5f ? 1 :
677 distSq < 2.5f * 2.5f ? 2 :
680 !segBB.
roundOut().makeOutset(dilation, dilation).contains(col, row)) {
685 int deltaWindingScore = 0;
688 deltaWindingScore = -1;
690 deltaWindingScore = 1;
695 if (currDistSq < distSq) {
696 dataPtr[idx].
fDistSq = currDistSq;
705template <
int distanceMagnitude>
710 dist = SkTPin<float>(-dist, -distanceMagnitude, distanceMagnitude * 127.0f / 128.0f);
713 dist += distanceMagnitude;
733 path.transform(dfMatrix, &xformPath);
741 expectPathBounds.
contains(pathBounds));
765 expectPathBounds.
contains(pathBounds));
778 while (
auto e = iter.
next()) {
780 case SkPathEdgeIter::Edge::kLine: {
784 case SkPathEdgeIter::Edge::kQuad:
787 case SkPathEdgeIter::Edge::kConic: {
791 for (
int i = 0; i < converter.countQuads(); ++i) {
796 case SkPathEdgeIter::Edge::kCubic: {
807 for (
int row = 0; row <
height; ++row) {
809 constexpr DFSign kInside = -1;
810 constexpr DFSign kOutside = 1;
812 int windingNumber = 0;
813 for (
int col = 0; col <
width; ++col) {
814 int idx = (row *
width) + col;
820 dfSign = windingNumber ? kInside : kOutside;
823 dfSign = windingNumber ? kOutside : kInside;
826 dfSign = (windingNumber % 2) ? kInside : kOutside;
829 dfSign = (windingNumber % 2) ? kOutside : kInside;
833 const float miniDist = sqrt(dataPtr[idx].fDistSq);
834 const float dist = dfSign * miniDist;
836 unsigned char pixelVal = pack_distance_field_val<SK_DistanceFieldMagnitude>(dist);
838 distanceField[(row * rowBytes) + col] = pixelVal;
842 if (windingNumber != 0) {
843 SkDEBUGFAIL(
"Winding number should be zero at the end of a scan line.");
845 for (
int col = 0; col <
width; ++col) {
846 int idx = (row *
width) + col;
847 DFSign dfSign = workingPath.
contains(col + 0.5, row + 0.5) ? kInside : kOutside;
848 const float miniDist = sqrt(dataPtr[idx].fDistSq);
849 const float dist = dfSign * miniDist;
851 unsigned char pixelVal = pack_distance_field_val<SK_DistanceFieldMagnitude>(dist);
853 distanceField[(row * rowBytes) + col] = pixelVal;
void precomputation_for_row(RowData *rowData, const PathSegment &segment, const SkPoint &pointLeft, const SkPoint &pointRight)
static const double kClose
static bool is_colinear(const SkPoint pts[3])
static void init_distances(DFData *data, int size)
static unsigned char pack_distance_field_val(float dist)
SegSide calculate_side_of_quad(const PathSegment &segment, const SkPoint &point, const DPoint &xFormPt, const RowData &rowData)
static void calculate_distance_field_data(PathSegmentArray *segments, DFData *dataPtr, int width, int height)
static void add_quad(const SkPoint pts[3], PathSegmentArray *segments)
static const float kConicTolerance
static double sign_of(const double &val)
static float distance_to_segment(const SkPoint &point, const PathSegment &segment, const RowData &rowData, SegSide *side)
static float calculate_nearest_point_for_quad(const PathSegment &segment, const DPoint &xFormPt)
static const double kNearlyZero
static const double kTangentTolerance
static bool nearly_zero(double x, double tolerance=kNearlyZero)
static bool between_closed_open(double a, double b, double c, double tolerance=0.0, bool xformToleranceToX=false)
static void add_line(const SkPoint pts[2], PathSegmentArray *segments)
static void add_cubic(const SkPoint pts[4], PathSegmentArray *segments)
static bool between_closed(double a, double b, double c, double tolerance=0.0, bool xformToleranceToX=false)
TArray< PathSegment, true > PathSegmentArray
static bool nearly_equal(double x, double y, double tolerance=kNearlyZero, bool xformToleranceToX=false)
static const double kCloseSqd
bool GrGenerateDistanceFieldFromPath(unsigned char *distanceField, const SkPath &path, const SkMatrix &drawMatrix, int width, int height, size_t rowBytes)
bool IsDistanceFieldSupportedFillType(SkPathFillType fFillType)
#define SkDEBUGFAIL(message)
#define SK_DistanceFieldPad
#define SK_DistanceFieldMagnitude
static int side(double x)
#define SkScalarRoundToInt(x)
#define SkScalarCeilToInt(x)
Type::kYUV Type::kRGBA() int(0.7 *637)
DPoint mapPoint(const DPoint &src) const
DPoint mapPoint(const SkPoint &src) const
void setAffine(double m11, double m12, double m13, double m21, double m22, double m23)
double & operator[](int index)
double operator[](int index) const
const SkPoint & endPt() const
enum PathSegment::@376 fType
double fTangentTolScaledSqd
DAffineMatrix fXformMatrix
SkMatrix & postTranslate(SkScalar dx, SkScalar dy)
SkScalar conicWeight() const
SkPathFillType getFillType() const
const SkRect & getBounds() const
void transform(const SkMatrix &matrix, SkPath *dst, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
bool contains(SkScalar x, SkScalar y) const
static SkScalar DistanceToSqd(const SkPoint &pt, const SkPoint &a)
static void GrowToInclude(SkRect *r, const SkPoint &pt)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
void convertCubicToQuads(const SkPoint p[4], SkScalar tolScale, skia_private::TArray< SkPoint, true > *quads)
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
SIN Vec< N, float > sqrt(const Vec< N, float > &x)
enum RowData::IntersectionType fIntersectionType
int32_t fTop
smaller y-axis bounds
static constexpr SkIRect MakeWH(int32_t w, int32_t h)
int32_t fLeft
smaller x-axis bounds
bool contains(int32_t x, int32_t y) const
static constexpr SkPoint Make(float x, float y)
SkScalar fBottom
larger y-axis bounds
SkScalar fLeft
smaller x-axis bounds
SkRect makeOutset(float dx, float dy) const
SkScalar fRight
larger x-axis bounds
void roundOut(SkIRect *dst) const
void set(const SkIRect &src)
SkScalar fTop
smaller y-axis bounds