gfx/skia/trunk/src/effects/gradients/SkClampRange.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial