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 | |
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 | 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 | |
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 | |