LCOV - code coverage report
Current view: top level - gfx/src - nsRect.h (source / functions) Hit Total Coverage
Test: output.info Lines: 81 123 65.9 %
Date: 2017-07-14 16:53:18 Functions: 19 24 79.2 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       5             : 
       6             : 
       7             : #ifndef NSRECT_H
       8             : #define NSRECT_H
       9             : 
      10             : #include <stdio.h>                      // for FILE
      11             : #include <stdint.h>                     // for int32_t, int64_t
      12             : #include <algorithm>                    // for min/max
      13             : #include "mozilla/Likely.h"             // for MOZ_UNLIKELY
      14             : #include "mozilla/gfx/Rect.h"
      15             : #include "nsCoord.h"                    // for nscoord, etc
      16             : #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
      17             : #include "nsPoint.h"                    // for nsIntPoint, nsPoint
      18             : #include "nsMargin.h"                   // for nsIntMargin, nsMargin
      19             : #include "nsSize.h"                     // for IntSize, nsSize
      20             : #include "nscore.h"                     // for NS_BUILD_REFCNT_LOGGING
      21             : 
      22             : typedef mozilla::gfx::IntRect nsIntRect;
      23             : 
      24             : struct nsRect :
      25             :   public mozilla::gfx::BaseRect<nscoord, nsRect, nsPoint, nsSize, nsMargin> {
      26             :   typedef mozilla::gfx::BaseRect<nscoord, nsRect, nsPoint, nsSize, nsMargin> Super;
      27             : 
      28             :   static void VERIFY_COORD(nscoord aValue) { ::VERIFY_COORD(aValue); }
      29             : 
      30             :   // Constructors
      31       82803 :   nsRect() : Super()
      32             :   {
      33       82803 :     MOZ_COUNT_CTOR(nsRect);
      34       82803 :   }
      35       75180 :   nsRect(const nsRect& aRect) : Super(aRect)
      36             :   {
      37       75180 :     MOZ_COUNT_CTOR(nsRect);
      38       75180 :   }
      39       23752 :   nsRect(const nsPoint& aOrigin, const nsSize &aSize) : Super(aOrigin, aSize)
      40             :   {
      41       23752 :     MOZ_COUNT_CTOR(nsRect);
      42       23752 :   }
      43       35168 :   nsRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight) :
      44       35168 :       Super(aX, aY, aWidth, aHeight)
      45             :   {
      46       35168 :     MOZ_COUNT_CTOR(nsRect);
      47       35168 :   }
      48             : 
      49             : #ifdef NS_BUILD_REFCNT_LOGGING
      50      431038 :   ~nsRect() {
      51      215520 :     MOZ_COUNT_DTOR(nsRect);
      52      215518 :   }
      53             : #endif
      54             : 
      55             :   // We have saturating versions of all the Union methods. These avoid
      56             :   // overflowing nscoord values in the 'width' and 'height' fields by
      57             :   // clamping the width and height values to nscoord_MAX if necessary.
      58             : 
      59       15004 :   MOZ_MUST_USE nsRect SaturatingUnion(const nsRect& aRect) const
      60             :   {
      61       15004 :     if (IsEmpty()) {
      62        3886 :       return aRect;
      63       11118 :     } else if (aRect.IsEmpty()) {
      64        3299 :       return *static_cast<const nsRect*>(this);
      65             :     } else {
      66        7819 :       return SaturatingUnionEdges(aRect);
      67             :     }
      68             :   }
      69             : 
      70       11014 :   MOZ_MUST_USE nsRect SaturatingUnionEdges(const nsRect& aRect) const
      71             :   {
      72             : #ifdef NS_COORD_IS_FLOAT
      73             :     return UnionEdges(aRect);
      74             : #else
      75       11014 :     nsRect result;
      76       11014 :     result.x = std::min(aRect.x, x);
      77       11014 :     int64_t w = std::max(int64_t(aRect.x) + aRect.width, int64_t(x) + width) - result.x;
      78       11014 :     if (MOZ_UNLIKELY(w > nscoord_MAX)) {
      79             :       // Clamp huge negative x to nscoord_MIN / 2 and try again.
      80           0 :       result.x = std::max(result.x, nscoord_MIN / 2);
      81           0 :       w = std::max(int64_t(aRect.x) + aRect.width, int64_t(x) + width) - result.x;
      82           0 :       if (MOZ_UNLIKELY(w > nscoord_MAX)) {
      83           0 :         w = nscoord_MAX;
      84             :       }
      85             :     }
      86       11014 :     result.width = nscoord(w);
      87             : 
      88       11014 :     result.y = std::min(aRect.y, y);
      89       11014 :     int64_t h = std::max(int64_t(aRect.y) + aRect.height, int64_t(y) + height) - result.y;
      90       11014 :     if (MOZ_UNLIKELY(h > nscoord_MAX)) {
      91             :       // Clamp huge negative y to nscoord_MIN / 2 and try again.
      92           0 :       result.y = std::max(result.y, nscoord_MIN / 2);
      93           0 :       h = std::max(int64_t(aRect.y) + aRect.height, int64_t(y) + height) - result.y;
      94           0 :       if (MOZ_UNLIKELY(h > nscoord_MAX)) {
      95           0 :         h = nscoord_MAX;
      96             :       }
      97             :     }
      98       11014 :     result.height = nscoord(h);
      99       11014 :     return result;
     100             : #endif
     101             :   }
     102             : 
     103             : #ifndef NS_COORD_IS_FLOAT
     104             :   // Make all nsRect Union methods be saturating.
     105        3195 :   MOZ_MUST_USE nsRect UnionEdges(const nsRect& aRect) const
     106             :   {
     107        3195 :     return SaturatingUnionEdges(aRect);
     108             :   }
     109        3195 :   void UnionRectEdges(const nsRect& aRect1, const nsRect& aRect2)
     110             :   {
     111        3195 :     *this = aRect1.UnionEdges(aRect2);
     112        3195 :   }
     113       15004 :   MOZ_MUST_USE nsRect Union(const nsRect& aRect) const
     114             :   {
     115       15004 :     return SaturatingUnion(aRect);
     116             :   }
     117       13623 :   void UnionRect(const nsRect& aRect1, const nsRect& aRect2)
     118             :   {
     119       13623 :     *this = aRect1.Union(aRect2);
     120       13623 :   }
     121             : #endif
     122             : 
     123             :   void SaturatingUnionRect(const nsRect& aRect1, const nsRect& aRect2)
     124             :   {
     125             :     *this = aRect1.SaturatingUnion(aRect2);
     126             :   }
     127             :   void SaturatingUnionRectEdges(const nsRect& aRect1, const nsRect& aRect2)
     128             :   {
     129             :     *this = aRect1.SaturatingUnionEdges(aRect2);
     130             :   }
     131             : 
     132             :   // Return whether this rect's right or bottom edge overflow int32.
     133             :   bool Overflows() const;
     134             : 
     135             :   /**
     136             :    * Return this rect scaled to a different appunits per pixel (APP) ratio.
     137             :    * In the RoundOut version we make the rect the smallest rect containing the
     138             :    * unrounded result. In the RoundIn version we make the rect the largest rect
     139             :    * contained in the unrounded result.
     140             :    * @param aFromAPP the APP to scale from
     141             :    * @param aToAPP the APP to scale to
     142             :    * @note this can turn an empty rectangle into a non-empty rectangle
     143             :    */
     144             :   MOZ_MUST_USE inline nsRect
     145             :     ScaleToOtherAppUnitsRoundOut(int32_t aFromAPP, int32_t aToAPP) const;
     146             :   MOZ_MUST_USE inline nsRect
     147             :     ScaleToOtherAppUnitsRoundIn(int32_t aFromAPP, int32_t aToAPP) const;
     148             : 
     149             :   MOZ_MUST_USE inline mozilla::gfx::IntRect
     150             :   ScaleToNearestPixels(float aXScale, float aYScale,
     151             :                        nscoord aAppUnitsPerPixel) const;
     152             : 
     153             :   MOZ_MUST_USE inline mozilla::gfx::IntRect
     154             :   ToNearestPixels(nscoord aAppUnitsPerPixel) const;
     155             : 
     156             :   // Note: this can turn an empty rectangle into a non-empty rectangle
     157             :   MOZ_MUST_USE inline mozilla::gfx::IntRect
     158             :   ScaleToOutsidePixels(float aXScale, float aYScale,
     159             :                        nscoord aAppUnitsPerPixel) const;
     160             : 
     161             :   // Note: this can turn an empty rectangle into a non-empty rectangle
     162             :   MOZ_MUST_USE inline mozilla::gfx::IntRect
     163             :   ToOutsidePixels(nscoord aAppUnitsPerPixel) const;
     164             : 
     165             :   MOZ_MUST_USE inline mozilla::gfx::IntRect
     166             :   ScaleToInsidePixels(float aXScale, float aYScale,
     167             :                       nscoord aAppUnitsPerPixel) const;
     168             : 
     169             :   MOZ_MUST_USE inline mozilla::gfx::IntRect
     170             :   ToInsidePixels(nscoord aAppUnitsPerPixel) const;
     171             : 
     172             :   // This is here only to keep IPDL-generated code happy. DO NOT USE.
     173         344 :   bool operator==(const nsRect& aRect) const
     174             :   {
     175         344 :     return IsEqualEdges(aRect);
     176             :   }
     177             : 
     178             :   MOZ_MUST_USE inline nsRect RemoveResolution(const float aResolution) const;
     179             : };
     180             : 
     181             : /*
     182             :  * App Unit/Pixel conversions
     183             :  */
     184             : 
     185             : inline nsRect
     186           0 : nsRect::ScaleToOtherAppUnitsRoundOut(int32_t aFromAPP, int32_t aToAPP) const
     187             : {
     188           0 :   if (aFromAPP == aToAPP) {
     189           0 :     return *this;
     190             :   }
     191             : 
     192           0 :   nsRect rect;
     193           0 :   nscoord right = NSToCoordCeil(NSCoordScale(XMost(), aFromAPP, aToAPP));
     194           0 :   nscoord bottom = NSToCoordCeil(NSCoordScale(YMost(), aFromAPP, aToAPP));
     195           0 :   rect.x = NSToCoordFloor(NSCoordScale(x, aFromAPP, aToAPP));
     196           0 :   rect.y = NSToCoordFloor(NSCoordScale(y, aFromAPP, aToAPP));
     197           0 :   rect.width = (right - rect.x);
     198           0 :   rect.height = (bottom - rect.y);
     199             : 
     200           0 :   return rect;
     201             : }
     202             : 
     203             : inline nsRect
     204           0 : nsRect::ScaleToOtherAppUnitsRoundIn(int32_t aFromAPP, int32_t aToAPP) const
     205             : {
     206           0 :   if (aFromAPP == aToAPP) {
     207           0 :     return *this;
     208             :   }
     209             : 
     210           0 :   nsRect rect;
     211           0 :   nscoord right = NSToCoordFloor(NSCoordScale(XMost(), aFromAPP, aToAPP));
     212           0 :   nscoord bottom = NSToCoordFloor(NSCoordScale(YMost(), aFromAPP, aToAPP));
     213           0 :   rect.x = NSToCoordCeil(NSCoordScale(x, aFromAPP, aToAPP));
     214           0 :   rect.y = NSToCoordCeil(NSCoordScale(y, aFromAPP, aToAPP));
     215           0 :   rect.width = (right - rect.x);
     216           0 :   rect.height = (bottom - rect.y);
     217             : 
     218           0 :   return rect;
     219             : }
     220             : 
     221             : // scale the rect but round to preserve centers
     222             : inline mozilla::gfx::IntRect
     223        2834 : nsRect::ScaleToNearestPixels(float aXScale, float aYScale,
     224             :                              nscoord aAppUnitsPerPixel) const
     225             : {
     226        2834 :   mozilla::gfx::IntRect rect;
     227        2834 :   rect.x = NSToIntRoundUp(NSAppUnitsToDoublePixels(x, aAppUnitsPerPixel) * aXScale);
     228        2834 :   rect.y = NSToIntRoundUp(NSAppUnitsToDoublePixels(y, aAppUnitsPerPixel) * aYScale);
     229             :   // Avoid negative widths and heights due to overflow
     230        5668 :   rect.width  = std::max(0, NSToIntRoundUp(NSAppUnitsToDoublePixels(XMost(),
     231        5668 :                                aAppUnitsPerPixel) * aXScale) - rect.x);
     232        5668 :   rect.height = std::max(0, NSToIntRoundUp(NSAppUnitsToDoublePixels(YMost(),
     233        5668 :                                aAppUnitsPerPixel) * aYScale) - rect.y);
     234        2834 :   return rect;
     235             : }
     236             : 
     237             : // scale the rect but round to smallest containing rect
     238             : inline mozilla::gfx::IntRect
     239        4503 : nsRect::ScaleToOutsidePixels(float aXScale, float aYScale,
     240             :                              nscoord aAppUnitsPerPixel) const
     241             : {
     242        4503 :   mozilla::gfx::IntRect rect;
     243        4503 :   rect.x = NSToIntFloor(NSAppUnitsToFloatPixels(x, float(aAppUnitsPerPixel)) * aXScale);
     244        4503 :   rect.y = NSToIntFloor(NSAppUnitsToFloatPixels(y, float(aAppUnitsPerPixel)) * aYScale);
     245             :   // Avoid negative widths and heights due to overflow
     246        9006 :   rect.width  = std::max(0, NSToIntCeil(NSAppUnitsToFloatPixels(XMost(),
     247        9006 :                             float(aAppUnitsPerPixel)) * aXScale) - rect.x);
     248        9006 :   rect.height = std::max(0, NSToIntCeil(NSAppUnitsToFloatPixels(YMost(),
     249        9006 :                             float(aAppUnitsPerPixel)) * aYScale) - rect.y);
     250        4503 :   return rect;
     251             : }
     252             : 
     253             : // scale the rect but round to largest contained rect
     254             : inline mozilla::gfx::IntRect
     255          28 : nsRect::ScaleToInsidePixels(float aXScale, float aYScale,
     256             :                             nscoord aAppUnitsPerPixel) const
     257             : {
     258          28 :   mozilla::gfx::IntRect rect;
     259          28 :   rect.x = NSToIntCeil(NSAppUnitsToFloatPixels(x, float(aAppUnitsPerPixel)) * aXScale);
     260          28 :   rect.y = NSToIntCeil(NSAppUnitsToFloatPixels(y, float(aAppUnitsPerPixel)) * aYScale);
     261             :   // Avoid negative widths and heights due to overflow
     262          56 :   rect.width  = std::max(0, NSToIntFloor(NSAppUnitsToFloatPixels(XMost(),
     263          56 :                              float(aAppUnitsPerPixel)) * aXScale) - rect.x);
     264          56 :   rect.height = std::max(0, NSToIntFloor(NSAppUnitsToFloatPixels(YMost(),
     265          56 :                              float(aAppUnitsPerPixel)) * aYScale) - rect.y);
     266          28 :   return rect;
     267             : }
     268             : 
     269             : inline mozilla::gfx::IntRect
     270          41 : nsRect::ToNearestPixels(nscoord aAppUnitsPerPixel) const
     271             : {
     272          41 :   return ScaleToNearestPixels(1.0f, 1.0f, aAppUnitsPerPixel);
     273             : }
     274             : 
     275             : inline mozilla::gfx::IntRect
     276         199 : nsRect::ToOutsidePixels(nscoord aAppUnitsPerPixel) const
     277             : {
     278         199 :   return ScaleToOutsidePixels(1.0f, 1.0f, aAppUnitsPerPixel);
     279             : }
     280             : 
     281             : inline mozilla::gfx::IntRect
     282           0 : nsRect::ToInsidePixels(nscoord aAppUnitsPerPixel) const
     283             : {
     284           0 :   return ScaleToInsidePixels(1.0f, 1.0f, aAppUnitsPerPixel);
     285             : }
     286             : 
     287             : inline nsRect
     288           0 : nsRect::RemoveResolution(const float aResolution) const
     289             : {
     290           0 :   MOZ_ASSERT(aResolution > 0.0f);
     291           0 :   nsRect rect;
     292           0 :   rect.x = NSToCoordRound(NSCoordToFloat(x) / aResolution);
     293           0 :   rect.y = NSToCoordRound(NSCoordToFloat(y) / aResolution);
     294             :   // A 1x1 rect indicates we are just hit testing a point, so pass down a 1x1
     295             :   // rect as well instead of possibly rounding the width or height to zero.
     296           0 :   if (width == 1 && height == 1) {
     297           0 :     rect.width = rect.height = 1;
     298             :   } else {
     299           0 :     rect.width = NSToCoordCeil(NSCoordToFloat(width) / aResolution);
     300           0 :     rect.height = NSToCoordCeil(NSCoordToFloat(height) / aResolution);
     301             :   }
     302             : 
     303           0 :   return rect;
     304             : }
     305             : 
     306             : const mozilla::gfx::IntRect& GetMaxSizedIntRect();
     307             : 
     308             : // app units are integer multiples of pixels, so no rounding needed
     309             : template<class units>
     310             : nsRect
     311         246 : ToAppUnits(const mozilla::gfx::IntRectTyped<units>& aRect, nscoord aAppUnitsPerPixel)
     312             : {
     313         246 :   return nsRect(NSIntPixelsToAppUnits(aRect.x, aAppUnitsPerPixel),
     314         246 :                 NSIntPixelsToAppUnits(aRect.y, aAppUnitsPerPixel),
     315         246 :                 NSIntPixelsToAppUnits(aRect.width, aAppUnitsPerPixel),
     316         984 :                 NSIntPixelsToAppUnits(aRect.height, aAppUnitsPerPixel));
     317             : }
     318             : 
     319             : #ifdef DEBUG
     320             : // Diagnostics
     321             : extern FILE* operator<<(FILE* out, const nsRect& rect);
     322             : #endif // DEBUG
     323             : 
     324             : #endif /* NSRECT_H */

Generated by: LCOV version 1.13