/* libs/graphics/sgl/SkAntiRun.h ** ** Copyright 2006, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ #ifndef SkAntiRun_DEFINED #define SkAntiRun_DEFINED #include "SkBlitter.h" inline int sk_make_nonzero_neg_one(int x) { return (x | -x) >> 31; } #if 0 template <int kShift> class SkAntiRun { static uint8_t coverage_to_alpha(int aa) { aa <<= 8 - 2*kShift; aa -= aa >> (8 - kShift - 1); return SkToU8(aa); } public: void set(int start, int stop) { SkASSERT(start >= 0 && stop > start); #if 1 int fb = start & kMask; int fe = stop & kMask; int n = (stop >> kShift) - (start >> kShift) - 1; if (n < 0) { fb = fe - fb; n = 0; fe = 0; } else { if (fb == 0) n += 1; else fb = (1 << kShift) - fb; } fStartAlpha = coverage_to_alpha(fb); fMiddleCount = n; fStopAlpha = coverage_to_alpha(fe); #else int x0 = start >> kShift; int x1 = (stop - 1) >> kShift; int middle = x1 - x0; int aa; if (middle == 0) { aa = stop - start; aa <<= 8 - 2*kShift; aa -= aa >> (8 - kShift - 1); SkASSERT(aa > 0 && aa < kMax); fStartAlpha = SkToU8(aa); fMiddleCount = 0; fStopAlpha = 0; } else { int aa = start & kMask; aa <<= 8 - 2*kShift; aa -= aa >> (8 - kShift - 1); SkASSERT(aa >= 0 && aa < kMax); if (aa) fStartAlpha = SkToU8(kMax - aa); else { fStartAlpha = 0; middle += 1; } aa = stop & kMask; aa <<= 8 - 2*kShift; aa -= aa >> (8 - kShift - 1); SkASSERT(aa >= 0 && aa < kMax); middle += sk_make_nonzero_neg_one(aa); fStopAlpha = SkToU8(aa); fMiddleCount = middle; } SkASSERT(fStartAlpha < kMax); SkASSERT(fStopAlpha < kMax); #endif } void blit(int x, int y, SkBlitter* blitter) { int16_t runs[2]; runs[0] = 1; runs[1] = 0; if (fStartAlpha) { blitter->blitAntiH(x, y, &fStartAlpha, runs); x += 1; } if (fMiddleCount) { blitter->blitH(x, y, fMiddleCount); x += fMiddleCount; } if (fStopAlpha) blitter->blitAntiH(x, y, &fStopAlpha, runs); } uint8_t getStartAlpha() const { return fStartAlpha; } int getMiddleCount() const { return fMiddleCount; } uint8_t getStopAlpha() const { return fStopAlpha; } private: uint8_t fStartAlpha, fStopAlpha; int fMiddleCount; enum { kMask = (1 << kShift) - 1, kMax = (1 << (8 - kShift)) - 1 }; }; #endif //////////////////////////////////////////////////////////////////////////////////// class SkAlphaRuns { public: int16_t* fRuns; uint8_t* fAlpha; bool empty() const { SkASSERT(fRuns[0] > 0); return fAlpha[0] == 0 && fRuns[fRuns[0]] == 0; } void reset(int width); void add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, U8CPU maxValue); SkDEBUGCODE(void assertValid(int y, int maxStep) const;) SkDEBUGCODE(void dump() const;) static void Break(int16_t runs[], uint8_t alpha[], int x, int count); static void BreakAt(int16_t runs[], uint8_t alpha[], int x) { while (x > 0) { int n = runs[0]; SkASSERT(n > 0); if (x < n) { alpha[x] = alpha[0]; runs[0] = SkToS16(x); runs[x] = SkToS16(n - x); break; } runs += n; alpha += n; x -= n; } } private: SkDEBUGCODE(int fWidth;) SkDEBUGCODE(void validate() const;) }; #endif