blob: 116d132a5d6438406b0878e87209f6e84dea8cdd [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
10#include "SkAntiRun.h"
reed@google.comfa57ae72011-05-31 19:18:02 +000011#include "SkUtils.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000012
mike@reedtribe.orgd11f0e02011-04-09 19:39:25 +000013void SkAlphaRuns::reset(int width) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000014 SkASSERT(width > 0);
15
reed@google.comfa57ae72011-05-31 19:18:02 +000016#ifdef SK_DEBUG
17 sk_memset16((uint16_t*)fRuns, (uint16_t)(-42), width);
18#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +000019 fRuns[0] = SkToS16(width);
20 fRuns[width] = 0;
21 fAlpha[0] = 0;
22
23 SkDEBUGCODE(fWidth = width;)
24 SkDEBUGCODE(this->validate();)
25}
26
mike@reedtribe.orgd11f0e02011-04-09 19:39:25 +000027void SkAlphaRuns::Break(int16_t runs[], uint8_t alpha[], int x, int count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000028 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
mike@reedtribe.orgd11f0e02011-04-09 19:39:25 +000036 while (x > 0) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000037 int n = runs[0];
38 SkASSERT(n > 0);
39
mike@reedtribe.orgd11f0e02011-04-09 19:39:25 +000040 if (x < n) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000041 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
mike@reedtribe.orgd11f0e02011-04-09 19:39:25 +000055 for (;;) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000056 int n = runs[0];
57 SkASSERT(n > 0);
58
mike@reedtribe.orgd11f0e02011-04-09 19:39:25 +000059 if (x < n) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000060 alpha[x] = alpha[0];
61 runs[0] = SkToS16(x);
62 runs[x] = SkToS16(n - x);
63 break;
64 }
65 x -= n;
mike@reedtribe.orgd11f0e02011-04-09 19:39:25 +000066 if (x <= 0) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000067 break;
mike@reedtribe.orgd11f0e02011-04-09 19:39:25 +000068 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000069 runs += n;
70 alpha += n;
71 }
72}
73
reed@google.comfa57ae72011-05-31 19:18:02 +000074int SkAlphaRuns::add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha,
75 U8CPU maxValue, int offsetX) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000076 SkASSERT(middleCount >= 0);
77 SkASSERT(x >= 0 && x + (startAlpha != 0) + middleCount + (stopAlpha != 0) <= fWidth);
78
reed@google.comfa57ae72011-05-31 19:18:02 +000079 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;
reed@android.com8a1c16f2008-12-17 15:59:43 +000085
mike@reedtribe.orgd11f0e02011-04-09 19:39:25 +000086 if (startAlpha) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000087 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;
reed@google.comfa57ae72011-05-31 19:18:02 +0000100 lastAlpha += x; // we don't want the +1
reed@android.com8a1c16f2008-12-17 15:59:43 +0000101 SkDEBUGCODE(this->validate();)
102 }
mike@reedtribe.orgd11f0e02011-04-09 19:39:25 +0000103
104 if (middleCount) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000105 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();)
reed@google.comfa57ae72011-05-31 19:18:02 +0000118 lastAlpha = alpha;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000119 }
mike@reedtribe.orgd11f0e02011-04-09 19:39:25 +0000120
121 if (stopAlpha) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000122 SkAlphaRuns::Break(runs, alpha, x, 1);
reed@google.comfa57ae72011-05-31 19:18:02 +0000123 alpha += x;
124 alpha[0] = SkToU8(alpha[0] + stopAlpha);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000125 SkDEBUGCODE(this->validate();)
reed@google.comfa57ae72011-05-31 19:18:02 +0000126 lastAlpha = alpha;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127 }
reed@google.comfa57ae72011-05-31 19:18:02 +0000128
129 return lastAlpha - fAlpha; // new offsetX
reed@android.com8a1c16f2008-12-17 15:59:43 +0000130}
131
132#ifdef SK_DEBUG
mike@reedtribe.orgd11f0e02011-04-09 19:39:25 +0000133 void SkAlphaRuns::assertValid(int y, int maxStep) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000134 int max = (y + 1) * maxStep - (y == maxStep - 1);
135
136 const int16_t* runs = fRuns;
137 const uint8_t* alpha = fAlpha;
138
mike@reedtribe.orgd11f0e02011-04-09 19:39:25 +0000139 while (*runs) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000140 SkASSERT(*alpha <= max);
141 alpha += *runs;
142 runs += *runs;
143 }
144 }
145
mike@reedtribe.orgd11f0e02011-04-09 19:39:25 +0000146 void SkAlphaRuns::dump() const {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000147 const int16_t* runs = fRuns;
148 const uint8_t* alpha = fAlpha;
149
150 SkDebugf("Runs");
mike@reedtribe.orgd11f0e02011-04-09 19:39:25 +0000151 while (*runs) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000152 int n = *runs;
153
154 SkDebugf(" %02x", *alpha);
mike@reedtribe.orgd11f0e02011-04-09 19:39:25 +0000155 if (n > 1) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000156 SkDebugf(",%d", n);
mike@reedtribe.orgd11f0e02011-04-09 19:39:25 +0000157 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000158 alpha += n;
159 runs += n;
160 }
161 SkDebugf("\n");
162 }
163
mike@reedtribe.orgd11f0e02011-04-09 19:39:25 +0000164 void SkAlphaRuns::validate() const {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000165 SkASSERT(fWidth > 0);
166
167 int count = 0;
168 const int16_t* runs = fRuns;
169
mike@reedtribe.orgd11f0e02011-04-09 19:39:25 +0000170 while (*runs) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000171 SkASSERT(*runs > 0);
172 count += *runs;
173 SkASSERT(count <= fWidth);
174 runs += *runs;
175 }
176 SkASSERT(count == fWidth);
177 }
178#endif
179