blob: 091223631fed4b4058a6ed93d59a5de638701999 [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.come4646db2013-02-22 14:02:58 +000017// 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))
reed@google.com09a029b2012-10-30 14:28:03 +000019
reed@android.com8a1c16f2008-12-17 15:59:43 +000020struct 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);
reed@google.comb6a2ba72012-08-02 16:08:51 +000041 // call this version if you know you don't have a clip
42 inline int setLine(const SkPoint& p0, const SkPoint& p1, int shiftUp);
reed@android.com8a1c16f2008-12-17 15:59:43 +000043 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 {
reed@android.com8a1c16f2008-12-17 15:59:43 +000053 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 +000054 }
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
67struct SkQuadraticEdge : public SkEdge {
68 SkFixed fQx, fQy;
69 SkFixed fQDx, fQDy;
70 SkFixed fQDDx, fQDDy;
71 SkFixed fQLastX, fQLastY;
72
reed@android.comc07d23a2009-02-06 13:30:58 +000073 int setQuadratic(const SkPoint pts[3], int shiftUp);
reed@android.com8a1c16f2008-12-17 15:59:43 +000074 int updateQuadratic();
75};
76
77struct 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
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 {
reed@google.comb6a2ba72012-08-02 16:08:51 +000092 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);
reed@google.comb6a2ba72012-08-02 16:08:51 +000097 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000098
reed@google.comb6a2ba72012-08-02 16:08:51 +000099 int winding = 1;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000100
reed@google.comb6a2ba72012-08-02 16:08:51 +0000101 if (y0 > y1) {
102 SkTSwap(x0, x1);
103 SkTSwap(y0, y1);
104 winding = -1;
105 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000106
reed@google.comb6a2ba72012-08-02 16:08:51 +0000107 int top = SkFDot6Round(y0);
108 int bot = SkFDot6Round(y1);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000109
reed@google.comb6a2ba72012-08-02 16:08:51 +0000110 // are we a zero-height line?
111 if (top == bot) {
112 return 0;
113 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000114
reed@google.comb6a2ba72012-08-02 16:08:51 +0000115 SkFixed slope = SkFDot6Div(x1 - x0, y1 - y0);
reed@google.com09a029b2012-10-30 14:28:03 +0000116 const int dy = SkEdge_Compute_DY(top, y0);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000117
reed@google.com09a029b2012-10-30 14:28:03 +0000118 fX = SkFDot6ToFixed(x0 + SkFixedMul(slope, dy)); // + SK_Fixed1/2
reed@google.comb6a2ba72012-08-02 16:08:51 +0000119 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
reed@android.com8a1c16f2008-12-17 15:59:43 +0000129#endif