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