1 /*
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 
8 #ifndef SkScanPriv_DEFINED
9 #define SkScanPriv_DEFINED
10 
11 #include "include/core/SkPath.h"
12 #include "src/core/SkBlitter.h"
13 #include "src/core/SkScan.h"
14 
15 // controls how much we super-sample (when we use that scan convertion)
16 #define SK_SUPERSAMPLE_SHIFT    2
17 
18 class SkScanClipper {
19 public:
20     SkScanClipper(SkBlitter* blitter, const SkRegion* clip, const SkIRect& bounds,
21                   bool skipRejectTest = false, bool boundsPreClipped = false);
22 
getBlitter()23     SkBlitter*      getBlitter() const { return fBlitter; }
getClipRect()24     const SkIRect*  getClipRect() const { return fClipRect; }
25 
26 private:
27     SkRectClipBlitter   fRectBlitter;
28     SkRgnClipBlitter    fRgnBlitter;
29 #ifdef SK_DEBUG
30     SkRectClipCheckBlitter fRectClipCheckBlitter;
31 #endif
32     SkBlitter*          fBlitter;
33     const SkIRect*      fClipRect;
34 };
35 
36 void sk_fill_path(const SkPath& path, const SkIRect& clipRect,
37                   SkBlitter* blitter, int start_y, int stop_y, int shiftEdgesUp,
38                   bool pathContainedInClip);
39 
40 // blit the rects above and below avoid, clipped to clip
41 void sk_blit_above(SkBlitter*, const SkIRect& avoid, const SkRegion& clip);
42 void sk_blit_below(SkBlitter*, const SkIRect& avoid, const SkRegion& clip);
43 
44 template<class EdgeType>
remove_edge(EdgeType * edge)45 static inline void remove_edge(EdgeType* edge) {
46     edge->fPrev->fNext = edge->fNext;
47     edge->fNext->fPrev = edge->fPrev;
48 }
49 
50 template<class EdgeType>
insert_edge_after(EdgeType * edge,EdgeType * afterMe)51 static inline void insert_edge_after(EdgeType* edge, EdgeType* afterMe) {
52     edge->fPrev = afterMe;
53     edge->fNext = afterMe->fNext;
54     afterMe->fNext->fPrev = edge;
55     afterMe->fNext = edge;
56 }
57 
58 template<class EdgeType>
backward_insert_edge_based_on_x(EdgeType * edge)59 static void backward_insert_edge_based_on_x(EdgeType* edge) {
60     SkFixed x = edge->fX;
61     EdgeType* prev = edge->fPrev;
62     while (prev->fPrev && prev->fX > x) {
63         prev = prev->fPrev;
64     }
65     if (prev->fNext != edge) {
66         remove_edge(edge);
67         insert_edge_after(edge, prev);
68     }
69 }
70 
71 // Start from the right side, searching backwards for the point to begin the new edge list
72 // insertion, marching forwards from here. The implementation could have started from the left
73 // of the prior insertion, and search to the right, or with some additional caching, binary
74 // search the starting point. More work could be done to determine optimal new edge insertion.
75 template<class EdgeType>
backward_insert_start(EdgeType * prev,SkFixed x)76 static EdgeType* backward_insert_start(EdgeType* prev, SkFixed x) {
77     while (prev->fPrev && prev->fX > x) {
78         prev = prev->fPrev;
79     }
80     return prev;
81 }
82 
83 // Check if the path is a rect and fat enough after clipping; if so, blit it.
TryBlitFatAntiRect(SkBlitter * blitter,const SkPath & path,const SkIRect & clip)84 static inline bool TryBlitFatAntiRect(SkBlitter* blitter, const SkPath& path, const SkIRect& clip) {
85     SkRect rect;
86     if (!path.isRect(&rect)) {
87         return false; // not rect
88     }
89     if (!rect.intersect(SkRect::Make(clip))) {
90         return true; // The intersection is empty. Hence consider it done.
91     }
92     SkIRect bounds = rect.roundOut();
93     if (bounds.width() < 3) {
94         return false; // not fat
95     }
96     blitter->blitFatAntiRect(rect);
97     return true;
98 }
99 
100 #endif
101