зеркало из https://github.com/mozilla/moz-skia.git
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
This commit is contained in:
Родитель
a563162780
Коммит
3cfda413a2
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SkGammaMaskFilter_DEFINED
|
||||
#define SkGammaMaskFilter_DEFINED
|
||||
|
||||
#include "SkMaskFilter.h"
|
||||
#include "SkScalar.h"
|
||||
|
||||
/** \class SkGammaMaskFilter
|
||||
|
||||
Applies a table lookup on each of the alpha values in the mask.
|
||||
An arbitrary table can be assigned, or a gamma (pow) table is computed
|
||||
based on the specified exponent.
|
||||
*/
|
||||
class SkGammaMaskFilter : public SkMaskFilter {
|
||||
public:
|
||||
SkGammaMaskFilter();
|
||||
SkGammaMaskFilter(SkScalar gamma);
|
||||
SkGammaMaskFilter(const uint8_t table[256]);
|
||||
virtual ~SkGammaMaskFilter();
|
||||
|
||||
void setGamma(SkScalar gamma);
|
||||
void setGammaTable(const uint8_t table[256]);
|
||||
|
||||
// overrides from SkMaskFilter
|
||||
virtual SkMask::Format getFormat();
|
||||
virtual bool filterMask(SkMask*, const SkMask&, const SkMatrix&, SkIPoint*);
|
||||
|
||||
// overrides from SkFlattenable
|
||||
virtual void flatten(SkFlattenableWriteBuffer& wb);
|
||||
virtual Factory getFactory();
|
||||
|
||||
protected:
|
||||
SkGammaMaskFilter(SkFlattenableReadBuffer& rb);
|
||||
static SkFlattenable* Factory(SkFlattenableReadBuffer&);
|
||||
|
||||
private:
|
||||
uint8_t fTable[256];
|
||||
|
||||
typedef SkMaskFilter INHERITED;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
Загрузка…
Ссылка в новой задаче