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