Home | History | Annotate | Download | only in core
      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