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