SkEdge.h revision 8f4d2306fa866a26f9448048ff63f692b2ba43aa
1
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
9
10#ifndef SkEdge_DEFINED
11#define SkEdge_DEFINED
12
13#include "SkRect.h"
14#include "SkFDot6.h"
15#include "SkMath.h"
16
17// 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))
19
20struct 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);
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
67struct SkQuadraticEdge : public SkEdge {
68    SkFixed fQx, fQy;
69    SkFixed fQDx, fQDy;
70    SkFixed fQDDx, fQDDy;
71    SkFixed fQLastX, fQLastY;
72
73    int setQuadratic(const SkPoint pts[3], int shiftUp);
74    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
88int SkEdge::setLine(const SkPoint& p0, const SkPoint& p1, int shift) {
89    SkFDot6 x0, y0, x1, y1;
90
91    {
92        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);
97    }
98
99    int winding = 1;
100
101    if (y0 > y1) {
102        SkTSwap(x0, x1);
103        SkTSwap(y0, y1);
104        winding = -1;
105    }
106
107    int top = SkFDot6Round(y0);
108    int bot = SkFDot6Round(y1);
109
110    // are we a zero-height line?
111    if (top == bot) {
112        return 0;
113    }
114
115    SkFixed slope = SkFDot6Div(x1 - x0, y1 - y0);
116    const int dy  = SkEdge_Compute_DY(top, y0);
117
118    fX          = SkFDot6ToFixed(x0 + SkFixedMul(slope, dy));   // + SK_Fixed1/2
119    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
129#endif
130