180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc.
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTableMaskFilter.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkFlattenableBuffers.h"
12096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "SkString.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkTableMaskFilter::SkTableMaskFilter() {
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < 256; i++) {
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fTable[i] = i;
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkTableMaskFilter::SkTableMaskFilter(const uint8_t table[256]) {
21363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    memcpy(fTable, table, sizeof(fTable));
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkTableMaskFilter::~SkTableMaskFilter() {}
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkTableMaskFilter::filterMask(SkMask* dst, const SkMask& src,
27363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                 const SkMatrix&, SkIPoint* margin) const {
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (src.fFormat != SkMask::kA8_Format) {
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fBounds = src.fBounds;
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fRowBytes = SkAlign4(dst->fBounds.width());
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fFormat = SkMask::kA8_Format;
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fImage = NULL;
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (src.fImage) {
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst->fImage = SkMask::AllocImage(dst->computeImageSize());
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const uint8_t* srcP = src.fImage;
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        uint8_t* dstP = dst->fImage;
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const uint8_t* table = fTable;
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int dstWidth = dst->fBounds.width();
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int extraZeros = dst->fRowBytes - dstWidth;
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int y = dst->fBounds.height() - 1; y >= 0; --y) {
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int x = dstWidth - 1; x >= 0; --x) {
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dstP[x] = table[srcP[x]];
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            srcP += src.fRowBytes;
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // we can't just inc dstP by rowbytes, because if it has any
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // padding between its width and its rowbytes, we need to zero those
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // so that the bitters can read those safely if that is faster for
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // them
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dstP += dstWidth;
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int i = extraZeros - 1; i >= 0; --i) {
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                *dstP++ = 0;
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (margin) {
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        margin->set(0, 0);
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
68363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerSkMask::Format SkTableMaskFilter::getFormat() const {
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkMask::kA8_Format;
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkTableMaskFilter::flatten(SkFlattenableWriteBuffer& wb) const {
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->INHERITED::flatten(wb);
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    wb.writeByteArray(fTable, 256);
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkTableMaskFilter::SkTableMaskFilter(SkFlattenableReadBuffer& rb)
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        : INHERITED(rb) {
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(256 == rb.getArrayCount());
800a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    rb.readByteArray(fTable, 256);
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkTableMaskFilter::MakeGammaTable(uint8_t table[256], SkScalar gamma) {
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const float dx = 1 / 255.0f;
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const float g = SkScalarToFloat(gamma);
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float x = 0;
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < 256; i++) {
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     // float ee = powf(x, g) * 255;
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        table[i] = SkPin32(sk_float_round2int(powf(x, g) * 255), 0, 255);
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        x += dx;
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkTableMaskFilter::MakeClipTable(uint8_t table[256], uint8_t min,
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      uint8_t max) {
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (0 == max) {
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        max = 1;
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (min >= max) {
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        min = max - 1;
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(min < max);
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFixed scale = (1 << 16) * 255 / (max - min);
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    memset(table, 0, min + 1);
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = min + 1; i < max; i++) {
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int value = SkFixedRound(scale * (i - min));
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(value <= 255);
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        table[i] = value;
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    memset(table + max, 255, 256 - max);
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int j;
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (j = 0; j < 256; j++) {
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (table[j]) {
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDebugf("%d %d start [%d]", min, max, j);
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (; j < 256; j++) {
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDebugf(" %d", table[j]);
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDebugf("\n\n");
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
130096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
131096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#ifdef SK_DEVELOPER
132096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergervoid SkTableMaskFilter::toString(SkString* str) const {
133096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    str->append("SkTableMaskFilter: (");
134096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
135096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    str->append("table: ");
136096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    for (int i = 0; i < 255; ++i) {
137096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        str->appendf("%d, ", fTable[i]);
138096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
139096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    str->appendf("%d", fTable[255]);
140096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
141096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    str->append(")");
142096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger}
143096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#endif
144