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