|
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) ((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, |
|
40 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 |
|
46 inline bool intersectsClip(const SkIRect& clip) const { |
|
47 SkASSERT(fFirstY < clip.fBottom); |
|
48 return fLastY >= clip.fTop; |
|
49 } |
|
50 |
|
51 #ifdef SK_DEBUG |
|
52 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 |
|
56 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 int setQuadratic(const SkPoint pts[3], int shiftUp); |
|
74 int updateQuadratic(); |
|
75 }; |
|
76 |
|
77 struct SkCubicEdge : public SkEdge { |
|
78 SkFixed fCx, fCy; |
|
79 SkFixed fCDx, fCDy; |
|
80 SkFixed fCDDx, fCDDy; |
|
81 SkFixed fCDDDx, fCDDDy; |
|
82 SkFixed fCLastX, fCLastY; |
|
83 |
|
84 int setCubic(const SkPoint pts[4], const SkIRect* clip, int shiftUp); |
|
85 int updateCubic(); |
|
86 }; |
|
87 |
|
88 int SkEdge::setLine(const SkPoint& p0, const SkPoint& p1, int shift) { |
|
89 SkFDot6 x0, y0, x1, y1; |
|
90 |
|
91 { |
|
92 float scale = float(1 << (shift + 6)); |
|
93 x0 = int(p0.fX * scale); |
|
94 y0 = int(p0.fY * scale); |
|
95 x1 = int(p1.fX * scale); |
|
96 y1 = int(p1.fY * scale); |
|
97 } |
|
98 |
|
99 int winding = 1; |
|
100 |
|
101 if (y0 > y1) { |
|
102 SkTSwap(x0, x1); |
|
103 SkTSwap(y0, y1); |
|
104 winding = -1; |
|
105 } |
|
106 |
|
107 int top = SkFDot6Round(y0); |
|
108 int bot = SkFDot6Round(y1); |
|
109 |
|
110 // are we a zero-height line? |
|
111 if (top == bot) { |
|
112 return 0; |
|
113 } |
|
114 |
|
115 SkFixed slope = SkFDot6Div(x1 - x0, y1 - y0); |
|
116 const int dy = SkEdge_Compute_DY(top, y0); |
|
117 |
|
118 fX = SkFDot6ToFixed(x0 + SkFixedMul(slope, dy)); // + SK_Fixed1/2 |
|
119 fDX = slope; |
|
120 fFirstY = top; |
|
121 fLastY = bot - 1; |
|
122 fCurveCount = 0; |
|
123 fWinding = SkToS8(winding); |
|
124 fCurveShift = 0; |
|
125 return 1; |
|
126 } |
|
127 |
|
128 |
|
129 #endif |