1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#include "SkTableMaskFilter.h"
11#include "SkReadBuffer.h"
12#include "SkWriteBuffer.h"
13#include "SkString.h"
14
15SkTableMaskFilter::SkTableMaskFilter() {
16    for (int i = 0; i < 256; i++) {
17        fTable[i] = i;
18    }
19}
20
21SkTableMaskFilter::SkTableMaskFilter(const uint8_t table[256]) {
22    memcpy(fTable, table, sizeof(fTable));
23}
24
25SkTableMaskFilter::~SkTableMaskFilter() {}
26
27bool SkTableMaskFilter::filterMask(SkMask* dst, const SkMask& src,
28                                 const SkMatrix&, SkIPoint* margin) const {
29    if (src.fFormat != SkMask::kA8_Format) {
30        return false;
31    }
32
33    dst->fBounds = src.fBounds;
34    dst->fRowBytes = SkAlign4(dst->fBounds.width());
35    dst->fFormat = SkMask::kA8_Format;
36    dst->fImage = NULL;
37
38    if (src.fImage) {
39        dst->fImage = SkMask::AllocImage(dst->computeImageSize());
40
41        const uint8_t* srcP = src.fImage;
42        uint8_t* dstP = dst->fImage;
43        const uint8_t* table = fTable;
44        int dstWidth = dst->fBounds.width();
45        int extraZeros = dst->fRowBytes - dstWidth;
46
47        for (int y = dst->fBounds.height() - 1; y >= 0; --y) {
48            for (int x = dstWidth - 1; x >= 0; --x) {
49                dstP[x] = table[srcP[x]];
50            }
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