180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2012 Google Inc.
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifndef SkMaskGamma_DEFINED
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkMaskGamma_DEFINED
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTypes.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkColor.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkColorPriv.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkRefCnt.h"
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/**
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * SkColorSpaceLuminance is used to convert luminances to and from linear and
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * perceptual color spaces.
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Luma is used to specify a linear luminance value [0.0, 1.0].
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Luminance is used to specify a luminance value in an arbitrary color space [0.0, 1.0].
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkColorSpaceLuminance : SkNoncopyable {
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual ~SkColorSpaceLuminance() { }
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Converts a color component luminance in the color space to a linear luma. */
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual SkScalar toLuma(SkScalar gamma, SkScalar luminance) const = 0;
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Converts a linear luma to a color component luminance in the color space. */
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual SkScalar fromLuma(SkScalar gamma, SkScalar luma) const = 0;
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Converts a color to a luminance value. */
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static U8CPU computeLuminance(SkScalar gamma, SkColor c) {
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const SkColorSpaceLuminance& luminance = Fetch(gamma);
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar r = luminance.toLuma(gamma, SkIntToScalar(SkColorGetR(c)) / 255);
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar g = luminance.toLuma(gamma, SkIntToScalar(SkColorGetG(c)) / 255);
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar b = luminance.toLuma(gamma, SkIntToScalar(SkColorGetB(c)) / 255);
38910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        SkScalar luma = r * SK_LUM_COEFF_R +
39910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                        g * SK_LUM_COEFF_G +
40910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                        b * SK_LUM_COEFF_B;
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(luma <= SK_Scalar1);
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return SkScalarRoundToInt(luminance.fromLuma(gamma, luma) * 255);
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Retrieves the SkColorSpaceLuminance for the given gamma. */
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const SkColorSpaceLuminance& Fetch(SkScalar gamma);
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///@{
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/**
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Scales base <= 2^N-1 to 2^8-1
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * @param N [1, 8] the number of bits used by base.
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * @param base the number to be scaled to [0, 255].
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutemplate<U8CPU N> static inline U8CPU sk_t_scale255(U8CPU base) {
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    base <<= (8 - N);
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    U8CPU lum = base;
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (unsigned int i = N; i < 8; i += N) {
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        lum |= base >> i;
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return lum;
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutemplate<> /*static*/ inline U8CPU sk_t_scale255<1>(U8CPU base) {
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return base * 0xFF;
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutemplate<> /*static*/ inline U8CPU sk_t_scale255<2>(U8CPU base) {
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return base * 0x55;
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutemplate<> /*static*/ inline U8CPU sk_t_scale255<4>(U8CPU base) {
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return base * 0x11;
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutemplate<> /*static*/ inline U8CPU sk_t_scale255<8>(U8CPU base) {
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return base;
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///@}
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutemplate <int R_LUM_BITS, int G_LUM_BITS, int B_LUM_BITS> class SkTMaskPreBlend;
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkTMaskGamma_build_correcting_lut(uint8_t table[256], U8CPU srcI, SkScalar contrast,
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                       const SkColorSpaceLuminance& srcConvert, SkScalar srcGamma,
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                       const SkColorSpaceLuminance& dstConvert, SkScalar dstGamma);
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/**
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * A regular mask contains linear alpha values. A gamma correcting mask
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * contains non-linear alpha values in an attempt to create gamma correct blits
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * in the presence of a gamma incorrect (linear) blend in the blitter.
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * SkMaskGamma creates and maintains tables which convert linear alpha values
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * to gamma correcting alpha values.
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * @param R The number of luminance bits to use [1, 8] from the red channel.
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * @param G The number of luminance bits to use [1, 8] from the green channel.
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * @param B The number of luminance bits to use [1, 8] from the blue channel.
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutemplate <int R_LUM_BITS, int G_LUM_BITS, int B_LUM_BITS> class SkTMaskGamma : public SkRefCnt {
95910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    SK_DECLARE_INST_COUNT(SkTMaskGamma)
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
98363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    /** Creates a linear SkTMaskGamma. */
99363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkTMaskGamma() : fIsLinear(true) { }
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * Creates tables to convert linear alpha values to gamma correcting alpha
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * values.
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * @param contrast A value in the range [0.0, 1.0] which indicates the
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *                 amount of artificial contrast to add.
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * @param paint The color space in which the paint color was chosen.
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * @param device The color space of the target device.
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkTMaskGamma(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma) : fIsLinear(false) {
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const SkColorSpaceLuminance& paintConvert = SkColorSpaceLuminance::Fetch(paintGamma);
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const SkColorSpaceLuminance& deviceConvert = SkColorSpaceLuminance::Fetch(deviceGamma);
113363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        for (U8CPU i = 0; i < (1 << MAX_LUM_BITS); ++i) {
114363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            U8CPU lum = sk_t_scale255<MAX_LUM_BITS>(i);
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkTMaskGamma_build_correcting_lut(fGammaTables[i], lum, contrast,
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                              paintConvert, paintGamma,
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                              deviceConvert, deviceGamma);
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
121d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    /** Given a color, returns the closest canonical color. */
122d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    static SkColor CanonicalColor(SkColor color) {
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return SkColorSetRGB(
124363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                   sk_t_scale255<R_LUM_BITS>(SkColorGetR(color) >> (8 - R_LUM_BITS)),
125363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                   sk_t_scale255<G_LUM_BITS>(SkColorGetG(color) >> (8 - G_LUM_BITS)),
126363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                   sk_t_scale255<B_LUM_BITS>(SkColorGetB(color) >> (8 - B_LUM_BITS)));
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** The type of the mask pre-blend which will be returned from preBlend(SkColor). */
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    typedef SkTMaskPreBlend<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS> PreBlend;
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * Provides access to the tables appropriate for converting linear alpha
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * values into gamma correcting alpha values when drawing the given color
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * through the mask. The destination color will be approximated.
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
137363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    PreBlend preBlend(SkColor color) const;
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
140363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    static const int MAX_LUM_BITS =
141363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger          B_LUM_BITS > (R_LUM_BITS > G_LUM_BITS ? R_LUM_BITS : G_LUM_BITS)
142363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        ? B_LUM_BITS : (R_LUM_BITS > G_LUM_BITS ? R_LUM_BITS : G_LUM_BITS);
143363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    uint8_t fGammaTables[1 << MAX_LUM_BITS][256];
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool fIsLinear;
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    typedef SkRefCnt INHERITED;
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/**
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * SkTMaskPreBlend is a tear-off of SkTMaskGamma. It provides the tables to
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * convert a linear alpha value for a given channel to a gamma correcting alpha
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * value for that channel. This class is immutable.
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * If fR, fG, or fB is NULL, all of them will be. This indicates that no mask
156363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * pre blend should be applied. SkTMaskPreBlend::isApplicable() is provided as
157363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * a convenience function to test for the absence of this case.
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutemplate <int R_LUM_BITS, int G_LUM_BITS, int B_LUM_BITS> class SkTMaskPreBlend {
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
161363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkTMaskPreBlend(const SkTMaskGamma<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>* parent,
162363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    const uint8_t* r, const uint8_t* g, const uint8_t* b)
163363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    : fParent(SkSafeRef(parent)), fR(r), fG(g), fB(b) { }
164363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
165363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkAutoTUnref<const SkTMaskGamma<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS> > fParent;
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    friend class SkTMaskGamma<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>;
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
168363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    /** Creates a non applicable SkTMaskPreBlend. */
169363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkTMaskPreBlend() : fParent(), fR(NULL), fG(NULL), fB(NULL) { }
170363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * This copy contructor exists for correctness, but should never be called
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * when return value optimization is enabled.
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkTMaskPreBlend(const SkTMaskPreBlend<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>& that)
176363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    : fParent(SkSafeRef(that.fParent.get())), fR(that.fR), fG(that.fG), fB(that.fB) { }
177363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ~SkTMaskPreBlend() { }
179363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
180363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    /** True if this PreBlend should be applied. When false, fR, fG, and fB are NULL. */
181363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    bool isApplicable() const {
182363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return NULL != this->fG;
183363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
184363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const uint8_t* fR;
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const uint8_t* fG;
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const uint8_t* fB;
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutemplate <int R_LUM_BITS, int G_LUM_BITS, int B_LUM_BITS>
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkTMaskPreBlend<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>
192363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerSkTMaskGamma<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>::preBlend(SkColor color) const {
193363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return fIsLinear ? SkTMaskPreBlend<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>()
194363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                     : SkTMaskPreBlend<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>(this,
195363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                         fGammaTables[SkColorGetR(color) >> (8 - MAX_LUM_BITS)],
196363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                         fGammaTables[SkColorGetG(color) >> (8 - MAX_LUM_BITS)],
197363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                         fGammaTables[SkColorGetB(color) >> (8 - MAX_LUM_BITS)]);
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///@{
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/**
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *  If APPLY_LUT is false, returns component unchanged.
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *  If APPLY_LUT is true, returns lut[component].
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *  @param APPLY_LUT whether or not the look-up table should be applied to component.
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *  @component the initial component.
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *  @lut a look-up table which transforms the component.
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutemplate<bool APPLY_LUT> static inline U8CPU sk_apply_lut_if(U8CPU component, const uint8_t*) {
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return component;
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutemplate<> /*static*/ inline U8CPU sk_apply_lut_if<true>(U8CPU component, const uint8_t* lut) {
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return lut[component];
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///@}
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
217