blob: 22a26d00c89b53214d96c46d2867a11957d424d2 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
10#ifndef SkEdge_DEFINED
11#define SkEdge_DEFINED
12
13#include "SkRect.h"
reed@google.comb6a2ba72012-08-02 16:08:51 +000014#include "SkFDot6.h"
15#include "SkMath.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000016
17struct SkEdge {
18 enum Type {
19 kLine_Type,
20 kQuad_Type,
21 kCubic_Type
22 };
23
24 SkEdge* fNext;
25 SkEdge* fPrev;
26
27 SkFixed fX;
28 SkFixed fDX;
29 int32_t fFirstY;
30 int32_t fLastY;
31 int8_t fCurveCount; // only used by kQuad(+) and kCubic(-)
32 uint8_t fCurveShift; // appled to all Dx/DDx/DDDx except for fCubicDShift exception
33 uint8_t fCubicDShift; // applied to fCDx and fCDy only in cubic
34 int8_t fWinding; // 1 or -1
35
36 int setLine(const SkPoint& p0, const SkPoint& p1, const SkIRect* clip,
37 int shiftUp);
reed@google.comb6a2ba72012-08-02 16:08:51 +000038 // call this version if you know you don't have a clip
39 inline int setLine(const SkPoint& p0, const SkPoint& p1, int shiftUp);
reed@android.com8a1c16f2008-12-17 15:59:43 +000040 inline int updateLine(SkFixed ax, SkFixed ay, SkFixed bx, SkFixed by);
41 void chopLineWithClip(const SkIRect& clip);
42
43 inline bool intersectsClip(const SkIRect& clip) const {
44 SkASSERT(fFirstY < clip.fBottom);
45 return fLastY >= clip.fTop;
46 }
47
48#ifdef SK_DEBUG
49 void dump() const {
reed@android.com8a1c16f2008-12-17 15:59:43 +000050 SkDebugf("edge: firstY:%d lastY:%d x:%g dx:%g w:%d\n", fFirstY, fLastY, SkFixedToFloat(fX), SkFixedToFloat(fDX), fWinding);
reed@android.com8a1c16f2008-12-17 15:59:43 +000051 }
52
53 void validate() const {
54 SkASSERT(fPrev && fNext);
55 SkASSERT(fPrev->fNext == this);
56 SkASSERT(fNext->fPrev == this);
57
58 SkASSERT(fFirstY <= fLastY);
59 SkASSERT(SkAbs32(fWinding) == 1);
60 }
61#endif
62};
63
64struct SkQuadraticEdge : public SkEdge {
65 SkFixed fQx, fQy;
66 SkFixed fQDx, fQDy;
67 SkFixed fQDDx, fQDDy;
68 SkFixed fQLastX, fQLastY;
69
reed@android.comc07d23a2009-02-06 13:30:58 +000070 int setQuadratic(const SkPoint pts[3], int shiftUp);
reed@android.com8a1c16f2008-12-17 15:59:43 +000071 int updateQuadratic();
72};
73
74struct SkCubicEdge : public SkEdge {
75 SkFixed fCx, fCy;
76 SkFixed fCDx, fCDy;
77 SkFixed fCDDx, fCDDy;
78 SkFixed fCDDDx, fCDDDy;
79 SkFixed fCLastX, fCLastY;
80
81 int setCubic(const SkPoint pts[4], const SkIRect* clip, int shiftUp);
82 int updateCubic();
83};
84
reed@google.comb6a2ba72012-08-02 16:08:51 +000085int SkEdge::setLine(const SkPoint& p0, const SkPoint& p1, int shift) {
86 SkFDot6 x0, y0, x1, y1;
87
88 {
89#ifdef SK_SCALAR_IS_FLOAT
90 float scale = float(1 << (shift + 6));
91 x0 = int(p0.fX * scale);
92 y0 = int(p0.fY * scale);
93 x1 = int(p1.fX * scale);
94 y1 = int(p1.fY * scale);
95#else
96 shift = 10 - shift;
97 x0 = p0.fX >> shift;
98 y0 = p0.fY >> shift;
99 x1 = p1.fX >> shift;
100 y1 = p1.fY >> shift;
101#endif
102 }
103
104 int winding = 1;
105
106 if (y0 > y1) {
107 SkTSwap(x0, x1);
108 SkTSwap(y0, y1);
109 winding = -1;
110 }
111
112 int top = SkFDot6Round(y0);
113 int bot = SkFDot6Round(y1);
114
115 // are we a zero-height line?
116 if (top == bot) {
117 return 0;
118 }
119
120 SkFixed slope = SkFDot6Div(x1 - x0, y1 - y0);
121
122 fX = SkFDot6ToFixed(x0 + SkFixedMul(slope, (32 - y0) & 63)); // + SK_Fixed1/2
123 fDX = slope;
124 fFirstY = top;
125 fLastY = bot - 1;
126 fCurveCount = 0;
127 fWinding = SkToS8(winding);
128 fCurveShift = 0;
129 return 1;
130}
131
132
reed@android.com8a1c16f2008-12-17 15:59:43 +0000133#endif