LCOV - code coverage report
Current view: top level - gfx/src - nsCoord.h (source / functions) Hit Total Coverage
Test: output.info Lines: 42 80 52.5 %
Date: 2018-08-07 16:35:00 Functions: 0 0 -
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13-14-ga5dd952