blob: 8edbf7e40178c2317d2491418f8400ceca0724c0 [file] [log] [blame]
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +00001/*
2 Copyright 2011 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
reed@android.com3f2025f2009-10-29 17:37:56 +000017#include "SkTableMaskFilter.h"
18
19SkTableMaskFilter::SkTableMaskFilter() {
20 for (int i = 0; i < 256; i++) {
21 fTable[i] = i;
22 }
23}
24
25SkTableMaskFilter::SkTableMaskFilter(const uint8_t table[256]) {
26 this->setTable(table);
27}
28
29SkTableMaskFilter::~SkTableMaskFilter() {}
30
31void SkTableMaskFilter::setTable(const uint8_t table[256]) {
32 memcpy(fTable, table, 256);
33}
34
35bool SkTableMaskFilter::filterMask(SkMask* dst, const SkMask& src,
36 const SkMatrix&, SkIPoint* margin) {
37 if (src.fFormat != SkMask::kA8_Format) {
38 return false;
39 }
40
41 dst->fBounds = src.fBounds;
42 dst->fRowBytes = SkAlign4(dst->fBounds.width());
43 dst->fFormat = SkMask::kA8_Format;
44 dst->fImage = NULL;
45
46 if (src.fImage) {
47 dst->fImage = SkMask::AllocImage(dst->computeImageSize());
48
49 const uint8_t* srcP = src.fImage;
50 uint8_t* dstP = dst->fImage;
51 const uint8_t* table = fTable;
52 int dstWidth = dst->fBounds.width();
53 int extraZeros = dst->fRowBytes - dstWidth;
54
55 for (int y = dst->fBounds.height() - 1; y >= 0; --y) {
56 for (int x = dstWidth - 1; x >= 0; --x) {
57 dstP[x] = table[srcP[x]];
58 }
59 srcP += src.fRowBytes;
60 // we can't just inc dstP by rowbytes, because if it has any
61 // padding between its width and its rowbytes, we need to zero those
62 // so that the bitters can read those safely if that is faster for
63 // them
64 dstP += dstWidth;
65 for (int i = extraZeros - 1; i >= 0; --i) {
66 *dstP++ = 0;
67 }
68 }
69 }
70
71 if (margin) {
72 margin->set(0, 0);
73 }
74 return true;
75}
76
77SkMask::Format SkTableMaskFilter::getFormat() {
78 return SkMask::kA8_Format;
79}
80
81void SkTableMaskFilter::flatten(SkFlattenableWriteBuffer& wb) {
82 this->INHERITED::flatten(wb);
83 wb.writePad(fTable, 256);
84}
85
86SkTableMaskFilter::SkTableMaskFilter(SkFlattenableReadBuffer& rb)
87 : INHERITED(rb) {
88 rb.read(fTable, 256);
89}
90
91SkFlattenable* SkTableMaskFilter::Factory(SkFlattenableReadBuffer& rb) {
92 return SkNEW_ARGS(SkTableMaskFilter, (rb));
93}
94
95SkFlattenable::Factory SkTableMaskFilter::getFactory() {
96 return SkTableMaskFilter::Factory;
97}
98
99///////////////////////////////////////////////////////////////////////////////
100
101void SkTableMaskFilter::MakeGammaTable(uint8_t table[256], SkScalar gamma) {
102 float x = 0;
103 const float dx = 1 / 255.0f;
104 for (int i = 0; i < 256; i++) {
105 table[i] = SkPin32(SkScalarRound(powf(x, gamma) * 255), 0, 255);
106 x += dx;
107 }
108}
109
110void SkTableMaskFilter::MakeClipTable(uint8_t table[256], uint8_t min,
111 uint8_t max) {
112 if (0 == max) {
113 max = 1;
114 }
115 if (min >= max) {
116 min = max - 1;
117 }
118 SkASSERT(min < max);
119
120 SkFixed scale = (1 << 16) * 255 / (max - min);
121 memset(table, 0, min + 1);
122 for (int i = min + 1; i < max; i++) {
123 int value = SkFixedRound(scale * (i - min));
124 SkASSERT(value <= 255);
125 table[i] = value;
126 }
127 memset(table + max, 255, 256 - max);
128
129#if 0
130 int j;
131 for (j = 0; j < 256; j++) {
132 if (table[j]) {
133 break;
134 }
135 }
136 SkDebugf("%d %d start [%d]", min, max, j);
137 for (; j < 256; j++) {
138 SkDebugf(" %d", table[j]);
139 }
140 SkDebugf("\n\n");
141#endif
142}
143