2008-11-04 Simon Fraser <simon.fraser@apple.com>

        Reviewed by Dave Hyatt

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

        Rename absolutePosition() to localToAbsolute(), and add the ability
        to optionally take transforms into account (which will eventually be the
        default behavior).

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@38098 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent b8b5aa1d
2008-11-04 Simon Fraser <simon.fraser@apple.com>
Reviewed by Dave Hyatt
https://bugs.webkit.org/show_bug.cgi?id=21941
Rename absolutePosition() to localToAbsolute(), and add the ability
to optionally take transforms into account (which will eventually be the
default behavior).
* WebCore.base.exp:
* WebCore.xcodeproj/project.pbxproj:
* dom/ContainerNode.cpp:
(WebCore::ContainerNode::getUpperLeftCorner):
(WebCore::ContainerNode::getLowerRightCorner):
(WebCore::ContainerNode::getRect):
* dom/ContainerNode.h:
* dom/MouseRelatedEvent.cpp:
(WebCore::MouseRelatedEvent::receivedTarget):
* dom/Node.cpp:
(WebCore::Node::getRect):
* editing/SelectionController.cpp:
(WebCore::SelectionController::layout):
(WebCore::SelectionController::caretRect):
* editing/visible_units.cpp:
(WebCore::previousLinePosition):
(WebCore::nextLinePosition):
* html/HTMLAnchorElement.cpp:
(WebCore::HTMLAnchorElement::isKeyboardFocusable):
(WebCore::HTMLAnchorElement::defaultEventHandler):
* html/HTMLAreaElement.cpp:
(WebCore::HTMLAreaElement::getRect):
* html/HTMLImageElement.cpp:
(WebCore::HTMLImageElement::x):
(WebCore::HTMLImageElement::y):
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::defaultEventHandler):
* html/HTMLInputElement.h:
* page/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::boundingBoxRect):
* page/EventHandler.cpp:
(WebCore::EventHandler::handleDrag):
* platform/graphics/FloatPoint.h:
(WebCore::roundedIntPoint):
* platform/graphics/IntSize.h:
(WebCore::IntSize::expand):
* rendering/LayoutState.cpp:
(WebCore::LayoutState::LayoutState):
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::layoutBlock):
(WebCore::RenderBlock::paintObject):
(WebCore::RenderBlock::selectionGapRects):
(WebCore::RenderBlock::fillBlockSelectionGaps):
(WebCore::RenderBlock::nodeAtPoint):
(WebCore::RenderBlock::positionForCoordinates):
* rendering/RenderBox.cpp:
(WebCore::RenderBox::localToAbsolute):
(WebCore::RenderBox::computeAbsoluteRepaintRect):
(WebCore::RenderBox::caretRect):
* rendering/RenderBox.h:
(WebCore::RenderBox::relativePositionOffset):
* rendering/RenderContainer.cpp:
(WebCore::RenderContainer::addLineBoxRects):
* rendering/RenderFlow.cpp:
(WebCore::RenderFlow::absoluteClippedOverflowRect):
(WebCore::RenderFlow::caretRect):
(WebCore::RenderFlow::addFocusRingRects):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::updateLayerPosition):
(WebCore::RenderLayer::convertToLayerCoords):
(WebCore::RenderLayer::addScrolledContentOffset):
(WebCore::RenderLayer::subtractScrolledContentOffset):
(WebCore::RenderLayer::scrollRectToVisible):
* rendering/RenderLayer.h:
(WebCore::RenderLayer::scrolledContentOffset):
(WebCore::RenderLayer::relativePositionOffset):
* rendering/RenderListBox.cpp:
(WebCore::RenderListBox::panScroll):
(WebCore::RenderListBox::scrollToward):
* rendering/RenderListMarker.cpp:
(WebCore::RenderListMarker::selectionRect):
* rendering/RenderObject.cpp:
(WebCore::RenderObject::absoluteBoundingBoxRect):
(WebCore::RenderObject::computeAbsoluteRepaintRect):
(WebCore::RenderObject::localToAbsolute):
(WebCore::RenderObject::addDashboardRegions):
(WebCore::RenderObject::absoluteContentBox):
(WebCore::RenderObject::absoluteOutlineBox):
* rendering/RenderObject.h:
(WebCore::RenderObject::localToAbsoluteForContent):
* rendering/RenderPart.cpp:
(WebCore::RenderPart::updateWidgetPosition):
* rendering/RenderReplaced.cpp:
(WebCore::RenderReplaced::selectionRect):
* rendering/RenderSVGInlineText.cpp:
(WebCore::RenderSVGInlineText::computeAbsoluteRectForRange):
* rendering/RenderSVGText.cpp:
(WebCore::RenderSVGText::absoluteRects):
* rendering/RenderTableCell.cpp:
(WebCore::RenderTableCell::localToAbsolute):
* rendering/RenderTableCell.h:
* rendering/RenderText.cpp:
(WebCore::RenderText::addLineBoxRects):
(WebCore::RenderText::caretRect):
(WebCore::RenderText::selectionRect):
* rendering/RenderVideo.cpp:
(WebCore::RenderVideo::updatePlayer):
* rendering/RenderView.cpp:
(WebCore::RenderView::localToAbsolute):
* rendering/RenderView.h:
* rendering/RenderWidget.cpp:
(WebCore::RenderWidget::updateWidgetPosition):
* svg/SVGSVGElement.cpp:
(WebCore::SVGSVGElement::getScreenCTM):
2008-11-03 Yael Aharon <yael.aharon@nokia.com>
Reviewed by Simon Hausmann.
......
......@@ -566,6 +566,7 @@ __ZN7WebCore8Document4bodyEv
__ZN7WebCore8DragDataC1EP11objc_objectRKNS_8IntPointES5_NS_13DragOperationEPNS_16PasteboardHelperE
__ZN7WebCore8FormDataD1Ev
__ZN7WebCore8IntPointC1ERK8_NSPoint
__ZNK7WebCore10FloatPointcv8_NSPointEv
__ZN7WebCore8Settings14setJavaEnabledEb
__ZN7WebCore8Settings16setUsesPageCacheEb
__ZN7WebCore8Settings16setZoomsTextOnlyEb
......
......@@ -29,6 +29,7 @@
#include "Editor.h"
#include "EventNames.h"
#include "ExceptionCode.h"
#include "FloatRect.h"
#include "Frame.h"
#include "FrameView.h"
#include "InlineTextBox.h"
......@@ -647,25 +648,26 @@ void ContainerNode::cloneChildNodes(ContainerNode *clone)
document()->frame()->editor()->deleteButtonController()->enable();
}
bool ContainerNode::getUpperLeftCorner(int &xPos, int &yPos) const
// FIXME: This doesn't work correctly with transforms.
bool ContainerNode::getUpperLeftCorner(FloatPoint& point) const
{
if (!renderer())
return false;
// What is this code really trying to do?
RenderObject *o = renderer();
RenderObject *p = o;
xPos = yPos = 0;
if (!o->isInline() || o->isReplaced()) {
o->absolutePosition(xPos, yPos);
point = o->localToAbsolute();
return true;
}
// find the next text/image child, to get a position
while(o) {
while (o) {
p = o;
if (o->firstChild())
o = o->firstChild();
else if(o->nextSibling())
else if (o->nextSibling())
o = o->nextSibling();
else {
RenderObject *next = 0;
......@@ -680,70 +682,72 @@ bool ContainerNode::getUpperLeftCorner(int &xPos, int &yPos) const
}
if (!o->isInline() || o->isReplaced()) {
o->absolutePosition(xPos, yPos);
point = o->localToAbsolute();
return true;
}
if (p->element() && p->element() == this && o->isText() && !o->isBR() && !static_cast<RenderText*>(o)->firstTextBox()) {
// do nothing - skip unrendered whitespace that is a child or next sibling of the anchor
} else if ((o->isText() && !o->isBR()) || o->isReplaced()) {
o->container()->absolutePosition(xPos, yPos);
point = o->container()->localToAbsolute();
if (o->isText() && static_cast<RenderText *>(o)->firstTextBox()) {
xPos += static_cast<RenderText *>(o)->minXPos();
yPos += static_cast<RenderText *>(o)->firstTextBox()->root()->topOverflow();
} else {
xPos += o->xPos();
yPos += o->yPos();
}
point.move(static_cast<RenderText *>(o)->minXPos(),
static_cast<RenderText *>(o)->firstTextBox()->root()->topOverflow());
} else
point.move(o->xPos(), o->yPos());
return true;
}
}
// If the target doesn't have any children or siblings that could be used to calculate the scroll position, we must be
// at the end of the document. Scroll to the bottom.
// at the end of the document. Scroll to the bottom. FIXME: who said anything about scrolling?
if (!o && document()->view()) {
yPos += document()->view()->contentsHeight();
point = FloatPoint(0, document()->view()->contentsHeight());
return true;
}
return false;
}
bool ContainerNode::getLowerRightCorner(int &xPos, int &yPos) const
// FIXME: This doesn't work correctly with transforms.
bool ContainerNode::getLowerRightCorner(FloatPoint& point) const
{
if (!renderer())
return false;
RenderObject *o = renderer();
xPos = yPos = 0;
if (!o->isInline() || o->isReplaced())
{
o->absolutePosition(xPos, yPos);
xPos += o->width();
yPos += o->height() + o->borderTopExtra() + o->borderBottomExtra();
point = o->localToAbsolute();
point.move(o->width(),
o->height() + o->borderTopExtra() + o->borderBottomExtra());
return true;
}
// find the last text/image child, to get a position
while(o) {
if(o->lastChild())
while (o) {
if (o->lastChild())
o = o->lastChild();
else if(o->previousSibling())
else if (o->previousSibling())
o = o->previousSibling();
else {
RenderObject *prev = 0;
while(!prev) {
o = o->parent();
if(!o) return false;
if (!o)
return false;
prev = o->previousSibling();
}
o = prev;
}
if (o->isText() || o->isReplaced()) {
o->container()->absolutePosition(xPos, yPos);
point = o->container()->localToAbsolute();
int xOffset;
if (o->isText())
xPos += static_cast<RenderText *>(o)->minXPos() + o->width();
xOffset = static_cast<RenderText *>(o)->minXPos() + o->width();
else
xPos += o->xPos()+o->width();
yPos += o->yPos()+o->height();
xOffset = o->xPos() + o->width();
point.move(xOffset, o->yPos() + o->height());
return true;
}
}
......@@ -752,29 +756,24 @@ bool ContainerNode::getLowerRightCorner(int &xPos, int &yPos) const
IntRect ContainerNode::getRect() const
{
int xPos = 0, yPos = 0, xEnd = 0, yEnd = 0;
bool foundUpperLeft = getUpperLeftCorner(xPos,yPos);
bool foundLowerRight = getLowerRightCorner(xEnd,yEnd);
FloatPoint upperLeft, lowerRight;
bool foundUpperLeft = getUpperLeftCorner(upperLeft);
bool foundLowerRight = getLowerRightCorner(lowerRight);
// If we've found one corner, but not the other,
// then we should just return a point at the corner that we did find.
if (foundUpperLeft != foundLowerRight)
{
if (foundUpperLeft) {
xEnd = xPos;
yEnd = yPos;
} else {
xPos = xEnd;
yPos = yEnd;
}
if (foundUpperLeft)
lowerRight = upperLeft;
else
upperLeft = lowerRight;
}
if (xEnd < xPos)
xEnd = xPos;
if (yEnd < yPos)
yEnd = yPos;
return IntRect(xPos, yPos, xEnd - xPos, yEnd - yPos);
lowerRight.setX(max(upperLeft.x(), lowerRight.x()));
lowerRight.setY(max(upperLeft.y(), lowerRight.y()));
return enclosingIntRect(FloatRect(upperLeft, lowerRight - upperLeft));
}
void ContainerNode::setFocus(bool received)
......
......@@ -25,6 +25,7 @@
#define ContainerNode_h
#include "EventTargetNode.h"
#include "FloatPoint.h"
namespace WebCore {
......@@ -89,8 +90,8 @@ protected:
private:
static void dispatchPostAttachCallbacks();
bool getUpperLeftCorner(int& x, int& y) const;
bool getLowerRightCorner(int& x, int& y) const;
bool getUpperLeftCorner(FloatPoint&) const;
bool getLowerRightCorner(FloatPoint&) const;
Node* m_firstChild;
Node* m_lastChild;
......
......@@ -133,11 +133,11 @@ void MouseRelatedEvent::receivedTarget()
// Adjust offsetX/Y to be relative to the target's position.
if (!isSimulated()) {
if (RenderObject* r = targ->renderer()) {
int rx, ry;
if (r->absolutePosition(rx, ry)) {
m_offsetX -= rx;
m_offsetY -= ry;
}
// FIXME: This doesn't work correctly with transforms. We need
// an absoluteToLocal() method.
FloatPoint absPos = r->localToAbsolute();
m_offsetX -= absPos.x();
m_offsetY -= absPos.y();
}
}
......
......@@ -409,10 +409,12 @@ bool Node::shouldUseInputMethod() const
IntRect Node::getRect() const
{
int _x, _y;
if (renderer() && renderer()->absolutePosition(_x, _y))
return IntRect( _x, _y, renderer()->width(), renderer()->height() + renderer()->borderTopExtra() + renderer()->borderBottomExtra());
// FIXME: broken with transforms
if (renderer()) {
FloatPoint absPos = renderer()->localToAbsolute();
return IntRect(roundedIntPoint(absPos),
IntSize(renderer()->width(), renderer()->height() + renderer()->borderTopExtra() + renderer()->borderBottomExtra()));
}
return IntRect();
}
......
......@@ -740,9 +740,9 @@ void SelectionController::layout()
ASSERT(pos.deepEquivalent().node()->renderer());
m_caretRect = pos.caretRect();
int x, y;
pos.deepEquivalent().node()->renderer()->absolutePositionForContent(x, y);
m_caretPositionOnLayout = IntPoint(x, y);
// FIXME: broken with transforms
FloatPoint absPos = pos.deepEquivalent().node()->renderer()->localToAbsoluteForContent(FloatPoint());
m_caretPositionOnLayout = roundedIntPoint(absPos);
}
}
......@@ -757,9 +757,8 @@ IntRect SelectionController::caretRect() const
IntRect caret = m_caretRect;
if (m_sel.start().node() && m_sel.start().node()->renderer()) {
int x, y;
m_sel.start().node()->renderer()->absolutePositionForContent(x, y);
caret.move(IntPoint(x, y) - m_caretPositionOnLayout);
FloatPoint absPos = m_sel.start().node()->renderer()->localToAbsoluteForContent(FloatPoint());
caret.move(roundedIntPoint(absPos) - m_caretPositionOnLayout);
}
return caret;
......
......@@ -493,16 +493,15 @@ VisiblePosition previousLinePosition(const VisiblePosition &visiblePosition, int
}
if (root) {
// FIXME: Can be wrong for multi-column layout.
int absx, absy;
containingBlock->absolutePositionForContent(absx, absy);
// FIXME: Can be wrong for multi-column layout, and with transforms
FloatPoint absPos = containingBlock->localToAbsoluteForContent(FloatPoint());
if (containingBlock->hasOverflowClip())
containingBlock->layer()->subtractScrollOffset(absx, absy);
RenderObject *renderer = root->closestLeafChildForXPos(x - absx, isEditablePosition(p))->object();
absPos -= containingBlock->layer()->scrolledContentOffset();
RenderObject *renderer = root->closestLeafChildForXPos(x - absPos.x(), isEditablePosition(p))->object();
Node* node = renderer->element();
if (editingIgnoresContent(node))
return Position(node->parent(), node->nodeIndex());
return renderer->positionForCoordinates(x - absx, root->topOverflow());
return renderer->positionForCoordinates(x - absPos.x(), root->topOverflow());
}
// Could not find a previous line. This means we must already be on the first line.
......@@ -595,16 +594,15 @@ VisiblePosition nextLinePosition(const VisiblePosition &visiblePosition, int x)
}
if (root) {
// FIXME: Can be wrong for multi-column layout.
int absx, absy;
containingBlock->absolutePositionForContent(absx, absy);
// FIXME: Can be wrong for multi-column layout and with transforms
FloatPoint absPos = containingBlock->localToAbsoluteForContent(FloatPoint());
if (containingBlock->hasOverflowClip())
containingBlock->layer()->subtractScrollOffset(absx, absy);
RenderObject *renderer = root->closestLeafChildForXPos(x - absx, isEditablePosition(p))->object();
absPos -= containingBlock->layer()->scrolledContentOffset();
RenderObject *renderer = root->closestLeafChildForXPos(x - absPos.x(), isEditablePosition(p))->object();
Node* node = renderer->element();
if (editingIgnoresContent(node))
return Position(node->parent(), node->nodeIndex());
return renderer->positionForCoordinates(x - absx, root->topOverflow());
return renderer->positionForCoordinates(x - absPos.x(), root->topOverflow());
}
// Could not find a next line. This means we must already be on the last line.
......
......@@ -115,9 +115,8 @@ bool HTMLAnchorElement::isKeyboardFocusable(KeyboardEvent* event) const
return true;
Vector<IntRect> rects;
int x, y;
renderer()->absolutePosition(x, y);
renderer()->absoluteRects(rects, x, y);
FloatPoint absPos = renderer()->localToAbsolute();
renderer()->absoluteRects(rects, absPos.x(), absPos.y());
size_t n = rects.size();
for (size_t i = 0; i < n; ++i)
if (!rects[i].isEmpty())
......@@ -200,10 +199,10 @@ void HTMLAnchorElement::defaultEventHandler(Event* evt)
if (img && img->isServerMap()) {
RenderImage* r = static_cast<RenderImage*>(img->renderer());
if (r && e) {
int absx, absy;
r->absolutePosition(absx, absy);
int x = e->pageX() - absx;
int y = e->pageY() - absy;
// FIXME: broken with transforms
FloatPoint absPos = r->localToAbsolute();
int x = e->pageX() - absPos.x();
int y = e->pageY() - absPos.y();
url += "?";
url += String::number(x);
url += ",";
......
......@@ -86,10 +86,10 @@ bool HTMLAreaElement::mapMouseEvent(int x, int y, const IntSize& size, HitTestRe
IntRect HTMLAreaElement::getRect(RenderObject* obj) const
{
int dx, dy;
obj->absolutePosition(dx, dy);
// FIXME: This doesn't work correctly with transforms.
FloatPoint absPos = obj->localToAbsolute();
Path p = getRegion(m_lastSize);
p.translate(IntSize(dx, dy));
p.translate(absPos - FloatPoint());
return enclosingIntRect(p.boundingRect());
}
......
......@@ -407,9 +407,10 @@ int HTMLImageElement::x() const
RenderObject* r = renderer();
if (!r)
return 0;
int x, y;
r->absolutePosition(x, y);
return x;
// FIXME: This doesn't work correctly with transforms.
FloatPoint absPos = r->localToAbsolute();
return absPos.x();
}
int HTMLImageElement::y() const
......@@ -417,9 +418,10 @@ int HTMLImageElement::y() const
RenderObject* r = renderer();
if (!r)
return 0;
int x, y;
r->absolutePosition(x, y);
return y;
// FIXME: This doesn't work correctly with transforms.
FloatPoint absPos = r->localToAbsolute();
return absPos.y();
}
bool HTMLImageElement::complete() const
......
......@@ -1183,11 +1183,10 @@ void HTMLInputElement::defaultEventHandler(Event* evt)
xPos = 0;
yPos = 0;
} else {
int offsetX, offsetY;
renderer()->absolutePosition(offsetX, offsetY);
xPos = me->pageX() - offsetX;
// FIXME: Why is yPos a short?
yPos = me->pageY() - offsetY;
// FIXME: This doesn't work correctly with transforms.
IntPoint absOffset = roundedIntPoint(renderer()->localToAbsolute());
xPos = me->pageX() - absOffset.x();
yPos = me->pageY() - absOffset.y();
}
}
......
......@@ -228,9 +228,9 @@ private:
String m_value;
String m_originalValue;
int xPos;
int yPos;
int m_maxLen;
short m_size;
short yPos;
int m_size;
short m_maxResults;
......
......@@ -920,9 +920,8 @@ IntRect AccessibilityRenderObject::boundingBoxRect() const
// FIXME: This doesn't work correctly with transforms.
Vector<IntRect> rects;
int x, y;
obj->absolutePosition(x, y);
obj->absoluteRects(rects, x, y);
FloatPoint absPos = obj->localToAbsolute();
obj->absoluteRects(rects, absPos.x(), absPos.y());
const size_t n = rects.size();
for (size_t i = 0; i < n; ++i) {
IntRect r = rects[i];
......
......@@ -2023,10 +2023,10 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event)
// Check to see if the is a DOM based drag, if it is get the DOM specified drag
// image and offset
if (dragState().m_dragSrcIsDHTML) {
int srcX, srcY;
if (RenderObject* renderer = dragState().m_dragSrc->renderer()) {
renderer->absolutePosition(srcX, srcY);
IntSize delta = m_mouseDownPos - IntPoint(srcX, srcY);
// FIXME: This doesn't work correctly with transforms.
FloatPoint absPos = renderer->localToAbsolute();
IntSize delta = m_mouseDownPos - roundedIntPoint(absPos);
dragState().m_dragClipboard->setDragImageElement(dragState().m_dragSrc.get(), IntPoint() + delta);
} else {
// The renderer has disappeared, this can happen if the onStartDrag handler has hidden
......
......@@ -28,6 +28,7 @@
#define FloatPoint_h
#include "FloatSize.h"
#include "IntPoint.h"
#include <wtf/Platform.h>
#if PLATFORM(CG)
......@@ -146,6 +147,11 @@ inline bool operator!=(const FloatPoint& a, const FloatPoint& b)
return a.x() != b.x() || a.y() != b.y();
}
inline IntPoint roundedIntPoint(const FloatPoint& p)
{
return IntPoint(static_cast<int>(roundf(p.x())), static_cast<int>(roundf(p.y())));
}
}
#endif
......@@ -67,6 +67,12 @@ public:
bool isEmpty() const { return m_width <= 0 || m_height <= 0; }
void expand(int width, int height)
{
m_width += width;
m_height += height;
}
IntSize expandedTo(const IntSize& other) const
{
return IntSize(m_width > other.m_width ? m_width : other.m_width,
......
......@@ -40,20 +40,15 @@ LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize&
bool fixed = renderer->isPositioned() && renderer->style()->position() == FixedPosition;
if (fixed) {
int fixedX = 0;
int fixedY = 0;
renderer->view()->absolutePosition(fixedX, fixedY, true);
m_offset = IntSize(fixedX, fixedY) + offset;
// FIXME: This doesn't work correctly with transforms.
FloatPoint fixedOffset = renderer->view()->localToAbsolute(FloatPoint(), true);
m_offset = IntSize(fixedOffset.x(), fixedOffset.y()) + offset;
} else
m_offset = prev->m_offset + offset;
if (renderer->isRelPositioned()) {
if (renderer->hasLayer()) {
int relX = 0;
int relY = 0;
renderer->layer()->relativePositionOffset(relX, relY);
m_offset += IntSize(relX, relY);
}
if (renderer->hasLayer())
m_offset += renderer->layer()->relativePositionOffset();