Home | History | Annotate | Download | only in effects
      1 /*
      2  * Copyright 2011 Google Inc.
      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 #include "SkColorMatrixFilter.h"
      9 #include "SkColorSpace.h"
     10 #include "SkColorSpaceXformer.h"
     11 #if SK_SUPPORT_GPU
     12     #include "GrFragmentProcessor.h"
     13 #endif
     14 
     15 static SkScalar byte_to_scale(U8CPU byte) {
     16     if (0xFF == byte) {
     17         // want to get this exact
     18         return 1;
     19     } else {
     20         return byte * 0.00392156862745f;
     21     }
     22 }
     23 
     24 // If we can't reduce to a mode filter in MakeLightingFilter(), this is the general case.
     25 // We operate as a matrix color filter, but remember our input colors in case we're asked
     26 // to onMakeColorSpace() a new filter.
     27 class SkLightingColorFilter : public SkColorFilter {
     28 public:
     29     SkLightingColorFilter(SkColor mul, SkColor add) : fMul(mul), fAdd(add) {
     30         SkColorMatrix matrix;
     31         matrix.setScale(byte_to_scale(SkColorGetR(mul)),
     32                         byte_to_scale(SkColorGetG(mul)),
     33                         byte_to_scale(SkColorGetB(mul)),
     34                         1);
     35         matrix.postTranslate(SkIntToScalar(SkColorGetR(add)),
     36                              SkIntToScalar(SkColorGetG(add)),
     37                              SkIntToScalar(SkColorGetB(add)),
     38                              0);
     39         fMatrixFilter = SkColorFilter::MakeMatrixFilterRowMajor255(matrix.fMat);
     40     }
     41 
     42     // Overriding this method is the class' raison d'etre.
     43     sk_sp<SkColorFilter> onMakeColorSpace(SkColorSpaceXformer* xformer) const override {
     44         SkColor add = xformer->apply(fAdd);
     45         if (add != fAdd) {
     46             return sk_make_sp<SkLightingColorFilter>(fMul, add);
     47         }
     48         return this->INHERITED::onMakeColorSpace(xformer);
     49     }
     50 
     51     // Let fMatrixFilter handle all the other calls directly.
     52 
     53     uint32_t getFlags() const override {
     54         return fMatrixFilter->getFlags();
     55     }
     56     bool asColorMatrix(SkScalar matrix[20]) const override {
     57         return fMatrixFilter->asColorMatrix(matrix);
     58     }
     59     void onAppendStages(SkRasterPipeline* p, SkColorSpace* cs, SkArenaAlloc* alloc,
     60                         bool shaderIsOpaque) const override {
     61         fMatrixFilter->appendStages(p, cs, alloc, shaderIsOpaque);
     62     }
     63 
     64     // TODO: might want to remember we're a lighting color filter through serialization?
     65     void flatten(SkWriteBuffer& buf) const override { return fMatrixFilter->flatten(buf); }
     66     Factory getFactory() const override             { return fMatrixFilter->getFactory(); }
     67 
     68 #if SK_SUPPORT_GPU
     69     std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
     70             GrContext* ctx, const GrColorSpaceInfo& csi) const override {
     71         return fMatrixFilter->asFragmentProcessor(ctx, csi);
     72     }
     73 #endif
     74 
     75 #ifndef SK_IGNORE_TO_STRING
     76     void toString(SkString* str) const override { fMatrixFilter->toString(str); }
     77 #endif
     78 
     79 private:
     80     SkColor              fMul, fAdd;
     81     sk_sp<SkColorFilter> fMatrixFilter;
     82 
     83     typedef SkColorFilter INHERITED;
     84 };
     85 
     86 sk_sp<SkColorFilter> SkColorMatrixFilter::MakeLightingFilter(SkColor mul, SkColor add) {
     87     const SkColor opaqueAlphaMask = SK_ColorBLACK;
     88     // omit the alpha and compare only the RGB values
     89     if (0 == (add & ~opaqueAlphaMask)) {
     90         return SkColorFilter::MakeModeFilter(mul | opaqueAlphaMask, SkBlendMode::kModulate);
     91     }
     92     return sk_make_sp<SkLightingColorFilter>(mul, add);
     93 }
     94