Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2006 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #ifndef SkEdge_DEFINED
     11 #define SkEdge_DEFINED
     12 
     13 #include "SkRect.h"
     14 #include "SkFDot6.h"
     15 #include "SkMath.h"
     16 
     17 // This correctly favors the lower-pixel when y0 is on a 1/2 pixel boundary
     18 #define SkEdge_Compute_DY(top, y0)  ((top << 6) + 32 - (y0))
     19 
     20 struct SkEdge {
     21     enum Type {
     22         kLine_Type,
     23         kQuad_Type,
     24         kCubic_Type
     25     };
     26 
     27     SkEdge* fNext;
     28     SkEdge* fPrev;
     29 
     30     SkFixed fX;
     31     SkFixed fDX;
     32     int32_t fFirstY;
     33     int32_t fLastY;
     34     int8_t fCurveCount;    // only used by kQuad(+) and kCubic(-)
     35     uint8_t fCurveShift;    // appled to all Dx/DDx/DDDx except for fCubicDShift exception
     36     uint8_t fCubicDShift;   // applied to fCDx and fCDy only in cubic
     37     int8_t  fWinding;       // 1 or -1
     38 
     39     int setLine(const SkPoint& p0, const SkPoint& p1, const SkIRect* clip, int shiftUp);
     40     // call this version if you know you don't have a clip
     41     inline int setLine(const SkPoint& p0, const SkPoint& p1, int shiftUp);
     42     inline int updateLine(SkFixed ax, SkFixed ay, SkFixed bx, SkFixed by);
     43     void chopLineWithClip(const SkIRect& clip);
     44 
     45     inline bool intersectsClip(const SkIRect& clip) const {
     46         SkASSERT(fFirstY < clip.fBottom);
     47         return fLastY >= clip.fTop;
     48     }
     49 
     50 #ifdef SK_DEBUG
     51     void dump() const {
     52         SkDebugf("edge: firstY:%d lastY:%d x:%g dx:%g w:%d\n", fFirstY, fLastY, SkFixedToFloat(fX), SkFixedToFloat(fDX), fWinding);
     53     }
     54 
     55     void validate() const {
     56         SkASSERT(fPrev && fNext);
     57         SkASSERT(fPrev->fNext == this);
     58         SkASSERT(fNext->fPrev == this);
     59 
     60         SkASSERT(fFirstY <= fLastY);
     61         SkASSERT(SkAbs32(fWinding) == 1);
     62     }
     63 #endif
     64 };
     65 
     66 struct SkQuadraticEdge : public SkEdge {
     67     SkFixed fQx, fQy;
     68     SkFixed fQDx, fQDy;
     69     SkFixed fQDDx, fQDDy;
     70     SkFixed fQLastX, fQLastY;
     71 
     72     int setQuadratic(const SkPoint pts[3], int shiftUp);
     73     int updateQuadratic();
     74 };
     75 
     76 struct SkCubicEdge : public SkEdge {
     77     SkFixed fCx, fCy;
     78     SkFixed fCDx, fCDy;
     79     SkFixed fCDDx, fCDDy;
     80     SkFixed fCDDDx, fCDDDy;
     81     SkFixed fCLastX, fCLastY;
     82 
     83     int setCubic(const SkPoint pts[4], int shiftUp);
     84     int updateCubic();
     85 };
     86 
     87 int SkEdge::setLine(const SkPoint& p0, const SkPoint& p1, int shift) {
     88     SkFDot6 x0, y0, x1, y1;
     89 
     90     {
     91 #ifdef SK_RASTERIZE_EVEN_ROUNDING
     92         x0 = SkScalarRoundToFDot6(p0.fX, shift);
     93         y0 = SkScalarRoundToFDot6(p0.fY, shift);
     94         x1 = SkScalarRoundToFDot6(p1.fX, shift);
     95         y1 = SkScalarRoundToFDot6(p1.fY, shift);
     96 #else
     97         float scale = float(1 << (shift + 6));
     98         x0 = int(p0.fX * scale);
     99         y0 = int(p0.fY * scale);
    100         x1 = int(p1.fX * scale);
    101         y1 = int(p1.fY * scale);
    102 #endif
    103     }
    104 
    105     int winding = 1;
    106 
    107     if (y0 > y1) {
    108         SkTSwap(x0, x1);
    109         SkTSwap(y0, y1);
    110         winding = -1;
    111     }
    112 
    113     int top = SkFDot6Round(y0);
    114     int bot = SkFDot6Round(y1);
    115 
    116     // are we a zero-height line?
    117     if (top == bot) {
    118         return 0;
    119     }
    120 
    121     SkFixed slope = SkFDot6Div(x1 - x0, y1 - y0);
    122     const SkFDot6 dy  = SkEdge_Compute_DY(top, y0);
    123 
    124     fX          = SkFDot6ToFixed(x0 + SkFixedMul(slope, dy));   // + SK_Fixed1/2
    125     fDX         = slope;
    126     fFirstY     = top;
    127     fLastY      = bot - 1;
    128     fCurveCount = 0;
    129     fWinding    = SkToS8(winding);
    130     fCurveShift = 0;
    131     return 1;
    132 }
    133 
    134 
    135 #endif
    136