blob: c36ba246ced641d40192458722bce31634744747 [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
reed@google.com09a029b2012-10-30 14:28:03 +000017//#ifdef SK_IGNORE_SETLINE_FIX
18#if 1
19 #define SkEdge_Compute_DY(top, y0) ((32 - (y0)) & 63)
20#else
21 // This is correct, as it favors the lower-pixel when y0 is on a 1/2 pixel
22 // boundary, returning 64 instead of the old code, which returns 0.
23 #define SkEdge_Compute_DY(top, y0) ((top << 6) + 32 - (y0))
24#endif
25
reed@android.com8a1c16f2008-12-17 15:59:43 +000026struct SkEdge {
27 enum Type {
28 kLine_Type,
29 kQuad_Type,
30 kCubic_Type
31 };
32
33 SkEdge* fNext;
34 SkEdge* fPrev;
35
36 SkFixed fX;
37 SkFixed fDX;
38 int32_t fFirstY;
39 int32_t fLastY;
40 int8_t fCurveCount; // only used by kQuad(+) and kCubic(-)
41 uint8_t fCurveShift; // appled to all Dx/DDx/DDDx except for fCubicDShift exception
42 uint8_t fCubicDShift; // applied to fCDx and fCDy only in cubic
43 int8_t fWinding; // 1 or -1
44
45 int setLine(const SkPoint& p0, const SkPoint& p1, const SkIRect* clip,
46 int shiftUp);
reed@google.comb6a2ba72012-08-02 16:08:51 +000047 // call this version if you know you don't have a clip
48 inline int setLine(const SkPoint& p0, const SkPoint& p1, int shiftUp);
reed@android.com8a1c16f2008-12-17 15:59:43 +000049 inline int updateLine(SkFixed ax, SkFixed ay, SkFixed bx, SkFixed by);
50 void chopLineWithClip(const SkIRect& clip);
51
52 inline bool intersectsClip(const SkIRect& clip) const {
53 SkASSERT(fFirstY < clip.fBottom);
54 return fLastY >= clip.fTop;
55 }
56
57#ifdef SK_DEBUG
58 void dump() const {
reed@android.com8a1c16f2008-12-17 15:59:43 +000059 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 +000060 }
61
62 void validate() const {
63 SkASSERT(fPrev && fNext);
64 SkASSERT(fPrev->fNext == this);
65 SkASSERT(fNext->fPrev == this);
66
67 SkASSERT(fFirstY <= fLastY);
68 SkASSERT(SkAbs32(fWinding) == 1);
69 }
70#endif
71};
72
73struct SkQuadraticEdge : public SkEdge {
74 SkFixed fQx, fQy;
75 SkFixed fQDx, fQDy;
76 SkFixed fQDDx, fQDDy;
77 SkFixed fQLastX, fQLastY;
78
reed@android.comc07d23a2009-02-06 13:30:58 +000079 int setQuadratic(const SkPoint pts[3], int shiftUp);
reed@android.com8a1c16f2008-12-17 15:59:43 +000080 int updateQuadratic();
81};
82
83struct SkCubicEdge : public SkEdge {
84 SkFixed fCx, fCy;
85 SkFixed fCDx, fCDy;
86 SkFixed fCDDx, fCDDy;
87 SkFixed fCDDDx, fCDDDy;
88 SkFixed fCLastX, fCLastY;
89
90 int setCubic(const SkPoint pts[4], const SkIRect* clip, int shiftUp);
91 int updateCubic();
92};
93
reed@google.comb6a2ba72012-08-02 16:08:51 +000094int SkEdge::setLine(const SkPoint& p0, const SkPoint& p1, int shift) {
95 SkFDot6 x0, y0, x1, y1;
rmistry@google.comfbfcd562012-08-23 18:09:54 +000096
reed@google.comb6a2ba72012-08-02 16:08:51 +000097 {
98#ifdef SK_SCALAR_IS_FLOAT
99 float scale = float(1 << (shift + 6));
100 x0 = int(p0.fX * scale);
101 y0 = int(p0.fY * scale);
102 x1 = int(p1.fX * scale);
103 y1 = int(p1.fY * scale);
104#else
105 shift = 10 - shift;
106 x0 = p0.fX >> shift;
107 y0 = p0.fY >> shift;
108 x1 = p1.fX >> shift;
109 y1 = p1.fY >> shift;
110#endif
111 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000112
reed@google.comb6a2ba72012-08-02 16:08:51 +0000113 int winding = 1;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000114
reed@google.comb6a2ba72012-08-02 16:08:51 +0000115 if (y0 > y1) {
116 SkTSwap(x0, x1);
117 SkTSwap(y0, y1);
118 winding = -1;
119 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000120
reed@google.comb6a2ba72012-08-02 16:08:51 +0000121 int top = SkFDot6Round(y0);
122 int bot = SkFDot6Round(y1);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000123
reed@google.comb6a2ba72012-08-02 16:08:51 +0000124 // are we a zero-height line?
125 if (top == bot) {
126 return 0;
127 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000128
reed@google.comb6a2ba72012-08-02 16:08:51 +0000129 SkFixed slope = SkFDot6Div(x1 - x0, y1 - y0);
reed@google.com09a029b2012-10-30 14:28:03 +0000130 const int dy = SkEdge_Compute_DY(top, y0);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000131
reed@google.com09a029b2012-10-30 14:28:03 +0000132 fX = SkFDot6ToFixed(x0 + SkFixedMul(slope, dy)); // + SK_Fixed1/2
reed@google.comb6a2ba72012-08-02 16:08:51 +0000133 fDX = slope;
134 fFirstY = top;
135 fLastY = bot - 1;
136 fCurveCount = 0;
137 fWinding = SkToS8(winding);
138 fCurveShift = 0;
139 return 1;
140}
141
142
reed@android.com8a1c16f2008-12-17 15:59:43 +0000143#endif