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.
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/. */
7 #ifndef NSRECT_H
8 #define NSRECT_H
10 #include <stdio.h> // for FILE
11 #include <stdint.h> // for int32_t, int64_t
12 #include <algorithm> // for min/max
13 #include "nsDebug.h" // for NS_WARNING
14 #include "gfxCore.h" // for NS_GFX
15 #include "mozilla/Likely.h" // for MOZ_UNLIKELY
16 #include "mozilla/gfx/BaseRect.h" // for BaseRect
17 #include "nsCoord.h" // for nscoord, etc
18 #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
19 #include "nsPoint.h" // for nsIntPoint, nsPoint
20 #include "nsSize.h" // for nsIntSize, nsSize
21 #include "nscore.h" // for NS_BUILD_REFCNT_LOGGING
23 struct nsIntRect;
24 struct nsMargin;
25 struct nsIntMargin;
27 struct NS_GFX nsRect :
28 public mozilla::gfx::BaseRect<nscoord, nsRect, nsPoint, nsSize, nsMargin> {
29 typedef mozilla::gfx::BaseRect<nscoord, nsRect, nsPoint, nsSize, nsMargin> Super;
31 static void VERIFY_COORD(nscoord aValue) { ::VERIFY_COORD(aValue); }
33 // Constructors
34 nsRect() : Super()
35 {
36 MOZ_COUNT_CTOR(nsRect);
37 }
38 nsRect(const nsRect& aRect) : Super(aRect)
39 {
40 MOZ_COUNT_CTOR(nsRect);
41 }
42 nsRect(const nsPoint& aOrigin, const nsSize &aSize) : Super(aOrigin, aSize)
43 {
44 MOZ_COUNT_CTOR(nsRect);
45 }
46 nsRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight) :
47 Super(aX, aY, aWidth, aHeight)
48 {
49 MOZ_COUNT_CTOR(nsRect);
50 }
52 #ifdef NS_BUILD_REFCNT_LOGGING
53 ~nsRect() {
54 MOZ_COUNT_DTOR(nsRect);
55 }
56 #endif
58 // We have saturating versions of all the Union methods. These avoid
59 // overflowing nscoord values in the 'width' and 'height' fields by
60 // clamping the width and height values to nscoord_MAX if necessary.
62 nsRect SaturatingUnion(const nsRect& aRect) const
63 {
64 if (IsEmpty()) {
65 return aRect;
66 } else if (aRect.IsEmpty()) {
67 return *static_cast<const nsRect*>(this);
68 } else {
69 return SaturatingUnionEdges(aRect);
70 }
71 }
73 nsRect SaturatingUnionEdges(const nsRect& aRect) const
74 {
75 #ifdef NS_COORD_IS_FLOAT
76 return UnionEdges(aRect);
77 #else
78 nsRect result;
79 result.x = std::min(aRect.x, x);
80 int64_t w = std::max(int64_t(aRect.x) + aRect.width, int64_t(x) + width) - result.x;
81 if (MOZ_UNLIKELY(w > nscoord_MAX)) {
82 NS_WARNING("Overflowed nscoord_MAX in conversion to nscoord width");
83 // Clamp huge negative x to nscoord_MIN / 2 and try again.
84 result.x = std::max(result.x, nscoord_MIN / 2);
85 w = std::max(int64_t(aRect.x) + aRect.width, int64_t(x) + width) - result.x;
86 if (MOZ_UNLIKELY(w > nscoord_MAX)) {
87 w = nscoord_MAX;
88 }
89 }
90 result.width = nscoord(w);
92 result.y = std::min(aRect.y, y);
93 int64_t h = std::max(int64_t(aRect.y) + aRect.height, int64_t(y) + height) - result.y;
94 if (MOZ_UNLIKELY(h > nscoord_MAX)) {
95 NS_WARNING("Overflowed nscoord_MAX in conversion to nscoord height");
96 // Clamp huge negative y to nscoord_MIN / 2 and try again.
97 result.y = std::max(result.y, nscoord_MIN / 2);
98 h = std::max(int64_t(aRect.y) + aRect.height, int64_t(y) + height) - result.y;
99 if (MOZ_UNLIKELY(h > nscoord_MAX)) {
100 h = nscoord_MAX;
101 }
102 }
103 result.height = nscoord(h);
104 return result;
105 #endif
106 }
108 #ifndef NS_COORD_IS_FLOAT
109 // Make all nsRect Union methods be saturating.
110 nsRect UnionEdges(const nsRect& aRect) const
111 {
112 return SaturatingUnionEdges(aRect);
113 }
114 void UnionRectEdges(const nsRect& aRect1, const nsRect& aRect2)
115 {
116 *this = aRect1.UnionEdges(aRect2);
117 }
118 nsRect Union(const nsRect& aRect) const
119 {
120 return SaturatingUnion(aRect);
121 }
122 void UnionRect(const nsRect& aRect1, const nsRect& aRect2)
123 {
124 *this = aRect1.Union(aRect2);
125 }
126 #endif
128 void SaturatingUnionRect(const nsRect& aRect1, const nsRect& aRect2)
129 {
130 *this = aRect1.SaturatingUnion(aRect2);
131 }
132 void SaturatingUnionRectEdges(const nsRect& aRect1, const nsRect& aRect2)
133 {
134 *this = aRect1.SaturatingUnionEdges(aRect2);
135 }
137 // Converts this rect from aFromAPP, an appunits per pixel ratio, to aToAPP.
138 // In the RoundOut version we make the rect the smallest rect containing the
139 // unrounded result. In the RoundIn version we make the rect the largest rect
140 // contained in the unrounded result.
141 // Note: this can turn an empty rectangle into a non-empty rectangle
142 inline nsRect ConvertAppUnitsRoundOut(int32_t aFromAPP, int32_t aToAPP) const;
143 inline nsRect ConvertAppUnitsRoundIn(int32_t aFromAPP, int32_t aToAPP) const;
145 inline nsIntRect ScaleToNearestPixels(float aXScale, float aYScale,
146 nscoord aAppUnitsPerPixel) const;
147 inline nsIntRect ToNearestPixels(nscoord aAppUnitsPerPixel) const;
148 // Note: this can turn an empty rectangle into a non-empty rectangle
149 inline nsIntRect ScaleToOutsidePixels(float aXScale, float aYScale,
150 nscoord aAppUnitsPerPixel) const;
151 // Note: this can turn an empty rectangle into a non-empty rectangle
152 inline nsIntRect ToOutsidePixels(nscoord aAppUnitsPerPixel) const;
153 inline nsIntRect ScaleToInsidePixels(float aXScale, float aYScale,
154 nscoord aAppUnitsPerPixel) const;
155 inline nsIntRect ToInsidePixels(nscoord aAppUnitsPerPixel) const;
157 // This is here only to keep IPDL-generated code happy. DO NOT USE.
158 bool operator==(const nsRect& aRect) const
159 {
160 return IsEqualEdges(aRect);
161 }
162 };
164 struct NS_GFX nsIntRect :
165 public mozilla::gfx::BaseRect<int32_t, nsIntRect, nsIntPoint, nsIntSize, nsIntMargin> {
166 typedef mozilla::gfx::BaseRect<int32_t, nsIntRect, nsIntPoint, nsIntSize, nsIntMargin> Super;
168 // Constructors
169 nsIntRect() : Super()
170 {
171 }
172 nsIntRect(const nsIntRect& aRect) : Super(aRect)
173 {
174 }
175 nsIntRect(const nsIntPoint& aOrigin, const nsIntSize &aSize) : Super(aOrigin, aSize)
176 {
177 }
178 nsIntRect(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight) :
179 Super(aX, aY, aWidth, aHeight)
180 {
181 }
183 inline nsRect ToAppUnits(nscoord aAppUnitsPerPixel) const;
185 // Returns a special nsIntRect that's used in some places to signify
186 // "all available space".
187 static const nsIntRect& GetMaxSizedIntRect() {
188 static const nsIntRect r(0, 0, INT32_MAX, INT32_MAX);
189 return r;
190 }
192 // This is here only to keep IPDL-generated code happy. DO NOT USE.
193 bool operator==(const nsIntRect& aRect) const
194 {
195 return IsEqualEdges(aRect);
196 }
197 };
199 /*
200 * App Unit/Pixel conversions
201 */
203 inline nsRect
204 nsRect::ConvertAppUnitsRoundOut(int32_t aFromAPP, int32_t aToAPP) const
205 {
206 if (aFromAPP == aToAPP) {
207 return *this;
208 }
210 nsRect rect;
211 nscoord right = NSToCoordCeil(NSCoordScale(XMost(), aFromAPP, aToAPP));
212 nscoord bottom = NSToCoordCeil(NSCoordScale(YMost(), aFromAPP, aToAPP));
213 rect.x = NSToCoordFloor(NSCoordScale(x, aFromAPP, aToAPP));
214 rect.y = NSToCoordFloor(NSCoordScale(y, aFromAPP, aToAPP));
215 rect.width = (right - rect.x);
216 rect.height = (bottom - rect.y);
218 return rect;
219 }
221 inline nsRect
222 nsRect::ConvertAppUnitsRoundIn(int32_t aFromAPP, int32_t aToAPP) const
223 {
224 if (aFromAPP == aToAPP) {
225 return *this;
226 }
228 nsRect rect;
229 nscoord right = NSToCoordFloor(NSCoordScale(XMost(), aFromAPP, aToAPP));
230 nscoord bottom = NSToCoordFloor(NSCoordScale(YMost(), aFromAPP, aToAPP));
231 rect.x = NSToCoordCeil(NSCoordScale(x, aFromAPP, aToAPP));
232 rect.y = NSToCoordCeil(NSCoordScale(y, aFromAPP, aToAPP));
233 rect.width = (right - rect.x);
234 rect.height = (bottom - rect.y);
236 return rect;
237 }
239 // scale the rect but round to preserve centers
240 inline nsIntRect
241 nsRect::ScaleToNearestPixels(float aXScale, float aYScale,
242 nscoord aAppUnitsPerPixel) const
243 {
244 nsIntRect rect;
245 rect.x = NSToIntRoundUp(NSAppUnitsToDoublePixels(x, aAppUnitsPerPixel) * aXScale);
246 rect.y = NSToIntRoundUp(NSAppUnitsToDoublePixels(y, aAppUnitsPerPixel) * aYScale);
247 rect.width = NSToIntRoundUp(NSAppUnitsToDoublePixels(XMost(),
248 aAppUnitsPerPixel) * aXScale) - rect.x;
249 rect.height = NSToIntRoundUp(NSAppUnitsToDoublePixels(YMost(),
250 aAppUnitsPerPixel) * aYScale) - rect.y;
251 return rect;
252 }
254 // scale the rect but round to smallest containing rect
255 inline nsIntRect
256 nsRect::ScaleToOutsidePixels(float aXScale, float aYScale,
257 nscoord aAppUnitsPerPixel) const
258 {
259 nsIntRect rect;
260 rect.x = NSToIntFloor(NSAppUnitsToFloatPixels(x, float(aAppUnitsPerPixel)) * aXScale);
261 rect.y = NSToIntFloor(NSAppUnitsToFloatPixels(y, float(aAppUnitsPerPixel)) * aYScale);
262 rect.width = NSToIntCeil(NSAppUnitsToFloatPixels(XMost(),
263 float(aAppUnitsPerPixel)) * aXScale) - rect.x;
264 rect.height = NSToIntCeil(NSAppUnitsToFloatPixels(YMost(),
265 float(aAppUnitsPerPixel)) * aYScale) - rect.y;
266 return rect;
267 }
269 // scale the rect but round to largest contained rect
270 inline nsIntRect
271 nsRect::ScaleToInsidePixels(float aXScale, float aYScale,
272 nscoord aAppUnitsPerPixel) const
273 {
274 nsIntRect rect;
275 rect.x = NSToIntCeil(NSAppUnitsToFloatPixels(x, float(aAppUnitsPerPixel)) * aXScale);
276 rect.y = NSToIntCeil(NSAppUnitsToFloatPixels(y, float(aAppUnitsPerPixel)) * aYScale);
277 rect.width = NSToIntFloor(NSAppUnitsToFloatPixels(XMost(),
278 float(aAppUnitsPerPixel)) * aXScale) - rect.x;
279 rect.height = NSToIntFloor(NSAppUnitsToFloatPixels(YMost(),
280 float(aAppUnitsPerPixel)) * aYScale) - rect.y;
281 return rect;
282 }
284 inline nsIntRect
285 nsRect::ToNearestPixels(nscoord aAppUnitsPerPixel) const
286 {
287 return ScaleToNearestPixels(1.0f, 1.0f, aAppUnitsPerPixel);
288 }
290 inline nsIntRect
291 nsRect::ToOutsidePixels(nscoord aAppUnitsPerPixel) const
292 {
293 return ScaleToOutsidePixels(1.0f, 1.0f, aAppUnitsPerPixel);
294 }
296 inline nsIntRect
297 nsRect::ToInsidePixels(nscoord aAppUnitsPerPixel) const
298 {
299 return ScaleToInsidePixels(1.0f, 1.0f, aAppUnitsPerPixel);
300 }
302 // app units are integer multiples of pixels, so no rounding needed
303 inline nsRect
304 nsIntRect::ToAppUnits(nscoord aAppUnitsPerPixel) const
305 {
306 return nsRect(NSIntPixelsToAppUnits(x, aAppUnitsPerPixel),
307 NSIntPixelsToAppUnits(y, aAppUnitsPerPixel),
308 NSIntPixelsToAppUnits(width, aAppUnitsPerPixel),
309 NSIntPixelsToAppUnits(height, aAppUnitsPerPixel));
310 }
312 #ifdef DEBUG
313 // Diagnostics
314 extern NS_GFX FILE* operator<<(FILE* out, const nsRect& rect);
315 #endif // DEBUG
317 #endif /* NSRECT_H */