Home | History | Annotate | Download | only in core
      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 || bounds.height() < 3) {
     94         return false; // not fat
     95     }
     96     blitter->blitFatAntiRect(rect);
     97     return true;
     98 }
     99 
    100 #endif
    101