зеркало из https://github.com/mozilla/pjs.git
Bug 417255. Rework getClientRects/getBoundingClientRect/offset* code to use a generic rectangle iterator API which drills down through anonymous blocks, fixing IE compat. r+sr=dbaron
This commit is contained in:
Родитель
964b6b2778
Коммит
5d3a393ced
|
@ -810,19 +810,16 @@ nsNSElementTearoff::GetElementsByClassName(const nsAString& aClasses,
|
||||||
return nsDocument::GetElementsByClassNameHelper(mContent, aClasses, aReturn);
|
return nsDocument::GetElementsByClassNameHelper(mContent, aClasses, aReturn);
|
||||||
}
|
}
|
||||||
|
|
||||||
static nsPoint
|
static nsIFrame*
|
||||||
GetOffsetFromInitialContainingBlock(nsIFrame* aFrame)
|
GetContainingBlockForClientRect(nsIFrame* aFrame)
|
||||||
{
|
{
|
||||||
nsIFrame* refFrame = aFrame->GetParent();
|
|
||||||
if (!refFrame)
|
|
||||||
return nsPoint(0, 0);
|
|
||||||
|
|
||||||
// get the nearest enclosing SVG foreign object frame or the root frame
|
// get the nearest enclosing SVG foreign object frame or the root frame
|
||||||
while (refFrame->GetParent() &&
|
while (aFrame->GetParent() &&
|
||||||
!refFrame->IsFrameOfType(nsIFrame::eSVGForeignObject))
|
!aFrame->IsFrameOfType(nsIFrame::eSVGForeignObject)) {
|
||||||
refFrame = refFrame->GetParent();
|
aFrame = aFrame->GetParent();
|
||||||
|
}
|
||||||
|
|
||||||
return aFrame->GetOffsetTo(refFrame);
|
return aFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double
|
static double
|
||||||
|
@ -847,25 +844,6 @@ SetTextRectangle(const nsRect& aLayoutRect, nsPresContext* aPresContext,
|
||||||
RoundFloat(aLayoutRect.YMost()*t2pScaled)*scaleInv - y);
|
RoundFloat(aLayoutRect.YMost()*t2pScaled)*scaleInv - y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PRBool
|
|
||||||
TryGetSVGBoundingRect(nsIFrame* aFrame, nsRect* aRect)
|
|
||||||
{
|
|
||||||
#ifdef MOZ_SVG
|
|
||||||
nsRect r;
|
|
||||||
nsIFrame* outer = nsSVGUtils::GetOuterSVGFrameAndCoveredRegion(aFrame, &r);
|
|
||||||
if (!outer)
|
|
||||||
return PR_FALSE;
|
|
||||||
|
|
||||||
// r is in pixels relative to 'outer', get it into twips
|
|
||||||
// relative to ICB origin
|
|
||||||
r.ScaleRoundOut(1.0/aFrame->PresContext()->AppUnitsPerDevPixel());
|
|
||||||
*aRect = r + GetOffsetFromInitialContainingBlock(outer);
|
|
||||||
return PR_TRUE;
|
|
||||||
#else
|
|
||||||
return PR_FALSE;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsNSElementTearoff::GetBoundingClientRect(nsIDOMTextRectangle** aResult)
|
nsNSElementTearoff::GetBoundingClientRect(nsIDOMTextRectangle** aResult)
|
||||||
{
|
{
|
||||||
|
@ -881,75 +859,44 @@ nsNSElementTearoff::GetBoundingClientRect(nsIDOMTextRectangle** aResult)
|
||||||
// display:none, perhaps? Return the empty rect
|
// display:none, perhaps? Return the empty rect
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsPresContext* presContext = frame->PresContext();
|
nsPresContext* presContext = frame->PresContext();
|
||||||
|
nsRect r = nsLayoutUtils::GetAllInFlowRectsUnion(frame,
|
||||||
nsRect r;
|
GetContainingBlockForClientRect(frame));
|
||||||
if (TryGetSVGBoundingRect(frame, &r)) {
|
|
||||||
// Currently SVG frames don't have continuations but I don't want things to
|
|
||||||
// break if that changes.
|
|
||||||
while ((frame = nsLayoutUtils::GetNextContinuationOrSpecialSibling(frame)) != nsnull) {
|
|
||||||
nsRect nextRect;
|
|
||||||
#ifdef DEBUG
|
|
||||||
PRBool isSVG =
|
|
||||||
#endif
|
|
||||||
TryGetSVGBoundingRect(frame, &nextRect);
|
|
||||||
NS_ASSERTION(isSVG, "SVG frames must have SVG continuations");
|
|
||||||
r.UnionRect(r, nextRect);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// The weird frame layout of tables requires this
|
|
||||||
if (frame->GetType() == nsGkAtoms::tableOuterFrame) {
|
|
||||||
nsIFrame* innerTable = frame->GetFirstChild(nsnull);
|
|
||||||
if (innerTable) {
|
|
||||||
r = nsLayoutUtils::GetAllInFlowBoundingRect(innerTable) + innerTable->GetPosition();
|
|
||||||
}
|
|
||||||
nsIFrame* caption = frame->GetFirstChild(nsGkAtoms::captionList);
|
|
||||||
if (caption) {
|
|
||||||
r.UnionRect(r, nsLayoutUtils::GetAllInFlowBoundingRect(caption) + caption->GetPosition());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
r = nsLayoutUtils::GetAllInFlowBoundingRect(frame);
|
|
||||||
}
|
|
||||||
r += GetOffsetFromInitialContainingBlock(frame);
|
|
||||||
}
|
|
||||||
SetTextRectangle(r, presContext, rect);
|
SetTextRectangle(r, presContext, rect);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static nsresult
|
struct RectListBuilder : public nsLayoutUtils::RectCallback {
|
||||||
AddRectanglesForFrames(nsTextRectangleList* aRectList, nsIFrame* aFrame)
|
nsPresContext* mPresContext;
|
||||||
{
|
nsTextRectangleList* mRectList;
|
||||||
if (!aFrame)
|
nsresult mRV;
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
nsPresContext* presContext = aFrame->PresContext();
|
RectListBuilder(nsPresContext* aPresContext, nsTextRectangleList* aList)
|
||||||
for (nsIFrame* f = aFrame; f;
|
: mPresContext(aPresContext), mRectList(aList),
|
||||||
f = nsLayoutUtils::GetNextContinuationOrSpecialSibling(f)) {
|
mRV(NS_OK) {}
|
||||||
|
|
||||||
|
virtual void AddRect(const nsRect& aRect) {
|
||||||
nsRefPtr<nsTextRectangle> rect = new nsTextRectangle();
|
nsRefPtr<nsTextRectangle> rect = new nsTextRectangle();
|
||||||
if (!rect)
|
if (!rect) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
mRV = NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
return;
|
||||||
nsRect r;
|
|
||||||
if (!TryGetSVGBoundingRect(f, &r)) {
|
|
||||||
r = nsRect(GetOffsetFromInitialContainingBlock(f), f->GetSize());
|
|
||||||
}
|
}
|
||||||
SetTextRectangle(r, presContext, rect);
|
|
||||||
aRectList->Append(rect);
|
SetTextRectangle(aRect, mPresContext, rect);
|
||||||
|
mRectList->Append(rect);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsNSElementTearoff::GetClientRects(nsIDOMTextRectangleList** aResult)
|
nsNSElementTearoff::GetClientRects(nsIDOMTextRectangleList** aResult)
|
||||||
{
|
{
|
||||||
*aResult = nsnull;
|
*aResult = nsnull;
|
||||||
|
|
||||||
// Weak ref, since we addref it below
|
|
||||||
nsRefPtr<nsTextRectangleList> rectList = new nsTextRectangleList();
|
nsRefPtr<nsTextRectangleList> rectList = new nsTextRectangleList();
|
||||||
if (!rectList)
|
if (!rectList)
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
nsIFrame* frame = mContent->GetPrimaryFrame(Flush_Layout);
|
nsIFrame* frame = mContent->GetPrimaryFrame(Flush_Layout);
|
||||||
if (!frame) {
|
if (!frame) {
|
||||||
// display:none, perhaps? Return an empty list
|
// display:none, perhaps? Return an empty list
|
||||||
|
@ -957,21 +904,11 @@ nsNSElementTearoff::GetClientRects(nsIDOMTextRectangleList** aResult)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame->GetType() == nsGkAtoms::tableOuterFrame) {
|
RectListBuilder builder(frame->PresContext(), rectList);
|
||||||
// The weird frame layout of tables requires this
|
nsLayoutUtils::GetAllInFlowRects(frame,
|
||||||
nsIFrame* innerTable = frame->GetFirstChild(nsnull);
|
GetContainingBlockForClientRect(frame), &builder);
|
||||||
nsresult rv = AddRectanglesForFrames(rectList, innerTable);
|
if (NS_FAILED(builder.mRV))
|
||||||
if (NS_FAILED(rv))
|
return builder.mRV;
|
||||||
return rv;
|
|
||||||
nsIFrame* caption = frame->GetFirstChild(nsGkAtoms::captionList);
|
|
||||||
rv = AddRectanglesForFrames(rectList, caption);
|
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return rv;
|
|
||||||
} else {
|
|
||||||
nsresult rv = AddRectanglesForFrames(rectList, frame);
|
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
*aResult = rectList.forget().get();
|
*aResult = rectList.forget().get();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,6 +170,7 @@ _TEST_FILES = test_bug5141.html \
|
||||||
test_bug414190.html \
|
test_bug414190.html \
|
||||||
test_bug414796.html \
|
test_bug414796.html \
|
||||||
test_bug416383.html \
|
test_bug416383.html \
|
||||||
|
test_bug417255.html \
|
||||||
test_bug417384.html \
|
test_bug417384.html \
|
||||||
test_bug418214.html \
|
test_bug418214.html \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=417255
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test for Bug 417255</title>
|
||||||
|
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
<style>
|
||||||
|
.spacer { display:inline-block; height:10px; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=417255">Mozilla Bug 417255</a>
|
||||||
|
<p id="display" style="width:800px"></p>
|
||||||
|
|
||||||
|
<p><span id="s1" style="border:2px dotted red;"><span class="spacer" style="width:100px"></span>
|
||||||
|
<div style="width:500px; height:100px; background:yellow;"></div>
|
||||||
|
<span class="spacer" style="width:200px"></span></span>
|
||||||
|
|
||||||
|
<p><span id="s2" style="border:2px dotted red;"><span class="spacer" style="width:100px"></span>
|
||||||
|
<div style="width:150px; height:100px; background:yellow;"></div>
|
||||||
|
<span class="spacer" style="width:200px"></span></span>
|
||||||
|
|
||||||
|
<!-- test nested spans around the IB split -->
|
||||||
|
<p><span id="s3" style="border:2px dotted red;"><span><span class="spacer" style="width:100px"></span>
|
||||||
|
<div style="width:500px; height:100px; background:yellow;"></div>
|
||||||
|
<span class="spacer" style="width:200px"></span></span></span>
|
||||||
|
|
||||||
|
<div id="content" style="display: none">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<pre id="test">
|
||||||
|
<script class="testbody" type="text/javascript">
|
||||||
|
|
||||||
|
function getWidth(box) {
|
||||||
|
return box.right - box.left;
|
||||||
|
}
|
||||||
|
|
||||||
|
function doTest(id, boundsWidth, w1, w2, w3) {
|
||||||
|
var s = document.getElementById(id);
|
||||||
|
is(s.offsetWidth, boundsWidth, "bad offsetWidth");
|
||||||
|
is(getWidth(s.getBoundingClientRect()), boundsWidth, "bad getBoundingClientRect width");
|
||||||
|
is(getWidth(s.getClientRects()[0]), w1, "bad getClientRects width");
|
||||||
|
is(getWidth(s.getClientRects()[1]), w2, "bad getClientRects width");
|
||||||
|
is(getWidth(s.getClientRects()[2]), w3, "bad getClientRects width");
|
||||||
|
}
|
||||||
|
|
||||||
|
doTest("s1", 500, 104, 500, 204);
|
||||||
|
doTest("s2", 204, 104, 150, 204);
|
||||||
|
doTest("s3", 500, 104, 500, 204);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -512,8 +512,6 @@ nsGenericHTMLElement::GetOffsetRect(nsRect& aRect, nsIContent** aOffsetParent)
|
||||||
parent = parent->GetParent();
|
parent = parent->GetParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the union of all rectangles in this and continuation frames.
|
|
||||||
nsRect rcFrame = nsLayoutUtils::GetAllInFlowBoundingRect(frame);
|
|
||||||
nsIContent* docElement = GetCurrentDoc()->GetRootContent();
|
nsIContent* docElement = GetCurrentDoc()->GetRootContent();
|
||||||
nsIContent* content = frame->GetContent();
|
nsIContent* content = frame->GetContent();
|
||||||
|
|
||||||
|
@ -594,6 +592,12 @@ nsGenericHTMLElement::GetOffsetRect(nsRect& aRect, nsIContent** aOffsetParent)
|
||||||
// Convert to pixels.
|
// Convert to pixels.
|
||||||
aRect.x = nsPresContext::AppUnitsToIntCSSPixels(origin.x);
|
aRect.x = nsPresContext::AppUnitsToIntCSSPixels(origin.x);
|
||||||
aRect.y = nsPresContext::AppUnitsToIntCSSPixels(origin.y);
|
aRect.y = nsPresContext::AppUnitsToIntCSSPixels(origin.y);
|
||||||
|
|
||||||
|
// Get the union of all rectangles in this and continuation frames.
|
||||||
|
// It doesn't really matter what we use as aRelativeTo here, since
|
||||||
|
// we only care about the size. Using 'parent' might make things
|
||||||
|
// a bit faster by speeding up the internal GetOffsetTo operations.
|
||||||
|
nsRect rcFrame = nsLayoutUtils::GetAllInFlowRectsUnion(frame, parent);
|
||||||
aRect.width = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.width);
|
aRect.width = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.width);
|
||||||
aRect.height = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.height);
|
aRect.height = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.height);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#include "nsGkAtoms.h"
|
#include "nsGkAtoms.h"
|
||||||
#include "nsIAtom.h"
|
#include "nsIAtom.h"
|
||||||
#include "nsCSSPseudoElements.h"
|
#include "nsCSSPseudoElements.h"
|
||||||
|
#include "nsCSSAnonBoxes.h"
|
||||||
#include "nsIView.h"
|
#include "nsIView.h"
|
||||||
#include "nsIScrollableView.h"
|
#include "nsIScrollableView.h"
|
||||||
#include "nsPlaceholderFrame.h"
|
#include "nsPlaceholderFrame.h"
|
||||||
|
@ -70,9 +71,11 @@
|
||||||
#include "nsCSSRendering.h"
|
#include "nsCSSRendering.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
|
|
||||||
|
#ifdef MOZ_SVG
|
||||||
|
#include "nsSVGUtils.h"
|
||||||
|
#endif
|
||||||
#ifdef MOZ_SVG_FOREIGNOBJECT
|
#ifdef MOZ_SVG_FOREIGNOBJECT
|
||||||
#include "nsSVGForeignObjectFrame.h"
|
#include "nsSVGForeignObjectFrame.h"
|
||||||
#include "nsSVGUtils.h"
|
|
||||||
#include "nsSVGOuterSVGFrame.h"
|
#include "nsSVGOuterSVGFrame.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1080,27 +1083,73 @@ nsLayoutUtils::BinarySearchForPosition(nsIRenderingContext* aRendContext,
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRect
|
static void
|
||||||
nsLayoutUtils::GetAllInFlowBoundingRect(nsIFrame* aFrame)
|
AddRectsForFrame(nsIFrame* aFrame, nsIFrame* aRelativeTo,
|
||||||
|
nsLayoutUtils::RectCallback* aCallback)
|
||||||
{
|
{
|
||||||
// Get the union of all rectangles in this and continuation frames
|
nsIAtom* pseudoType = aFrame->GetStyleContext()->GetPseudoType();
|
||||||
nsRect r = aFrame->GetRect();
|
|
||||||
nsIFrame* parent = aFrame->GetParent();
|
|
||||||
if (!parent)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
for (nsIFrame* f = nsLayoutUtils::GetNextContinuationOrSpecialSibling(aFrame);
|
if (pseudoType == nsCSSAnonBoxes::tableOuter) {
|
||||||
f; f = nsLayoutUtils::GetNextContinuationOrSpecialSibling(f)) {
|
AddRectsForFrame(aFrame->GetFirstChild(nsnull), aRelativeTo,
|
||||||
r.UnionRect(r, nsRect(f->GetOffsetTo(parent), f->GetSize()));
|
aCallback);
|
||||||
|
nsIFrame* kid = aFrame->GetFirstChild(nsGkAtoms::captionList);
|
||||||
|
if (kid) {
|
||||||
|
AddRectsForFrame(kid, aRelativeTo, aCallback);
|
||||||
|
}
|
||||||
|
} else if (pseudoType == nsCSSAnonBoxes::mozAnonymousBlock ||
|
||||||
|
pseudoType == nsCSSAnonBoxes::mozAnonymousPositionedBlock ||
|
||||||
|
pseudoType == nsCSSAnonBoxes::mozMathMLAnonymousBlock ||
|
||||||
|
pseudoType == nsCSSAnonBoxes::mozXULAnonymousBlock) {
|
||||||
|
for (nsIFrame* kid = aFrame->GetFirstChild(nsnull); kid; kid = kid->GetNextSibling()) {
|
||||||
|
AddRectsForFrame(kid, aRelativeTo, aCallback);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#ifdef MOZ_SVG
|
||||||
|
nsRect r;
|
||||||
|
nsIFrame* outer = nsSVGUtils::GetOuterSVGFrameAndCoveredRegion(aFrame, &r);
|
||||||
|
if (outer) {
|
||||||
|
// r is in pixels relative to 'outer', get it into appunits
|
||||||
|
// relative to aRelativeTo
|
||||||
|
r.ScaleRoundOut(1.0/aFrame->PresContext()->AppUnitsPerDevPixel());
|
||||||
|
aCallback->AddRect(r + outer->GetOffsetTo(aRelativeTo));
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
aCallback->AddRect(nsRect(aFrame->GetOffsetTo(aRelativeTo), aFrame->GetSize()));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (r.IsEmpty()) {
|
void
|
||||||
// It could happen that all the rects are empty (eg zero-width or
|
nsLayoutUtils::GetAllInFlowRects(nsIFrame* aFrame, nsIFrame* aRelativeTo,
|
||||||
// zero-height). In that case, use the first rect for the frame.
|
RectCallback* aCallback)
|
||||||
r = aFrame->GetRect();
|
{
|
||||||
|
while (aFrame) {
|
||||||
|
AddRectsForFrame(aFrame, aRelativeTo, aCallback);
|
||||||
|
aFrame = nsLayoutUtils::GetNextContinuationOrSpecialSibling(aFrame);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return r - aFrame->GetPosition();
|
struct RectAccumulator : public nsLayoutUtils::RectCallback {
|
||||||
|
nsRect mResultRect;
|
||||||
|
nsRect mFirstRect;
|
||||||
|
PRPackedBool mSeenFirstRect;
|
||||||
|
|
||||||
|
RectAccumulator() : mSeenFirstRect(PR_FALSE) {}
|
||||||
|
|
||||||
|
virtual void AddRect(const nsRect& aRect) {
|
||||||
|
mResultRect.UnionRect(mResultRect, aRect);
|
||||||
|
if (!mSeenFirstRect) {
|
||||||
|
mSeenFirstRect = PR_TRUE;
|
||||||
|
mFirstRect = aRect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
nsRect
|
||||||
|
nsLayoutUtils::GetAllInFlowRectsUnion(nsIFrame* aFrame, nsIFrame* aRelativeTo) {
|
||||||
|
RectAccumulator accumulator;
|
||||||
|
GetAllInFlowRects(aFrame, aRelativeTo, &accumulator);
|
||||||
|
return accumulator.mResultRect.IsEmpty() ? accumulator.mFirstRect
|
||||||
|
: accumulator.mResultRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
|
@ -471,13 +471,27 @@ public:
|
||||||
PRInt32& aIndex,
|
PRInt32& aIndex,
|
||||||
PRInt32& aTextWidth);
|
PRInt32& aTextWidth);
|
||||||
|
|
||||||
|
class RectCallback {
|
||||||
|
public:
|
||||||
|
virtual void AddRect(const nsRect& aRect) = 0;
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* Get the union of all rects in aFrame and its continuations, relative
|
* Collect all CSS border-boxes associated with aFrame and its
|
||||||
* to aFrame's origin. Scrolling is taken into account, but this shouldn't
|
* continuations, "drilling down" through outer table frames and
|
||||||
* matter because it should be impossible to have some continuations scrolled
|
* some anonymous blocks since they're not real CSS boxes.
|
||||||
* differently from others.
|
* The boxes are positioned relative to aRelativeTo (taking scrolling
|
||||||
|
* into account) and passed to the callback in frame-tree order.
|
||||||
|
* If aFrame is null, no boxes are returned.
|
||||||
|
* For SVG frames, returns one rectangle, the bounding box.
|
||||||
*/
|
*/
|
||||||
static nsRect GetAllInFlowBoundingRect(nsIFrame* aFrame);
|
static void GetAllInFlowRects(nsIFrame* aFrame, nsIFrame* aRelativeTo,
|
||||||
|
RectCallback* aCallback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the union of all rects returned by GetAllInFlowRects. If
|
||||||
|
* the union is empty, returns the first rect.
|
||||||
|
*/
|
||||||
|
static nsRect GetAllInFlowRectsUnion(nsIFrame* aFrame, nsIFrame* aRelativeTo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the font metrics corresponding to the frame's style data.
|
* Get the font metrics corresponding to the frame's style data.
|
||||||
|
|
|
@ -173,9 +173,6 @@ nsBoxObject::GetOffsetRect(nsRect& aRect)
|
||||||
// Get its origin
|
// Get its origin
|
||||||
nsPoint origin = frame->GetPositionIgnoringScrolling();
|
nsPoint origin = frame->GetPositionIgnoringScrolling();
|
||||||
|
|
||||||
// Get the union of all rectangles in this and continuation frames
|
|
||||||
nsRect rcFrame = nsLayoutUtils::GetAllInFlowBoundingRect(frame);
|
|
||||||
|
|
||||||
// Find the frame parent whose content is the document element.
|
// Find the frame parent whose content is the document element.
|
||||||
nsIContent *docElement = mContent->GetCurrentDoc()->GetRootContent();
|
nsIContent *docElement = mContent->GetCurrentDoc()->GetRootContent();
|
||||||
nsIFrame* parent = frame->GetParent();
|
nsIFrame* parent = frame->GetParent();
|
||||||
|
@ -210,10 +207,16 @@ nsBoxObject::GetOffsetRect(nsRect& aRect)
|
||||||
|
|
||||||
aRect.x = nsPresContext::AppUnitsToIntCSSPixels(origin.x);
|
aRect.x = nsPresContext::AppUnitsToIntCSSPixels(origin.x);
|
||||||
aRect.y = nsPresContext::AppUnitsToIntCSSPixels(origin.y);
|
aRect.y = nsPresContext::AppUnitsToIntCSSPixels(origin.y);
|
||||||
|
|
||||||
|
// Get the union of all rectangles in this and continuation frames.
|
||||||
|
// It doesn't really matter what we use as aRelativeTo here, since
|
||||||
|
// we only care about the size. Using 'parent' might make things
|
||||||
|
// a bit faster by speeding up the internal GetOffsetTo operations.
|
||||||
|
nsRect rcFrame = nsLayoutUtils::GetAllInFlowRectsUnion(frame, parent);
|
||||||
aRect.width = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.width);
|
aRect.width = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.width);
|
||||||
aRect.height = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.height);
|
aRect.height = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче