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 "SkPath.h" 12 #include "SkScan.h" 13 #include "SkBlitter.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 23 SkBlitter* getBlitter() const { return fBlitter; } 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> 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> 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> 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> 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. 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