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 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 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 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 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 186