gfx/src/nsCoord.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

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 */

mercurial