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 18class SkScanClipper { 19public: 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 26private: 27 SkRectClipBlitter fRectBlitter; 28 SkRgnClipBlitter fRgnBlitter; 29#ifdef SK_DEBUG 30 SkRectClipCheckBlitter fRectClipCheckBlitter; 31#endif 32 SkBlitter* fBlitter; 33 const SkIRect* fClipRect; 34}; 35 36void 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 41void sk_blit_above(SkBlitter*, const SkIRect& avoid, const SkRegion& clip); 42void sk_blit_below(SkBlitter*, const SkIRect& avoid, const SkRegion& clip); 43 44template<class EdgeType> 45static inline void remove_edge(EdgeType* edge) { 46 edge->fPrev->fNext = edge->fNext; 47 edge->fNext->fPrev = edge->fPrev; 48} 49 50template<class EdgeType> 51static 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 58template<class EdgeType> 59static 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. 75template<class EdgeType> 76static 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. 84static 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 || bounds.height() < 3) { 94 return false; // not fat 95 } 96 blitter->blitFatAntiRect(rect); 97 return true; 98} 99 100#endif 101