Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef NSCOORD_H
7 #define NSCOORD_H
9 #include "nsAlgorithm.h"
10 #include "nscore.h"
11 #include "nsMathUtils.h"
12 #include <math.h>
13 #include <float.h>
15 #include "nsDebug.h"
16 #include <algorithm>
18 /*
19 * Basic type used for the geometry classes.
20 *
21 * Normally all coordinates are maintained in an app unit coordinate
22 * space. An app unit is 1/60th of a CSS device pixel, which is, in turn
23 * an integer number of device pixels, such at the CSS DPI is as close to
24 * 96dpi as possible.
25 */
27 // This controls whether we're using integers or floats for coordinates. We
28 // want to eventually use floats.
29 //#define NS_COORD_IS_FLOAT
31 inline float NS_IEEEPositiveInfinity() {
32 union { uint32_t mPRUint32; float mFloat; } pun;
33 pun.mPRUint32 = 0x7F800000;
34 return pun.mFloat;
35 }
36 inline bool NS_IEEEIsNan(float aF) {
37 union { uint32_t mBits; float mFloat; } pun;
38 pun.mFloat = aF;
39 return (pun.mBits & 0x7F800000) == 0x7F800000 &&
40 (pun.mBits & 0x007FFFFF) != 0;
41 }
43 #ifdef NS_COORD_IS_FLOAT
44 typedef float nscoord;
45 #define nscoord_MAX NS_IEEEPositiveInfinity()
46 #else
47 typedef int32_t nscoord;
48 #define nscoord_MAX nscoord(1 << 30)
49 #endif
51 #define nscoord_MIN (-nscoord_MAX)
53 inline void VERIFY_COORD(nscoord aCoord) {
54 #ifdef NS_COORD_IS_FLOAT
55 NS_ASSERTION(floorf(aCoord) == aCoord,
56 "Coords cannot have fractions");
57 #endif
58 }
60 inline nscoord NSToCoordRound(float aValue)
61 {
62 #if defined(XP_WIN32) && defined(_M_IX86) && !defined(__GNUC__)
63 return NS_lroundup30(aValue);
64 #else
65 return nscoord(floorf(aValue + 0.5f));
66 #endif /* XP_WIN32 && _M_IX86 && !__GNUC__ */
67 }
69 inline nscoord NSToCoordRound(double aValue)
70 {
71 #if defined(XP_WIN32) && defined(_M_IX86) && !defined(__GNUC__)
72 return NS_lroundup30((float)aValue);
73 #else
74 return nscoord(floor(aValue + 0.5f));
75 #endif /* XP_WIN32 && _M_IX86 && !__GNUC__ */
76 }
78 inline nscoord NSToCoordRoundWithClamp(float aValue)
79 {
80 #ifndef NS_COORD_IS_FLOAT
81 // Bounds-check before converting out of float, to avoid overflow
82 if (aValue >= nscoord_MAX) {
83 return nscoord_MAX;
84 }
85 if (aValue <= nscoord_MIN) {
86 return nscoord_MIN;
87 }
88 #endif
89 return NSToCoordRound(aValue);
90 }
92 /**
93 * Returns aCoord * aScale, capping the product to nscoord_MAX or nscoord_MIN as
94 * appropriate for the signs of aCoord and aScale. If requireNotNegative is
95 * true, this method will enforce that aScale is not negative; use that
96 * parametrization to get a check of that fact in debug builds.
97 */
98 inline nscoord _nscoordSaturatingMultiply(nscoord aCoord, float aScale,
99 bool requireNotNegative) {
100 VERIFY_COORD(aCoord);
101 if (requireNotNegative) {
102 NS_ABORT_IF_FALSE(aScale >= 0.0f,
103 "negative scaling factors must be handled manually");
104 }
105 #ifdef NS_COORD_IS_FLOAT
106 return floorf(aCoord * aScale);
107 #else
108 float product = aCoord * aScale;
109 if (requireNotNegative ? aCoord > 0 : (aCoord > 0) == (aScale > 0))
110 return NSToCoordRoundWithClamp(std::min<float>(nscoord_MAX, product));
111 return NSToCoordRoundWithClamp(std::max<float>(nscoord_MIN, product));
112 #endif
113 }
115 /**
116 * Returns aCoord * aScale, capping the product to nscoord_MAX or nscoord_MIN as
117 * appropriate for the sign of aCoord. This method requires aScale to not be
118 * negative; use this method when you know that aScale should never be
119 * negative to get a sanity check of that invariant in debug builds.
120 */
121 inline nscoord NSCoordSaturatingNonnegativeMultiply(nscoord aCoord, float aScale) {
122 return _nscoordSaturatingMultiply(aCoord, aScale, true);
123 }
125 /**
126 * Returns aCoord * aScale, capping the product to nscoord_MAX or nscoord_MIN as
127 * appropriate for the signs of aCoord and aScale.
128 */
129 inline nscoord NSCoordSaturatingMultiply(nscoord aCoord, float aScale) {
130 return _nscoordSaturatingMultiply(aCoord, aScale, false);
131 }
133 /**
134 * Returns a + b, capping the sum to nscoord_MAX.
135 *
136 * This function assumes that neither argument is nscoord_MIN.
137 *
138 * Note: If/when we start using floats for nscoords, this function won't be as
139 * necessary. Normal float addition correctly handles adding with infinity,
140 * assuming we aren't adding nscoord_MIN. (-infinity)
141 */
142 inline nscoord
143 NSCoordSaturatingAdd(nscoord a, nscoord b)
144 {
145 VERIFY_COORD(a);
146 VERIFY_COORD(b);
148 #ifdef NS_COORD_IS_FLOAT
149 // Float math correctly handles a+b, given that neither is -infinity.
150 return a + b;
151 #else
152 if (a == nscoord_MAX || b == nscoord_MAX) {
153 // infinity + anything = anything + infinity = infinity
154 return nscoord_MAX;
155 } else {
156 // a + b = a + b
157 // Cap the result, just in case we're dealing with numbers near nscoord_MAX
158 return std::min(nscoord_MAX, a + b);
159 }
160 #endif
161 }
163 /**
164 * Returns a - b, gracefully handling cases involving nscoord_MAX.
165 * This function assumes that neither argument is nscoord_MIN.
166 *
167 * The behavior is as follows:
168 *
169 * a) infinity - infinity -> infMinusInfResult
170 * b) N - infinity -> 0 (unexpected -- triggers NOTREACHED)
171 * c) infinity - N -> infinity
172 * d) N1 - N2 -> N1 - N2
173 *
174 * Note: For float nscoords, cases (c) and (d) are handled by normal float
175 * math. We still need to explicitly specify the behavior for cases (a)
176 * and (b), though. (Under normal float math, those cases would return NaN
177 * and -infinity, respectively.)
178 */
179 inline nscoord
180 NSCoordSaturatingSubtract(nscoord a, nscoord b,
181 nscoord infMinusInfResult)
182 {
183 VERIFY_COORD(a);
184 VERIFY_COORD(b);
186 if (b == nscoord_MAX) {
187 if (a == nscoord_MAX) {
188 // case (a)
189 return infMinusInfResult;
190 } else {
191 // case (b)
192 NS_NOTREACHED("Attempted to subtract [n - nscoord_MAX]");
193 return 0;
194 }
195 } else {
196 #ifdef NS_COORD_IS_FLOAT
197 // case (c) and (d) for floats. (float math handles both)
198 return a - b;
199 #else
200 if (a == nscoord_MAX) {
201 // case (c) for integers
202 return nscoord_MAX;
203 } else {
204 // case (d) for integers
205 // Cap the result, in case we're dealing with numbers near nscoord_MAX
206 return std::min(nscoord_MAX, a - b);
207 }
208 }
209 #endif
210 }
212 inline float NSCoordToFloat(nscoord aCoord) {
213 VERIFY_COORD(aCoord);
214 #ifdef NS_COORD_IS_FLOAT
215 NS_ASSERTION(!NS_IEEEIsNan(aCoord), "NaN encountered in float conversion");
216 #endif
217 return (float)aCoord;
218 }
220 /*
221 * Coord Rounding Functions
222 */
223 inline nscoord NSToCoordFloor(float aValue)
224 {
225 return nscoord(floorf(aValue));
226 }
228 inline nscoord NSToCoordFloor(double aValue)
229 {
230 return nscoord(floor(aValue));
231 }
233 inline nscoord NSToCoordFloorClamped(float aValue)
234 {
235 #ifndef NS_COORD_IS_FLOAT
236 // Bounds-check before converting out of float, to avoid overflow
237 if (aValue >= nscoord_MAX) {
238 return nscoord_MAX;
239 }
240 if (aValue <= nscoord_MIN) {
241 return nscoord_MIN;
242 }
243 #endif
244 return NSToCoordFloor(aValue);
245 }
247 inline nscoord NSToCoordCeil(float aValue)
248 {
249 return nscoord(ceilf(aValue));
250 }
252 inline nscoord NSToCoordCeil(double aValue)
253 {
254 return nscoord(ceil(aValue));
255 }
257 inline nscoord NSToCoordCeilClamped(double aValue)
258 {
259 #ifndef NS_COORD_IS_FLOAT
260 // Bounds-check before converting out of double, to avoid overflow
261 if (aValue >= nscoord_MAX) {
262 return nscoord_MAX;
263 }
264 if (aValue <= nscoord_MIN) {
265 return nscoord_MIN;
266 }
267 #endif
268 return NSToCoordCeil(aValue);
269 }
271 /*
272 * Int Rounding Functions
273 */
274 inline int32_t NSToIntFloor(float aValue)
275 {
276 return int32_t(floorf(aValue));
277 }
279 inline int32_t NSToIntCeil(float aValue)
280 {
281 return int32_t(ceilf(aValue));
282 }
284 inline int32_t NSToIntRound(float aValue)
285 {
286 return NS_lroundf(aValue);
287 }
289 inline int32_t NSToIntRound(double aValue)
290 {
291 return NS_lround(aValue);
292 }
294 inline int32_t NSToIntRoundUp(double aValue)
295 {
296 return int32_t(floor(aValue + 0.5));
297 }
299 /*
300 * App Unit/Pixel conversions
301 */
302 inline nscoord NSFloatPixelsToAppUnits(float aPixels, float aAppUnitsPerPixel)
303 {
304 return NSToCoordRoundWithClamp(aPixels * aAppUnitsPerPixel);
305 }
307 inline nscoord NSIntPixelsToAppUnits(int32_t aPixels, int32_t aAppUnitsPerPixel)
308 {
309 // The cast to nscoord makes sure we don't overflow if we ever change
310 // nscoord to float
311 nscoord r = aPixels * (nscoord)aAppUnitsPerPixel;
312 VERIFY_COORD(r);
313 return r;
314 }
316 inline float NSAppUnitsToFloatPixels(nscoord aAppUnits, float aAppUnitsPerPixel)
317 {
318 return (float(aAppUnits) / aAppUnitsPerPixel);
319 }
321 inline double NSAppUnitsToDoublePixels(nscoord aAppUnits, double aAppUnitsPerPixel)
322 {
323 return (double(aAppUnits) / aAppUnitsPerPixel);
324 }
326 inline int32_t NSAppUnitsToIntPixels(nscoord aAppUnits, float aAppUnitsPerPixel)
327 {
328 return NSToIntRound(float(aAppUnits) / aAppUnitsPerPixel);
329 }
331 inline float NSCoordScale(nscoord aCoord, int32_t aFromAPP, int32_t aToAPP)
332 {
333 return (NSCoordToFloat(aCoord) * aToAPP) / aFromAPP;
334 }
336 /// handy constants
337 #define TWIPS_PER_POINT_INT 20
338 #define TWIPS_PER_POINT_FLOAT 20.0f
339 #define POINTS_PER_INCH_INT 72
340 #define POINTS_PER_INCH_FLOAT 72.0f
341 #define CM_PER_INCH_FLOAT 2.54f
342 #define MM_PER_INCH_FLOAT 25.4f
344 /*
345 * Twips/unit conversions
346 */
347 inline float NSUnitsToTwips(float aValue, float aPointsPerUnit)
348 {
349 return aValue * aPointsPerUnit * TWIPS_PER_POINT_FLOAT;
350 }
352 inline float NSTwipsToUnits(float aTwips, float aUnitsPerPoint)
353 {
354 return (aTwips * (aUnitsPerPoint / TWIPS_PER_POINT_FLOAT));
355 }
357 /// Unit conversion macros
358 //@{
359 #define NS_POINTS_TO_TWIPS(x) NSUnitsToTwips((x), 1.0f)
360 #define NS_INCHES_TO_TWIPS(x) NSUnitsToTwips((x), POINTS_PER_INCH_FLOAT) // 72 points per inch
362 #define NS_MILLIMETERS_TO_TWIPS(x) NSUnitsToTwips((x), (POINTS_PER_INCH_FLOAT * 0.03937f))
364 #define NS_POINTS_TO_INT_TWIPS(x) NSToIntRound(NS_POINTS_TO_TWIPS(x))
365 #define NS_INCHES_TO_INT_TWIPS(x) NSToIntRound(NS_INCHES_TO_TWIPS(x))
367 #define NS_TWIPS_TO_INCHES(x) NSTwipsToUnits((x), 1.0f / POINTS_PER_INCH_FLOAT)
369 #define NS_TWIPS_TO_MILLIMETERS(x) NSTwipsToUnits((x), 1.0f / (POINTS_PER_INCH_FLOAT * 0.03937f))
370 //@}
372 #endif /* NSCOORD_H */