1 
2 /*
3  * Copyright 2011 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 #ifndef GrPaint_DEFINED
11 #define GrPaint_DEFINED
12 
13 #include "GrColor.h"
14 #include "GrFragmentStage.h"
15 #include "GrXferProcessor.h"
16 #include "effects/GrPorterDuffXferProcessor.h"
17 
18 #include "SkRegion.h"
19 #include "SkXfermode.h"
20 
21 /**
22  * The paint describes how color and coverage are computed at each pixel by GrContext draw
23  * functions and the how color is blended with the destination pixel.
24  *
25  * The paint allows installation of custom color and coverage stages. New types of stages are
26  * created by subclassing GrProcessor.
27  *
28  * The primitive color computation starts with the color specified by setColor(). This color is the
29  * input to the first color stage. Each color stage feeds its output to the next color stage.
30  *
31  * Fractional pixel coverage follows a similar flow. The coverage is initially the value specified
32  * by setCoverage(). This is input to the first coverage stage. Coverage stages are chained
33  * together in the same manner as color stages. The output of the last stage is modulated by any
34  * fractional coverage produced by anti-aliasing. This last step produces the final coverage, C.
35  *
36  * setXPFactory is used to control blending between the output color and dest. It also implements
37  * the application of fractional coverage from the coverage pipeline.
38  */
39 class GrPaint {
40 public:
41     GrPaint();
42 
GrPaint(const GrPaint & paint)43     GrPaint(const GrPaint& paint) { *this = paint; }
44 
~GrPaint()45     ~GrPaint() {}
46 
47     /**
48      * The initial color of the drawn primitive. Defaults to solid white.
49      */
setColor(GrColor color)50     void setColor(GrColor color) { fColor = color; }
getColor()51     GrColor getColor() const { return fColor; }
52 
53     /**
54      * Should primitives be anti-aliased or not. Defaults to false.
55      */
setAntiAlias(bool aa)56     void setAntiAlias(bool aa) { fAntiAlias = aa; }
isAntiAlias()57     bool isAntiAlias() const { return fAntiAlias; }
58 
59     /**
60      * Should dithering be applied. Defaults to false.
61      */
setDither(bool dither)62     void setDither(bool dither) { fDither = dither; }
isDither()63     bool isDither() const { return fDither; }
64 
setXPFactory(const GrXPFactory * xpFactory)65     const GrXPFactory* setXPFactory(const GrXPFactory* xpFactory) {
66         fXPFactory.reset(SkRef(xpFactory));
67         return xpFactory;
68     }
69 
setPorterDuffXPFactory(SkXfermode::Mode mode)70     void setPorterDuffXPFactory(SkXfermode::Mode mode) {
71         fXPFactory.reset(GrPorterDuffXPFactory::Create(mode));
72     }
73 
74     void setCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage = false);
75 
76     /**
77      * Appends an additional color processor to the color computation.
78      */
addColorProcessor(const GrFragmentProcessor * fp)79     const GrFragmentProcessor* addColorProcessor(const GrFragmentProcessor* fp) {
80         SkASSERT(fp);
81         SkNEW_APPEND_TO_TARRAY(&fColorStages, GrFragmentStage, (fp));
82         return fp;
83     }
84 
85     /**
86      * Appends an additional coverage processor to the coverage computation.
87      */
addCoverageProcessor(const GrFragmentProcessor * fp)88     const GrFragmentProcessor* addCoverageProcessor(const GrFragmentProcessor* fp) {
89         SkASSERT(fp);
90         SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrFragmentStage, (fp));
91         return fp;
92     }
93 
94     /**
95      * Helpers for adding color or coverage effects that sample a texture. The matrix is applied
96      * to the src space position to compute texture coordinates.
97      */
98     void addColorTextureProcessor(GrTexture*, const SkMatrix&);
99     void addCoverageTextureProcessor(GrTexture*, const SkMatrix&);
100     void addColorTextureProcessor(GrTexture*, const SkMatrix&, const GrTextureParams&);
101     void addCoverageTextureProcessor(GrTexture*, const SkMatrix&, const GrTextureParams&);
102 
numColorStages()103     int numColorStages() const { return fColorStages.count(); }
numCoverageStages()104     int numCoverageStages() const { return fCoverageStages.count(); }
numTotalStages()105     int numTotalStages() const { return this->numColorStages() + this->numCoverageStages(); }
106 
getXPFactory()107     const GrXPFactory* getXPFactory() const {
108         if (!fXPFactory) {
109             fXPFactory.reset(GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode));
110         }
111         return fXPFactory.get();
112     }
113 
getColorStage(int s)114     const GrFragmentStage& getColorStage(int s) const { return fColorStages[s]; }
getCoverageStage(int s)115     const GrFragmentStage& getCoverageStage(int s) const { return fCoverageStages[s]; }
116 
117     GrPaint& operator=(const GrPaint& paint) {
118         fAntiAlias = paint.fAntiAlias;
119         fDither = paint.fDither;
120 
121         fColor = paint.fColor;
122 
123         fColorStages = paint.fColorStages;
124         fCoverageStages = paint.fCoverageStages;
125 
126         fXPFactory.reset(SkRef(paint.getXPFactory()));
127 
128         return *this;
129     }
130 
131     /**
132      * Returns true if isOpaque would return true and the paint represents a solid constant color
133      * draw. If the result is true, constantColor will be updated to contain the constant color.
134      */
135     bool isOpaqueAndConstantColor(GrColor* constantColor) const;
136 
137 private:
138     mutable SkAutoTUnref<const GrXPFactory> fXPFactory;
139     SkSTArray<4, GrFragmentStage>   fColorStages;
140     SkSTArray<2, GrFragmentStage>   fCoverageStages;
141 
142     bool                            fAntiAlias;
143     bool                            fDither;
144 
145     GrColor                         fColor;
146 };
147 
148 #endif
149