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 SkColorFilter_DEFINED
9#define SkColorFilter_DEFINED
10
11#include "SkColor.h"
12#include "SkFlattenable.h"
13#include "SkTDArray.h"
14#include "SkXfermode.h"
15
16class SkBitmap;
17class GrProcessor;
18class GrContext;
19
20/**
21 *  ColorFilters are optional objects in the drawing pipeline. When present in
22 *  a paint, they are called with the "src" colors, and return new colors, which
23 *  are then passed onto the next stage (either ImageFilter or Xfermode).
24 *
25 *  All subclasses are required to be reentrant-safe : it must be legal to share
26 *  the same instance between several threads.
27 */
28class SK_API SkColorFilter : public SkFlattenable {
29public:
30    SK_DECLARE_INST_COUNT(SkColorFilter)
31
32    /**
33     *  If the filter can be represented by a source color plus Mode, this
34     *  returns true, and sets (if not NULL) the color and mode appropriately.
35     *  If not, this returns false and ignores the parameters.
36     */
37    virtual bool asColorMode(SkColor* color, SkXfermode::Mode* mode) const;
38
39    /**
40     *  If the filter can be represented by a 5x4 matrix, this
41     *  returns true, and sets the matrix appropriately.
42     *  If not, this returns false and ignores the parameter.
43     */
44    virtual bool asColorMatrix(SkScalar matrix[20]) const;
45
46    /**
47     *  If the filter can be represented by per-component table, return true,
48     *  and if table is not null, copy the bitmap containing the table into it.
49     *
50     *  The table bitmap will be in SkBitmap::kA8_Config. Each row corresponding
51     *  to each component in ARGB order. e.g. row[0] == alpha, row[1] == red,
52     *  etc. To transform a color, you (logically) perform the following:
53     *
54     *      a' = *table.getAddr8(a, 0);
55     *      r' = *table.getAddr8(r, 1);
56     *      g' = *table.getAddr8(g, 2);
57     *      b' = *table.getAddr8(b, 3);
58     *
59     *  The original component value is the horizontal index for a given row,
60     *  and the stored value at that index is the new value for that component.
61     */
62    virtual bool asComponentTable(SkBitmap* table) const;
63
64    /** Called with a scanline of colors, as if there was a shader installed.
65        The implementation writes out its filtered version into result[].
66        Note: shader and result may be the same buffer.
67        @param src      array of colors, possibly generated by a shader
68        @param count    the number of entries in the src[] and result[] arrays
69        @param result   written by the filter
70    */
71    virtual void filterSpan(const SkPMColor src[], int count, SkPMColor result[]) const = 0;
72
73    enum Flags {
74        /** If set the filter methods will not change the alpha channel of the colors.
75        */
76        kAlphaUnchanged_Flag = 0x01,
77    };
78
79    /** Returns the flags for this filter. Override in subclasses to return custom flags.
80    */
81    virtual uint32_t getFlags() const { return 0; }
82
83    /**
84     *  If this subclass can optimally createa composition with the inner filter, return it as
85     *  a new filter (which the caller must unref() when it is done). If no such optimization
86     *  is known, return NULL.
87     *
88     *  e.g. result(color) == this_filter(inner(color))
89     */
90    virtual SkColorFilter* newComposed(const SkColorFilter* /*inner*/) const { return NULL; }
91
92    /**
93     *  Apply this colorfilter to the specified SkColor. This routine handles
94     *  converting to SkPMColor, calling the filter, and then converting back
95     *  to SkColor. This method is not virtual, but will call filterSpan()
96     *   which is virtual.
97     */
98    SkColor filterColor(SkColor) const;
99
100    /** Create a colorfilter that uses the specified color and mode.
101        If the Mode is DST, this function will return NULL (since that
102        mode will have no effect on the result).
103        @param c    The source color used with the specified mode
104        @param mode The xfermode mode that is applied to each color in
105                        the colorfilter's filterSpan[16,32] methods
106        @return colorfilter object that applies the src color and mode,
107                    or NULL if the mode will have no effect.
108    */
109    static SkColorFilter* CreateModeFilter(SkColor c, SkXfermode::Mode mode);
110
111    /** Create a colorfilter that multiplies the RGB channels by one color, and
112        then adds a second color, pinning the result for each component to
113        [0..255]. The alpha components of the mul and add arguments
114        are ignored.
115    */
116    static SkColorFilter* CreateLightingFilter(SkColor mul, SkColor add);
117
118    /** Construct a colorfilter whose effect is to first apply the inner filter and then apply
119     *  the outer filter to the result of the inner's.
120     *  The reference counts for outer and inner are incremented.
121     *
122     *  Due to internal limits, it is possible that this will return NULL, so the caller must
123     *  always check.
124     */
125    static SkColorFilter* CreateComposeFilter(SkColorFilter* outer, SkColorFilter* inner);
126
127    /**
128     *  A subclass may implement this factory function to work with the GPU backend.
129     *  If it returns true, then 1 or more fragment processors will have been appended to the
130     *  array, each of which has been ref'd, so that the caller is responsible for calling unref()
131     *  on them when they are finished. If more than one processor is appended, they will be
132     *  applied in FIFO order.
133     *
134     *  The fragment processor(s) must each return their color as a premul normalized value
135     *  e.g. each component between [0..1] and each color component <= alpha.
136     *
137     *  If the subclass returns false, then it should not modify the array at all.
138     */
139    virtual bool asFragmentProcessors(GrContext*, SkTDArray<GrFragmentProcessor*>*) const {
140        return false;
141    }
142
143    SK_TO_STRING_PUREVIRT()
144
145    SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
146    SK_DEFINE_FLATTENABLE_TYPE(SkColorFilter)
147
148protected:
149    SkColorFilter() {}
150
151private:
152    /*
153     *  Returns 1 if this is a single filter (not a composition of other filters), otherwise it
154     *  reutrns the number of leaf-node filters in a composition. This should be the same value
155     *  as the number of GrFragmentProcessors returned by asFragmentProcessors's array parameter.
156     *
157     *  e.g. compose(filter, compose(compose(filter, filter), filter)) --> 4
158     */
159    virtual int privateComposedFilterCount() const { return 1; }
160    friend class SkComposeColorFilter;
161
162    typedef SkFlattenable INHERITED;
163};
164
165#endif
166