Thu, 22 Jan 2015 13:21:57 +0100
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 | } |