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
13void 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
27void 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
74int 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 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
180