Home | History | Annotate | Download | only in core
      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 
     13 void 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 
     27 void 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 
     74 int 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