2008-12-06 Simon Fraser <simon.fraser@apple.com>

        Reviewed by Dave Hyatt

        https://bugs.webkit.org/show_bug.cgi?id=15671

        Fix caret rendering to behave correctly with transforms:
        * Rename caretRect() methods to localCaretRect() and
          absoluteCaretBounds() as appropriate
        * Fix localCaretRect() methods to return a rect in the
          appropriate coordinates.
        * Pass tx, ty down through the paintCaret() methods, after fixing them
          up to account for differences between contents coords, and renderer-local
          coords (via RenderBlock::offsetForContents()).
        * Remove m_caretPositionOnLayout from SelectionController, and instead
          call invalidateSelection() from RenderLayer::scrollToOffset(), because
          we can no longer assume simple x/y offsets from scrolling with transforms.
        * Move the logic to compute which RenderObject actually paints the caret into
          SelectionController::caretRenderer(), rather than having it in RenderBlock.
        * SelectionController now computes and caches a local caret rect. For invalidation,
          it computes the absolute bounds of that (possibly transformed) local rect.
          The local rect is computed in the coordinate system of the RenderObject that
          will paint the caret (this may require offsetting from the actual renderer
          at the start of the selection).
        * Fix LayoutState(RenderObject* root) to take transforms into account
        * Make offsetFromContainer() a virtual method on RenderObject, and implement
          the RenderObject version. It's used to map from selection start renderer
          to caret renderer.

        Test: fast/transforms/transformed-caret.html


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@39069 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 37783ff3
2008-12-06 Simon Fraser <simon.fraser@apple.com>
Reviewed by Dave Hyatt
https://bugs.webkit.org/show_bug.cgi?id=15671
* fast/transforms/transformed-caret.html: Added.
* platform/mac/fast/transforms/transformed-caret-expected.checksum: Added.
* platform/mac/fast/transforms/transformed-caret-expected.png: Added.
* platform/mac/fast/transforms/transformed-caret-expected.txt: Added.
New testcase for caret on transformed element.
* platform/mac/fast/transforms/transformed-focused-text-input-expected.checksum:
* platform/mac/fast/transforms/transformed-focused-text-input-expected.png:
Fix expected now that caret rendering works properly.
2008-12-05 Chris Marrin <cmarrin@apple.com>
Reviewed by Dave Hyatt.
......
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Caret with transform</title>
<style type="text/css" media="screen">
#box {
height: 200px;
width: 300px;
margin: 80px;
border: 1px solid black;
font-size: 60pt;
-webkit-transform: rotate(30deg);
}
</style>
<script type="text/javascript" charset="utf-8">
function focusBox()
{
var box = document.getElementById('box');
// box.focus();
window.getSelection().setPosition(box, box.childNodes.length);
}
</script>
</head>
<body onload="focusBox()">
<p>The caret should render correctly in transformed elements<br>
<a href="https://bugs.webkit.org/show_bug.cgi?id=15671">https://bugs.webkit.org/show_bug.cgi?id=15671</a></p>
<div id="box" contenteditable>
Caret
</div>
</body>
</html>
accbe7d6475699d4cea6780bb7dd6c26
\ No newline at end of file
layer at (0,0) size 800x600
RenderView at (0,0) size 800x600
layer at (0,0) size 800x414
RenderBlock {HTML} at (0,0) size 800x414
RenderBody {BODY} at (8,16) size 784x318
RenderBlock {P} at (0,0) size 784x36
RenderText {#text} at (0,0) size 362x18
text run at (0,0) width 362: "The caret should render correctly in transformed elements"
RenderBR {BR} at (362,14) size 0x0
RenderInline {A} at (0,0) size 305x18 [color=#0000EE]
RenderText {#text} at (0,18) size 305x18
text run at (0,18) width 305: "https://bugs.webkit.org/show_bug.cgi?id=15671"
layer at (88,132) size 302x202
RenderBlock {DIV} at (80,116) size 302x202 [border: (1px solid #000000)]
RenderText {#text} at (1,1) size 174x92
text run at (1,1) width 174: "Caret"
caret: position 6 of child 0 {#text} of child 3 {DIV} of child 1 {BODY} of child 1 {HTML} of document
fa6de2b6b71b17e1f6f508bc258ea165
\ No newline at end of file
7eb3da3403bb6fb0bb27d1eb1bf3bda7
\ No newline at end of file
2008-12-06 Simon Fraser <simon.fraser@apple.com>
Reviewed by Dave Hyatt
https://bugs.webkit.org/show_bug.cgi?id=15671
Fix caret rendering to behave correctly with transforms:
* Rename caretRect() methods to localCaretRect() and
absoluteCaretBounds() as appropriate
* Fix localCaretRect() methods to return a rect in the
appropriate coordinates.
* Pass tx, ty down through the paintCaret() methods, after fixing them
up to account for differences between contents coords, and renderer-local
coords (via RenderBlock::offsetForContents()).
* Remove m_caretPositionOnLayout from SelectionController, and instead
call invalidateSelection() from RenderLayer::scrollToOffset(), because
we can no longer assume simple x/y offsets from scrolling with transforms.
* Move the logic to compute which RenderObject actually paints the caret into
SelectionController::caretRenderer(), rather than having it in RenderBlock.
* SelectionController now computes and caches a local caret rect. For invalidation,
it computes the absolute bounds of that (possibly transformed) local rect.
The local rect is computed in the coordinate system of the RenderObject that
will paint the caret (this may require offsetting from the actual renderer
at the start of the selection).
* Fix LayoutState(RenderObject* root) to take transforms into account
* Make offsetFromContainer() a virtual method on RenderObject, and implement
the RenderObject version. It's used to map from selection start renderer
to caret renderer.
Test: fast/transforms/transformed-caret.html
* WebCore.base.exp:
* editing/DeleteSelectionCommand.cpp:
(WebCore::DeleteSelectionCommand::mergeParagraphs):
* editing/SelectionController.cpp:
(WebCore::SelectionController::SelectionController):
(WebCore::absoluteCaretY):
(WebCore::SelectionController::modify):
(WebCore::SelectionController::xPosForVerticalArrowNavigation):
(WebCore::SelectionController::layout):
(WebCore::SelectionController::caretRenderer):
(WebCore::SelectionController::localCaretRect):
(WebCore::SelectionController::absoluteCaretBounds):
(WebCore::SelectionController::caretRepaintRect):
(WebCore::SelectionController::recomputeCaretRect):
(WebCore::SelectionController::invalidateCaretRect):
(WebCore::SelectionController::paintCaret):
(WebCore::SelectionController::caretRendersInsideNode):
* editing/SelectionController.h:
* editing/VisiblePosition.cpp:
(WebCore::VisiblePosition::localCaretRect):
(WebCore::VisiblePosition::absoluteCaretBounds):
(WebCore::VisiblePosition::xOffsetForVerticalNavigation):
* editing/VisiblePosition.h:
* editing/mac/SelectionControllerMac.mm:
(WebCore::SelectionController::notifyAccessibilityForSelectionChange):
* html/HTMLElement.cpp:
(WebCore::HTMLElement::isContentEditable):
* page/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::boundsForVisiblePositionRange):
* page/Frame.cpp:
(WebCore::Frame::firstRectForRange):
(WebCore::Frame::selectionLayoutChanged):
(WebCore::Frame::paintCaret):
(WebCore::Frame::paintDragCaret):
(WebCore::Frame::revealSelection):
(WebCore::Frame::revealCaret):
* page/Frame.h:
* rendering/LayoutState.cpp:
(WebCore::LayoutState::LayoutState):
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::paintCaret):
(WebCore::RenderBlock::paintObject):
(WebCore::RenderBlock::positionForCoordinates):
(WebCore::RenderBlock::offsetForContents):
* rendering/RenderBlock.h:
* rendering/RenderBox.cpp:
(WebCore::RenderBox::localCaretRect):
* rendering/RenderBox.h:
* rendering/RenderFlow.cpp:
(WebCore::RenderFlow::localCaretRect):
* rendering/RenderFlow.h:
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::scrollToOffset):
* rendering/RenderObject.cpp:
(WebCore::RenderObject::localCaretRect):
* rendering/RenderObject.h:
* rendering/RenderSVGInlineText.cpp:
(WebCore::RenderSVGInlineText::localCaretRect):
* rendering/RenderSVGInlineText.h:
* rendering/RenderText.cpp:
(WebCore::RenderText::RenderText):
(WebCore::RenderText::localCaretRect):
* rendering/RenderText.h:
2008-12-06 David Kilzer <ddkilzer@apple.com>
Bug 22711: Current svn (build 39065) fails to compile
......@@ -773,7 +773,8 @@ __ZNK7WebCore15ResourceRequest12nsURLRequestEv
__ZNK7WebCore15VisiblePosition14characterAfterEv
__ZNK7WebCore15VisiblePosition4nextEb
__ZNK7WebCore15VisiblePosition8previousEb
__ZNK7WebCore15VisiblePosition9caretRectEv
__ZNK7WebCore15VisiblePosition14localCaretRectERPNS_12RenderObjectE
__ZNK7WebCore15VisiblePosition19absoluteCaretBoundsEv
__ZNK7WebCore16HTMLInputElement12autoCompleteEv
__ZNK7WebCore16ResourceResponse13nsURLResponseEv
__ZNK7WebCore17ResourceErrorBase8lazyInitEv
......
......@@ -592,7 +592,7 @@ void DeleteSelectionCommand::mergeParagraphs()
// The rule for merging into an empty block is: only do so if its farther to the right.
// FIXME: Consider RTL.
// FIXME: handleSpecialCaseBRDelete prevents us from getting here in a case like <ul><li>foo<br><br></li></ul>^foo
if (isStartOfParagraph(mergeDestination) && startOfParagraphToMove.caretRect().x() > mergeDestination.caretRect().x()) {
if (isStartOfParagraph(mergeDestination) && startOfParagraphToMove.absoluteCaretBounds().x() > mergeDestination.absoluteCaretBounds().x()) {
ASSERT(mergeDestination.deepEquivalent().downstream().node()->hasTagName(brTag));
removeNodeAndPruneAncestors(mergeDestination.deepEquivalent().downstream().node());
m_endingPosition = startOfParagraphToMove.deepEquivalent();
......
......@@ -62,12 +62,13 @@ using namespace HTMLNames;
const int NoXPosForVerticalArrowNavigation = INT_MIN;
SelectionController::SelectionController(Frame* frame, bool isDragCaretController)
: m_needsLayout(true)
: m_frame(frame)
, m_xPosForVerticalArrowNavigation(NoXPosForVerticalArrowNavigation)
, m_needsLayout(true)
, m_absCaretBoundsDirty(true)
, m_lastChangeWasHorizontalExtension(false)
, m_frame(frame)
, m_isDragCaretController(isDragCaretController)
, m_isCaretBlinkingSuspended(false)
, m_xPosForVerticalArrowNavigation(NoXPosForVerticalArrowNavigation)
, m_focused(false)
{
}
......@@ -550,9 +551,9 @@ bool SelectionController::modify(EAlteration alter, EDirection dir, TextGranular
}
// FIXME: Maybe baseline would be better?
static bool caretY(const VisiblePosition &c, int &y)
static bool absoluteCaretY(const VisiblePosition &c, int &y)
{
IntRect rect = c.caretRect();
IntRect rect = c.absoluteCaretBounds();
if (rect.isEmpty())
return false;
y = rect.y() + rect.height() / 2;
......@@ -596,7 +597,7 @@ bool SelectionController::modify(EAlteration alter, int verticalDistance, bool u
}
int startY;
if (!caretY(pos, startY))
if (!absoluteCaretY(pos, startY))
return false;
if (up)
startY = -startY;
......@@ -609,7 +610,7 @@ bool SelectionController::modify(EAlteration alter, int verticalDistance, bool u
if (next.isNull() || next == p)
break;
int nextY;
if (!caretY(next, nextY))
if (!absoluteCaretY(next, nextY))
break;
if (up)
nextY = -nextY;
......@@ -680,7 +681,7 @@ int SelectionController::xPosForVerticalArrowNavigation(EPositionType type)
VisiblePosition visiblePosition(pos, m_sel.affinity());
// VisiblePosition creation can fail here if a node containing the selection becomes visibility:hidden
// after the selection is created and before this function is called.
x = visiblePosition.isNotNull() ? visiblePosition.caretRect().x() : 0;
x = visiblePosition.isNotNull() ? visiblePosition.xOffsetForVerticalNavigation() : 0;
m_xPosForVerticalArrowNavigation = x;
}
else
......@@ -723,43 +724,79 @@ void SelectionController::layout()
{
if (isNone() || !m_sel.start().node()->inDocument() || !m_sel.end().node()->inDocument()) {
m_caretRect = IntRect();
m_caretPositionOnLayout = IntPoint();
return;
}
m_sel.start().node()->document()->updateRendering();
m_caretRect = IntRect();
m_caretPositionOnLayout = IntPoint();
if (isCaret()) {
VisiblePosition pos(m_sel.start(), m_sel.affinity());
if (pos.isNotNull()) {
ASSERT(pos.deepEquivalent().node()->renderer());
m_caretRect = pos.caretRect();
// FIXME: broken with transforms
FloatPoint absPos = pos.deepEquivalent().node()->renderer()->localToAbsoluteForContent(FloatPoint());
m_caretPositionOnLayout = roundedIntPoint(absPos);
// First compute a rect local to the renderer at the selection start
RenderObject* renderer;
IntRect localRect = pos.localCaretRect(renderer);
// Get the renderer that will be responsible for painting the caret (which
// is either the renderer we just found, or one of its containers)
RenderObject* caretPainter = caretRenderer();
// Compute an offset between the renderer and the caretPainter
IntSize offsetFromPainter;
bool unrooted = false;
while (renderer != caretPainter) {
RenderObject* containerObject = renderer->container();
if (!containerObject) {
unrooted = true;
break;
}
offsetFromPainter += renderer->offsetFromContainer(containerObject);
renderer = containerObject;
}
if (!unrooted) {
// Move the caret rect to the coords of the painter
localRect.move(offsetFromPainter);
m_caretRect = localRect;
}
m_absCaretBoundsDirty = true;
}
}
m_needsLayout = false;
}
IntRect SelectionController::caretRect() const
RenderObject* SelectionController::caretRenderer() const
{
Node* node = m_sel.start().node();
if (!node)
return 0;
RenderObject* renderer = node->renderer();
if (!renderer)
return 0;
// if caretNode is a block and caret is inside it then caret should be painted by that block
bool paintedByBlock = renderer->isBlockFlow() && caretRendersInsideNode(node);
return paintedByBlock ? renderer : renderer->containingBlock();
}
IntRect SelectionController::localCaretRect() const
{
if (m_needsLayout)
const_cast<SelectionController *>(this)->layout();
IntRect caret = m_caretRect;
if (m_sel.start().node() && m_sel.start().node()->renderer()) {
FloatPoint absPos = m_sel.start().node()->renderer()->localToAbsoluteForContent(FloatPoint());
caret.move(roundedIntPoint(absPos) - m_caretPositionOnLayout);
}
return m_caretRect;
}
return caret;
IntRect SelectionController::absoluteCaretBounds()
{
recomputeCaretRect();
return m_absCaretBounds;
}
static IntRect repaintRectForCaret(IntRect caret)
......@@ -774,7 +811,13 @@ static IntRect repaintRectForCaret(IntRect caret)
IntRect SelectionController::caretRepaintRect() const
{
return repaintRectForCaret(caretRect());
IntRect localRect = repaintRectForCaret(localCaretRect());
RenderObject* caretPainter = caretRenderer();
if (caretPainter)
return caretPainter->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoundingBox();
return IntRect();
}
bool SelectionController::recomputeCaretRect()
......@@ -791,14 +834,22 @@ bool SelectionController::recomputeCaretRect()
IntRect oldRect = m_caretRect;
m_needsLayout = true;
IntRect newRect = caretRect();
if (oldRect == newRect)
IntRect newRect = localCaretRect();
if (oldRect == newRect && !m_absCaretBoundsDirty)
return false;
IntRect oldAbsRepaintRect = m_absCaretBounds;
m_absCaretBounds = caretRepaintRect();
m_absCaretBoundsDirty = false;
if (oldAbsRepaintRect == m_absCaretBounds)
return false;
if (RenderView* view = static_cast<RenderView*>(m_frame->document()->renderer())) {
view->repaintViewRectangle(repaintRectForCaret(oldRect), false);
view->repaintViewRectangle(repaintRectForCaret(newRect), false);
view->repaintViewRectangle(oldAbsRepaintRect, false);
view->repaintViewRectangle(m_absCaretBounds, false);
}
return true;
}
......@@ -809,6 +860,8 @@ void SelectionController::invalidateCaretRect()
Document* d = m_sel.start().node()->document();
// recomputeCaretRect will always return false for the drag caret,
// because its m_frame is always 0.
bool caretRectChanged = recomputeCaretRect();
// EDIT FIXME: This is an unfortunate hack.
......@@ -830,15 +883,17 @@ void SelectionController::invalidateCaretRect()
}
}
void SelectionController::paintCaret(GraphicsContext *p, const IntRect &rect)
void SelectionController::paintCaret(GraphicsContext* p, int tx, int ty, const IntRect& clipRect)
{
if (! m_sel.isCaret())
return;
if (m_needsLayout)
layout();
IntRect caret = intersection(caretRect(), rect);
IntRect drawingRect = localCaretRect();
drawingRect.move(tx, ty);
IntRect caret = intersection(drawingRect, clipRect);
if (!caret.isEmpty()) {
Color caretColor = Color::black;
Element* element = rootEditableElement();
......@@ -1089,12 +1144,11 @@ bool SelectionController::isInPasswordField() const
return static_cast<HTMLInputElement*>(startNode)->inputType() == HTMLInputElement::PASSWORD;
}
bool SelectionController::isInsideNode() const
bool SelectionController::caretRendersInsideNode(Node* node) const
{
Node* startNode = start().node();
if (!startNode)
if (!node)
return false;
return !isTableElement(startNode) && !editingIgnoresContent(startNode);
return !isTableElement(node) && !editingIgnoresContent(node);
}
void SelectionController::focusedOrActiveStateChanged()
......@@ -1151,7 +1205,7 @@ bool SelectionController::isFocusedAndActive() const
{
return m_focused && m_frame->page() && m_frame->page()->focusController()->isActive();
}
#ifndef NDEBUG
void SelectionController::formatForDebugger(char* buffer, unsigned length) const
......
......@@ -85,7 +85,13 @@ public:
Position start() const { return m_sel.start(); }
Position end() const { return m_sel.end(); }
IntRect caretRect() const;
// Return the renderer that is responsible for painting the caret (in the selection start node)
RenderObject* caretRenderer() const;
// Caret rect local to the caret's renderer
IntRect localCaretRect() const;
// Bounds of (possibly transformed) caret in absolute coords
IntRect absoluteCaretBounds();
void setNeedsLayout(bool flag = true);
void setLastChangeWasHorizontalExtension(bool b) { m_lastChangeWasHorizontalExtension = b; }
......@@ -96,7 +102,6 @@ public:
bool isRange() const { return m_sel.isRange(); }
bool isCaretOrRange() const { return m_sel.isCaretOrRange(); }
bool isInPasswordField() const;
bool isInsideNode() const;
PassRefPtr<Range> toRange() const { return m_sel.toRange(); }
......@@ -106,7 +111,7 @@ public:
bool recomputeCaretRect(); // returns true if caret rect moved
void invalidateCaretRect();
void paintCaret(GraphicsContext*, const IntRect&);
void paintCaret(GraphicsContext*, int tx, int ty, const IntRect& clipRect);
// Used to suspend caret blinking while the mouse is down.
void setCaretBlinkingSuspended(bool suspended) { m_isCaretBlinkingSuspended = suspended; }
......@@ -144,25 +149,23 @@ private:
#endif
void focusedOrActiveStateChanged();
bool caretRendersInsideNode(Node*) const;
Frame* m_frame;
int m_xPosForVerticalArrowNavigation;
Selection m_sel;
IntRect m_caretRect; // caret coordinates, size, and position
// m_caretPositionOnLayout stores the scroll offset on the previous call to SelectionController::layout().
// When asked for caretRect(), we correct m_caretRect for offset due to scrolling since the last layout().
// This is faster than doing another layout().
IntPoint m_caretPositionOnLayout;
IntRect m_caretRect; // caret rect in coords local to the renderer responsible for painting the caret
IntRect m_absCaretBounds; // absolute bounding rect for the caret
bool m_needsLayout : 1; // true if the caret and expectedVisible rectangles need to be calculated
bool m_absCaretBoundsDirty: 1;
bool m_lastChangeWasHorizontalExtension : 1;
Frame* m_frame;
bool m_isDragCaretController;
bool m_isDragCaretController : 1;
bool m_isCaretBlinkingSuspended : 1;
bool m_focused : 1;
bool m_isCaretBlinkingSuspended;
int m_xPosForVerticalArrowNavigation;
bool m_focused;
};
inline bool operator==(const SelectionController& a, const SelectionController& b)
......
......@@ -29,6 +29,7 @@
#include "CString.h"
#include "Document.h"
#include "Element.h"
#include "FloatRect.h"
#include "HTMLNames.h"
#include "InlineTextBox.h"
#include "Logging.h"
......@@ -523,13 +524,15 @@ UChar VisiblePosition::characterAfter() const
return textNode->data()[offset];
}
IntRect VisiblePosition::caretRect() const
IntRect VisiblePosition::localCaretRect(RenderObject*& renderer) const
{
Node* node = m_deepPosition.node();
if (!node)
if (!node) {
renderer = 0;
return IntRect();
RenderObject* renderer = node->renderer();
}
renderer = node->renderer();
if (!renderer)
return IntRect();
......@@ -540,7 +543,30 @@ IntRect VisiblePosition::caretRect() const
if (inlineBox)
renderer = inlineBox->object();
return renderer->caretRect(inlineBox, caretOffset);
return renderer->localCaretRect(inlineBox, caretOffset);
}
IntRect VisiblePosition::absoluteCaretBounds() const
{
RenderObject* renderer;
IntRect localRect = localCaretRect(renderer);
if (localRect.isEmpty() || !renderer)
return IntRect();
return renderer->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoundingBox();
}
int VisiblePosition::xOffsetForVerticalNavigation() const
{
RenderObject* renderer;
IntRect localRect = localCaretRect(renderer);
if (localRect.isEmpty() || !renderer)
return 0;
// This ignores transforms on purpose, for now. Vertical navigation is done
// without consulting transforms, so that 'up' in transformed text is 'up'
// relative to the text, not absolute 'up'.
return renderer->localToAbsolute(localRect.location()).x();
}
void VisiblePosition::debugPosition(const char* msg) const
......
......@@ -90,8 +90,14 @@ public:
m_deepPosition.getInlineBoxAndOffset(m_affinity, primaryDirection, inlineBox, caretOffset);
}
IntRect caretRect() const;
// Rect is local to the returned renderer
IntRect localCaretRect(RenderObject*&) const;
// Bounds of (possibly transformed) caret in absolute coords
IntRect absoluteCaretBounds() const;
// Abs x position of the caret ignoring transforms.
// FIXME: navigation with transforms should be smarter.
int xOffsetForVerticalNavigation() const;
#ifndef NDEBUG
void formatForDebugger(char* buffer, unsigned length) const;
void showTreeForThis() const;
......
......@@ -47,7 +47,7 @@ void SelectionController::notifyAccessibilityForSelectionChange()
if (UAZoomEnabled() && m_sel.isCaret() && m_sel.start().node()) {
RenderView *renderView = static_cast<RenderView*>(m_sel.start().node()->renderer());
if (renderView) {
IntRect selectionRect = caretRect();
IntRect selectionRect = absoluteCaretBounds();
IntRect viewRect = renderView->viewRect();
FrameView* frameView = renderView->view()->frameView();
if (frameView) {
......
......@@ -610,6 +610,8 @@ bool HTMLElement::isContentEditable() const
if (document()->frame() && document()->frame()->isContentEditable())
return true;
// FIXME: this is a terrible thing to do here:
// https://bugs.webkit.org/show_bug.cgi?id=21834
document()->updateRendering();
if (!renderer()) {
......
......@@ -1630,19 +1630,19 @@ IntRect AccessibilityRenderObject::boundsForVisiblePositionRange(const VisiblePo
// Create a mutable VisiblePositionRange.
VisiblePositionRange range(visiblePositionRange);
IntRect rect1 = range.start.caretRect();
IntRect rect2 = range.end.caretRect();
IntRect rect1 = range.start.absoluteCaretBounds();