blob: 0bd6c2ca68b1f2afa2589ccc1bb1ce6627e3e7ea [file] [log] [blame]
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkColorMatrixFilter.h"
#include "SkColorSpace.h"
#include "SkColorSpaceXformer.h"
#if SK_SUPPORT_GPU
#include "GrFragmentProcessor.h"
#endif
static SkScalar byte_to_scale(U8CPU byte) {
if (0xFF == byte) {
// want to get this exact
return 1;
} else {
return byte * 0.00392156862745f;
}
}
// If we can't reduce to a mode filter in MakeLightingFilter(), this is the general case.
// We operate as a matrix color filter, but remember our input colors in case we're asked
// to onMakeColorSpace() a new filter.
class SkLightingColorFilter : public SkColorFilter {
public:
SkLightingColorFilter(SkColor mul, SkColor add) : fMul(mul), fAdd(add) {
SkColorMatrix matrix;
matrix.setScale(byte_to_scale(SkColorGetR(mul)),
byte_to_scale(SkColorGetG(mul)),
byte_to_scale(SkColorGetB(mul)),
1);
matrix.postTranslate(SkIntToScalar(SkColorGetR(add)),
SkIntToScalar(SkColorGetG(add)),
SkIntToScalar(SkColorGetB(add)),
0);
fMatrixFilter = SkColorFilter::MakeMatrixFilterRowMajor255(matrix.fMat);
}
// Overriding this method is the class' raison d'etre.
sk_sp<SkColorFilter> onMakeColorSpace(SkColorSpaceXformer* xformer) const override {
SkColor add = xformer->apply(fAdd);
if (add != fAdd) {
return sk_make_sp<SkLightingColorFilter>(fMul, add);
}
return this->INHERITED::onMakeColorSpace(xformer);
}
// Let fMatrixFilter handle all the other calls directly.
uint32_t getFlags() const override {
return fMatrixFilter->getFlags();
}
bool asColorMatrix(SkScalar matrix[20]) const override {
return fMatrixFilter->asColorMatrix(matrix);
}
void onAppendStages(SkRasterPipeline* p, SkColorSpace* cs, SkArenaAlloc* alloc,
bool shaderIsOpaque) const override {
fMatrixFilter->appendStages(p, cs, alloc, shaderIsOpaque);
}
// TODO: might want to remember we're a lighting color filter through serialization?
void flatten(SkWriteBuffer& buf) const override { return fMatrixFilter->flatten(buf); }
Factory getFactory() const override { return fMatrixFilter->getFactory(); }
#if SK_SUPPORT_GPU
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext* ctx,
SkColorSpace* cs) const override {
return fMatrixFilter->asFragmentProcessor(ctx, cs);
}
#endif
#ifndef SK_IGNORE_TO_STRING
void toString(SkString* str) const override { fMatrixFilter->toString(str); }
#endif
private:
SkColor fMul, fAdd;
sk_sp<SkColorFilter> fMatrixFilter;
typedef SkColorFilter INHERITED;
};
sk_sp<SkColorFilter> SkColorMatrixFilter::MakeLightingFilter(SkColor mul, SkColor add) {
const SkColor opaqueAlphaMask = SK_ColorBLACK;
// omit the alpha and compare only the RGB values
if (0 == (add & ~opaqueAlphaMask)) {
return SkColorFilter::MakeModeFilter(mul | opaqueAlphaMask, SkBlendMode::kModulate);
}
return sk_make_sp<SkLightingColorFilter>(mul, add);
}