Bug 1508381 - remove now-unnecessary TASKCLUSTER_* variables r=tomprince
[gecko.git] / gfx / src / nsRect.h
blobcc533b20d49a4f809f3fa78e5d44ca745e1df111
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/. */
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 "mozilla/Likely.h" // for MOZ_UNLIKELY
14 #include "mozilla/gfx/Rect.h"
15 #include "mozilla/gfx/2D.h"
16 #include "mozilla/gfx/Logging.h"
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 "nsMargin.h" // for nsIntMargin, nsMargin
21 #include "nsSize.h" // for IntSize, nsSize
22 #include "nscore.h" // for NS_BUILD_REFCNT_LOGGING
23 #if !defined(ANDROID) && (defined(__SSE2__) || defined(_M_X64) || \
24 (defined(_M_IX86_FP) && _M_IX86_FP >= 2))
25 # if defined(_MSC_VER) && !defined(__clang__)
26 # include "smmintrin.h"
27 # else
28 # include "emmintrin.h"
29 # endif
30 #endif
32 typedef mozilla::gfx::IntRect nsIntRect;
34 struct nsRect : public mozilla::gfx::BaseRect<nscoord, nsRect, nsPoint, nsSize,
35 nsMargin> {
36 typedef mozilla::gfx::BaseRect<nscoord, nsRect, nsPoint, nsSize, nsMargin>
37 Super;
39 static void VERIFY_COORD(nscoord aValue) { ::VERIFY_COORD(aValue); }
41 // Constructors
42 nsRect() : Super() { MOZ_COUNT_CTOR(nsRect); }
43 nsRect(const nsRect& aRect) : Super(aRect) { MOZ_COUNT_CTOR(nsRect); }
44 nsRect(const nsPoint& aOrigin, const nsSize& aSize) : Super(aOrigin, aSize) {
45 MOZ_COUNT_CTOR(nsRect);
47 nsRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
48 : Super(aX, aY, aWidth, aHeight) {
49 MOZ_COUNT_CTOR(nsRect);
52 #ifdef NS_BUILD_REFCNT_LOGGING
53 ~nsRect() { MOZ_COUNT_DTOR(nsRect); }
54 #endif
56 // We have saturating versions of all the Union methods. These avoid
57 // overflowing nscoord values in the 'width' and 'height' fields by
58 // clamping the width and height values to nscoord_MAX if necessary.
60 MOZ_MUST_USE nsRect SaturatingUnion(const nsRect& aRect) const {
61 if (IsEmpty()) {
62 return aRect;
63 } else if (aRect.IsEmpty()) {
64 return *static_cast<const nsRect*>(this);
65 } else {
66 return SaturatingUnionEdges(aRect);
70 MOZ_MUST_USE nsRect SaturatingUnionEdges(const nsRect& aRect) const {
71 #ifdef NS_COORD_IS_FLOAT
72 return UnionEdges(aRect);
73 #else
74 nscoord resultX = std::min(aRect.X(), x);
75 int64_t w =
76 std::max(int64_t(aRect.X()) + aRect.Width(), int64_t(x) + width) -
77 resultX;
78 if (MOZ_UNLIKELY(w > nscoord_MAX)) {
79 // Clamp huge negative x to nscoord_MIN / 2 and try again.
80 resultX = std::max(resultX, nscoord_MIN / 2);
81 w = std::max(int64_t(aRect.X()) + aRect.Width(), int64_t(x) + width) -
82 resultX;
83 if (MOZ_UNLIKELY(w > nscoord_MAX)) {
84 w = nscoord_MAX;
88 nscoord resultY = std::min(aRect.y, y);
89 int64_t h =
90 std::max(int64_t(aRect.Y()) + aRect.Height(), int64_t(y) + height) -
91 resultY;
92 if (MOZ_UNLIKELY(h > nscoord_MAX)) {
93 // Clamp huge negative y to nscoord_MIN / 2 and try again.
94 resultY = std::max(resultY, nscoord_MIN / 2);
95 h = std::max(int64_t(aRect.Y()) + aRect.Height(), int64_t(y) + height) -
96 resultY;
97 if (MOZ_UNLIKELY(h > nscoord_MAX)) {
98 h = nscoord_MAX;
101 return nsRect(resultX, resultY, nscoord(w), nscoord(h));
102 #endif
105 #ifndef NS_COORD_IS_FLOAT
106 // Make all nsRect Union methods be saturating.
107 MOZ_MUST_USE nsRect UnionEdges(const nsRect& aRect) const {
108 return SaturatingUnionEdges(aRect);
110 void UnionRectEdges(const nsRect& aRect1, const nsRect& aRect2) {
111 *this = aRect1.UnionEdges(aRect2);
113 MOZ_MUST_USE nsRect Union(const nsRect& aRect) const {
114 return SaturatingUnion(aRect);
116 MOZ_MUST_USE nsRect UnsafeUnion(const nsRect& aRect) const {
117 return Super::Union(aRect);
119 void UnionRect(const nsRect& aRect1, const nsRect& aRect2) {
120 *this = aRect1.Union(aRect2);
123 # if defined(_MSC_VER) && !defined(__clang__) && \
124 (defined(_M_X64) || defined(_M_IX86))
125 // Only MSVC supports inlining intrinsics for archs you're not compiling for.
126 MOZ_MUST_USE nsRect Intersect(const nsRect& aRect) const {
127 nsRect result;
128 if (mozilla::gfx::Factory::HasSSE4()) {
129 __m128i rect1 = _mm_loadu_si128((__m128i*)&aRect); // x1, y1, w1, h1
130 __m128i rect2 = _mm_loadu_si128((__m128i*)this); // x2, y2, w2, h2
132 __m128i resultRect = _mm_max_epi32(rect1, rect2); // xr, yr, zz, zz
134 // result.width = std::min<int32_t>(x - result.x + width,
135 // aRect.x - result.x + aRect.width);
136 // result.height = std::min<int32_t>(y - result.y + height,
137 // aRect.y - result.y + aRect.height);
138 __m128i widthheight = _mm_min_epi32(
139 _mm_add_epi32(_mm_sub_epi32(rect1, resultRect),
140 _mm_srli_si128(rect1, 8)),
141 _mm_add_epi32(_mm_sub_epi32(rect2, resultRect),
142 _mm_srli_si128(rect2, 8))); // w, h, zz, zz
143 widthheight = _mm_slli_si128(widthheight, 8); // 00, 00, wr, hr
145 resultRect =
146 _mm_blend_epi16(resultRect, widthheight, 0xF0); // xr, yr, wr, hr
148 if ((_mm_movemask_ps(_mm_castsi128_ps(
149 _mm_cmplt_epi32(resultRect, _mm_setzero_si128()))) &
150 0xC) != 0) {
151 // It's potentially more efficient to store all 0s. But the non SSE4
152 // code leaves x/y intact so let's do the same here.
153 resultRect = _mm_and_si128(resultRect,
154 _mm_set_epi32(0, 0, 0xFFFFFFFF, 0xFFFFFFFF));
157 _mm_storeu_si128((__m128i*)&result, resultRect);
159 return result;
162 result.x = std::max<int32_t>(x, aRect.x);
163 result.y = std::max<int32_t>(y, aRect.y);
164 result.width = std::min<int32_t>(x - result.x + width,
165 aRect.x - result.x + aRect.width);
166 result.height = std::min<int32_t>(y - result.y + height,
167 aRect.y - result.y + aRect.height);
168 if (result.width < 0 || result.height < 0) {
169 result.SizeTo(0, 0);
171 return result;
174 bool IntersectRect(const nsRect& aRect1, const nsRect& aRect2) {
175 if (mozilla::gfx::Factory::HasSSE4()) {
176 __m128i rect1 = _mm_loadu_si128((__m128i*)&aRect1); // x1, y1, w1, h1
177 __m128i rect2 = _mm_loadu_si128((__m128i*)&aRect2); // x2, y2, w2, h2
179 __m128i resultRect = _mm_max_epi32(rect1, rect2); // xr, yr, zz, zz
180 // result.width = std::min<int32_t>(x - result.x + width,
181 // aRect.x - result.x + aRect.width);
182 // result.height = std::min<int32_t>(y - result.y + height,
183 // aRect.y - result.y + aRect.height);
184 __m128i widthheight = _mm_min_epi32(
185 _mm_add_epi32(_mm_sub_epi32(rect1, resultRect),
186 _mm_srli_si128(rect1, 8)),
187 _mm_add_epi32(_mm_sub_epi32(rect2, resultRect),
188 _mm_srli_si128(rect2, 8))); // w, h, zz, zz
189 widthheight = _mm_slli_si128(widthheight, 8); // 00, 00, wr, hr
191 resultRect =
192 _mm_blend_epi16(resultRect, widthheight, 0xF0); // xr, yr, wr, hr
194 if ((_mm_movemask_ps(_mm_castsi128_ps(
195 _mm_cmpgt_epi32(resultRect, _mm_setzero_si128()))) &
196 0xC) != 0xC) {
197 // It's potentially more efficient to store all 0s. But the non SSE4
198 // code leaves x/y intact so let's do the same here.
199 resultRect = _mm_and_si128(resultRect,
200 _mm_set_epi32(0, 0, 0xFFFFFFFF, 0xFFFFFFFF));
201 _mm_storeu_si128((__m128i*)this, resultRect);
202 return false;
205 _mm_storeu_si128((__m128i*)this, resultRect);
207 return true;
210 int32_t newX = std::max<int32_t>(aRect1.x, aRect2.x);
211 int32_t newY = std::max<int32_t>(aRect1.y, aRect2.y);
212 width = std::min<int32_t>(aRect1.x - newX + aRect1.width,
213 aRect2.x - newX + aRect2.width);
214 height = std::min<int32_t>(aRect1.y - newY + aRect1.height,
215 aRect2.y - newY + aRect2.height);
216 x = newX;
217 y = newY;
218 if (width <= 0 || height <= 0) {
219 SizeTo(0, 0);
220 return false;
222 return true;
224 # endif
225 #endif
227 void SaturatingUnionRect(const nsRect& aRect1, const nsRect& aRect2) {
228 *this = aRect1.SaturatingUnion(aRect2);
230 void SaturatingUnionRectEdges(const nsRect& aRect1, const nsRect& aRect2) {
231 *this = aRect1.SaturatingUnionEdges(aRect2);
234 // Return whether this rect's right or bottom edge overflow int32.
235 bool Overflows() const;
238 * Return this rect scaled to a different appunits per pixel (APP) ratio.
239 * In the RoundOut version we make the rect the smallest rect containing the
240 * unrounded result. In the RoundIn version we make the rect the largest rect
241 * contained in the unrounded result.
242 * @param aFromAPP the APP to scale from
243 * @param aToAPP the APP to scale to
244 * @note this can turn an empty rectangle into a non-empty rectangle
246 MOZ_MUST_USE inline nsRect ScaleToOtherAppUnitsRoundOut(int32_t aFromAPP,
247 int32_t aToAPP) const;
248 MOZ_MUST_USE inline nsRect ScaleToOtherAppUnitsRoundIn(int32_t aFromAPP,
249 int32_t aToAPP) const;
251 MOZ_MUST_USE inline mozilla::gfx::IntRect ScaleToNearestPixels(
252 float aXScale, float aYScale, nscoord aAppUnitsPerPixel) const;
254 MOZ_MUST_USE inline mozilla::gfx::IntRect ToNearestPixels(
255 nscoord aAppUnitsPerPixel) const;
257 // Note: this can turn an empty rectangle into a non-empty rectangle
258 MOZ_MUST_USE inline mozilla::gfx::IntRect ScaleToOutsidePixels(
259 float aXScale, float aYScale, nscoord aAppUnitsPerPixel) const;
261 // Note: this can turn an empty rectangle into a non-empty rectangle
262 MOZ_MUST_USE inline mozilla::gfx::IntRect ToOutsidePixels(
263 nscoord aAppUnitsPerPixel) const;
265 MOZ_MUST_USE inline mozilla::gfx::IntRect ScaleToInsidePixels(
266 float aXScale, float aYScale, nscoord aAppUnitsPerPixel) const;
268 MOZ_MUST_USE inline mozilla::gfx::IntRect ToInsidePixels(
269 nscoord aAppUnitsPerPixel) const;
271 // This is here only to keep IPDL-generated code happy. DO NOT USE.
272 bool operator==(const nsRect& aRect) const { return IsEqualEdges(aRect); }
274 MOZ_MUST_USE inline nsRect RemoveResolution(const float aResolution) const;
278 * App Unit/Pixel conversions
281 inline nsRect nsRect::ScaleToOtherAppUnitsRoundOut(int32_t aFromAPP,
282 int32_t aToAPP) const {
283 if (aFromAPP == aToAPP) {
284 return *this;
287 nsRect rect;
288 rect.SetBox(NSToCoordFloor(NSCoordScale(x, aFromAPP, aToAPP)),
289 NSToCoordFloor(NSCoordScale(y, aFromAPP, aToAPP)),
290 NSToCoordCeil(NSCoordScale(XMost(), aFromAPP, aToAPP)),
291 NSToCoordCeil(NSCoordScale(YMost(), aFromAPP, aToAPP)));
292 return rect;
295 inline nsRect nsRect::ScaleToOtherAppUnitsRoundIn(int32_t aFromAPP,
296 int32_t aToAPP) const {
297 if (aFromAPP == aToAPP) {
298 return *this;
301 nsRect rect;
302 rect.SetBox(NSToCoordCeil(NSCoordScale(x, aFromAPP, aToAPP)),
303 NSToCoordCeil(NSCoordScale(y, aFromAPP, aToAPP)),
304 NSToCoordFloor(NSCoordScale(XMost(), aFromAPP, aToAPP)),
305 NSToCoordFloor(NSCoordScale(YMost(), aFromAPP, aToAPP)));
306 return rect;
309 #if !defined(ANDROID) && (defined(__SSE2__) || defined(_M_X64) || \
310 (defined(_M_IX86_FP) && _M_IX86_FP >= 2))
311 // Life would be so much better if we had SSE4 here.
312 static MOZ_ALWAYS_INLINE __m128i floor_ps2epi32(__m128 x) {
313 __m128 one = _mm_set_ps(1.0f, 1.0f, 1.0f, 1.0f);
315 __m128 t = _mm_cvtepi32_ps(_mm_cvttps_epi32(x));
316 __m128 r = _mm_sub_ps(t, _mm_and_ps(_mm_cmplt_ps(x, t), one));
318 return _mm_cvttps_epi32(r);
321 static MOZ_ALWAYS_INLINE __m128i ceil_ps2epi32(__m128 x) {
322 __m128 t = _mm_sub_ps(_mm_setzero_ps(), x);
323 __m128i r = _mm_sub_epi32(_mm_setzero_si128(), floor_ps2epi32(t));
325 return r;
327 #endif
329 // scale the rect but round to preserve centers
330 inline mozilla::gfx::IntRect nsRect::ScaleToNearestPixels(
331 float aXScale, float aYScale, nscoord aAppUnitsPerPixel) const {
332 mozilla::gfx::IntRect rect;
333 // Android x86 builds have bindgen issues.
334 #if !defined(ANDROID) && (defined(__SSE2__) || defined(_M_X64) || \
335 (defined(_M_IX86_FP) && _M_IX86_FP >= 2))
336 __m128 appUnitsPacked = _mm_set_ps(aAppUnitsPerPixel, aAppUnitsPerPixel,
337 aAppUnitsPerPixel, aAppUnitsPerPixel);
338 __m128 scalesPacked = _mm_set_ps(aYScale, aXScale, aYScale, aXScale);
339 __m128 biasesPacked = _mm_set_ps(0.5f, 0.5f, 0.5f, 0.5f);
341 __m128i rectPacked = _mm_loadu_si128((__m128i*)this);
342 __m128i topLeft = _mm_slli_si128(rectPacked, 8);
344 rectPacked = _mm_add_epi32(rectPacked, topLeft); // X, Y, XMost(), YMost()
346 __m128 rectFloat = _mm_cvtepi32_ps(rectPacked);
348 // Scale, i.e. ([ x y xmost ymost ] / aAppUnitsPerPixel) * [ aXScale aYScale
349 // aXScale aYScale ]
350 rectFloat = _mm_mul_ps(_mm_div_ps(rectFloat, appUnitsPacked), scalesPacked);
352 // Floor
353 // Executed with bias and roundmode down, since round-nearest rounds 0.5
354 // downward half the time.
355 rectFloat = _mm_add_ps(rectFloat, biasesPacked);
356 rectPacked = floor_ps2epi32(rectFloat);
358 topLeft = _mm_slli_si128(rectPacked, 8);
359 rectPacked = _mm_sub_epi32(rectPacked, topLeft); // X, Y, Width, Height
361 // Avoid negative width/height due to overflow.
362 __m128i mask = _mm_or_si128(_mm_cmpgt_epi32(rectPacked, _mm_setzero_si128()),
363 _mm_set_epi32(0, 0, 0xFFFFFFFF, 0xFFFFFFFF));
364 // Mask will now contain [ 0xFFFFFFFF 0xFFFFFFFF (width <= 0 ? 0 : 0xFFFFFFFF)
365 // (height <= 0 ? 0 : 0xFFFFFFFF) ]
366 rectPacked = _mm_and_si128(rectPacked, mask);
368 _mm_storeu_si128((__m128i*)&rect, rectPacked);
369 #else
370 rect.SetNonEmptyBox(
371 NSToIntRoundUp(NSAppUnitsToFloatPixels(x, aAppUnitsPerPixel) * aXScale),
372 NSToIntRoundUp(NSAppUnitsToFloatPixels(y, aAppUnitsPerPixel) * aYScale),
373 NSToIntRoundUp(NSAppUnitsToFloatPixels(XMost(), aAppUnitsPerPixel) *
374 aXScale),
375 NSToIntRoundUp(NSAppUnitsToFloatPixels(YMost(), aAppUnitsPerPixel) *
376 aYScale));
377 #endif
378 return rect;
381 // scale the rect but round to smallest containing rect
382 inline mozilla::gfx::IntRect nsRect::ScaleToOutsidePixels(
383 float aXScale, float aYScale, nscoord aAppUnitsPerPixel) const {
384 mozilla::gfx::IntRect rect;
385 // Android x86 builds have bindgen issues.
386 #if !defined(ANDROID) && (defined(__SSE2__) || defined(_M_X64) || \
387 (defined(_M_IX86_FP) && _M_IX86_FP >= 2))
388 __m128 appUnitsPacked = _mm_set_ps(aAppUnitsPerPixel, aAppUnitsPerPixel,
389 aAppUnitsPerPixel, aAppUnitsPerPixel);
390 __m128 scalesPacked = _mm_set_ps(aYScale, aXScale, aYScale, aXScale);
392 __m128i rectPacked = _mm_loadu_si128((__m128i*)this); // x, y, w, h
393 __m128i topLeft = _mm_slli_si128(rectPacked, 8); // 0, 0, x, y
395 rectPacked = _mm_add_epi32(rectPacked, topLeft); // X, Y, XMost(), YMost()
397 __m128 rectFloat = _mm_cvtepi32_ps(rectPacked);
399 // Scale i.e. ([ x y xmost ymost ] / aAppUnitsPerPixel) *
400 // [ aXScale aYScale aXScale aYScale ]
401 rectFloat = _mm_mul_ps(_mm_div_ps(rectFloat, appUnitsPacked), scalesPacked);
402 rectPacked = ceil_ps2epi32(rectFloat); // xx, xx, XMost(), YMost()
403 __m128i tmp = floor_ps2epi32(rectFloat); // x, y, xx, xx
405 // _mm_move_sd is 1 cycle method of getting the blending we want.
406 rectPacked = _mm_castpd_si128(
407 _mm_move_sd(_mm_castsi128_pd(rectPacked),
408 _mm_castsi128_pd(tmp))); // x, y, XMost(), YMost()
410 topLeft = _mm_slli_si128(rectPacked, 8); // 0, 0, r.x, r.y
411 rectPacked = _mm_sub_epi32(rectPacked, topLeft); // r.x, r.y, r.w, r.h
413 // Avoid negative width/height due to overflow.
414 __m128i mask = _mm_or_si128(_mm_cmpgt_epi32(rectPacked, _mm_setzero_si128()),
415 _mm_set_epi32(0, 0, 0xFFFFFFFF, 0xFFFFFFFF));
416 // clang-format off
417 // Mask will now contain [ 0xFFFFFFFF 0xFFFFFFFF (width <= 0 ? 0 : 0xFFFFFFFF) (height <= 0 ? 0 : 0xFFFFFFFF) ]
418 // clang-format on
419 rectPacked = _mm_and_si128(rectPacked, mask);
421 _mm_storeu_si128((__m128i*)&rect, rectPacked);
422 #else
423 rect.SetNonEmptyBox(
424 NSToIntFloor(NSAppUnitsToFloatPixels(x, float(aAppUnitsPerPixel)) *
425 aXScale),
426 NSToIntFloor(NSAppUnitsToFloatPixels(y, float(aAppUnitsPerPixel)) *
427 aYScale),
428 NSToIntCeil(NSAppUnitsToFloatPixels(XMost(), float(aAppUnitsPerPixel)) *
429 aXScale),
430 NSToIntCeil(NSAppUnitsToFloatPixels(YMost(), float(aAppUnitsPerPixel)) *
431 aYScale));
432 #endif
433 return rect;
436 // scale the rect but round to largest contained rect
437 inline mozilla::gfx::IntRect nsRect::ScaleToInsidePixels(
438 float aXScale, float aYScale, nscoord aAppUnitsPerPixel) const {
439 mozilla::gfx::IntRect rect;
440 rect.SetNonEmptyBox(
441 NSToIntCeil(NSAppUnitsToFloatPixels(x, float(aAppUnitsPerPixel)) *
442 aXScale),
443 NSToIntCeil(NSAppUnitsToFloatPixels(y, float(aAppUnitsPerPixel)) *
444 aYScale),
445 NSToIntFloor(NSAppUnitsToFloatPixels(XMost(), float(aAppUnitsPerPixel)) *
446 aXScale),
447 NSToIntFloor(NSAppUnitsToFloatPixels(YMost(), float(aAppUnitsPerPixel)) *
448 aYScale));
449 return rect;
452 inline mozilla::gfx::IntRect nsRect::ToNearestPixels(
453 nscoord aAppUnitsPerPixel) const {
454 return ScaleToNearestPixels(1.0f, 1.0f, aAppUnitsPerPixel);
457 inline mozilla::gfx::IntRect nsRect::ToOutsidePixels(
458 nscoord aAppUnitsPerPixel) const {
459 return ScaleToOutsidePixels(1.0f, 1.0f, aAppUnitsPerPixel);
462 inline mozilla::gfx::IntRect nsRect::ToInsidePixels(
463 nscoord aAppUnitsPerPixel) const {
464 return ScaleToInsidePixels(1.0f, 1.0f, aAppUnitsPerPixel);
467 inline nsRect nsRect::RemoveResolution(const float aResolution) const {
468 MOZ_ASSERT(aResolution > 0.0f);
469 nsRect rect;
470 rect.MoveTo(NSToCoordRound(NSCoordToFloat(x) / aResolution),
471 NSToCoordRound(NSCoordToFloat(y) / aResolution));
472 // A 1x1 rect indicates we are just hit testing a point, so pass down a 1x1
473 // rect as well instead of possibly rounding the width or height to zero.
474 if (width == 1 && height == 1) {
475 rect.SizeTo(1, 1);
476 } else {
477 rect.SizeTo(NSToCoordCeil(NSCoordToFloat(width) / aResolution),
478 NSToCoordCeil(NSCoordToFloat(height) / aResolution));
481 return rect;
484 const mozilla::gfx::IntRect& GetMaxSizedIntRect();
486 // app units are integer multiples of pixels, so no rounding needed
487 template <class units>
488 nsRect ToAppUnits(const mozilla::gfx::IntRectTyped<units>& aRect,
489 nscoord aAppUnitsPerPixel) {
490 return nsRect(NSIntPixelsToAppUnits(aRect.X(), aAppUnitsPerPixel),
491 NSIntPixelsToAppUnits(aRect.Y(), aAppUnitsPerPixel),
492 NSIntPixelsToAppUnits(aRect.Width(), aAppUnitsPerPixel),
493 NSIntPixelsToAppUnits(aRect.Height(), aAppUnitsPerPixel));
496 #ifdef DEBUG
497 // Diagnostics
498 extern FILE* operator<<(FILE* out, const nsRect& rect);
499 #endif // DEBUG
501 #endif /* NSRECT_H */