diff options
author | 2009-10-29 15:19:10 +0000 | |
---|---|---|
committer | 2009-10-29 15:19:10 +0000 | |
commit | 3cfda413a2eadedc1ef9db3c980e78f4d415d6dc (patch) | |
tree | 7999c4f978f93d2312a8b86d19c2e92d47c01247 /src | |
parent | a563162780d589938aef8a4d8b63d2957139313b (diff) |
add gamma maskfilter, especially nice when applied after a blur
git-svn-id: http://skia.googlecode.com/svn/trunk@411 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/effects/SkGammaMaskFilter.cpp | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/src/effects/SkGammaMaskFilter.cpp b/src/effects/SkGammaMaskFilter.cpp new file mode 100644 index 0000000000..ebf13fcf60 --- /dev/null +++ b/src/effects/SkGammaMaskFilter.cpp @@ -0,0 +1,95 @@ +#include "SkGammaMaskFilter.h" + +SkGammaMaskFilter::SkGammaMaskFilter() { + for (int i = 0; i < 256; i++) { + fTable[i] = i; + } +} + +SkGammaMaskFilter::SkGammaMaskFilter(SkScalar gamma) { + this->setGamma(gamma); +} + +SkGammaMaskFilter::SkGammaMaskFilter(const uint8_t table[256]) { + this->setGammaTable(table); +} + +SkGammaMaskFilter::~SkGammaMaskFilter() {} + +void SkGammaMaskFilter::setGamma(SkScalar gamma) { + float x = 0; + const float dx = 1 / 255.0f; + for (int i = 0; i < 256; i++) { + fTable[i] = SkPin32(SkScalarRound(powf(x, gamma) * 255), 0, 255); + x += dx; + } +} + +void SkGammaMaskFilter::setGammaTable(const uint8_t table[256]) { + memcpy(fTable, table, 256); +} + +SkMask::Format SkGammaMaskFilter::getFormat() { + return SkMask::kA8_Format; +} + +bool SkGammaMaskFilter::filterMask(SkMask* dst, const SkMask& src, + const SkMatrix&, SkIPoint* margin) { + if (src.fFormat != SkMask::kA8_Format) { + return false; + } + + dst->fBounds = src.fBounds; + dst->fRowBytes = SkAlign4(dst->fBounds.width()); + dst->fFormat = SkMask::kA8_Format; + dst->fImage = NULL; + + if (src.fImage) { + dst->fImage = SkMask::AllocImage(dst->computeImageSize()); + + const uint8_t* srcP = src.fImage; + uint8_t* dstP = dst->fImage; + const uint8_t* table = fTable; + int dstWidth = dst->fBounds.width(); + int extraZeros = dst->fRowBytes - dstWidth; + + for (int y = dst->fBounds.height() - 1; y >= 0; --y) { + for (int x = dstWidth - 1; x >= 0; --x) { + dstP[x] = table[srcP[x]]; + } + srcP += src.fRowBytes; + // we can't just inc dstP by rowbytes, because if it has any + // padding between its width and its rowbytes, we need to zero those + // so that the bitters can read those safely if that is faster for + // them + dstP += dstWidth; + for (int i = extraZeros - 1; i >= 0; --i) { + *dstP++ = 0; + } + } + } + + if (margin) { + margin->set(0, 0); + } + return true; +} + +void SkGammaMaskFilter::flatten(SkFlattenableWriteBuffer& wb) { + this->INHERITED::flatten(wb); + wb.writePad(fTable, 256); +} + +SkGammaMaskFilter::SkGammaMaskFilter(SkFlattenableReadBuffer& rb) + : INHERITED(rb) { + rb.read(fTable, 256); +} + +SkFlattenable* SkGammaMaskFilter::Factory(SkFlattenableReadBuffer& rb) { + return SkNEW_ARGS(SkGammaMaskFilter, (rb)); +} + +SkFlattenable::Factory SkGammaMaskFilter::getFactory() { + return SkGammaMaskFilter::Factory; +} + |