Bug 727942 - getRange/CharacterExtents is broken when page is zoomed, r=tbsaunde

This commit is contained in:
Alexander Surkov 2012-10-20 20:04:45 +09:00
parent 602db403b7
commit 3af429c4b8
4 changed files with 116 additions and 14 deletions

View File

@ -143,19 +143,19 @@ nsIntRect
HyperTextAccessible::GetBoundsForString(nsIFrame* aFrame, uint32_t aStartRenderedOffset,
uint32_t aEndRenderedOffset)
{
nsIntRect screenRect;
NS_ENSURE_TRUE(aFrame, screenRect);
nsPresContext* presContext = mDoc->PresContext();
if (aFrame->GetType() != nsGkAtoms::textFrame) {
// XXX fallback for non-text frames, happens for bullets right now
// but in the future bullets will have proper text frames
return aFrame->GetScreenRectExternal();
return aFrame->GetScreenRectInAppUnits().
ToNearestPixels(presContext->AppUnitsPerDevPixel());
}
int32_t startContentOffset, endContentOffset;
nsresult rv = RenderedToContentOffset(aFrame, aStartRenderedOffset, &startContentOffset);
NS_ENSURE_SUCCESS(rv, screenRect);
NS_ENSURE_SUCCESS(rv, nsIntRect());
rv = RenderedToContentOffset(aFrame, aEndRenderedOffset, &endContentOffset);
NS_ENSURE_SUCCESS(rv, screenRect);
NS_ENSURE_SUCCESS(rv, nsIntRect());
nsIFrame *frame;
int32_t startContentOffsetInFrame;
@ -163,16 +163,15 @@ HyperTextAccessible::GetBoundsForString(nsIFrame* aFrame, uint32_t aStartRendere
// the primary frame passed in
rv = aFrame->GetChildFrameContainingOffset(startContentOffset, false,
&startContentOffsetInFrame, &frame);
NS_ENSURE_SUCCESS(rv, screenRect);
nsPresContext* context = mDoc->PresContext();
NS_ENSURE_SUCCESS(rv, nsIntRect());
nsRect screenRect;
while (frame && startContentOffset < endContentOffset) {
// Start with this frame's screen rect, which we will
// shrink based on the substring we care about within it.
// We will then add that frame to the total screenRect we
// are returning.
nsIntRect frameScreenRect = frame->GetScreenRectExternal();
nsRect frameScreenRect = frame->GetScreenRectInAppUnits();
// Get the length of the substring in this frame that we want the bounds for
int32_t startFrameTextOffset, endFrameTextOffset;
@ -185,13 +184,13 @@ HyperTextAccessible::GetBoundsForString(nsIFrame* aFrame, uint32_t aStartRendere
nsPoint frameTextStartPoint;
rv = frame->GetPointFromOffset(startContentOffset, &frameTextStartPoint);
NS_ENSURE_SUCCESS(rv, nsIntRect());
frameScreenRect.x += context->AppUnitsToDevPixels(frameTextStartPoint.x);
frameScreenRect.x += frameTextStartPoint.x;
// Use the point for the end offset to calculate the width
nsPoint frameTextEndPoint;
rv = frame->GetPointFromOffset(startContentOffset + frameSubStringLength, &frameTextEndPoint);
NS_ENSURE_SUCCESS(rv, nsIntRect());
frameScreenRect.width = context->AppUnitsToDevPixels(frameTextEndPoint.x - frameTextStartPoint.x);
frameScreenRect.width = frameTextEndPoint.x - frameTextStartPoint.x;
screenRect.UnionRect(frameScreenRect, screenRect);
@ -201,7 +200,7 @@ HyperTextAccessible::GetBoundsForString(nsIFrame* aFrame, uint32_t aStartRendere
frame = frame->GetNextContinuation();
}
return screenRect;
return screenRect.ToNearestPixels(presContext->AppUnitsPerDevPixel());
}
/*
@ -376,8 +375,9 @@ HyperTextAccessible::GetPosAndText(int32_t& aStartOffset, int32_t& aEndOffset,
}
}
if (aBoundsRect) {
aBoundsRect->UnionRect(*aBoundsRect,
frame->GetScreenRectExternal());
nsIntRect frameScreenRect = frame->GetScreenRectInAppUnits().
ToNearestPixels(frame->PresContext()->AppUnitsPerDevPixel());
aBoundsRect->UnionRect(*aBoundsRect, frameScreenRect);
}
}
if (!startFrame) {

View File

@ -14,6 +14,7 @@ include $(DEPTH)/config/autoconf.mk
MOCHITEST_A11Y_FILES =\
test_list.html \
test_select.html \
test_zoom_text.html \
test_zoom.html \
$(NULL)

View File

@ -0,0 +1,72 @@
<!DOCTYPE html>
<html>
<head>
<title>The text range boundary when page is zoomed</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"></meta>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../layout.js"></script>
<script type="application/javascript"
src="../browser.js"></script>
<script type="application/javascript">
function doTest()
{
var tabDocument = currentTabDocument();
var hyperTextNode = tabDocument.getElementById("paragraph");
var textNode = hyperTextNode.firstChild;
var [x, y, width, height] = getBounds(textNode);
testTextBounds(hyperTextNode, 0, -1, [x, y, width, height],
COORDTYPE_SCREEN_RELATIVE);
zoomDocument(tabDocument, 2.0);
var [x, y, width, height] = getBounds(textNode);
testTextBounds(hyperTextNode, 0, -1, [x, y, width, height],
COORDTYPE_SCREEN_RELATIVE);
zoomDocument(tabDocument, 1.0);
closeBrowserWindow();
SimpleTest.finish();
}
var url = "data:text/html,<html>" +
"<meta http-equiv='Content-Type' content='text/html;charset=utf-8'>" +
"</meta><body>" +
"<p id='paragraph' style='font-family: monospace;'>Tilimilitryamdiya</p>" +
"</body></html>";
SimpleTest.waitForExplicitFinish();
openBrowserWindow(doTest,
url,
{ left: 0, top: 0, width: 600, height: 600 });
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=727942"
title="Text range boundaries are incorrect when page is zoomed">
Mozilla Bug 727942
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -131,6 +131,35 @@ function testBounds(aID, aRect)
is(height, expectedHeight, "Wrong height of " + prettyName(aID));
}
/**
* Test text bounds that is enclosed betwene the given offsets.
*/
function testTextBounds(aID, aStartOffset, aEndOffset, aRect, aCoordOrigin)
{
var [expectedX, expectedY, expectedWidth, expectedHeight] = aRect;
var xObj = {}, yObj = {}, widthObj = {}, heightObj = {};
var hyperText = getAccessible(aID, [nsIAccessibleText]);
hyperText.getRangeExtents(0, -1, xObj, yObj, widthObj, heightObj, aCoordOrigin);
is(xObj.value, expectedX,
"Wrong x coordinate of text between offsets (" + aStartOffset + ", " +
aEndOffset + ") for " + prettyName(aID));
is(yObj.value, expectedY,
"Wrong y coordinate of text between offsets (" + aStartOffset + ", " +
aEndOffset + ") for " + prettyName(aID));
var msg = "Wrong width of text between offsets (" + aStartOffset + ", " +
aEndOffset + ") for " + prettyName(aID);
if (widthObj.value == expectedWidth)
ok(true, msg);
else
todo(false, msg); // fails on some windows machines
is(heightObj.value, expectedHeight,
"Wrong height of text between offsets (" + aStartOffset + ", " +
aEndOffset + ") for " + prettyName(aID));
}
/**
* Return the accessible coordinates relative to the screen in device pixels.
*/