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