|
|
1 |
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
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 |
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 |
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/. */ |
4 |
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
5 |
|
5 |
|
6 |
#include "GeometryUtils.h" |
6 |
#include "GeometryUtils.h" |
7 |
|
7 |
|
|
|
8 |
#include "mozilla/dom/DOMPointBinding.h" |
8 |
#include "mozilla/dom/GeometryUtilsBinding.h" |
9 |
#include "mozilla/dom/GeometryUtilsBinding.h" |
9 |
#include "mozilla/dom/Element.h" |
10 |
#include "mozilla/dom/Element.h" |
10 |
#include "mozilla/dom/Text.h" |
11 |
#include "mozilla/dom/Text.h" |
|
|
12 |
#include "mozilla/dom/DOMPoint.h" |
11 |
#include "mozilla/dom/DOMQuad.h" |
13 |
#include "mozilla/dom/DOMQuad.h" |
|
|
14 |
#include "mozilla/dom/DOMRect.h" |
12 |
#include "nsIFrame.h" |
15 |
#include "nsIFrame.h" |
13 |
#include "nsGenericDOMDataNode.h" |
16 |
#include "nsGenericDOMDataNode.h" |
14 |
#include "nsCSSFrameConstructor.h" |
17 |
#include "nsCSSFrameConstructor.h" |
15 |
#include "nsLayoutUtils.h" |
18 |
#include "nsLayoutUtils.h" |
16 |
#include "nsSVGUtils.h" |
19 |
#include "nsSVGUtils.h" |
17 |
|
20 |
|
18 |
using namespace mozilla; |
21 |
using namespace mozilla; |
19 |
using namespace mozilla::dom; |
22 |
using namespace mozilla::dom; |
20 |
|
23 |
|
21 |
namespace mozilla { |
24 |
namespace mozilla { |
22 |
|
25 |
|
23 |
typedef OwningTextOrElementOrDocument GeometryNode; |
|
|
24 |
|
25 |
enum GeometryNodeType { |
26 |
enum GeometryNodeType { |
26 |
GEOMETRY_NODE_ELEMENT, |
27 |
GEOMETRY_NODE_ELEMENT, |
27 |
GEOMETRY_NODE_TEXT, |
28 |
GEOMETRY_NODE_TEXT, |
28 |
GEOMETRY_NODE_DOCUMENT |
29 |
GEOMETRY_NODE_DOCUMENT |
29 |
}; |
30 |
}; |
30 |
|
31 |
|
31 |
static nsIFrame* |
32 |
static nsIFrame* |
32 |
GetFrameForNode(nsINode* aNode, GeometryNodeType aType) |
33 |
GetFrameForNode(nsINode* aNode, GeometryNodeType aType) |
Lines 50-106
GetFrameForNode(nsINode* aNode, Geometry
|
Link Here
|
---|
|
50 |
} |
51 |
} |
51 |
default: |
52 |
default: |
52 |
MOZ_ASSERT(false, "Unknown GeometryNodeType"); |
53 |
MOZ_ASSERT(false, "Unknown GeometryNodeType"); |
53 |
return nullptr; |
54 |
return nullptr; |
54 |
} |
55 |
} |
55 |
} |
56 |
} |
56 |
|
57 |
|
57 |
static nsIFrame* |
58 |
static nsIFrame* |
58 |
GetFrameForGeometryNode(const Optional<GeometryNode>& aGeometryNode, |
59 |
GetFrameForGeometryNode(const Optional<OwningGeometryNode>& aGeometryNode, |
59 |
nsINode* aDefaultNode) |
60 |
nsINode* aDefaultNode) |
60 |
{ |
61 |
{ |
61 |
if (!aGeometryNode.WasPassed()) { |
62 |
if (!aGeometryNode.WasPassed()) { |
62 |
return GetFrameForNode(aDefaultNode->OwnerDoc(), GEOMETRY_NODE_DOCUMENT); |
63 |
return GetFrameForNode(aDefaultNode->OwnerDoc(), GEOMETRY_NODE_DOCUMENT); |
63 |
} |
64 |
} |
64 |
|
65 |
|
65 |
const GeometryNode& value = aGeometryNode.Value(); |
66 |
const OwningGeometryNode& value = aGeometryNode.Value(); |
66 |
if (value.IsElement()) { |
67 |
if (value.IsElement()) { |
67 |
return GetFrameForNode(value.GetAsElement(), GEOMETRY_NODE_ELEMENT); |
68 |
return GetFrameForNode(value.GetAsElement(), GEOMETRY_NODE_ELEMENT); |
68 |
} |
69 |
} |
69 |
if (value.IsDocument()) { |
70 |
if (value.IsDocument()) { |
70 |
return GetFrameForNode(value.GetAsDocument(), GEOMETRY_NODE_DOCUMENT); |
71 |
return GetFrameForNode(value.GetAsDocument(), GEOMETRY_NODE_DOCUMENT); |
71 |
} |
72 |
} |
72 |
return GetFrameForNode(value.GetAsText(), GEOMETRY_NODE_TEXT); |
73 |
return GetFrameForNode(value.GetAsText(), GEOMETRY_NODE_TEXT); |
73 |
} |
74 |
} |
74 |
|
75 |
|
75 |
static nsIFrame* |
76 |
static nsIFrame* |
|
|
77 |
GetFrameForGeometryNode(const GeometryNode& aGeometryNode) |
78 |
{ |
79 |
if (aGeometryNode.IsElement()) { |
80 |
return GetFrameForNode(&aGeometryNode.GetAsElement(), GEOMETRY_NODE_ELEMENT); |
81 |
} |
82 |
if (aGeometryNode.IsDocument()) { |
83 |
return GetFrameForNode(&aGeometryNode.GetAsDocument(), GEOMETRY_NODE_DOCUMENT); |
84 |
} |
85 |
return GetFrameForNode(&aGeometryNode.GetAsText(), GEOMETRY_NODE_TEXT); |
86 |
} |
87 |
|
88 |
static nsIFrame* |
76 |
GetFrameForNode(nsINode* aNode) |
89 |
GetFrameForNode(nsINode* aNode) |
77 |
{ |
90 |
{ |
78 |
if (aNode->IsElement()) { |
91 |
if (aNode->IsElement()) { |
79 |
return GetFrameForNode(aNode, GEOMETRY_NODE_ELEMENT); |
92 |
return GetFrameForNode(aNode, GEOMETRY_NODE_ELEMENT); |
80 |
} |
93 |
} |
81 |
if (aNode == aNode->OwnerDoc()) { |
94 |
if (aNode == aNode->OwnerDoc()) { |
82 |
return GetFrameForNode(aNode, GEOMETRY_NODE_DOCUMENT); |
95 |
return GetFrameForNode(aNode, GEOMETRY_NODE_DOCUMENT); |
83 |
} |
96 |
} |
84 |
NS_ASSERTION(aNode->IsNodeOfType(nsINode::eTEXT), "Unknown node type"); |
97 |
NS_ASSERTION(aNode->IsNodeOfType(nsINode::eTEXT), "Unknown node type"); |
85 |
return GetFrameForNode(aNode, GEOMETRY_NODE_TEXT); |
98 |
return GetFrameForNode(aNode, GEOMETRY_NODE_TEXT); |
86 |
} |
99 |
} |
87 |
|
100 |
|
88 |
static nsIFrame* |
101 |
static nsIFrame* |
89 |
GetFirstNonAnonymousFrameForGeometryNode(const Optional<GeometryNode>& aNode, |
102 |
GetFirstNonAnonymousFrameForGeometryNode(const Optional<OwningGeometryNode>& aNode, |
90 |
nsINode* aDefaultNode) |
103 |
nsINode* aDefaultNode) |
91 |
{ |
104 |
{ |
92 |
nsIFrame* f = GetFrameForGeometryNode(aNode, aDefaultNode); |
105 |
nsIFrame* f = GetFrameForGeometryNode(aNode, aDefaultNode); |
93 |
if (f) { |
106 |
if (f) { |
94 |
f = nsLayoutUtils::GetFirstNonAnonymousFrame(f); |
107 |
f = nsLayoutUtils::GetFirstNonAnonymousFrame(f); |
95 |
} |
108 |
} |
96 |
return f; |
109 |
return f; |
97 |
} |
110 |
} |
98 |
|
111 |
|
|
|
112 |
static nsIFrame* |
113 |
GetFirstNonAnonymousFrameForGeometryNode(const GeometryNode& aNode) |
114 |
{ |
115 |
nsIFrame* f = GetFrameForGeometryNode(aNode); |
116 |
if (f) { |
117 |
f = nsLayoutUtils::GetFirstNonAnonymousFrame(f); |
118 |
} |
119 |
return f; |
120 |
} |
121 |
|
122 |
static nsIFrame* |
123 |
GetFirstNonAnonymousFrameForNode(nsINode* aNode) |
124 |
{ |
125 |
nsIFrame* f = GetFrameForNode(aNode); |
126 |
if (f) { |
127 |
f = nsLayoutUtils::GetFirstNonAnonymousFrame(f); |
128 |
} |
129 |
return f; |
130 |
} |
131 |
|
99 |
/** |
132 |
/** |
100 |
* This can modify aFrame to point to a different frame. This is needed to |
133 |
* This can modify aFrame to point to a different frame. This is needed to |
101 |
* handle SVG, where SVG elements can only compute a rect that's valid with |
134 |
* handle SVG, where SVG elements can only compute a rect that's valid with |
102 |
* respect to the "outer SVG" frame. |
135 |
* respect to the "outer SVG" frame. |
103 |
*/ |
136 |
*/ |
104 |
static nsRect |
137 |
static nsRect |
105 |
GetBoxRectForFrame(nsIFrame** aFrame, CSSBoxType aType) |
138 |
GetBoxRectForFrame(nsIFrame** aFrame, CSSBoxType aType) |
106 |
{ |
139 |
{ |
Lines 230-238
void GetBoxQuads(nsINode* aNode,
|
Link Here
|
---|
|
230 |
// GetBoxRectForFrame can modify relativeToFrame so call it first. |
263 |
// GetBoxRectForFrame can modify relativeToFrame so call it first. |
231 |
nsPoint relativeToTopLeft = |
264 |
nsPoint relativeToTopLeft = |
232 |
GetBoxRectForFrame(&relativeToFrame, CSSBoxType::Border).TopLeft(); |
265 |
GetBoxRectForFrame(&relativeToFrame, CSSBoxType::Border).TopLeft(); |
233 |
AccumulateQuadCallback callback(ownerDoc, aResult, relativeToFrame, |
266 |
AccumulateQuadCallback callback(ownerDoc, aResult, relativeToFrame, |
234 |
relativeToTopLeft, aOptions.mBox); |
267 |
relativeToTopLeft, aOptions.mBox); |
235 |
nsLayoutUtils::GetAllInFlowBoxes(frame, &callback); |
268 |
nsLayoutUtils::GetAllInFlowBoxes(frame, &callback); |
236 |
} |
269 |
} |
237 |
|
270 |
|
|
|
271 |
static void |
272 |
TransformCSSPoints(nsINode* aTo, const GeometryNode& aFrom, |
273 |
uint32_t aPointCount, gfxPoint* aPoints, |
274 |
const ConvertCoordinateOptions& aOptions, ErrorResult& aRv) |
275 |
{ |
276 |
nsIFrame* fromFrame = GetFirstNonAnonymousFrameForGeometryNode(aFrom); |
277 |
nsIFrame* toFrame = GetFirstNonAnonymousFrameForNode(aTo); |
278 |
if (!fromFrame || !toFrame) { |
279 |
aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR); |
280 |
return; |
281 |
} |
282 |
if (!CheckFramesInSameTopLevelBrowsingContext(fromFrame, toFrame)) { |
283 |
aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR); |
284 |
return; |
285 |
} |
286 |
|
287 |
nsPoint fromOffset = GetBoxRectForFrame(&fromFrame, aOptions.mFromBox).TopLeft(); |
288 |
nsPoint toOffset = GetBoxRectForFrame(&toFrame, aOptions.mToBox).TopLeft(); |
289 |
gfxPoint fromOffsetGfx(nsPresContext::AppUnitsToFloatCSSPixels(fromOffset.x), |
290 |
nsPresContext::AppUnitsToFloatCSSPixels(fromOffset.y)); |
291 |
for (uint32_t i = 0; i < aPointCount; ++i) { |
292 |
aPoints[i] += fromOffsetGfx; |
293 |
} |
294 |
nsLayoutUtils::TransformResult rv = |
295 |
nsLayoutUtils::TransformCSSPoints(fromFrame, toFrame, aPointCount, aPoints); |
296 |
if (rv == nsLayoutUtils::TRANSFORM_SUCCEEDED) { |
297 |
gfxPoint toOffsetGfx(nsPresContext::AppUnitsToFloatCSSPixels(toOffset.x), |
298 |
nsPresContext::AppUnitsToFloatCSSPixels(toOffset.y)); |
299 |
for (uint32_t i = 0; i < aPointCount; ++i) { |
300 |
aPoints[i] -= toOffsetGfx; |
301 |
} |
302 |
} else { |
303 |
PodZero(aPoints, aPointCount); |
304 |
} |
238 |
} |
305 |
} |
|
|
306 |
|
307 |
already_AddRefed<DOMQuad> |
308 |
ConvertQuadFromNode(nsINode* aTo, dom::DOMQuad& aQuad, |
309 |
const GeometryNode& aFrom, |
310 |
const dom::ConvertCoordinateOptions& aOptions, |
311 |
ErrorResult& aRv) |
312 |
{ |
313 |
gfxPoint points[4]; |
314 |
for (uint32_t i = 0; i < 4; ++i) { |
315 |
DOMPoint* p = aQuad.Point(i); |
316 |
if (p->W() != 1.0 || p->Z() != 0.0) { |
317 |
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); |
318 |
return nullptr; |
319 |
} |
320 |
points[i] = gfxPoint(p->X(), p->Y()); |
321 |
} |
322 |
TransformCSSPoints(aTo, aFrom, 4, points, aOptions, aRv); |
323 |
if (aRv.Failed()) { |
324 |
return nullptr; |
325 |
} |
326 |
nsRefPtr<DOMQuad> result = new DOMQuad(aTo->GetParentObject(), points); |
327 |
return result.forget(); |
328 |
} |
329 |
|
330 |
already_AddRefed<DOMQuad> |
331 |
ConvertRectFromNode(nsINode* aTo, dom::DOMRectReadOnly& aRect, |
332 |
const GeometryNode& aFrom, |
333 |
const dom::ConvertCoordinateOptions& aOptions, |
334 |
ErrorResult& aRv) |
335 |
{ |
336 |
gfxPoint points[4]; |
337 |
double x = aRect.X(), y = aRect.Y(), w = aRect.Width(), h = aRect.Height(); |
338 |
points[0] = gfxPoint(x, y); |
339 |
points[1] = gfxPoint(x + w, y); |
340 |
points[2] = gfxPoint(x + w, y + h); |
341 |
points[3] = gfxPoint(x, y + h); |
342 |
TransformCSSPoints(aTo, aFrom, 4, points, aOptions, aRv); |
343 |
if (aRv.Failed()) { |
344 |
return nullptr; |
345 |
} |
346 |
nsRefPtr<DOMQuad> result = new DOMQuad(aTo->GetParentObject(), points); |
347 |
return result.forget(); |
348 |
} |
349 |
|
350 |
already_AddRefed<DOMPoint> |
351 |
ConvertPointFromNode(nsINode* aTo, const dom::DOMPointInit& aPoint, |
352 |
const GeometryNode& aFrom, |
353 |
const dom::ConvertCoordinateOptions& aOptions, |
354 |
ErrorResult& aRv) |
355 |
{ |
356 |
if (aPoint.mW != 1.0 || aPoint.mZ != 0.0) { |
357 |
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); |
358 |
return nullptr; |
359 |
} |
360 |
gfxPoint point(aPoint.mX, aPoint.mY); |
361 |
TransformCSSPoints(aTo, aFrom, 1, &point, aOptions, aRv); |
362 |
if (aRv.Failed()) { |
363 |
return nullptr; |
364 |
} |
365 |
nsRefPtr<DOMPoint> result = new DOMPoint(aTo->GetParentObject(), point.x, point.y); |
366 |
return result.forget(); |
367 |
} |
368 |
|
369 |
} |