blob: 4f8611281a30607376eb63b227f2809120d2e553 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
mike@reedtribe.org676d69b2011-04-15 03:43:23 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * 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.
mike@reedtribe.org676d69b2011-04-15 03:43:23 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
mike@reedtribe.org676d69b2011-04-15 03:43:23 +000010#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 */
reedcaf7e932014-12-18 12:43:08 -080016static int chop(int64_t x0, SkGradFixed edge, int64_t x1, int64_t dx, int count) {
mike@reedtribe.org676d69b2011-04-15 03:43:23 +000017 SkASSERT(dx > 0);
18 SkASSERT(count >= 0);
19
20 if (x0 >= edge) {
21 return 0;
22 }
23 if (x1 <= edge) {
24 return count;
25 }
reed@google.com13659f12011-04-18 19:59:38 +000026 int64_t n = (edge - x0 + dx - 1) / dx;
mike@reedtribe.org676d69b2011-04-15 03:43:23 +000027 SkASSERT(n >= 0);
28 SkASSERT(n <= count);
reed@google.com13659f12011-04-18 19:59:38 +000029 return (int)n;
mike@reedtribe.org676d69b2011-04-15 03:43:23 +000030}
31
reedcaf7e932014-12-18 12:43:08 -080032void SkClampRange::initFor1(SkGradFixed fx) {
reed@google.com13659f12011-04-18 19:59:38 +000033 fCount0 = fCount1 = fCount2 = 0;
34 if (fx <= 0) {
35 fCount0 = 1;
reedcaf7e932014-12-18 12:43:08 -080036 } else if (fx < kFracMax_SkGradFixed) {
reed@google.com13659f12011-04-18 19:59:38 +000037 fCount1 = 1;
38 fFx1 = fx;
39 } else {
40 fCount2 = 1;
41 }
42}
43
reedcaf7e932014-12-18 12:43:08 -080044void SkClampRange::init(SkGradFixed fx0, SkGradFixed dx0, int count, int v0, int v1) {
mike@reedtribe.org676d69b2011-04-15 03:43:23 +000045 SkASSERT(count > 0);
46
47 fV0 = v0;
48 fV1 = v1;
49
reed@google.com13659f12011-04-18 19:59:38 +000050 // special case 1 == count, as it is slightly common for skia
51 // and avoids us ever calling divide or 64bit multiply
52 if (1 == count) {
53 this->initFor1(fx0);
54 return;
reed@google.com63c1ad82011-04-18 14:15:36 +000055 }
56
reed@google.com13659f12011-04-18 19:59:38 +000057 int64_t fx = fx0;
58 int64_t dx = dx0;
reedcaf7e932014-12-18 12:43:08 -080059
mike@reedtribe.org676d69b2011-04-15 03:43:23 +000060 // start with ex equal to the last computed value
reed@google.com13659f12011-04-18 19:59:38 +000061 int64_t ex = fx + (count - 1) * dx;
mike@reedtribe.org676d69b2011-04-15 03:43:23 +000062
reedcaf7e932014-12-18 12:43:08 -080063 if ((uint64_t)(fx | ex) <= kFracMax_SkGradFixed) {
mike@reedtribe.org676d69b2011-04-15 03:43:23 +000064 fCount0 = fCount2 = 0;
65 fCount1 = count;
reed@google.com13659f12011-04-18 19:59:38 +000066 fFx1 = fx0;
mike@reedtribe.org676d69b2011-04-15 03:43:23 +000067 return;
68 }
69 if (fx <= 0 && ex <= 0) {
70 fCount1 = fCount2 = 0;
71 fCount0 = count;
72 return;
73 }
reedcaf7e932014-12-18 12:43:08 -080074 if (fx >= kFracMax_SkGradFixed && ex >= kFracMax_SkGradFixed) {
mike@reedtribe.org676d69b2011-04-15 03:43:23 +000075 fCount0 = fCount1 = 0;
76 fCount2 = count;
77 return;
78 }
79
reed@google.com13659f12011-04-18 19:59:38 +000080 int extraCount = 0;
81
mike@reedtribe.org676d69b2011-04-15 03:43:23 +000082 // now make ex be 1 past the last computed value
83 ex += dx;
reedcaf7e932014-12-18 12:43:08 -080084
mike@reedtribe.org676d69b2011-04-15 03:43:23 +000085 bool doSwap = dx < 0;
86
87 if (doSwap) {
88 ex -= dx;
89 fx -= dx;
90 SkTSwap(fx, ex);
91 dx = -dx;
92 }
93
reed@google.com13659f12011-04-18 19:59:38 +000094
mike@reedtribe.org676d69b2011-04-15 03:43:23 +000095 fCount0 = chop(fx, 0, ex, dx, count);
96 count -= fCount0;
97 fx += fCount0 * dx;
98 SkASSERT(fx >= 0);
99 SkASSERT(fCount0 == 0 || (fx - dx) < 0);
reedcaf7e932014-12-18 12:43:08 -0800100 fCount1 = chop(fx, kFracMax_SkGradFixed, ex, dx, count);
mike@reedtribe.org676d69b2011-04-15 03:43:23 +0000101 count -= fCount1;
102 fCount2 = count;
103
104#ifdef SK_DEBUG
105 fx += fCount1 * dx;
106 SkASSERT(fx <= ex);
107 if (fCount2 > 0) {
reedcaf7e932014-12-18 12:43:08 -0800108 SkASSERT(fx >= kFracMax_SkGradFixed);
mike@reedtribe.org676d69b2011-04-15 03:43:23 +0000109 if (fCount1 > 0) {
reedcaf7e932014-12-18 12:43:08 -0800110 SkASSERT(fx - dx < kFracMax_SkGradFixed);
mike@reedtribe.org676d69b2011-04-15 03:43:23 +0000111 }
112 }
113#endif
114
115 if (doSwap) {
116 SkTSwap(fCount0, fCount2);
117 SkTSwap(fV0, fV1);
reed@google.com63c1ad82011-04-18 14:15:36 +0000118 dx = -dx;
119 }
120
121 if (fCount1 > 0) {
reed438b0d72014-12-19 07:40:26 -0800122 fFx1 = fx0 + fCount0 * dx;
reed@google.com13659f12011-04-18 19:59:38 +0000123 }
124
125 if (dx > 0) {
126 fCount2 += extraCount;
127 } else {
128 fCount0 += extraCount;
mike@reedtribe.org676d69b2011-04-15 03:43:23 +0000129 }
130}