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 
     20 void SkAlphaRuns::reset(int width)
     21 {
     22     SkASSERT(width > 0);
     23 
     24     fRuns[0] = SkToS16(width);
     25     fRuns[width] = 0;
     26     fAlpha[0] = 0;
     27 
     28     SkDEBUGCODE(fWidth = width;)
     29     SkDEBUGCODE(this->validate();)
     30 }
     31 
     32 void SkAlphaRuns::Break(int16_t runs[], uint8_t alpha[], int x, int count)
     33 {
     34     SkASSERT(count > 0 && x >= 0);
     35 
     36 //  SkAlphaRuns::BreakAt(runs, alpha, x);
     37 //  SkAlphaRuns::BreakAt(&runs[x], &alpha[x], count);
     38 
     39     int16_t* next_runs = runs + x;
     40     uint8_t*  next_alpha = alpha + x;
     41 
     42     while (x > 0)
     43     {
     44         int n = runs[0];
     45         SkASSERT(n > 0);
     46 
     47         if (x < n)
     48         {
     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     {
     65         int n = runs[0];
     66         SkASSERT(n > 0);
     67 
     68         if (x < n)
     69         {
     70             alpha[x] = alpha[0];
     71             runs[0] = SkToS16(x);
     72             runs[x] = SkToS16(n - x);
     73             break;
     74         }
     75         x -= n;
     76         if (x <= 0)
     77             break;
     78 
     79         runs += n;
     80         alpha += n;
     81     }
     82 }
     83 
     84 void SkAlphaRuns::add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, U8CPU maxValue)
     85 {
     86     SkASSERT(middleCount >= 0);
     87     SkASSERT(x >= 0 && x + (startAlpha != 0) + middleCount + (stopAlpha != 0) <= fWidth);
     88 
     89     int16_t*    runs = fRuns;
     90     uint8_t*     alpha = fAlpha;
     91 
     92     if (startAlpha)
     93     {
     94         SkAlphaRuns::Break(runs, alpha, x, 1);
     95         /*  I should be able to just add alpha[x] + startAlpha.
     96             However, if the trailing edge of the previous span and the leading
     97             edge of the current span round to the same super-sampled x value,
     98             I might overflow to 256 with this add, hence the funny subtract (crud).
     99         */
    100         unsigned tmp = alpha[x] + startAlpha;
    101         SkASSERT(tmp <= 256);
    102         alpha[x] = SkToU8(tmp - (tmp >> 8));    // was (tmp >> 7), but that seems wrong if we're trying to catch 256
    103 
    104         runs += x + 1;
    105         alpha += x + 1;
    106         x = 0;
    107         SkDEBUGCODE(this->validate();)
    108     }
    109     if (middleCount)
    110     {
    111         SkAlphaRuns::Break(runs, alpha, x, middleCount);
    112         alpha += x;
    113         runs += x;
    114         x = 0;
    115         do {
    116             alpha[0] = SkToU8(alpha[0] + maxValue);
    117             int n = runs[0];
    118             SkASSERT(n <= middleCount);
    119             alpha += n;
    120             runs += n;
    121             middleCount -= n;
    122         } while (middleCount > 0);
    123         SkDEBUGCODE(this->validate();)
    124     }
    125     if (stopAlpha)
    126     {
    127         SkAlphaRuns::Break(runs, alpha, x, 1);
    128         alpha[x] = SkToU8(alpha[x] + stopAlpha);
    129         SkDEBUGCODE(this->validate();)
    130     }
    131 }
    132 
    133 #ifdef SK_DEBUG
    134     void SkAlphaRuns::assertValid(int y, int maxStep) const
    135     {
    136         int max = (y + 1) * maxStep - (y == maxStep - 1);
    137 
    138         const int16_t* runs = fRuns;
    139         const uint8_t*   alpha = fAlpha;
    140 
    141         while (*runs)
    142         {
    143             SkASSERT(*alpha <= max);
    144             alpha += *runs;
    145             runs += *runs;
    146         }
    147     }
    148 
    149     void SkAlphaRuns::dump() const
    150     {
    151         const int16_t* runs = fRuns;
    152         const uint8_t* alpha = fAlpha;
    153 
    154         SkDebugf("Runs");
    155         while (*runs)
    156         {
    157             int n = *runs;
    158 
    159             SkDebugf(" %02x", *alpha);
    160             if (n > 1)
    161                 SkDebugf(",%d", n);
    162             alpha += n;
    163             runs += n;
    164         }
    165         SkDebugf("\n");
    166     }
    167 
    168     void SkAlphaRuns::validate() const
    169     {
    170         SkASSERT(fWidth > 0);
    171 
    172         int         count = 0;
    173         const int16_t*  runs = fRuns;
    174 
    175         while (*runs)
    176         {
    177             SkASSERT(*runs > 0);
    178             count += *runs;
    179             SkASSERT(count <= fWidth);
    180             runs += *runs;
    181         }
    182         SkASSERT(count == fWidth);
    183     }
    184 #endif
    185 
    186