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 #include "SkUtils.h" 20 21 void SkAlphaRuns::reset(int width) { 22 SkASSERT(width > 0); 23 24 #ifdef SK_DEBUG 25 sk_memset16((uint16_t*)fRuns, (uint16_t)(-42), width); 26 #endif 27 fRuns[0] = SkToS16(width); 28 fRuns[width] = 0; 29 fAlpha[0] = 0; 30 31 SkDEBUGCODE(fWidth = width;) 32 SkDEBUGCODE(this->validate();) 33 } 34 35 void SkAlphaRuns::Break(int16_t runs[], uint8_t alpha[], int x, int count) { 36 SkASSERT(count > 0 && x >= 0); 37 38 // SkAlphaRuns::BreakAt(runs, alpha, x); 39 // SkAlphaRuns::BreakAt(&runs[x], &alpha[x], count); 40 41 int16_t* next_runs = runs + x; 42 uint8_t* next_alpha = alpha + x; 43 44 while (x > 0) { 45 int n = runs[0]; 46 SkASSERT(n > 0); 47 48 if (x < n) { 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 int n = runs[0]; 65 SkASSERT(n > 0); 66 67 if (x < n) { 68 alpha[x] = alpha[0]; 69 runs[0] = SkToS16(x); 70 runs[x] = SkToS16(n - x); 71 break; 72 } 73 x -= n; 74 if (x <= 0) { 75 break; 76 } 77 runs += n; 78 alpha += n; 79 } 80 } 81 82 int SkAlphaRuns::add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, 83 U8CPU maxValue, int offsetX) { 84 SkASSERT(middleCount >= 0); 85 SkASSERT(x >= 0 && x + (startAlpha != 0) + middleCount + (stopAlpha != 0) <= fWidth); 86 87 SkASSERT(fRuns[offsetX] >= 0); 88 89 int16_t* runs = fRuns + offsetX; 90 uint8_t* alpha = fAlpha + offsetX; 91 uint8_t* lastAlpha = alpha; 92 x -= offsetX; 93 94 if (startAlpha) { 95 SkAlphaRuns::Break(runs, alpha, x, 1); 96 /* I should be able to just add alpha[x] + startAlpha. 97 However, if the trailing edge of the previous span and the leading 98 edge of the current span round to the same super-sampled x value, 99 I might overflow to 256 with this add, hence the funny subtract (crud). 100 */ 101 unsigned tmp = alpha[x] + startAlpha; 102 SkASSERT(tmp <= 256); 103 alpha[x] = SkToU8(tmp - (tmp >> 8)); // was (tmp >> 7), but that seems wrong if we're trying to catch 256 104 105 runs += x + 1; 106 alpha += x + 1; 107 x = 0; 108 lastAlpha += x; // we don't want the +1 109 SkDEBUGCODE(this->validate();) 110 } 111 112 if (middleCount) { 113 SkAlphaRuns::Break(runs, alpha, x, middleCount); 114 alpha += x; 115 runs += x; 116 x = 0; 117 do { 118 alpha[0] = SkToU8(alpha[0] + maxValue); 119 int n = runs[0]; 120 SkASSERT(n <= middleCount); 121 alpha += n; 122 runs += n; 123 middleCount -= n; 124 } while (middleCount > 0); 125 SkDEBUGCODE(this->validate();) 126 lastAlpha = alpha; 127 } 128 129 if (stopAlpha) { 130 SkAlphaRuns::Break(runs, alpha, x, 1); 131 alpha += x; 132 alpha[0] = SkToU8(alpha[0] + stopAlpha); 133 SkDEBUGCODE(this->validate();) 134 lastAlpha = alpha; 135 } 136 137 return lastAlpha - fAlpha; // new offsetX 138 } 139 140 #ifdef SK_DEBUG 141 void SkAlphaRuns::assertValid(int y, int maxStep) const { 142 int max = (y + 1) * maxStep - (y == maxStep - 1); 143 144 const int16_t* runs = fRuns; 145 const uint8_t* alpha = fAlpha; 146 147 while (*runs) { 148 SkASSERT(*alpha <= max); 149 alpha += *runs; 150 runs += *runs; 151 } 152 } 153 154 void SkAlphaRuns::dump() const { 155 const int16_t* runs = fRuns; 156 const uint8_t* alpha = fAlpha; 157 158 SkDebugf("Runs"); 159 while (*runs) { 160 int n = *runs; 161 162 SkDebugf(" %02x", *alpha); 163 if (n > 1) { 164 SkDebugf(",%d", n); 165 } 166 alpha += n; 167 runs += n; 168 } 169 SkDebugf("\n"); 170 } 171 172 void SkAlphaRuns::validate() const { 173 SkASSERT(fWidth > 0); 174 175 int count = 0; 176 const int16_t* runs = fRuns; 177 178 while (*runs) { 179 SkASSERT(*runs > 0); 180 count += *runs; 181 SkASSERT(count <= fWidth); 182 runs += *runs; 183 } 184 SkASSERT(count == fWidth); 185 } 186 #endif 187 188