• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
intersectsClipSkEdge51     inline bool intersectsClip(const SkIRect& clip) const {
52         SkASSERT(fFirstY < clip.fBottom);
53         return fLastY >= clip.fTop;
54     }
55 
56 #ifdef SK_DEBUG
dumpSkEdge57     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 
validateSkEdge61     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 
setLine(const SkPoint & p0,const SkPoint & p1,int shift)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