1 /* 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
reset(int width)20 void 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
Break(int16_t runs[],uint8_t alpha[],int x,int count)32 void 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
add(int x,U8CPU startAlpha,int middleCount,U8CPU stopAlpha,U8CPU maxValue)84 void 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
assertValid(int y,int maxStep) const134 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
dump() const149 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
validate() const168 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
186