blob: 46b0206ee8d0746acde5bf218f5c4dffc7b65235 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* libs/graphics/sgl/SkAlphaRuns.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include "SkAntiRun.h"
19
20void SkAlphaRuns::reset(int width)
21{
22 SkASSERT(width > 0);
23
24 fRuns[0] = SkToS16(width);
25 fRuns[width] = 0;
26 fAlpha[0] = 0;
27
28 SkDEBUGCODE(fWidth = width;)
29 SkDEBUGCODE(this->validate();)
30}
31
32void SkAlphaRuns::Break(int16_t runs[], uint8_t alpha[], int x, int count)
33{
34 SkASSERT(count > 0 && x >= 0);
35
36// SkAlphaRuns::BreakAt(runs, alpha, x);
37// SkAlphaRuns::BreakAt(&runs[x], &alpha[x], count);
38
39 int16_t* next_runs = runs + x;
40 uint8_t* next_alpha = alpha + x;
41
42 while (x > 0)
43 {
44 int n = runs[0];
45 SkASSERT(n > 0);
46
47 if (x < n)
48 {
49 alpha[x] = alpha[0];
50 runs[0] = SkToS16(x);
51 runs[x] = SkToS16(n - x);
52 break;
53 }
54 runs += n;
55 alpha += n;
56 x -= n;
57 }
58
59 runs = next_runs;
60 alpha = next_alpha;
61 x = count;
62
63 for (;;)
64 {
65 int n = runs[0];
66 SkASSERT(n > 0);
67
68 if (x < n)
69 {
70 alpha[x] = alpha[0];
71 runs[0] = SkToS16(x);
72 runs[x] = SkToS16(n - x);
73 break;
74 }
75 x -= n;
76 if (x <= 0)
77 break;
78
79 runs += n;
80 alpha += n;
81 }
82}
83
84void SkAlphaRuns::add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, U8CPU maxValue)
85{
86 SkASSERT(middleCount >= 0);
87 SkASSERT(x >= 0 && x + (startAlpha != 0) + middleCount + (stopAlpha != 0) <= fWidth);
88
89 int16_t* runs = fRuns;
90 uint8_t* alpha = fAlpha;
91
92 if (startAlpha)
93 {
94 SkAlphaRuns::Break(runs, alpha, x, 1);
95 /* I should be able to just add alpha[x] + startAlpha.
96 However, if the trailing edge of the previous span and the leading
97 edge of the current span round to the same super-sampled x value,
98 I might overflow to 256 with this add, hence the funny subtract (crud).
99 */
100 unsigned tmp = alpha[x] + startAlpha;
101 SkASSERT(tmp <= 256);
102 alpha[x] = SkToU8(tmp - (tmp >> 8)); // was (tmp >> 7), but that seems wrong if we're trying to catch 256
103
104 runs += x + 1;
105 alpha += x + 1;
106 x = 0;
107 SkDEBUGCODE(this->validate();)
108 }
109 if (middleCount)
110 {
111 SkAlphaRuns::Break(runs, alpha, x, middleCount);
112 alpha += x;
113 runs += x;
114 x = 0;
115 do {
116 alpha[0] = SkToU8(alpha[0] + maxValue);
117 int n = runs[0];
118 SkASSERT(n <= middleCount);
119 alpha += n;
120 runs += n;
121 middleCount -= n;
122 } while (middleCount > 0);
123 SkDEBUGCODE(this->validate();)
124 }
125 if (stopAlpha)
126 {
127 SkAlphaRuns::Break(runs, alpha, x, 1);
128 alpha[x] = SkToU8(alpha[x] + stopAlpha);
129 SkDEBUGCODE(this->validate();)
130 }
131}
132
133#ifdef SK_DEBUG
134 void SkAlphaRuns::assertValid(int y, int maxStep) const
135 {
136 int max = (y + 1) * maxStep - (y == maxStep - 1);
137
138 const int16_t* runs = fRuns;
139 const uint8_t* alpha = fAlpha;
140
141 while (*runs)
142 {
143 SkASSERT(*alpha <= max);
144 alpha += *runs;
145 runs += *runs;
146 }
147 }
148
149 void SkAlphaRuns::dump() const
150 {
151 const int16_t* runs = fRuns;
152 const uint8_t* alpha = fAlpha;
153
154 SkDebugf("Runs");
155 while (*runs)
156 {
157 int n = *runs;
158
159 SkDebugf(" %02x", *alpha);
160 if (n > 1)
161 SkDebugf(",%d", n);
162 alpha += n;
163 runs += n;
164 }
165 SkDebugf("\n");
166 }
167
168 void SkAlphaRuns::validate() const
169 {
170 SkASSERT(fWidth > 0);
171
172 int count = 0;
173 const int16_t* runs = fRuns;
174
175 while (*runs)
176 {
177 SkASSERT(*runs > 0);
178 count += *runs;
179 SkASSERT(count <= fWidth);
180 runs += *runs;
181 }
182 SkASSERT(count == fWidth);
183 }
184#endif
185