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