☠☠ backed out by b7bb4f7697c3 ☠ ☠ | |
author | Robert O'Callahan <robert@ocallahan.org> |
Wed, 12 Mar 2014 09:11:38 +0800 | |
changeset 174244 | 4771c2b309ad3389e96de6960e5eb315fb4e0a06 |
parent 174243 | 8ad57cf09e758617455a8aebdc33867bb10093ba |
child 174245 | 896bfaeab866026e8499e015cf53edd010a8aff5 |
push id | 41230 |
push user | rocallahan@mozilla.com |
push date | Wed, 19 Mar 2014 06:26:26 +0000 |
treeherder | mozilla-inbound@2f3187619c9e [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | matspal |
bugs | 917755 |
milestone | 31.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
new file mode 100644 --- /dev/null +++ b/layout/base/GeometryUtils.cpp @@ -0,0 +1,238 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "GeometryUtils.h" + +#include "mozilla/dom/GeometryUtilsBinding.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/Text.h" +#include "mozilla/dom/DOMQuad.h" +#include "nsIFrame.h" +#include "nsGenericDOMDataNode.h" +#include "nsCSSFrameConstructor.h" +#include "nsLayoutUtils.h" +#include "nsSVGUtils.h" + +using namespace mozilla; +using namespace mozilla::dom; + +namespace mozilla { + +typedef OwningTextOrElementOrDocument GeometryNode; + +enum GeometryNodeType { + GEOMETRY_NODE_ELEMENT, + GEOMETRY_NODE_TEXT, + GEOMETRY_NODE_DOCUMENT +}; + +static nsIFrame* +GetFrameForNode(nsINode* aNode, GeometryNodeType aType) +{ + nsIDocument* doc = aNode->OwnerDoc(); + doc->FlushPendingNotifications(Flush_Layout); + switch (aType) { + case GEOMETRY_NODE_ELEMENT: + return aNode->AsContent()->GetPrimaryFrame(); + case GEOMETRY_NODE_TEXT: { + nsIPresShell* presShell = doc->GetShell(); + if (presShell) { + return presShell->FrameConstructor()->EnsureFrameForTextNode( + static_cast<nsGenericDOMDataNode*>(aNode)); + } + return nullptr; + } + case GEOMETRY_NODE_DOCUMENT: { + nsIPresShell* presShell = doc->GetShell(); + return presShell ? presShell->GetRootFrame() : nullptr; + } + default: + MOZ_ASSERT(false, "Unknown GeometryNodeType"); + return nullptr; + } +} + +static nsIFrame* +GetFrameForGeometryNode(const Optional<GeometryNode>& aGeometryNode, + nsINode* aDefaultNode) +{ + if (!aGeometryNode.WasPassed()) { + return GetFrameForNode(aDefaultNode->OwnerDoc(), GEOMETRY_NODE_DOCUMENT); + } + + const GeometryNode& value = aGeometryNode.Value(); + if (value.IsElement()) { + return GetFrameForNode(value.GetAsElement(), GEOMETRY_NODE_ELEMENT); + } + if (value.IsDocument()) { + return GetFrameForNode(value.GetAsDocument(), GEOMETRY_NODE_DOCUMENT); + } + return GetFrameForNode(value.GetAsText(), GEOMETRY_NODE_TEXT); +} + +static nsIFrame* +GetFrameForNode(nsINode* aNode) +{ + if (aNode->IsElement()) { + return GetFrameForNode(aNode, GEOMETRY_NODE_ELEMENT); + } + if (aNode == aNode->OwnerDoc()) { + return GetFrameForNode(aNode, GEOMETRY_NODE_DOCUMENT); + } + NS_ASSERTION(aNode->IsNodeOfType(nsINode::eTEXT), "Unknown node type"); + return GetFrameForNode(aNode, GEOMETRY_NODE_TEXT); +} + +static nsIFrame* +GetFirstNonAnonymousFrameForGeometryNode(const Optional<GeometryNode>& aNode, + nsINode* aDefaultNode) +{ + nsIFrame* f = GetFrameForGeometryNode(aNode, aDefaultNode); + if (f) { + f = nsLayoutUtils::GetFirstNonAnonymousFrame(f); + } + return f; +} + +/** + * This can modify aFrame to point to a different frame. This is needed to + * handle SVG, where SVG elements can only compute a rect that's valid with + * respect to the "outer SVG" frame. + */ +static nsRect +GetBoxRectForFrame(nsIFrame** aFrame, CSSBoxType aType) +{ + nsRect r; + nsIFrame* f = nsSVGUtils::GetOuterSVGFrameAndCoveredRegion(*aFrame, &r); + if (f) { + // For SVG, the BoxType is ignored. + *aFrame = f; + return r; + } + + f = *aFrame; + switch (aType) { + case CSSBoxType::Content: r = f->GetContentRectRelativeToSelf(); break; + case CSSBoxType::Padding: r = f->GetPaddingRectRelativeToSelf(); break; + case CSSBoxType::Border: r = nsRect(nsPoint(0, 0), f->GetSize()); break; + case CSSBoxType::Margin: { + r = nsRect(nsPoint(0, 0), f->GetSize()); + r.Inflate(f->GetUsedMargin()); + break; + } + default: MOZ_ASSERT(false, "unknown box type"); return r; + } + + return r; +} + +class AccumulateQuadCallback : public nsLayoutUtils::BoxCallback { +public: + AccumulateQuadCallback(nsISupports* aParentObject, + nsTArray<nsRefPtr<DOMQuad> >& aResult, + nsIFrame* aRelativeToFrame, + const nsPoint& aRelativeToBoxTopLeft, + CSSBoxType aBoxType) + : mParentObject(aParentObject) + , mResult(aResult) + , mRelativeToFrame(aRelativeToFrame) + , mRelativeToBoxTopLeft(aRelativeToBoxTopLeft) + , mBoxType(aBoxType) + { + } + + virtual void AddBox(nsIFrame* aFrame) MOZ_OVERRIDE + { + nsIFrame* f = aFrame; + nsRect box = GetBoxRectForFrame(&f, mBoxType); + nsPoint appUnits[4] = + { box.TopLeft(), box.TopRight(), box.BottomRight(), box.BottomLeft() }; + CSSPoint points[4]; + for (uint32_t i = 0; i < 4; ++i) { + points[i] = CSSPoint(nsPresContext::AppUnitsToFloatCSSPixels(appUnits[i].x), + nsPresContext::AppUnitsToFloatCSSPixels(appUnits[i].y)); + } + nsLayoutUtils::TransformResult rv = + nsLayoutUtils::TransformPoints(f, mRelativeToFrame, 4, points); + if (rv == nsLayoutUtils::TRANSFORM_SUCCEEDED) { + CSSPoint delta(nsPresContext::AppUnitsToFloatCSSPixels(mRelativeToBoxTopLeft.x), + nsPresContext::AppUnitsToFloatCSSPixels(mRelativeToBoxTopLeft.y)); + for (uint32_t i = 0; i < 4; ++i) { + points[i] -= delta; + } + } else { + PodArrayZero(points); + } + mResult.AppendElement(new DOMQuad(mParentObject, points)); + } + + nsISupports* mParentObject; + nsTArray<nsRefPtr<DOMQuad> >& mResult; + nsIFrame* mRelativeToFrame; + nsPoint mRelativeToBoxTopLeft; + CSSBoxType mBoxType; +}; + +static nsPresContext* +FindTopLevelPresContext(nsPresContext* aPC) +{ + bool isChrome = aPC->IsChrome(); + nsPresContext* pc = aPC; + for (;;) { + nsPresContext* parent = pc->GetParentPresContext(); + if (!parent || parent->IsChrome() != isChrome) { + return pc; + } + pc = parent; + } +} + +static bool +CheckFramesInSameTopLevelBrowsingContext(nsIFrame* aFrame1, nsIFrame* aFrame2) +{ + nsPresContext* pc1 = aFrame1->PresContext(); + nsPresContext* pc2 = aFrame2->PresContext(); + if (pc1 == pc2) { + return true; + } + if (nsContentUtils::IsCallerChrome()) { + return true; + } + if (FindTopLevelPresContext(pc1) == FindTopLevelPresContext(pc2)) { + return true; + } + return false; +} + +void GetBoxQuads(nsINode* aNode, + const dom::BoxQuadOptions& aOptions, + nsTArray<nsRefPtr<DOMQuad> >& aResult, + ErrorResult& aRv) +{ + nsIFrame* frame = GetFrameForNode(aNode); + if (!frame) { + // No boxes to return + return; + } + nsIDocument* ownerDoc = aNode->OwnerDoc(); + nsIFrame* relativeToFrame = + GetFirstNonAnonymousFrameForGeometryNode(aOptions.mRelativeTo, ownerDoc); + if (!relativeToFrame) { + aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR); + return; + } + if (!CheckFramesInSameTopLevelBrowsingContext(frame, relativeToFrame)) { + aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR); + return; + } + // GetBoxRectForFrame can modify relativeToFrame so call it first. + nsPoint relativeToTopLeft = + GetBoxRectForFrame(&relativeToFrame, CSSBoxType::Border).TopLeft(); + AccumulateQuadCallback callback(ownerDoc, aResult, relativeToFrame, + relativeToTopLeft, aOptions.mBox); + nsLayoutUtils::GetAllInFlowBoxes(frame, &callback); +} + +}
new file mode 100644 --- /dev/null +++ b/layout/base/GeometryUtils.h @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef MOZILLA_GEOMETRYUTILS_H_ +#define MOZILLA_GEOMETRYUTILS_H_ + +#include "mozilla/ErrorResult.h" +#include "nsTArray.h" +#include "nsCOMPtr.h" + +/** + * This file defines utility functions for converting between layout + * coordinate systems. + */ + +class nsINode; +class nsIDocument; + +namespace mozilla { + +namespace dom { +struct BoxQuadOptions; +class DOMQuad; +class Element; +class Text; +} + +/** + * Computes quads for aNode using aOptions, according to GeometryUtils.getBoxQuads. + * May set an error in aRv. + */ +void GetBoxQuads(nsINode* aNode, + const dom::BoxQuadOptions& aOptions, + nsTArray<nsRefPtr<dom::DOMQuad> >& aResult, + ErrorResult& aRv); + +} + +#endif /* MOZILLA_GEOMETRYUTILS_H_ */
--- a/layout/base/moz.build +++ b/layout/base/moz.build @@ -55,25 +55,27 @@ EXPORTS += [ 'nsStyleChangeList.h', 'ScrollbarStyles.h', 'StackArena.h', 'Units.h', 'UnitTransforms.h', ] EXPORTS.mozilla += [ + 'GeometryUtils.h', 'PaintTracker.h', ] UNIFIED_SOURCES += [ 'ActiveLayerTracker.cpp', 'DisplayItemClip.cpp', 'DisplayListClipState.cpp', 'FrameLayerBuilder.cpp', 'FramePropertyTable.cpp', + 'GeometryUtils.cpp', 'MaskLayerImageCache.cpp', 'nsCaret.cpp', 'nsCounterManager.cpp', 'nsCSSColorUtils.cpp', 'nsCSSFrameConstructor.cpp', 'nsCSSRendering.cpp', 'nsCSSRenderingBorders.cpp', 'nsDisplayList.cpp',