blob: 9be932552187e93d509fa2bfcf799abf019b6f5a [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00008
9#ifndef SkEdge_DEFINED
10#define SkEdge_DEFINED
11
12#include "SkRect.h"
reed@google.comb6a2ba72012-08-02 16:08:51 +000013#include "SkFDot6.h"
14#include "SkMath.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000015
reed@google.come4646db2013-02-22 14:02:58 +000016// This correctly favors the lower-pixel when y0 is on a 1/2 pixel boundary
caryclark3127c992015-12-09 12:02:30 -080017#define SkEdge_Compute_DY(top, y0) (SkLeftShift(top, 6) + 32 - (y0))
reed@google.com09a029b2012-10-30 14:28:03 +000018
reed@android.com8a1c16f2008-12-17 15:59:43 +000019struct SkEdge {
20 enum Type {
21 kLine_Type,
22 kQuad_Type,
23 kCubic_Type
24 };
25
26 SkEdge* fNext;
27 SkEdge* fPrev;
28
29 SkFixed fX;
30 SkFixed fDX;
31 int32_t fFirstY;
32 int32_t fLastY;
33 int8_t fCurveCount; // only used by kQuad(+) and kCubic(-)
34 uint8_t fCurveShift; // appled to all Dx/DDx/DDDx except for fCubicDShift exception
35 uint8_t fCubicDShift; // applied to fCDx and fCDy only in cubic
36 int8_t fWinding; // 1 or -1
37
reede053ca42015-03-19 09:49:09 -070038 int setLine(const SkPoint& p0, const SkPoint& p1, const SkIRect* clip, int shiftUp);
reed@google.comb6a2ba72012-08-02 16:08:51 +000039 // call this version if you know you don't have a clip
40 inline int setLine(const SkPoint& p0, const SkPoint& p1, int shiftUp);
reed@android.com8a1c16f2008-12-17 15:59:43 +000041 inline int updateLine(SkFixed ax, SkFixed ay, SkFixed bx, SkFixed by);
42 void chopLineWithClip(const SkIRect& clip);
43
44 inline bool intersectsClip(const SkIRect& clip) const {
45 SkASSERT(fFirstY < clip.fBottom);
46 return fLastY >= clip.fTop;
47 }
48
49#ifdef SK_DEBUG
50 void dump() const {
reed@android.com8a1c16f2008-12-17 15:59:43 +000051 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 +000052 }
53
54 void validate() const {
55 SkASSERT(fPrev && fNext);
56 SkASSERT(fPrev->fNext == this);
57 SkASSERT(fNext->fPrev == this);
58
59 SkASSERT(fFirstY <= fLastY);
60 SkASSERT(SkAbs32(fWinding) == 1);
61 }
62#endif
63};
64
65struct SkQuadraticEdge : public SkEdge {
66 SkFixed fQx, fQy;
67 SkFixed fQDx, fQDy;
68 SkFixed fQDDx, fQDDy;
69 SkFixed fQLastX, fQLastY;
70
liyuqian38911a72016-10-04 11:23:22 -070071 bool setQuadraticWithoutUpdate(const SkPoint pts[3], int shiftUp);
reed@android.comc07d23a2009-02-06 13:30:58 +000072 int setQuadratic(const SkPoint pts[3], int shiftUp);
reed@android.com8a1c16f2008-12-17 15:59:43 +000073 int updateQuadratic();
74};
75
76struct SkCubicEdge : public SkEdge {
77 SkFixed fCx, fCy;
78 SkFixed fCDx, fCDy;
79 SkFixed fCDDx, fCDDy;
80 SkFixed fCDDDx, fCDDDy;
81 SkFixed fCLastX, fCLastY;
82
liyuqian38911a72016-10-04 11:23:22 -070083 bool setCubicWithoutUpdate(const SkPoint pts[4], int shiftUp);
reede053ca42015-03-19 09:49:09 -070084 int setCubic(const SkPoint pts[4], int shiftUp);
reed@android.com8a1c16f2008-12-17 15:59:43 +000085 int updateCubic();
86};
87
reed@google.comb6a2ba72012-08-02 16:08:51 +000088int SkEdge::setLine(const SkPoint& p0, const SkPoint& p1, int shift) {
89 SkFDot6 x0, y0, x1, y1;
rmistry@google.comfbfcd562012-08-23 18:09:54 +000090
reed@google.comb6a2ba72012-08-02 16:08:51 +000091 {
george2f265282014-08-29 08:47:55 -070092#ifdef SK_RASTERIZE_EVEN_ROUNDING
93 x0 = SkScalarRoundToFDot6(p0.fX, shift);
94 y0 = SkScalarRoundToFDot6(p0.fY, shift);
95 x1 = SkScalarRoundToFDot6(p1.fX, shift);
96 y1 = SkScalarRoundToFDot6(p1.fY, shift);
97#else
reed@google.comb6a2ba72012-08-02 16:08:51 +000098 float scale = float(1 << (shift + 6));
99 x0 = int(p0.fX * scale);
100 y0 = int(p0.fY * scale);
101 x1 = int(p1.fX * scale);
102 y1 = int(p1.fY * scale);
george2f265282014-08-29 08:47:55 -0700103#endif
reed@google.comb6a2ba72012-08-02 16:08:51 +0000104 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000105
reed@google.comb6a2ba72012-08-02 16:08:51 +0000106 int winding = 1;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000107
reed@google.comb6a2ba72012-08-02 16:08:51 +0000108 if (y0 > y1) {
109 SkTSwap(x0, x1);
110 SkTSwap(y0, y1);
111 winding = -1;
112 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000113
reed@google.comb6a2ba72012-08-02 16:08:51 +0000114 int top = SkFDot6Round(y0);
115 int bot = SkFDot6Round(y1);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000116
reed@google.comb6a2ba72012-08-02 16:08:51 +0000117 // are we a zero-height line?
118 if (top == bot) {
119 return 0;
120 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000121
reed@google.comb6a2ba72012-08-02 16:08:51 +0000122 SkFixed slope = SkFDot6Div(x1 - x0, y1 - y0);
qiankun.miao1c762162015-03-11 11:12:59 -0700123 const SkFDot6 dy = SkEdge_Compute_DY(top, y0);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000124
reed@google.com09a029b2012-10-30 14:28:03 +0000125 fX = SkFDot6ToFixed(x0 + SkFixedMul(slope, dy)); // + SK_Fixed1/2
reed@google.comb6a2ba72012-08-02 16:08:51 +0000126 fDX = slope;
127 fFirstY = top;
128 fLastY = bot - 1;
129 fCurveCount = 0;
130 fWinding = SkToS8(winding);
131 fCurveShift = 0;
132 return 1;
133}
134
reed@android.com8a1c16f2008-12-17 15:59:43 +0000135#endif