DOMRect.cpp (5688B)
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 #include "mozilla/dom/DOMRect.h" 8 9 #include <cmath> 10 11 #include "js/StructuredClone.h" 12 #include "mozilla/AppUnits.h" 13 #include "mozilla/Casting.h" 14 #include "mozilla/dom/BindingDeclarations.h" 15 #include "mozilla/dom/DOMRectBinding.h" 16 #include "mozilla/dom/DOMRectListBinding.h" 17 #include "nsIGlobalObject.h" 18 #include "nsRect.h" 19 20 using namespace mozilla; 21 using namespace mozilla::dom; 22 23 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DOMRectReadOnly, mParent) 24 NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMRectReadOnly) 25 NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMRectReadOnly) 26 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMRectReadOnly) 27 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY 28 NS_INTERFACE_MAP_ENTRY(nsISupports) 29 NS_INTERFACE_MAP_END 30 31 JSObject* DOMRectReadOnly::WrapObject(JSContext* aCx, 32 JS::Handle<JSObject*> aGivenProto) { 33 MOZ_ASSERT(mParent); 34 return DOMRectReadOnly_Binding::Wrap(aCx, this, aGivenProto); 35 } 36 37 already_AddRefed<DOMRectReadOnly> DOMRectReadOnly::FromRect( 38 const GlobalObject& aGlobal, const DOMRectInit& aInit) { 39 RefPtr<DOMRectReadOnly> obj = new DOMRectReadOnly( 40 aGlobal.GetAsSupports(), aInit.mX, aInit.mY, aInit.mWidth, aInit.mHeight); 41 return obj.forget(); 42 } 43 44 already_AddRefed<DOMRectReadOnly> DOMRectReadOnly::Constructor( 45 const GlobalObject& aGlobal, double aX, double aY, double aWidth, 46 double aHeight) { 47 RefPtr<DOMRectReadOnly> obj = 48 new DOMRectReadOnly(aGlobal.GetAsSupports(), aX, aY, aWidth, aHeight); 49 return obj.forget(); 50 } 51 52 // https://drafts.fxtf.org/geometry/#structured-serialization 53 bool DOMRectReadOnly::WriteStructuredClone( 54 JSContext* aCx, JSStructuredCloneWriter* aWriter) const { 55 #define WriteDouble(d) \ 56 JS_WriteUint32Pair(aWriter, (BitwiseCast<uint64_t>(d) >> 32) & 0xffffffff, \ 57 BitwiseCast<uint64_t>(d) & 0xffffffff) 58 59 return WriteDouble(mX) && WriteDouble(mY) && WriteDouble(mWidth) && 60 WriteDouble(mHeight); 61 62 #undef WriteDouble 63 } 64 65 // static 66 already_AddRefed<DOMRectReadOnly> DOMRectReadOnly::ReadStructuredClone( 67 JSContext* aCx, nsIGlobalObject* aGlobal, 68 JSStructuredCloneReader* aReader) { 69 RefPtr<DOMRectReadOnly> retval = new DOMRectReadOnly(aGlobal); 70 if (!retval->ReadStructuredClone(aReader)) { 71 return nullptr; 72 } 73 return retval.forget(); 74 } 75 76 bool DOMRectReadOnly::ReadStructuredClone(JSStructuredCloneReader* aReader) { 77 uint32_t high; 78 uint32_t low; 79 80 #define ReadDouble(d) \ 81 if (!JS_ReadUint32Pair(aReader, &high, &low)) { \ 82 return false; \ 83 } \ 84 (*(d) = BitwiseCast<double>(static_cast<uint64_t>(high) << 32 | low)) 85 86 ReadDouble(&mX); 87 ReadDouble(&mY); 88 ReadDouble(&mWidth); 89 ReadDouble(&mHeight); 90 91 return true; 92 93 #undef ReadDouble 94 } 95 96 // ----------------------------------------------------------------------------- 97 98 JSObject* DOMRect::WrapObject(JSContext* aCx, 99 JS::Handle<JSObject*> aGivenProto) { 100 MOZ_ASSERT(mParent); 101 return DOMRect_Binding::Wrap(aCx, this, aGivenProto); 102 } 103 104 already_AddRefed<DOMRect> DOMRect::FromRect(const GlobalObject& aGlobal, 105 const DOMRectInit& aInit) { 106 RefPtr<DOMRect> obj = new DOMRect(aGlobal.GetAsSupports(), aInit.mX, aInit.mY, 107 aInit.mWidth, aInit.mHeight); 108 return obj.forget(); 109 } 110 111 already_AddRefed<DOMRect> DOMRect::Constructor(const GlobalObject& aGlobal, 112 double aX, double aY, 113 double aWidth, double aHeight) { 114 RefPtr<DOMRect> obj = 115 new DOMRect(aGlobal.GetAsSupports(), aX, aY, aWidth, aHeight); 116 return obj.forget(); 117 } 118 119 // static 120 already_AddRefed<DOMRect> DOMRect::ReadStructuredClone( 121 JSContext* aCx, nsIGlobalObject* aGlobal, 122 JSStructuredCloneReader* aReader) { 123 RefPtr<DOMRect> retval = new DOMRect(aGlobal); 124 if (!retval->ReadStructuredClone(aReader)) { 125 return nullptr; 126 } 127 return retval.forget(); 128 } 129 130 // ----------------------------------------------------------------------------- 131 132 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DOMRectList, mParent, mArray) 133 134 NS_INTERFACE_TABLE_HEAD(DOMRectList) 135 NS_WRAPPERCACHE_INTERFACE_TABLE_ENTRY 136 NS_INTERFACE_TABLE0(DOMRectList) 137 NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(DOMRectList) 138 NS_INTERFACE_MAP_END 139 140 NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMRectList) 141 NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMRectList) 142 143 JSObject* DOMRectList::WrapObject(JSContext* cx, 144 JS::Handle<JSObject*> aGivenProto) { 145 return mozilla::dom::DOMRectList_Binding::Wrap(cx, this, aGivenProto); 146 } 147 148 static double RoundFloat(double aValue) { return floor(aValue + 0.5); } 149 150 void DOMRect::SetLayoutRect(const nsRect& aLayoutRect) { 151 double scale = 65536.0; 152 // Round to the nearest 1/scale units. We choose scale so it can be 153 // represented exactly by machine floating point. 154 double scaleInv = 1 / scale; 155 double t2pScaled = scale / AppUnitsPerCSSPixel(); 156 double x = RoundFloat(aLayoutRect.x * t2pScaled) * scaleInv; 157 double y = RoundFloat(aLayoutRect.y * t2pScaled) * scaleInv; 158 SetRect(x, y, RoundFloat(aLayoutRect.XMost() * t2pScaled) * scaleInv - x, 159 RoundFloat(aLayoutRect.YMost() * t2pScaled) * scaleInv - y); 160 }