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) (SkLeftShift(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
intersectsClipSkEdge45 inline bool intersectsClip(const SkIRect& clip) const {
46 SkASSERT(fFirstY < clip.fBottom);
47 return fLastY >= clip.fTop;
48 }
49
50 #ifdef SK_DEBUG
dumpSkEdge51 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
validateSkEdge55 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
setLine(const SkPoint & p0,const SkPoint & p1,int shift)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