Home | History | Annotate | Download | only in gradients
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      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 "SkClampRange.h"
     11 
     12 /*
     13  *  returns [0..count] for the number of steps (<= count) for which x0 <= edge
     14  *  given each step is followed by x0 += dx
     15  */
     16 static int chop(int64_t x0, SkFixed edge, int64_t x1, int64_t dx, int count) {
     17     SkASSERT(dx > 0);
     18     SkASSERT(count >= 0);
     19 
     20     if (x0 >= edge) {
     21         return 0;
     22     }
     23     if (x1 <= edge) {
     24         return count;
     25     }
     26     int64_t n = (edge - x0 + dx - 1) / dx;
     27     SkASSERT(n >= 0);
     28     SkASSERT(n <= count);
     29     return (int)n;
     30 }
     31 
     32 static bool overflows_fixed(int64_t x) {
     33     return x < -SK_FixedMax || x > SK_FixedMax;
     34 }
     35 
     36 void SkClampRange::initFor1(SkFixed fx) {
     37     fCount0 = fCount1 = fCount2 = 0;
     38     if (fx <= 0) {
     39         fCount0 = 1;
     40     } else if (fx < 0xFFFF) {
     41         fCount1 = 1;
     42         fFx1 = fx;
     43     } else {
     44         fCount2 = 1;
     45     }
     46 }
     47 
     48 void SkClampRange::init(SkFixed fx0, SkFixed dx0, int count, int v0, int v1) {
     49     SkASSERT(count > 0);
     50 
     51     fV0 = v0;
     52     fV1 = v1;
     53 
     54     // special case 1 == count, as it is slightly common for skia
     55     // and avoids us ever calling divide or 64bit multiply
     56     if (1 == count) {
     57         this->initFor1(fx0);
     58         return;
     59     }
     60 
     61     int64_t fx = fx0;
     62     int64_t dx = dx0;
     63     // start with ex equal to the last computed value
     64     int64_t ex = fx + (count - 1) * dx;
     65 
     66     if ((uint64_t)(fx | ex) <= 0xFFFF) {
     67         fCount0 = fCount2 = 0;
     68         fCount1 = count;
     69         fFx1 = fx0;
     70         return;
     71     }
     72     if (fx <= 0 && ex <= 0) {
     73         fCount1 = fCount2 = 0;
     74         fCount0 = count;
     75         return;
     76     }
     77     if (fx >= 0xFFFF && ex >= 0xFFFF) {
     78         fCount0 = fCount1 = 0;
     79         fCount2 = count;
     80         return;
     81     }
     82 
     83     int extraCount = 0;
     84 
     85     // now make ex be 1 past the last computed value
     86     ex += dx;
     87     // now check for over/under flow
     88     if (overflows_fixed(ex)) {
     89         int originalCount = count;
     90         int64_t ccount;
     91         bool swap = dx < 0;
     92         if (swap) {
     93             dx = -dx;
     94             fx = -fx;
     95         }
     96         ccount = (SK_FixedMax - fx + dx - 1) / dx;
     97         if (swap) {
     98             dx = -dx;
     99             fx = -fx;
    100         }
    101         SkASSERT(ccount > 0 && ccount <= SK_FixedMax);
    102 
    103         count = (int)ccount;
    104         if (0 == count) {
    105             this->initFor1(fx0);
    106             if (dx > 0) {
    107                 fCount2 += originalCount - 1;
    108             } else {
    109                 fCount0 += originalCount - 1;
    110             }
    111             return;
    112         }
    113         extraCount = originalCount - count;
    114         ex = fx + dx * count;
    115     }
    116 
    117     bool doSwap = dx < 0;
    118 
    119     if (doSwap) {
    120         ex -= dx;
    121         fx -= dx;
    122         SkTSwap(fx, ex);
    123         dx = -dx;
    124     }
    125 
    126 
    127     fCount0 = chop(fx, 0, ex, dx, count);
    128     count -= fCount0;
    129     fx += fCount0 * dx;
    130     SkASSERT(fx >= 0);
    131     SkASSERT(fCount0 == 0 || (fx - dx) < 0);
    132     fCount1 = chop(fx, 0xFFFF, ex, dx, count);
    133     count -= fCount1;
    134     fCount2 = count;
    135 
    136 #ifdef SK_DEBUG
    137     fx += fCount1 * dx;
    138     SkASSERT(fx <= ex);
    139     if (fCount2 > 0) {
    140         SkASSERT(fx >= 0xFFFF);
    141         if (fCount1 > 0) {
    142             SkASSERT(fx - dx < 0xFFFF);
    143         }
    144     }
    145 #endif
    146 
    147     if (doSwap) {
    148         SkTSwap(fCount0, fCount2);
    149         SkTSwap(fV0, fV1);
    150         dx = -dx;
    151     }
    152 
    153     if (fCount1 > 0) {
    154         fFx1 = fx0 + fCount0 * (int)dx;
    155     }
    156 
    157     if (dx > 0) {
    158         fCount2 += extraCount;
    159     } else {
    160         fCount0 += extraCount;
    161     }
    162 }
    163