1 2 /* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #include "SkAntiRun.h" 11 #include "SkUtils.h" 12 13 void SkAlphaRuns::reset(int width) { 14 SkASSERT(width > 0); 15 16 #ifdef SK_DEBUG 17 sk_memset16((uint16_t*)fRuns, (uint16_t)(-42), width); 18 #endif 19 fRuns[0] = SkToS16(width); 20 fRuns[width] = 0; 21 fAlpha[0] = 0; 22 23 SkDEBUGCODE(fWidth = width;) 24 SkDEBUGCODE(this->validate();) 25 } 26 27 void SkAlphaRuns::Break(int16_t runs[], uint8_t alpha[], int x, int count) { 28 SkASSERT(count > 0 && x >= 0); 29 30 // SkAlphaRuns::BreakAt(runs, alpha, x); 31 // SkAlphaRuns::BreakAt(&runs[x], &alpha[x], count); 32 33 int16_t* next_runs = runs + x; 34 uint8_t* next_alpha = alpha + x; 35 36 while (x > 0) { 37 int n = runs[0]; 38 SkASSERT(n > 0); 39 40 if (x < n) { 41 alpha[x] = alpha[0]; 42 runs[0] = SkToS16(x); 43 runs[x] = SkToS16(n - x); 44 break; 45 } 46 runs += n; 47 alpha += n; 48 x -= n; 49 } 50 51 runs = next_runs; 52 alpha = next_alpha; 53 x = count; 54 55 for (;;) { 56 int n = runs[0]; 57 SkASSERT(n > 0); 58 59 if (x < n) { 60 alpha[x] = alpha[0]; 61 runs[0] = SkToS16(x); 62 runs[x] = SkToS16(n - x); 63 break; 64 } 65 x -= n; 66 if (x <= 0) { 67 break; 68 } 69 runs += n; 70 alpha += n; 71 } 72 } 73 74 int SkAlphaRuns::add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, 75 U8CPU maxValue, int offsetX) { 76 SkASSERT(middleCount >= 0); 77 SkASSERT(x >= 0 && x + (startAlpha != 0) + middleCount + (stopAlpha != 0) <= fWidth); 78 79 SkASSERT(fRuns[offsetX] >= 0); 80 81 int16_t* runs = fRuns + offsetX; 82 uint8_t* alpha = fAlpha + offsetX; 83 uint8_t* lastAlpha = alpha; 84 x -= offsetX; 85 86 if (startAlpha) { 87 SkAlphaRuns::Break(runs, alpha, x, 1); 88 /* I should be able to just add alpha[x] + startAlpha. 89 However, if the trailing edge of the previous span and the leading 90 edge of the current span round to the same super-sampled x value, 91 I might overflow to 256 with this add, hence the funny subtract (crud). 92 */ 93 unsigned tmp = alpha[x] + startAlpha; 94 SkASSERT(tmp <= 256); 95 alpha[x] = SkToU8(tmp - (tmp >> 8)); // was (tmp >> 7), but that seems wrong if we're trying to catch 256 96 97 runs += x + 1; 98 alpha += x + 1; 99 x = 0; 100 lastAlpha += x; // we don't want the +1 101 SkDEBUGCODE(this->validate();) 102 } 103 104 if (middleCount) { 105 SkAlphaRuns::Break(runs, alpha, x, middleCount); 106 alpha += x; 107 runs += x; 108 x = 0; 109 do { 110 alpha[0] = SkToU8(alpha[0] + maxValue); 111 int n = runs[0]; 112 SkASSERT(n <= middleCount); 113 alpha += n; 114 runs += n; 115 middleCount -= n; 116 } while (middleCount > 0); 117 SkDEBUGCODE(this->validate();) 118 lastAlpha = alpha; 119 } 120 121 if (stopAlpha) { 122 SkAlphaRuns::Break(runs, alpha, x, 1); 123 alpha += x; 124 alpha[0] = SkToU8(alpha[0] + stopAlpha); 125 SkDEBUGCODE(this->validate();) 126 lastAlpha = alpha; 127 } 128 129 return SkToS32(lastAlpha - fAlpha); // new offsetX 130 } 131 132 #ifdef SK_DEBUG 133 void SkAlphaRuns::assertValid(int y, int maxStep) const { 134 int max = (y + 1) * maxStep - (y == maxStep - 1); 135 136 const int16_t* runs = fRuns; 137 const uint8_t* alpha = fAlpha; 138 139 while (*runs) { 140 SkASSERT(*alpha <= max); 141 alpha += *runs; 142 runs += *runs; 143 } 144 } 145 146 void SkAlphaRuns::dump() const { 147 const int16_t* runs = fRuns; 148 const uint8_t* alpha = fAlpha; 149 150 SkDebugf("Runs"); 151 while (*runs) { 152 int n = *runs; 153 154 SkDebugf(" %02x", *alpha); 155 if (n > 1) { 156 SkDebugf(",%d", n); 157 } 158 alpha += n; 159 runs += n; 160 } 161 SkDebugf("\n"); 162 } 163 164 void SkAlphaRuns::validate() const { 165 SkASSERT(fWidth > 0); 166 167 int count = 0; 168 const int16_t* runs = fRuns; 169 170 while (*runs) { 171 SkASSERT(*runs > 0); 172 count += *runs; 173 SkASSERT(count <= fWidth); 174 runs += *runs; 175 } 176 SkASSERT(count == fWidth); 177 } 178 #endif 179