gfx/skia/trunk/src/core/SkMaskGamma.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /*
michael@0 2 * Copyright 2012 Google Inc.
michael@0 3 *
michael@0 4 * Use of this source code is governed by a BSD-style license that can be
michael@0 5 * found in the LICENSE file.
michael@0 6 */
michael@0 7
michael@0 8 #ifndef SkMaskGamma_DEFINED
michael@0 9 #define SkMaskGamma_DEFINED
michael@0 10
michael@0 11 #include "SkTypes.h"
michael@0 12 #include "SkColor.h"
michael@0 13 #include "SkColorPriv.h"
michael@0 14 #include "SkRefCnt.h"
michael@0 15
michael@0 16 /**
michael@0 17 * SkColorSpaceLuminance is used to convert luminances to and from linear and
michael@0 18 * perceptual color spaces.
michael@0 19 *
michael@0 20 * Luma is used to specify a linear luminance value [0.0, 1.0].
michael@0 21 * Luminance is used to specify a luminance value in an arbitrary color space [0.0, 1.0].
michael@0 22 */
michael@0 23 class SkColorSpaceLuminance : SkNoncopyable {
michael@0 24 public:
michael@0 25 virtual ~SkColorSpaceLuminance() { }
michael@0 26
michael@0 27 /** Converts a color component luminance in the color space to a linear luma. */
michael@0 28 virtual SkScalar toLuma(SkScalar gamma, SkScalar luminance) const = 0;
michael@0 29 /** Converts a linear luma to a color component luminance in the color space. */
michael@0 30 virtual SkScalar fromLuma(SkScalar gamma, SkScalar luma) const = 0;
michael@0 31
michael@0 32 /** Converts a color to a luminance value. */
michael@0 33 static U8CPU computeLuminance(SkScalar gamma, SkColor c) {
michael@0 34 const SkColorSpaceLuminance& luminance = Fetch(gamma);
michael@0 35 SkScalar r = luminance.toLuma(gamma, SkIntToScalar(SkColorGetR(c)) / 255);
michael@0 36 SkScalar g = luminance.toLuma(gamma, SkIntToScalar(SkColorGetG(c)) / 255);
michael@0 37 SkScalar b = luminance.toLuma(gamma, SkIntToScalar(SkColorGetB(c)) / 255);
michael@0 38 SkScalar luma = r * SK_LUM_COEFF_R +
michael@0 39 g * SK_LUM_COEFF_G +
michael@0 40 b * SK_LUM_COEFF_B;
michael@0 41 SkASSERT(luma <= SK_Scalar1);
michael@0 42 return SkScalarRoundToInt(luminance.fromLuma(gamma, luma) * 255);
michael@0 43 }
michael@0 44
michael@0 45 /** Retrieves the SkColorSpaceLuminance for the given gamma. */
michael@0 46 static const SkColorSpaceLuminance& Fetch(SkScalar gamma);
michael@0 47 };
michael@0 48
michael@0 49 ///@{
michael@0 50 /**
michael@0 51 * Scales base <= 2^N-1 to 2^8-1
michael@0 52 * @param N [1, 8] the number of bits used by base.
michael@0 53 * @param base the number to be scaled to [0, 255].
michael@0 54 */
michael@0 55 template<U8CPU N> static inline U8CPU sk_t_scale255(U8CPU base) {
michael@0 56 base <<= (8 - N);
michael@0 57 U8CPU lum = base;
michael@0 58 for (unsigned int i = N; i < 8; i += N) {
michael@0 59 lum |= base >> i;
michael@0 60 }
michael@0 61 return lum;
michael@0 62 }
michael@0 63 template<> /*static*/ inline U8CPU sk_t_scale255<1>(U8CPU base) {
michael@0 64 return base * 0xFF;
michael@0 65 }
michael@0 66 template<> /*static*/ inline U8CPU sk_t_scale255<2>(U8CPU base) {
michael@0 67 return base * 0x55;
michael@0 68 }
michael@0 69 template<> /*static*/ inline U8CPU sk_t_scale255<4>(U8CPU base) {
michael@0 70 return base * 0x11;
michael@0 71 }
michael@0 72 template<> /*static*/ inline U8CPU sk_t_scale255<8>(U8CPU base) {
michael@0 73 return base;
michael@0 74 }
michael@0 75 ///@}
michael@0 76
michael@0 77 template <int R_LUM_BITS, int G_LUM_BITS, int B_LUM_BITS> class SkTMaskPreBlend;
michael@0 78
michael@0 79 void SkTMaskGamma_build_correcting_lut(uint8_t table[256], U8CPU srcI, SkScalar contrast,
michael@0 80 const SkColorSpaceLuminance& srcConvert, SkScalar srcGamma,
michael@0 81 const SkColorSpaceLuminance& dstConvert, SkScalar dstGamma);
michael@0 82
michael@0 83 /**
michael@0 84 * A regular mask contains linear alpha values. A gamma correcting mask
michael@0 85 * contains non-linear alpha values in an attempt to create gamma correct blits
michael@0 86 * in the presence of a gamma incorrect (linear) blend in the blitter.
michael@0 87 *
michael@0 88 * SkMaskGamma creates and maintains tables which convert linear alpha values
michael@0 89 * to gamma correcting alpha values.
michael@0 90 * @param R The number of luminance bits to use [1, 8] from the red channel.
michael@0 91 * @param G The number of luminance bits to use [1, 8] from the green channel.
michael@0 92 * @param B The number of luminance bits to use [1, 8] from the blue channel.
michael@0 93 */
michael@0 94 template <int R_LUM_BITS, int G_LUM_BITS, int B_LUM_BITS> class SkTMaskGamma : public SkRefCnt {
michael@0 95 SK_DECLARE_INST_COUNT(SkTMaskGamma)
michael@0 96 public:
michael@0 97
michael@0 98 /** Creates a linear SkTMaskGamma. */
michael@0 99 SkTMaskGamma() : fIsLinear(true) { }
michael@0 100
michael@0 101 /**
michael@0 102 * Creates tables to convert linear alpha values to gamma correcting alpha
michael@0 103 * values.
michael@0 104 *
michael@0 105 * @param contrast A value in the range [0.0, 1.0] which indicates the
michael@0 106 * amount of artificial contrast to add.
michael@0 107 * @param paint The color space in which the paint color was chosen.
michael@0 108 * @param device The color space of the target device.
michael@0 109 */
michael@0 110 SkTMaskGamma(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma) : fIsLinear(false) {
michael@0 111 const SkColorSpaceLuminance& paintConvert = SkColorSpaceLuminance::Fetch(paintGamma);
michael@0 112 const SkColorSpaceLuminance& deviceConvert = SkColorSpaceLuminance::Fetch(deviceGamma);
michael@0 113 for (U8CPU i = 0; i < (1 << MAX_LUM_BITS); ++i) {
michael@0 114 U8CPU lum = sk_t_scale255<MAX_LUM_BITS>(i);
michael@0 115 SkTMaskGamma_build_correcting_lut(fGammaTables[i], lum, contrast,
michael@0 116 paintConvert, paintGamma,
michael@0 117 deviceConvert, deviceGamma);
michael@0 118 }
michael@0 119 }
michael@0 120
michael@0 121 /** Given a color, returns the closest canonical color. */
michael@0 122 static SkColor CanonicalColor(SkColor color) {
michael@0 123 return SkColorSetRGB(
michael@0 124 sk_t_scale255<R_LUM_BITS>(SkColorGetR(color) >> (8 - R_LUM_BITS)),
michael@0 125 sk_t_scale255<G_LUM_BITS>(SkColorGetG(color) >> (8 - G_LUM_BITS)),
michael@0 126 sk_t_scale255<B_LUM_BITS>(SkColorGetB(color) >> (8 - B_LUM_BITS)));
michael@0 127 }
michael@0 128
michael@0 129 /** The type of the mask pre-blend which will be returned from preBlend(SkColor). */
michael@0 130 typedef SkTMaskPreBlend<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS> PreBlend;
michael@0 131
michael@0 132 /**
michael@0 133 * Provides access to the tables appropriate for converting linear alpha
michael@0 134 * values into gamma correcting alpha values when drawing the given color
michael@0 135 * through the mask. The destination color will be approximated.
michael@0 136 */
michael@0 137 PreBlend preBlend(SkColor color) const;
michael@0 138
michael@0 139 private:
michael@0 140 static const int MAX_LUM_BITS =
michael@0 141 B_LUM_BITS > (R_LUM_BITS > G_LUM_BITS ? R_LUM_BITS : G_LUM_BITS)
michael@0 142 ? B_LUM_BITS : (R_LUM_BITS > G_LUM_BITS ? R_LUM_BITS : G_LUM_BITS);
michael@0 143 uint8_t fGammaTables[1 << MAX_LUM_BITS][256];
michael@0 144 bool fIsLinear;
michael@0 145
michael@0 146 typedef SkRefCnt INHERITED;
michael@0 147 };
michael@0 148
michael@0 149
michael@0 150 /**
michael@0 151 * SkTMaskPreBlend is a tear-off of SkTMaskGamma. It provides the tables to
michael@0 152 * convert a linear alpha value for a given channel to a gamma correcting alpha
michael@0 153 * value for that channel. This class is immutable.
michael@0 154 *
michael@0 155 * If fR, fG, or fB is NULL, all of them will be. This indicates that no mask
michael@0 156 * pre blend should be applied. SkTMaskPreBlend::isApplicable() is provided as
michael@0 157 * a convenience function to test for the absence of this case.
michael@0 158 */
michael@0 159 template <int R_LUM_BITS, int G_LUM_BITS, int B_LUM_BITS> class SkTMaskPreBlend {
michael@0 160 private:
michael@0 161 SkTMaskPreBlend(const SkTMaskGamma<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>* parent,
michael@0 162 const uint8_t* r, const uint8_t* g, const uint8_t* b)
michael@0 163 : fParent(SkSafeRef(parent)), fR(r), fG(g), fB(b) { }
michael@0 164
michael@0 165 SkAutoTUnref<const SkTMaskGamma<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS> > fParent;
michael@0 166 friend class SkTMaskGamma<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>;
michael@0 167 public:
michael@0 168 /** Creates a non applicable SkTMaskPreBlend. */
michael@0 169 SkTMaskPreBlend() : fParent(), fR(NULL), fG(NULL), fB(NULL) { }
michael@0 170
michael@0 171 /**
michael@0 172 * This copy contructor exists for correctness, but should never be called
michael@0 173 * when return value optimization is enabled.
michael@0 174 */
michael@0 175 SkTMaskPreBlend(const SkTMaskPreBlend<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>& that)
michael@0 176 : fParent(SkSafeRef(that.fParent.get())), fR(that.fR), fG(that.fG), fB(that.fB) { }
michael@0 177
michael@0 178 ~SkTMaskPreBlend() { }
michael@0 179
michael@0 180 /** True if this PreBlend should be applied. When false, fR, fG, and fB are NULL. */
michael@0 181 bool isApplicable() const {
michael@0 182 return NULL != this->fG;
michael@0 183 }
michael@0 184
michael@0 185 const uint8_t* fR;
michael@0 186 const uint8_t* fG;
michael@0 187 const uint8_t* fB;
michael@0 188 };
michael@0 189
michael@0 190 template <int R_LUM_BITS, int G_LUM_BITS, int B_LUM_BITS>
michael@0 191 SkTMaskPreBlend<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>
michael@0 192 SkTMaskGamma<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>::preBlend(SkColor color) const {
michael@0 193 return fIsLinear ? SkTMaskPreBlend<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>()
michael@0 194 : SkTMaskPreBlend<R_LUM_BITS, G_LUM_BITS, B_LUM_BITS>(this,
michael@0 195 fGammaTables[SkColorGetR(color) >> (8 - MAX_LUM_BITS)],
michael@0 196 fGammaTables[SkColorGetG(color) >> (8 - MAX_LUM_BITS)],
michael@0 197 fGammaTables[SkColorGetB(color) >> (8 - MAX_LUM_BITS)]);
michael@0 198 }
michael@0 199
michael@0 200 ///@{
michael@0 201 /**
michael@0 202 * If APPLY_LUT is false, returns component unchanged.
michael@0 203 * If APPLY_LUT is true, returns lut[component].
michael@0 204 * @param APPLY_LUT whether or not the look-up table should be applied to component.
michael@0 205 * @component the initial component.
michael@0 206 * @lut a look-up table which transforms the component.
michael@0 207 */
michael@0 208 template<bool APPLY_LUT> static inline U8CPU sk_apply_lut_if(U8CPU component, const uint8_t*) {
michael@0 209 return component;
michael@0 210 }
michael@0 211 template<> /*static*/ inline U8CPU sk_apply_lut_if<true>(U8CPU component, const uint8_t* lut) {
michael@0 212 return lut[component];
michael@0 213 }
michael@0 214 ///@}
michael@0 215
michael@0 216 #endif

mercurial