| OLD | NEW | 
| (Empty) |  | 
 |    1 /* | 
 |    2  * Copyright 2016 ARM Ltd. | 
 |    3  * | 
 |    4  * Use of this source code is governed by a BSD-style license that can be | 
 |    5  * found in the LICENSE file. | 
 |    6  */ | 
 |    7  | 
 |    8 #include "GrDistanceFieldGenFromVector.h" | 
 |    9 #include "SkPoint.h" | 
 |   10 #include "SkGeometry.h" | 
 |   11 #include "GrPathUtils.h" | 
 |   12 #include "GrConfig.h" | 
 |   13  | 
 |   14 /** | 
 |   15  * If a scanline (a row of texel) cross from the kRight_SegSide | 
 |   16  * of a segment to the kLeft_SegSide, the winding score should | 
 |   17  * add 1. | 
 |   18  * And winding score should subtract 1 if the scanline cross | 
 |   19  * from kLeft_SegSide to kRight_SegSide. | 
 |   20  * Always return kNA_SegSide if the scanline does not cross over | 
 |   21  * the segment. Winding score should be zero in this case. | 
 |   22  * You can get the winding number for each texel of the scanline | 
 |   23  * by adding the winding score from left to right. | 
 |   24  * Assuming we always start from outside, so the winding number | 
 |   25  * should always start from zero. | 
 |   26  *      ________         ________ | 
 |   27  *     |        |       |        | | 
 |   28  * ...R|L......L|R.....L|R......R|L..... <= Scanline & side of segment | 
 |   29  *     |+1      |-1     |-1      |+1     <= Winding score | 
 |   30  *   0 |   1    ^   0   ^  -1    |0      <= Winding number | 
 |   31  *     |________|       |________| | 
 |   32  * | 
 |   33  * .......NA................NA.......... | 
 |   34  *         0                 0 | 
 |   35  */ | 
 |   36 enum SegSide { | 
 |   37     kLeft_SegSide  = -1, | 
 |   38     kOn_SegSide    =  0, | 
 |   39     kRight_SegSide =  1, | 
 |   40     kNA_SegSide    =  2, | 
 |   41 }; | 
 |   42  | 
 |   43 struct DFData { | 
 |   44     float fDistSq;            // distance squared to nearest (so far) edge | 
 |   45     int   fDeltaWindingScore; // +1 or -1 whenever a scanline cross over a segme
     nt | 
 |   46 }; | 
 |   47  | 
 |   48 /////////////////////////////////////////////////////////////////////////////// | 
 |   49  | 
 |   50 /* | 
 |   51  * Type definition for double precision DScalar, DPoint and DAffineMatrix | 
 |   52  */ | 
 |   53  | 
 |   54 // Scalar with double precision | 
 |   55 typedef double DScalar; | 
 |   56  | 
 |   57 // Point with double precision | 
 |   58 struct DPoint { | 
 |   59     DScalar fX, fY; | 
 |   60  | 
 |   61     static DPoint Make(DScalar x, DScalar y) { | 
 |   62         DPoint pt; | 
 |   63         pt.set(x, y); | 
 |   64         return pt; | 
 |   65     } | 
 |   66  | 
 |   67     DScalar x() const { return fX; } | 
 |   68     DScalar y() const { return fY; } | 
 |   69  | 
 |   70     void set(DScalar x, DScalar y) { fX = x; fY = y; } | 
 |   71  | 
 |   72     /** Returns the euclidian distance from (0,0) to (x,y) | 
 |   73     */ | 
 |   74     static DScalar Length(DScalar x, DScalar y) { | 
 |   75         return sqrt(x * x + y * y); | 
 |   76     } | 
 |   77  | 
 |   78     /** Returns the euclidian distance between a and b | 
 |   79     */ | 
 |   80     static DScalar Distance(const DPoint& a, const DPoint& b) { | 
 |   81         return Length(a.fX - b.fX, a.fY - b.fY); | 
 |   82     } | 
 |   83  | 
 |   84     DScalar distanceToSqd(const DPoint& pt) const { | 
 |   85         DScalar dx = fX - pt.fX; | 
 |   86         DScalar dy = fY - pt.fY; | 
 |   87         return dx * dx + dy * dy; | 
 |   88     } | 
 |   89 }; | 
 |   90  | 
 |   91 // Matrix with double precision for affine transformation. | 
 |   92 // We don't store row 3 because its always (0, 0, 1). | 
 |   93 class DAffineMatrix { | 
 |   94 public: | 
 |   95     DScalar operator[](int index) const { | 
 |   96         SkASSERT((unsigned)index < 6); | 
 |   97         return fMat[index]; | 
 |   98     } | 
 |   99  | 
 |  100     DScalar& operator[](int index) { | 
 |  101         SkASSERT((unsigned)index < 6); | 
 |  102         return fMat[index]; | 
 |  103     } | 
 |  104  | 
 |  105     void setAffine(DScalar m11, DScalar m12, DScalar m13, | 
 |  106                    DScalar m21, DScalar m22, DScalar m23) { | 
 |  107         fMat[0] = m11; | 
 |  108         fMat[1] = m12; | 
 |  109         fMat[2] = m13; | 
 |  110         fMat[3] = m21; | 
 |  111         fMat[4] = m22; | 
 |  112         fMat[5] = m23; | 
 |  113     } | 
 |  114  | 
 |  115     /** Set the matrix to identity | 
 |  116     */ | 
 |  117     void reset() { | 
 |  118         fMat[0] = fMat[4] = 1.0; | 
 |  119         fMat[1] = fMat[3] = | 
 |  120         fMat[2] = fMat[5] = 0.0; | 
 |  121     } | 
 |  122  | 
 |  123     // alias for reset() | 
 |  124     void setIdentity() { this->reset(); } | 
 |  125  | 
 |  126     DPoint mapPoint(const SkPoint& src) const { | 
 |  127         DPoint pt = DPoint::Make(src.x(), src.y()); | 
 |  128         return this->mapPoint(pt); | 
 |  129     } | 
 |  130  | 
 |  131     DPoint mapPoint(const DPoint& src) const { | 
 |  132         return DPoint::Make(fMat[0] * src.x() + fMat[1] * src.y() + fMat[2], | 
 |  133                             fMat[3] * src.x() + fMat[4] * src.y() + fMat[5]); | 
 |  134     } | 
 |  135 private: | 
 |  136     DScalar fMat[6]; | 
 |  137 }; | 
 |  138  | 
 |  139 /////////////////////////////////////////////////////////////////////////////// | 
 |  140  | 
 |  141 static const DScalar kClose = (SK_Scalar1 / 16.0); | 
 |  142 static const DScalar kCloseSqd = SkScalarMul(kClose, kClose); | 
 |  143 static const DScalar kNearlyZero = (SK_Scalar1 / (1 << 15)); | 
 |  144  | 
 |  145 static inline bool between_closed_open(DScalar a, DScalar b, DScalar c, | 
 |  146                                        DScalar tolerance = kNearlyZero) { | 
 |  147     SkASSERT(tolerance >= 0.f); | 
 |  148     return b < c ? (a >= b - tolerance && a < c - tolerance) : | 
 |  149                    (a >= c - tolerance && a < b - tolerance); | 
 |  150 } | 
 |  151  | 
 |  152 static inline bool between_closed(DScalar a, DScalar b, DScalar c, | 
 |  153                                   DScalar tolerance = kNearlyZero) { | 
 |  154     SkASSERT(tolerance >= 0.f); | 
 |  155     return b < c ? (a >= b - tolerance && a <= c + tolerance) : | 
 |  156                    (a >= c - tolerance && a <= b + tolerance); | 
 |  157 } | 
 |  158  | 
 |  159 static inline bool nearly_zero(DScalar x, DScalar tolerance = kNearlyZero) { | 
 |  160     SkASSERT(tolerance >= 0.f); | 
 |  161     return fabs(x) <= tolerance; | 
 |  162 } | 
 |  163  | 
 |  164 static inline bool nearly_equal(DScalar x, DScalar y, DScalar tolerance = kNearl
     yZero) { | 
 |  165     SkASSERT(tolerance >= 0.f); | 
 |  166     return fabs(x - y) <= tolerance; | 
 |  167 } | 
 |  168  | 
 |  169 static inline float sign_of(const float &val) { | 
 |  170     return (val < 0.f) ? -1.f : 1.f; | 
 |  171 } | 
 |  172  | 
 |  173 static bool is_colinear(const SkPoint pts[3]) { | 
 |  174     return nearly_zero((pts[1].y() - pts[0].y()) * (pts[1].x() - pts[2].x()) - | 
 |  175                        (pts[1].y() - pts[2].y()) * (pts[1].x() - pts[0].x())); | 
 |  176 } | 
 |  177  | 
 |  178 class PathSegment { | 
 |  179 public: | 
 |  180     enum { | 
 |  181         // These enum values are assumed in member functions below. | 
 |  182         kLine = 0, | 
 |  183         kQuad = 1, | 
 |  184     } fType; | 
 |  185  | 
 |  186     // line uses 2 pts, quad uses 3 pts | 
 |  187     SkPoint fPts[3]; | 
 |  188  | 
 |  189     DPoint  fP0T, fP2T; | 
 |  190     DAffineMatrix fXformMatrix; | 
 |  191     DScalar fScalingFactor; | 
 |  192     SkRect  fBoundingBox; | 
 |  193  | 
 |  194     void init(); | 
 |  195  | 
 |  196     int countPoints() { | 
 |  197         GR_STATIC_ASSERT(0 == kLine && 1 == kQuad); | 
 |  198         return fType + 2; | 
 |  199     } | 
 |  200  | 
 |  201     const SkPoint& endPt() const { | 
 |  202         GR_STATIC_ASSERT(0 == kLine && 1 == kQuad); | 
 |  203         return fPts[fType + 1]; | 
 |  204     }; | 
 |  205 }; | 
 |  206  | 
 |  207 typedef SkTArray<PathSegment, true> PathSegmentArray; | 
 |  208  | 
 |  209 void PathSegment::init() { | 
 |  210     const DPoint p0 = DPoint::Make(fPts[0].x(), fPts[0].y()); | 
 |  211     const DPoint p2 = DPoint::Make(this->endPt().x(), this->endPt().y()); | 
 |  212     const DScalar p0x = p0.x(); | 
 |  213     const DScalar p0y = p0.y(); | 
 |  214     const DScalar p2x = p2.x(); | 
 |  215     const DScalar p2y = p2.y(); | 
 |  216  | 
 |  217     fBoundingBox.set(fPts[0], this->endPt()); | 
 |  218  | 
 |  219     if (fType == PathSegment::kLine) { | 
 |  220         fScalingFactor = DPoint::Distance(p0, p2); | 
 |  221  | 
 |  222         const DScalar cosTheta = (p2x - p0x) / fScalingFactor; | 
 |  223         const DScalar sinTheta = (p2y - p0y) / fScalingFactor; | 
 |  224  | 
 |  225         fXformMatrix.setAffine( | 
 |  226             cosTheta, sinTheta, -(cosTheta * p0x) - (sinTheta * p0y), | 
 |  227             -sinTheta, cosTheta, (sinTheta * p0x) - (cosTheta * p0y) | 
 |  228         ); | 
 |  229     } else { | 
 |  230         SkASSERT(fType == PathSegment::kQuad); | 
 |  231  | 
 |  232         // Calculate bounding box | 
 |  233         const SkPoint _P1mP0 = fPts[1] - fPts[0]; | 
 |  234         SkPoint t = _P1mP0 - fPts[2] + fPts[1]; | 
 |  235         t.fX = _P1mP0.x() / t.x(); | 
 |  236         t.fY = _P1mP0.y() / t.y(); | 
 |  237         t.fX = SkScalarClampMax(t.x(), 1.0); | 
 |  238         t.fY = SkScalarClampMax(t.y(), 1.0); | 
 |  239         t.fX = _P1mP0.x() * t.x(); | 
 |  240         t.fY = _P1mP0.y() * t.y(); | 
 |  241         const SkPoint m = fPts[0] + t; | 
 |  242         fBoundingBox.growToInclude(&m, 1); | 
 |  243  | 
 |  244         const DScalar p1x = fPts[1].x(); | 
 |  245         const DScalar p1y = fPts[1].y(); | 
 |  246  | 
 |  247         const DScalar p0xSqd = p0x * p0x; | 
 |  248         const DScalar p0ySqd = p0y * p0y; | 
 |  249         const DScalar p2xSqd = p2x * p2x; | 
 |  250         const DScalar p2ySqd = p2y * p2y; | 
 |  251         const DScalar p1xSqd = p1x * p1x; | 
 |  252         const DScalar p1ySqd = p1y * p1y; | 
 |  253  | 
 |  254         const DScalar p01xProd = p0x * p1x; | 
 |  255         const DScalar p02xProd = p0x * p2x; | 
 |  256         const DScalar b12xProd = p1x * p2x; | 
 |  257         const DScalar p01yProd = p0y * p1y; | 
 |  258         const DScalar p02yProd = p0y * p2y; | 
 |  259         const DScalar b12yProd = p1y * p2y; | 
 |  260  | 
 |  261         const DScalar sqrtA = p0y - (2.0 * p1y) + p2y; | 
 |  262         const DScalar a = sqrtA * sqrtA; | 
 |  263         const DScalar h = -1.0 * (p0y - (2.0 * p1y) + p2y) * (p0x - (2.0 * p1x) 
     + p2x); | 
 |  264         const DScalar sqrtB = p0x - (2.0 * p1x) + p2x; | 
 |  265         const DScalar b = sqrtB * sqrtB; | 
 |  266         const DScalar c = (p0xSqd * p2ySqd) - (4.0 * p01xProd * b12yProd) | 
 |  267                 - (2.0 * p02xProd * p02yProd) + (4.0 * p02xProd * p1ySqd) | 
 |  268                 + (4.0 * p1xSqd * p02yProd) - (4.0 * b12xProd * p01yProd) | 
 |  269                 + (p2xSqd * p0ySqd); | 
 |  270         const DScalar g = (p0x * p02yProd) - (2.0 * p0x * p1ySqd) | 
 |  271                 + (2.0 * p0x * b12yProd) - (p0x * p2ySqd) | 
 |  272                 + (2.0 * p1x * p01yProd) - (4.0 * p1x * p02yProd) | 
 |  273                 + (2.0 * p1x * b12yProd) - (p2x * p0ySqd) | 
 |  274                 + (2.0 * p2x * p01yProd) + (p2x * p02yProd) | 
 |  275                 - (2.0 * p2x * p1ySqd); | 
 |  276         const DScalar f = -((p0xSqd * p2y) - (2.0 * p01xProd * p1y) | 
 |  277                 - (2.0 * p01xProd * p2y) - (p02xProd * p0y) | 
 |  278                 + (4.0 * p02xProd * p1y) - (p02xProd * p2y) | 
 |  279                 + (2.0 * p1xSqd * p0y) + (2.0 * p1xSqd * p2y) | 
 |  280                 - (2.0 * b12xProd * p0y) - (2.0 * b12xProd * p1y) | 
 |  281                 + (p2xSqd * p0y)); | 
 |  282  | 
 |  283         const DScalar cosTheta = sqrt(a / (a + b)); | 
 |  284         const DScalar sinTheta = -1.0 * sign_of((a + b) * h) * sqrt(b / (a + b))
     ; | 
 |  285  | 
 |  286         const DScalar gDef = cosTheta * g - sinTheta * f; | 
 |  287         const DScalar fDef = sinTheta * g + cosTheta * f; | 
 |  288  | 
 |  289  | 
 |  290         const DScalar x0 = gDef / (a + b); | 
 |  291         const DScalar y0 = (1.0 / (2.0 * fDef)) * (c - (gDef * gDef / (a + b))); | 
 |  292  | 
 |  293  | 
 |  294         const DScalar lambda = -1.0 * ((a + b) / (2.0 * fDef)); | 
 |  295         fScalingFactor = (1.0 / lambda); | 
 |  296         fScalingFactor *= fScalingFactor; | 
 |  297  | 
 |  298         const DScalar lambda_cosTheta = lambda * cosTheta; | 
 |  299         const DScalar lambda_sinTheta = lambda * sinTheta; | 
 |  300  | 
 |  301         fXformMatrix.setAffine( | 
 |  302             lambda_cosTheta, -lambda_sinTheta, lambda * x0, | 
 |  303             lambda_sinTheta, lambda_cosTheta, lambda * y0 | 
 |  304         ); | 
 |  305     } | 
 |  306  | 
 |  307     fP0T = fXformMatrix.mapPoint(p0); | 
 |  308     fP2T = fXformMatrix.mapPoint(p2); | 
 |  309 } | 
 |  310  | 
 |  311 static void init_distances(DFData* data, int size) { | 
 |  312     DFData* currData = data; | 
 |  313  | 
 |  314     for (int i = 0; i < size; ++i) { | 
 |  315         // init distance to "far away" | 
 |  316         currData->fDistSq = SK_DistanceFieldMagnitude * SK_DistanceFieldMagnitud
     e; | 
 |  317         currData->fDeltaWindingScore = 0; | 
 |  318         ++currData; | 
 |  319     } | 
 |  320 } | 
 |  321  | 
 |  322 static inline bool get_direction(const SkPath& path, const SkMatrix& m, | 
 |  323                                  SkPathPriv::FirstDirection* dir) { | 
 |  324     if (!SkPathPriv::CheapComputeFirstDirection(path, dir)) { | 
 |  325         return false; | 
 |  326     } | 
 |  327  | 
 |  328     // check whether m reverses the orientation | 
 |  329     SkASSERT(!m.hasPerspective()); | 
 |  330     SkScalar det2x2 = SkScalarMul(m.get(SkMatrix::kMScaleX), m.get(SkMatrix::kMS
     caleY)) - | 
 |  331                       SkScalarMul(m.get(SkMatrix::kMSkewX), m.get(SkMatrix::kMSk
     ewY)); | 
 |  332  | 
 |  333     if (det2x2 < 0) { | 
 |  334         *dir = SkPathPriv::OppositeFirstDirection(*dir); | 
 |  335     } | 
 |  336     return true; | 
 |  337 } | 
 |  338  | 
 |  339 static inline void add_line_to_segment(const SkPoint pts[2], | 
 |  340                                        PathSegmentArray* segments) { | 
 |  341     segments->push_back(); | 
 |  342     segments->back().fType = PathSegment::kLine; | 
 |  343     segments->back().fPts[0] = pts[0]; | 
 |  344     segments->back().fPts[1] = pts[1]; | 
 |  345  | 
 |  346     segments->back().init(); | 
 |  347 } | 
 |  348  | 
 |  349 static inline void add_quad_segment(const SkPoint pts[3], | 
 |  350                                     PathSegmentArray* segments) { | 
 |  351     if (pts[0].distanceToSqd(pts[1]) < kCloseSqd || | 
 |  352         pts[1].distanceToSqd(pts[2]) < kCloseSqd || | 
 |  353         is_colinear(pts)) { | 
 |  354         if (pts[0] != pts[2]) { | 
 |  355             SkPoint line_pts[2]; | 
 |  356             line_pts[0] = pts[0]; | 
 |  357             line_pts[1] = pts[2]; | 
 |  358             add_line_to_segment(line_pts, segments); | 
 |  359         } | 
 |  360     } else { | 
 |  361         segments->push_back(); | 
 |  362         segments->back().fType = PathSegment::kQuad; | 
 |  363         segments->back().fPts[0] = pts[0]; | 
 |  364         segments->back().fPts[1] = pts[1]; | 
 |  365         segments->back().fPts[2] = pts[2]; | 
 |  366  | 
 |  367         segments->back().init(); | 
 |  368     } | 
 |  369 } | 
 |  370  | 
 |  371 static inline void add_cubic_segments(const SkPoint pts[4], | 
 |  372                                       SkPathPriv::FirstDirection dir, | 
 |  373                                       PathSegmentArray* segments) { | 
 |  374     SkSTArray<15, SkPoint, true> quads; | 
 |  375     GrPathUtils::convertCubicToQuads(pts, SK_Scalar1, true, dir, &quads); | 
 |  376     int count = quads.count(); | 
 |  377     for (int q = 0; q < count; q += 3) { | 
 |  378         add_quad_segment(&quads[q], segments); | 
 |  379     } | 
 |  380 } | 
 |  381  | 
 |  382 static float calculate_nearest_point_for_quad( | 
 |  383                 const PathSegment& segment, | 
 |  384                 const DPoint &xFormPt) { | 
 |  385     static const float kThird = 0.33333333333f; | 
 |  386     static const float kTwentySeventh = 0.037037037f; | 
 |  387  | 
 |  388     const float a = 0.5f - xFormPt.y(); | 
 |  389     const float b = -0.5f * xFormPt.x(); | 
 |  390  | 
 |  391     const float a3 = a * a * a; | 
 |  392     const float b2 = b * b; | 
 |  393  | 
 |  394     const float c = (b2 * 0.25f) + (a3 * kTwentySeventh); | 
 |  395  | 
 |  396     if (c >= 0.f) { | 
 |  397         const float sqrtC = sqrt(c); | 
 |  398         const float result = (float)cbrt((-b * 0.5f) + sqrtC) + (float)cbrt((-b 
     * 0.5f) - sqrtC); | 
 |  399         return result; | 
 |  400     } else { | 
 |  401         const float cosPhi = (float)sqrt((b2 * 0.25f) * (-27.f / a3)) * ((b > 0)
      ? -1.f : 1.f); | 
 |  402         const float phi = (float)acos(cosPhi); | 
 |  403         float result; | 
 |  404         if (xFormPt.x() > 0.f) { | 
 |  405             result = 2.f * (float)sqrt(-a * kThird) * (float)cos(phi * kThird); | 
 |  406             if (!between_closed(result, segment.fP0T.x(), segment.fP2T.x())) { | 
 |  407                 result = 2.f * (float)sqrt(-a * kThird) * (float)cos((phi * kThi
     rd) + (SK_ScalarPI * 2.f * kThird)); | 
 |  408             } | 
 |  409         } else { | 
 |  410             result = 2.f * (float)sqrt(-a * kThird) * (float)cos((phi * kThird) 
     + (SK_ScalarPI * 2.f * kThird)); | 
 |  411             if (!between_closed(result, segment.fP0T.x(), segment.fP2T.x())) { | 
 |  412                 result = 2.f * (float)sqrt(-a * kThird) * (float)cos(phi * kThir
     d); | 
 |  413             } | 
 |  414         } | 
 |  415         return result; | 
 |  416     } | 
 |  417 } | 
 |  418  | 
 |  419 // This structure contains some intermediate values shared by the same row. | 
 |  420 // It is used to calculate segment side of a quadratic bezier. | 
 |  421 struct RowData { | 
 |  422     // The intersection type of a scanline and y = x * x parabola in canonical s
     pace. | 
 |  423     enum IntersectionType { | 
 |  424         kNoIntersection, | 
 |  425         kVerticalLine, | 
 |  426         kTangentLine, | 
 |  427         kTwoPointsIntersect | 
 |  428     } fIntersectionType; | 
 |  429  | 
 |  430     // The direction of the quadratic segment in the canonical space. | 
 |  431     //  1: The quadratic segment going from negative x-axis to positive x-axis. | 
 |  432     // -1: The quadratic segment going from positive x-axis to negative x-axis. | 
 |  433     int fQuadXDirection; | 
 |  434  | 
 |  435     // The y-value(equal to x*x) of intersection point for the kVerticalLine int
     ersection type. | 
 |  436     DScalar fYAtIntersection; | 
 |  437  | 
 |  438     // The x-value for two intersection points. | 
 |  439     DScalar fXAtIntersection1; | 
 |  440     DScalar fXAtIntersection2; | 
 |  441 }; | 
 |  442  | 
 |  443 void precomputation_for_row( | 
 |  444             RowData *rowData, | 
 |  445             const PathSegment& segment, | 
 |  446             const SkPoint& pointLeft, | 
 |  447             const SkPoint& pointRight | 
 |  448             ) { | 
 |  449     if (segment.fType != PathSegment::kQuad) { | 
 |  450         return; | 
 |  451     } | 
 |  452  | 
 |  453     const DPoint& xFormPtLeft = segment.fXformMatrix.mapPoint(pointLeft); | 
 |  454     const DPoint& xFormPtRight = segment.fXformMatrix.mapPoint(pointRight);; | 
 |  455  | 
 |  456     rowData->fQuadXDirection = sign_of(segment.fP2T.x() - segment.fP0T.x()); | 
 |  457  | 
 |  458     const DScalar x1 = xFormPtLeft.x(); | 
 |  459     const DScalar y1 = xFormPtLeft.y(); | 
 |  460     const DScalar x2 = xFormPtRight.x(); | 
 |  461     const DScalar y2 = xFormPtRight.y(); | 
 |  462  | 
 |  463     if (nearly_equal(x1, x2)) { | 
 |  464         rowData->fIntersectionType = RowData::kVerticalLine; | 
 |  465         rowData->fYAtIntersection = x1 * x1; | 
 |  466         return; | 
 |  467     } | 
 |  468  | 
 |  469     // Line y = mx + b | 
 |  470     const DScalar m = (y2 - y1) / (x2 - x1); | 
 |  471     const DScalar b = -m * x1 + y1; | 
 |  472  | 
 |  473     const DScalar c = m * m + 4.0 * b; | 
 |  474  | 
 |  475     if (nearly_zero(c, 4.0 * kNearlyZero * kNearlyZero)) { | 
 |  476         rowData->fIntersectionType = RowData::kTangentLine; | 
 |  477         rowData->fXAtIntersection1 = m / 2.0; | 
 |  478         rowData->fXAtIntersection2 = m / 2.0; | 
 |  479     } else if (c < 0.0) { | 
 |  480         rowData->fIntersectionType = RowData::kNoIntersection; | 
 |  481         return; | 
 |  482     } else { | 
 |  483         rowData->fIntersectionType = RowData::kTwoPointsIntersect; | 
 |  484         const DScalar d = sqrt(c); | 
 |  485         rowData->fXAtIntersection1 = (m + d) / 2.0; | 
 |  486         rowData->fXAtIntersection2 = (m - d) / 2.0; | 
 |  487     } | 
 |  488 } | 
 |  489  | 
 |  490 SegSide calculate_side_of_quad( | 
 |  491             const PathSegment& segment, | 
 |  492             const SkPoint& point, | 
 |  493             const DPoint& xFormPt, | 
 |  494             const RowData& rowData) { | 
 |  495     SegSide side = kNA_SegSide; | 
 |  496  | 
 |  497     if (RowData::kVerticalLine == rowData.fIntersectionType) { | 
 |  498         side = (SegSide)(int)(sign_of(rowData.fYAtIntersection - xFormPt.y()) * 
     rowData.fQuadXDirection); | 
 |  499     } | 
 |  500     else if (RowData::kTwoPointsIntersect == rowData.fIntersectionType || | 
 |  501              RowData::kTangentLine == rowData.fIntersectionType) { | 
 |  502         const DScalar p1 = rowData.fXAtIntersection1; | 
 |  503         const DScalar p2 = rowData.fXAtIntersection2; | 
 |  504  | 
 |  505         int signP1 = sign_of(p1 - xFormPt.x()); | 
 |  506         if (between_closed(p1, segment.fP0T.x(), segment.fP2T.x())) { | 
 |  507             side = (SegSide)((-signP1) * rowData.fQuadXDirection); | 
 |  508         } | 
 |  509         if (between_closed(p2, segment.fP0T.x(), segment.fP2T.x())) { | 
 |  510             int signP2 = sign_of(p2 - xFormPt.x()); | 
 |  511             if (side == kNA_SegSide || signP2 == 1) { | 
 |  512                 side = (SegSide)(signP2 * rowData.fQuadXDirection); | 
 |  513             } | 
 |  514         } | 
 |  515  | 
 |  516         // The scanline is the tangent line of current quadratic segment. | 
 |  517         if (RowData::kTangentLine == rowData.fIntersectionType) { | 
 |  518             // The path start at the tangent point. | 
 |  519             if (nearly_equal(p1, segment.fP0T.x())) { | 
 |  520                 side = (SegSide)(side * (-signP1) * rowData.fQuadXDirection); | 
 |  521             } | 
 |  522  | 
 |  523             // The path end at the tangent point. | 
 |  524             if (nearly_equal(p1, segment.fP2T.x())) { | 
 |  525                 side = (SegSide)(side * signP1 * rowData.fQuadXDirection); | 
 |  526             } | 
 |  527         } | 
 |  528     } | 
 |  529  | 
 |  530     return side; | 
 |  531 } | 
 |  532  | 
 |  533 static float distance_to_segment(const SkPoint& point, | 
 |  534                                  const PathSegment& segment, | 
 |  535                                  const RowData& rowData, | 
 |  536                                  SegSide* side) { | 
 |  537     SkASSERT(side); | 
 |  538  | 
 |  539     const DPoint xformPt = segment.fXformMatrix.mapPoint(point); | 
 |  540  | 
 |  541     if (segment.fType == PathSegment::kLine) { | 
 |  542         float result = SK_DistanceFieldPad * SK_DistanceFieldPad; | 
 |  543  | 
 |  544         if (between_closed(xformPt.x(), segment.fP0T.x(), segment.fP2T.x())) { | 
 |  545             result = xformPt.y() * xformPt.y(); | 
 |  546         } else if (xformPt.x() < segment.fP0T.x()) { | 
 |  547             result = (xformPt.x() * xformPt.x() + xformPt.y() * xformPt.y()); | 
 |  548         } else { | 
 |  549             result = ((xformPt.x() - segment.fP2T.x()) * (xformPt.x() - segment.
     fP2T.x()) | 
 |  550                      + xformPt.y() * xformPt.y()); | 
 |  551         } | 
 |  552  | 
 |  553         if (between_closed_open(point.y(), segment.fBoundingBox.top(), | 
 |  554                                 segment.fBoundingBox.bottom())) { | 
 |  555             *side = (SegSide)(int)sign_of(-xformPt.y()); | 
 |  556         } else { | 
 |  557             *side = kNA_SegSide; | 
 |  558         } | 
 |  559         return result; | 
 |  560     } else { | 
 |  561         SkASSERT(segment.fType == PathSegment::kQuad); | 
 |  562  | 
 |  563         const float nearestPoint = calculate_nearest_point_for_quad(segment, xfo
     rmPt); | 
 |  564  | 
 |  565         float dist; | 
 |  566  | 
 |  567         if (between_closed(nearestPoint, segment.fP0T.x(), segment.fP2T.x())) { | 
 |  568             DPoint x = DPoint::Make(nearestPoint, nearestPoint * nearestPoint); | 
 |  569             dist = xformPt.distanceToSqd(x); | 
 |  570         } else { | 
 |  571             const float distToB0T = xformPt.distanceToSqd(segment.fP0T); | 
 |  572             const float distToB2T = xformPt.distanceToSqd(segment.fP2T); | 
 |  573  | 
 |  574             if (distToB0T < distToB2T) { | 
 |  575                 dist = distToB0T; | 
 |  576             } else { | 
 |  577                 dist = distToB2T; | 
 |  578             } | 
 |  579         } | 
 |  580  | 
 |  581         if (between_closed_open(point.y(), segment.fBoundingBox.top(), | 
 |  582                                 segment.fBoundingBox.bottom())) { | 
 |  583             *side = calculate_side_of_quad(segment, point, xformPt, rowData); | 
 |  584         } else { | 
 |  585             *side = kNA_SegSide; | 
 |  586         } | 
 |  587  | 
 |  588         return dist * segment.fScalingFactor; | 
 |  589     } | 
 |  590 } | 
 |  591  | 
 |  592 static void calculate_distance_field_data(PathSegmentArray* segments, | 
 |  593                                           DFData* dataPtr, | 
 |  594                                           int width, int height) { | 
 |  595     int count = segments->count(); | 
 |  596     for (int a = 0; a < count; ++a) { | 
 |  597         PathSegment& segment = (*segments)[a]; | 
 |  598         const SkRect& segBB = segment.fBoundingBox.makeOutset( | 
 |  599                                 SK_DistanceFieldPad, SK_DistanceFieldPad); | 
 |  600         int startColumn = segBB.left(); | 
 |  601         int endColumn = segBB.right() + 1; | 
 |  602  | 
 |  603         int startRow = segBB.top(); | 
 |  604         int endRow = segBB.bottom() + 1; | 
 |  605  | 
 |  606         SkASSERT((startColumn >= 0) && "StartColumn < 0!"); | 
 |  607         SkASSERT((endColumn <= width) && "endColumn > width!"); | 
 |  608         SkASSERT((startRow >= 0) && "StartRow < 0!"); | 
 |  609         SkASSERT((endRow <= height) && "EndRow > height!"); | 
 |  610  | 
 |  611         for (int row = startRow; row < endRow; ++row) { | 
 |  612             SegSide prevSide = kNA_SegSide; | 
 |  613             const float pY = row + 0.5f; | 
 |  614             RowData rowData; | 
 |  615  | 
 |  616             const SkPoint pointLeft = SkPoint::Make(startColumn, pY); | 
 |  617             const SkPoint pointRight = SkPoint::Make(endColumn, pY); | 
 |  618  | 
 |  619             precomputation_for_row(&rowData, segment, pointLeft, pointRight); | 
 |  620  | 
 |  621             for (int col = startColumn; col < endColumn; ++col) { | 
 |  622                 int idx = (row * width) + col; | 
 |  623  | 
 |  624                 const float pX = col + 0.5f; | 
 |  625                 const SkPoint point = SkPoint::Make(pX, pY); | 
 |  626  | 
 |  627                 const float distSq = dataPtr[idx].fDistSq; | 
 |  628                 int dilation = distSq < 1.5 * 1.5 ? 1 : | 
 |  629                                distSq < 2.5 * 2.5 ? 2 : | 
 |  630                                distSq < 3.5 * 3.5 ? 3 : SK_DistanceFieldPad; | 
 |  631                 if (dilation > SK_DistanceFieldPad) { | 
 |  632                     dilation = SK_DistanceFieldPad; | 
 |  633                 } | 
 |  634  | 
 |  635                 // Optimisation for not calculating some points. | 
 |  636                 if (dilation != SK_DistanceFieldPad && !segment.fBoundingBox.rou
     ndOut() | 
 |  637                     .makeOutset(dilation, dilation).contains(col, row)) { | 
 |  638                     continue; | 
 |  639                 } | 
 |  640  | 
 |  641                 SegSide side = kNA_SegSide; | 
 |  642                 int     deltaWindingScore = 0; | 
 |  643                 float   currDistSq = distance_to_segment(point, segment, rowData
     , &side); | 
 |  644                 if (prevSide == kLeft_SegSide && side == kRight_SegSide) { | 
 |  645                     deltaWindingScore = -1; | 
 |  646                 } else if (prevSide == kRight_SegSide && side == kLeft_SegSide) 
     { | 
 |  647                     deltaWindingScore = 1; | 
 |  648                 } | 
 |  649  | 
 |  650                 prevSide = side; | 
 |  651  | 
 |  652                 if (currDistSq < distSq) { | 
 |  653                     dataPtr[idx].fDistSq = currDistSq; | 
 |  654                 } | 
 |  655  | 
 |  656                 dataPtr[idx].fDeltaWindingScore += deltaWindingScore; | 
 |  657             } | 
 |  658         } | 
 |  659     } | 
 |  660 } | 
 |  661  | 
 |  662 static unsigned char pack_distance_field_val(float dist, float distanceMagnitude
     ) { | 
 |  663     // The distance field is constructed as unsigned char values, so that the ze
     ro value is at 128, | 
 |  664     // Beside 128, we have 128 values in range [0, 128), but only 127 values in 
     range (128, 255]. | 
 |  665     // So we multiply distanceMagnitude by 127/128 at the latter range to avoid 
     overflow. | 
 |  666     dist = SkScalarPin(-dist, -distanceMagnitude, distanceMagnitude * 127.0f / 1
     28.0f); | 
 |  667  | 
 |  668     // Scale into the positive range for unsigned distance | 
 |  669     dist += distanceMagnitude; | 
 |  670  | 
 |  671     // Scale into unsigned char range | 
 |  672     return (unsigned char)(dist / (2 * distanceMagnitude) * 256.0f); | 
 |  673 } | 
 |  674  | 
 |  675 bool GrGenerateDistanceFieldFromPath(unsigned char* distanceField, | 
 |  676                                      const SkPath& path, const SkMatrix& drawMat
     rix, | 
 |  677                                      int width, int height, size_t rowBytes) { | 
 |  678     SkASSERT(distanceField); | 
 |  679  | 
 |  680     SkMatrix m = drawMatrix; | 
 |  681     m.postTranslate(SK_DistanceFieldPad, SK_DistanceFieldPad); | 
 |  682  | 
 |  683     // create temp data | 
 |  684     size_t dataSize = width * height * sizeof(DFData); | 
 |  685     SkAutoSMalloc<1024> dfStorage(dataSize); | 
 |  686     DFData* dataPtr = (DFData*) dfStorage.get(); | 
 |  687  | 
 |  688     // create initial distance data | 
 |  689     init_distances(dataPtr, width * height); | 
 |  690  | 
 |  691     SkPath::Iter iter(path, true); | 
 |  692     SkSTArray<15, PathSegment, true> segments; | 
 |  693  | 
 |  694     SkPathPriv::FirstDirection dir; | 
 |  695     // get_direction can fail for some degenerate paths. | 
 |  696     if (path.getSegmentMasks() & SkPath::kCubic_SegmentMask && | 
 |  697         !get_direction(path, m, &dir)) { | 
 |  698         return false; | 
 |  699     } | 
 |  700  | 
 |  701     for (;;) { | 
 |  702         SkPoint pts[4]; | 
 |  703         SkPath::Verb verb = iter.next(pts); | 
 |  704         switch (verb) { | 
 |  705             case SkPath::kMove_Verb: | 
 |  706                 // m.mapPoints(pts, 1); | 
 |  707                 break; | 
 |  708             case SkPath::kLine_Verb: { | 
 |  709                 m.mapPoints(pts, 2); | 
 |  710                 add_line_to_segment(pts, &segments); | 
 |  711                 break; | 
 |  712             } | 
 |  713             case SkPath::kQuad_Verb: | 
 |  714                 m.mapPoints(pts, 3); | 
 |  715                 add_quad_segment(pts, &segments); | 
 |  716                 break; | 
 |  717             case SkPath::kConic_Verb: { | 
 |  718                 m.mapPoints(pts, 3); | 
 |  719                 SkScalar weight = iter.conicWeight(); | 
 |  720                 SkAutoConicToQuads converter; | 
 |  721                 const SkPoint* quadPts = converter.computeQuads(pts, weight, 0.5
     f); | 
 |  722                 for (int i = 0; i < converter.countQuads(); ++i) { | 
 |  723                     add_quad_segment(quadPts + 2*i, &segments); | 
 |  724                 } | 
 |  725                 break; | 
 |  726             } | 
 |  727             case SkPath::kCubic_Verb: { | 
 |  728                 m.mapPoints(pts, 4); | 
 |  729                 add_cubic_segments(pts, dir, &segments); | 
 |  730                 break; | 
 |  731             }; | 
 |  732             default: | 
 |  733                 break; | 
 |  734         } | 
 |  735         if (verb == SkPath::kDone_Verb) { | 
 |  736             break; | 
 |  737         } | 
 |  738     } | 
 |  739  | 
 |  740     calculate_distance_field_data(&segments, dataPtr, width, height); | 
 |  741  | 
 |  742     for (int row = 0; row < height; ++row) { | 
 |  743         int windingNumber = 0; // Winding number start from zero for each scanli
     ne | 
 |  744         for (int col = 0; col < width; ++col) { | 
 |  745             int idx = (row * width) + col; | 
 |  746             windingNumber += dataPtr[idx].fDeltaWindingScore; | 
 |  747  | 
 |  748             enum DFSign { | 
 |  749                 kInside = -1, | 
 |  750                 kOutside = 1 | 
 |  751             } dfSign; | 
 |  752  | 
 |  753             if (path.getFillType() == SkPath::kWinding_FillType) { | 
 |  754                 dfSign = windingNumber ? kInside : kOutside; | 
 |  755             } else if (path.getFillType() == SkPath::kInverseWinding_FillType) { | 
 |  756                 dfSign = windingNumber ? kOutside : kInside; | 
 |  757             } else if (path.getFillType() == SkPath::kEvenOdd_FillType) { | 
 |  758                 dfSign = (windingNumber % 2) ? kInside : kOutside; | 
 |  759             } else { | 
 |  760                 SkASSERT(path.getFillType() == SkPath::kInverseEvenOdd_FillType)
     ; | 
 |  761                 dfSign = (windingNumber % 2) ? kOutside : kInside; | 
 |  762             } | 
 |  763  | 
 |  764             // The winding number at the end of a scanline should be zero. | 
 |  765             if ((col == width - 1) && (windingNumber != 0)) { | 
 |  766                 SkASSERT(0 && "Winding number should be zero at the end of a sca
     n line."); | 
 |  767                 return false; | 
 |  768             } | 
 |  769  | 
 |  770             const float miniDist = sqrt(dataPtr[idx].fDistSq); | 
 |  771             const float dist = dfSign * miniDist; | 
 |  772  | 
 |  773             unsigned char pixelVal = | 
 |  774                 pack_distance_field_val(dist, (float)SK_DistanceFieldMagnitude); | 
 |  775  | 
 |  776             distanceField[(row * rowBytes) + col] = pixelVal; | 
 |  777         } | 
 |  778     } | 
 |  779     return true; | 
 |  780 } | 
| OLD | NEW |