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.

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

mercurial