1324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
2324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver/*
3324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Copyright 2011 Google Inc.
4324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *
5324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Use of this source code is governed by a BSD-style license that can be
6324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * found in the LICENSE file.
7324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */
8324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
9324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
10324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "SkTableMaskFilter.h"
11324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "SkReadBuffer.h"
12324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "SkWriteBuffer.h"
13324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "SkString.h"
14324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
15324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverSkTableMaskFilter::SkTableMaskFilter() {
16324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    for (int i = 0; i < 256; i++) {
17324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        fTable[i] = i;
18324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
19324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
20324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
21324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverSkTableMaskFilter::SkTableMaskFilter(const uint8_t table[256]) {
22324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    memcpy(fTable, table, sizeof(fTable));
23324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
24324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
25324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverSkTableMaskFilter::~SkTableMaskFilter() {}
26324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
27324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverbool SkTableMaskFilter::filterMask(SkMask* dst, const SkMask& src,
28324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                                 const SkMatrix&, SkIPoint* margin) const {
29324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (src.fFormat != SkMask::kA8_Format) {
30324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return false;
31324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    dst->fBounds = src.fBounds;
34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    dst->fRowBytes = SkAlign4(dst->fBounds.width());
35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    dst->fFormat = SkMask::kA8_Format;
36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    dst->fImage = NULL;
37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (src.fImage) {
39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        dst->fImage = SkMask::AllocImage(dst->computeImageSize());
40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        const uint8_t* srcP = src.fImage;
42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        uint8_t* dstP = dst->fImage;
43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        const uint8_t* table = fTable;
44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        int dstWidth = dst->fBounds.width();
45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        int extraZeros = dst->fRowBytes - dstWidth;
46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        for (int y = dst->fBounds.height() - 1; y >= 0; --y) {
48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            for (int x = dstWidth - 1; x >= 0; --x) {
49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                dstP[x] = table[srcP[x]];
50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
51            srcP += src.fRowBytes;
52            // we can't just inc dstP by rowbytes, because if it has any
53            // padding between its width and its rowbytes, we need to zero those
54            // so that the bitters can read those safely if that is faster for
55            // them
56            dstP += dstWidth;
57            for (int i = extraZeros - 1; i >= 0; --i) {
58                *dstP++ = 0;
59            }
60        }
61    }
62
63    if (margin) {
64        margin->set(0, 0);
65    }
66    return true;
67}
68
69SkMask::Format SkTableMaskFilter::getFormat() const {
70    return SkMask::kA8_Format;
71}
72
73void SkTableMaskFilter::flatten(SkWriteBuffer& wb) const {
74    wb.writeByteArray(fTable, 256);
75}
76
77SkFlattenable* SkTableMaskFilter::CreateProc(SkReadBuffer& buffer) {
78    uint8_t table[256];
79    if (!buffer.readByteArray(table, 256)) {
80        return NULL;
81    }
82    return Create(table);
83}
84
85#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
86SkTableMaskFilter::SkTableMaskFilter(SkReadBuffer& rb) : INHERITED(rb) {
87    SkASSERT(256 == rb.getArrayCount());
88    rb.readByteArray(fTable, 256);
89}
90#endif
91
92///////////////////////////////////////////////////////////////////////////////
93
94void SkTableMaskFilter::MakeGammaTable(uint8_t table[256], SkScalar gamma) {
95    const float dx = 1 / 255.0f;
96    const float g = SkScalarToFloat(gamma);
97
98    float x = 0;
99    for (int i = 0; i < 256; i++) {
100     // float ee = powf(x, g) * 255;
101        table[i] = SkPin32(sk_float_round2int(powf(x, g) * 255), 0, 255);
102        x += dx;
103    }
104}
105
106void SkTableMaskFilter::MakeClipTable(uint8_t table[256], uint8_t min,
107                                      uint8_t max) {
108    if (0 == max) {
109        max = 1;
110    }
111    if (min >= max) {
112        min = max - 1;
113    }
114    SkASSERT(min < max);
115
116    SkFixed scale = (1 << 16) * 255 / (max - min);
117    memset(table, 0, min + 1);
118    for (int i = min + 1; i < max; i++) {
119        int value = SkFixedRoundToInt(scale * (i - min));
120        SkASSERT(value <= 255);
121        table[i] = value;
122    }
123    memset(table + max, 255, 256 - max);
124
125#if 0
126    int j;
127    for (j = 0; j < 256; j++) {
128        if (table[j]) {
129            break;
130        }
131    }
132    SkDebugf("%d %d start [%d]", min, max, j);
133    for (; j < 256; j++) {
134        SkDebugf(" %d", table[j]);
135    }
136    SkDebugf("\n\n");
137#endif
138}
139
140#ifndef SK_IGNORE_TO_STRING
141void SkTableMaskFilter::toString(SkString* str) const {
142    str->append("SkTableMaskFilter: (");
143
144    str->append("table: ");
145    for (int i = 0; i < 255; ++i) {
146        str->appendf("%d, ", fTable[i]);
147    }
148    str->appendf("%d", fTable[255]);
149
150    str->append(")");
151}
152#endif
153