1e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
2e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/*
3e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * Copyright 2011 Google Inc.
4e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com *
5e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * Use of this source code is governed by a BSD-style license that can be
6e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * found in the LICENSE file.
7e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com */
8e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
9e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#ifndef SkAAClip_DEFINED
10e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#define SkAAClip_DEFINED
11e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
12e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkBlitter.h"
13e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkRegion.h"
14e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
15e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comclass SkAAClip {
16e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.compublic:
17e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkAAClip();
18e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkAAClip(const SkAAClip&);
19e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    ~SkAAClip();
20e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
21e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkAAClip& operator=(const SkAAClip&);
22e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    friend bool operator==(const SkAAClip&, const SkAAClip&);
23e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    friend bool operator!=(const SkAAClip& a, const SkAAClip& b) {
24e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        return !(a == b);
25e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
26e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
27e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    void swap(SkAAClip&);
28e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
2947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    bool isEmpty() const { return NULL == fRunHead; }
30e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const SkIRect& getBounds() const { return fBounds; }
31e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
32202ab2a5cabaf25a1e6ec47c0003da3213a79864reed    // Returns true iff the clip is not empty, and is just a hard-edged rect (no partial alpha).
33202ab2a5cabaf25a1e6ec47c0003da3213a79864reed    // If true, getBounds() can be used in place of this clip.
34202ab2a5cabaf25a1e6ec47c0003da3213a79864reed    bool isRect() const;
35202ab2a5cabaf25a1e6ec47c0003da3213a79864reed
36e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    bool setEmpty();
37e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    bool setRect(const SkIRect&);
38f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    bool setRect(const SkRect&, bool doAA = true);
39f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    bool setPath(const SkPath&, const SkRegion* clip = NULL, bool doAA = true);
40f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com    bool setRegion(const SkRegion&);
41322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    bool set(const SkAAClip&);
42e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
43e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    bool op(const SkAAClip&, const SkAAClip&, SkRegion::Op);
44e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
4547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    // Helpers for op()
4647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    bool op(const SkIRect&, SkRegion::Op);
470017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    bool op(const SkRect&, SkRegion::Op, bool doAA);
4847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com    bool op(const SkAAClip&, SkRegion::Op);
4947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com
5034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    bool translate(int dx, int dy, SkAAClip* dst) const;
5134f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    bool translate(int dx, int dy) {
5234f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        return this->translate(dx, dy, this);
5334f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    }
541c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com
55322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    /**
56322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com     *  Allocates a mask the size of the aaclip, and expands its data into
57322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com     *  the mask, using kA8_Format
58322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com     */
59322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    void copyToMask(SkMask*) const;
60322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com
61e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    // called internally
62fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
63e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    bool quickContains(int left, int top, int right, int bottom) const;
64045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    bool quickContains(const SkIRect& r) const {
65045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        return this->quickContains(r.fLeft, r.fTop, r.fRight, r.fBottom);
66045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
67045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
68a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com    const uint8_t* findRow(int y, int* lastYForRow = NULL) const;
69a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com    const uint8_t* findX(const uint8_t data[], int x, int* initialCount = NULL) const;
70e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
71322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    class Iter;
72e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    struct RunHead;
73e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    struct YOffset;
74322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com    class Builder;
75e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
76045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#ifdef SK_DEBUG
77045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    void validate() const;
786d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper    void debug(bool compress_y=false) const;
79045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#else
80045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    void validate() const {}
816d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper    void debug(bool compress_y=false) const {}
82045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif
83045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
84322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comprivate:
85e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkIRect  fBounds;
86e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    RunHead* fRunHead;
87e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
88e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    void freeRuns();
89045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    bool trimBounds();
90c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    bool trimTopBottom();
91c90419199525141a5b98091f856e359bf9daf5b1reed@google.com    bool trimLeftRight();
92e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
93e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    friend class Builder;
94e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    class BuilderBlitter;
95e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    friend class BuilderBlitter;
96e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com};
97e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
98e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com///////////////////////////////////////////////////////////////////////////////
99e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
100e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comclass SkAAClipBlitter : public SkBlitter {
101e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.compublic:
102045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkAAClipBlitter() : fScanlineScratch(NULL) {}
103e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    virtual ~SkAAClipBlitter();
104e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
105e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    void init(SkBlitter* blitter, const SkAAClip* aaclip) {
106e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        SkASSERT(aaclip && !aaclip->isEmpty());
107e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fBlitter = blitter;
108e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fAAClip = aaclip;
109e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com        fAAClipBounds = aaclip->getBounds();
110e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    }
111fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
112e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    virtual void blitH(int x, int y, int width) SK_OVERRIDE;
113e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    virtual void blitAntiH(int x, int y, const SkAlpha[],
114e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com                           const int16_t runs[]) SK_OVERRIDE;
115e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    virtual void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE;
116e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    virtual void blitRect(int x, int y, int width, int height) SK_OVERRIDE;
117e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    virtual void blitMask(const SkMask&, const SkIRect& clip) SK_OVERRIDE;
118e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    virtual const SkBitmap* justAnOpaqueColor(uint32_t* value) SK_OVERRIDE;
119fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
120e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comprivate:
121e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkBlitter*      fBlitter;
122e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    const SkAAClip* fAAClip;
123e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    SkIRect         fAAClipBounds;
124e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
125045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // point into fScanlineScratch
126e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    int16_t*        fRuns;
127045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkAlpha*        fAA;
128045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
129045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    enum {
130045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        kSize = 32 * 32
131045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    };
132045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkAutoSMalloc<kSize> fGrayMaskScratch;  // used for blitMask
133045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    void* fScanlineScratch;  // enough for a mask at 32bit, or runs+aa
134e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
135e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com    void ensureRunsAndAA();
136e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com};
137e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com
138e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#endif
139