Fix for 3673381, huge directory listing so slow it seems like a hang. Rework painti...
authorhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 Nov 2004 05:08:20 +0000 (05:08 +0000)
committerhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 Nov 2004 05:08:20 +0000 (05:08 +0000)
it crawls the line box tree instead of the render tree.  This allows more precise intersection/containment testing
that lets us short circuit earlier when painting and hit testing.

        Reviewed by mjs

        * khtml/khtml_part.cpp:
        (KHTMLPart::isPointInsideSelection):
        * khtml/rendering/render_block.cpp:
        (khtml::RenderBlock::paint):
        (khtml::RenderBlock::paintChildren):
        (khtml::RenderBlock::paintObject):
        (khtml::RenderBlock::paintFloats):
        (khtml::RenderBlock::nodeAtPoint):
        * khtml/rendering/render_block.h:
        * khtml/rendering/render_box.cpp:
        (RenderBox::nodeAtPoint):
        * khtml/rendering/render_box.h:
        * khtml/rendering/render_br.h:
        * khtml/rendering/render_canvas.cpp:
        (RenderCanvas::paint):
        * khtml/rendering/render_flow.cpp:
        (RenderFlow::paintLines):
        (RenderFlow::hitTestLines):
        (RenderFlow::caretRect):
        (RenderFlow::addFocusRingRects):
        (RenderFlow::paintFocusRing):
        (RenderFlow::paintOutlines):
        (RenderFlow::paintOutlineForLine):
        * khtml/rendering/render_flow.h:
        * khtml/rendering/render_frames.cpp:
        (RenderFrameSet::nodeAtPoint):
        * khtml/rendering/render_frames.h:
        * khtml/rendering/render_image.cpp:
        (RenderImage::nodeAtPoint):
        * khtml/rendering/render_image.h:
        * khtml/rendering/render_inline.cpp:
        (RenderInline::paint):
        (RenderInline::nodeAtPoint):
        * khtml/rendering/render_inline.h:
        * khtml/rendering/render_layer.cpp:
        (RenderLayer::paintLayer):
        (RenderLayer::hitTest):
        (RenderLayer::hitTestLayer):
        * khtml/rendering/render_layer.h:
        * khtml/rendering/render_line.cpp:
        (khtml::InlineBox::paint):
        (khtml::InlineBox::nodeAtPoint):
        (khtml::InlineFlowBox::flowObject):
        (khtml::InlineFlowBox::nodeAtPoint):
        (khtml::InlineFlowBox::paint):
        (khtml::InlineFlowBox::paintBackgrounds):
        (khtml::InlineFlowBox::paintBackground):
        (khtml::InlineFlowBox::paintBackgroundAndBorder):
        (khtml::InlineFlowBox::paintDecorations):
        (khtml::EllipsisBox::paint):
        (khtml::EllipsisBox::nodeAtPoint):
        (khtml::RootInlineBox::paintEllipsisBox):
        (khtml::RootInlineBox::paint):
        (khtml::RootInlineBox::nodeAtPoint):
        * khtml/rendering/render_line.h:
        (khtml::InlineRunBox::paintBackgroundAndBorder):
        * khtml/rendering/render_object.cpp:
        (RenderObject::hitTest):
        (RenderObject::setInnerNode):
        (RenderObject::nodeAtPoint):
        * khtml/rendering/render_object.h:
        (khtml::RenderObject::PaintInfo::PaintInfo):
        (khtml::RenderObject::PaintInfo::~PaintInfo):
        (khtml::RenderObject::paintingRootForChildren):
        (khtml::RenderObject::shouldPaintWithinRoot):
        * khtml/rendering/render_table.cpp:
        (RenderTable::layout):
        (RenderTable::paint):
        * khtml/rendering/render_text.cpp:
        (simpleDifferenceBetweenColors):
        (correctedTextColor):
        (InlineTextBox::nodeAtPoint):
        (InlineTextBox::paint):
        (InlineTextBox::selectionStartEnd):
        (InlineTextBox::paintSelection):
        (InlineTextBox::paintMarkedTextBackground):
        (InlineTextBox::paintDecoration):
        (RenderText::posOfChar):
        * khtml/rendering/render_text.h:
        (khtml::RenderText::paint):
        (khtml::RenderText::layout):
        (khtml::RenderText::nodeAtPoint):
        * khtml/xml/dom2_eventsimpl.cpp:
        (MouseEventImpl::computeLayerPos):
        * khtml/xml/dom_docimpl.cpp:
        (DocumentImpl::prepareMouseEvent):
        * kwq/KWQAccObject.mm:
        (-[KWQAccObject accessibilityHitTest:]):
        * kwq/KWQKHTMLPart.mm:
        (KWQKHTMLPart::scrollOverflowWithScrollWheelEvent):
        (KWQKHTMLPart::eventMayStartDrag):
        (KWQKHTMLPart::khtmlMouseMoveEvent):
        * kwq/WebCoreBridge.mm:
        (-[WebCoreBridge elementAtPoint:]):
        (-[WebCoreBridge _positionForPoint:]):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@8070 268f45cc-cd09-0410-ab3c-d52691b4dbfc

30 files changed:
WebCore/ChangeLog-2005-08-23
WebCore/khtml/khtml_part.cpp
WebCore/khtml/rendering/render_block.cpp
WebCore/khtml/rendering/render_block.h
WebCore/khtml/rendering/render_box.cpp
WebCore/khtml/rendering/render_box.h
WebCore/khtml/rendering/render_br.h
WebCore/khtml/rendering/render_canvas.cpp
WebCore/khtml/rendering/render_flow.cpp
WebCore/khtml/rendering/render_flow.h
WebCore/khtml/rendering/render_frames.cpp
WebCore/khtml/rendering/render_frames.h
WebCore/khtml/rendering/render_image.cpp
WebCore/khtml/rendering/render_image.h
WebCore/khtml/rendering/render_inline.cpp
WebCore/khtml/rendering/render_inline.h
WebCore/khtml/rendering/render_layer.cpp
WebCore/khtml/rendering/render_layer.h
WebCore/khtml/rendering/render_line.cpp
WebCore/khtml/rendering/render_line.h
WebCore/khtml/rendering/render_object.cpp
WebCore/khtml/rendering/render_object.h
WebCore/khtml/rendering/render_table.cpp
WebCore/khtml/rendering/render_text.cpp
WebCore/khtml/rendering/render_text.h
WebCore/khtml/xml/dom2_eventsimpl.cpp
WebCore/khtml/xml/dom_docimpl.cpp
WebCore/kwq/KWQAccObject.mm
WebCore/kwq/KWQKHTMLPart.mm
WebCore/kwq/WebCoreBridge.mm

index 39d04e3f9c257f37d3be8268345bb29302f4709f..e4c5f18275e05e17695875fb34edeb20d9460f5f 100644 (file)
@@ -1,3 +1,107 @@
+2004-11-22  David Hyatt  <hyatt@apple.com>
+
+       Fix for 3673381, huge directory listing so slow it seems like a hang.  Rework painting and hit testing so that
+       it crawls the line box tree instead of the render tree.  This allows more precise intersection/containment testing
+       that lets us short circuit earlier when painting and hit testing.
+       
+        Reviewed by mjs
+
+        * khtml/khtml_part.cpp:
+        (KHTMLPart::isPointInsideSelection):
+        * khtml/rendering/render_block.cpp:
+        (khtml::RenderBlock::paint):
+        (khtml::RenderBlock::paintChildren):
+        (khtml::RenderBlock::paintObject):
+        (khtml::RenderBlock::paintFloats):
+        (khtml::RenderBlock::nodeAtPoint):
+        * khtml/rendering/render_block.h:
+        * khtml/rendering/render_box.cpp:
+        (RenderBox::nodeAtPoint):
+        * khtml/rendering/render_box.h:
+        * khtml/rendering/render_br.h:
+        * khtml/rendering/render_canvas.cpp:
+        (RenderCanvas::paint):
+        * khtml/rendering/render_flow.cpp:
+        (RenderFlow::paintLines):
+        (RenderFlow::hitTestLines):
+        (RenderFlow::caretRect):
+        (RenderFlow::addFocusRingRects):
+        (RenderFlow::paintFocusRing):
+        (RenderFlow::paintOutlines):
+        (RenderFlow::paintOutlineForLine):
+        * khtml/rendering/render_flow.h:
+        * khtml/rendering/render_frames.cpp:
+        (RenderFrameSet::nodeAtPoint):
+        * khtml/rendering/render_frames.h:
+        * khtml/rendering/render_image.cpp:
+        (RenderImage::nodeAtPoint):
+        * khtml/rendering/render_image.h:
+        * khtml/rendering/render_inline.cpp:
+        (RenderInline::paint):
+        (RenderInline::nodeAtPoint):
+        * khtml/rendering/render_inline.h:
+        * khtml/rendering/render_layer.cpp:
+        (RenderLayer::paintLayer):
+        (RenderLayer::hitTest):
+        (RenderLayer::hitTestLayer):
+        * khtml/rendering/render_layer.h:
+        * khtml/rendering/render_line.cpp:
+        (khtml::InlineBox::paint):
+        (khtml::InlineBox::nodeAtPoint):
+        (khtml::InlineFlowBox::flowObject):
+        (khtml::InlineFlowBox::nodeAtPoint):
+        (khtml::InlineFlowBox::paint):
+        (khtml::InlineFlowBox::paintBackgrounds):
+        (khtml::InlineFlowBox::paintBackground):
+        (khtml::InlineFlowBox::paintBackgroundAndBorder):
+        (khtml::InlineFlowBox::paintDecorations):
+        (khtml::EllipsisBox::paint):
+        (khtml::EllipsisBox::nodeAtPoint):
+        (khtml::RootInlineBox::paintEllipsisBox):
+        (khtml::RootInlineBox::paint):
+        (khtml::RootInlineBox::nodeAtPoint):
+        * khtml/rendering/render_line.h:
+        (khtml::InlineRunBox::paintBackgroundAndBorder):
+        * khtml/rendering/render_object.cpp:
+        (RenderObject::hitTest):
+        (RenderObject::setInnerNode):
+        (RenderObject::nodeAtPoint):
+        * khtml/rendering/render_object.h:
+        (khtml::RenderObject::PaintInfo::PaintInfo):
+        (khtml::RenderObject::PaintInfo::~PaintInfo):
+        (khtml::RenderObject::paintingRootForChildren):
+        (khtml::RenderObject::shouldPaintWithinRoot):
+        * khtml/rendering/render_table.cpp:
+        (RenderTable::layout):
+        (RenderTable::paint):
+        * khtml/rendering/render_text.cpp:
+        (simpleDifferenceBetweenColors):
+        (correctedTextColor):
+        (InlineTextBox::nodeAtPoint):
+        (InlineTextBox::paint):
+        (InlineTextBox::selectionStartEnd):
+        (InlineTextBox::paintSelection):
+        (InlineTextBox::paintMarkedTextBackground):
+        (InlineTextBox::paintDecoration):
+        (RenderText::posOfChar):
+        * khtml/rendering/render_text.h:
+        (khtml::RenderText::paint):
+        (khtml::RenderText::layout):
+        (khtml::RenderText::nodeAtPoint):
+        * khtml/xml/dom2_eventsimpl.cpp:
+        (MouseEventImpl::computeLayerPos):
+        * khtml/xml/dom_docimpl.cpp:
+        (DocumentImpl::prepareMouseEvent):
+        * kwq/KWQAccObject.mm:
+        (-[KWQAccObject accessibilityHitTest:]):
+        * kwq/KWQKHTMLPart.mm:
+        (KWQKHTMLPart::scrollOverflowWithScrollWheelEvent):
+        (KWQKHTMLPart::eventMayStartDrag):
+        (KWQKHTMLPart::khtmlMouseMoveEvent):
+        * kwq/WebCoreBridge.mm:
+        (-[WebCoreBridge elementAtPoint:]):
+        (-[WebCoreBridge _positionForPoint:]):
+
 2004-11-22  Maciej Stachowiak  <mjs@apple.com>
 
         Reviewed by Dave.
index f8f4b07989bbbf9d098be19d08aa234ce45baad8..3bc8b2d33bb63efa4df5d60b1cbf3944aa726ad6 100644 (file)
@@ -4397,7 +4397,7 @@ bool KHTMLPart::isPointInsideSelection(int x, int y)
         return false;
     
     RenderObject::NodeInfo nodeInfo(true, true);
-    xmlDocImpl()->renderer()->layer()->nodeAtPoint(nodeInfo, x, y);
+    xmlDocImpl()->renderer()->layer()->hitTest(nodeInfo, x, y);
     NodeImpl *innerNode = nodeInfo.innerNode();
     if (!innerNode || !innerNode->renderer())
         return false;
index 61c6b8e8ac4f60a8fb2ba141fb9b42bf0e803843..ccfbc39fd634b3dc99e472947f6cf28eba8b6994 100644 (file)
@@ -1178,14 +1178,17 @@ void RenderBlock::paint(PaintInfo& i, int _tx, int _ty)
     _tx += m_x;
     _ty += m_y;
 
-    // check if we need to do anything at all...
-    if (!isRoot() && !isInlineFlow() && !isRelPositioned() && !isPositioned()) {
+    // Check if we need to do anything at all.
+    // FIXME: This check is limited to only the y-coordinates when it could check x as well.
+    // Compacts keep us from being strict about x-direction at the moment.
+    if (!isInlineFlow() && !isRoot()) {
         int h = m_overflowHeight;
         int yPos = _ty;
         if (m_floatingObjects && floatBottom() > h)
             h = floatBottom();
 
-        // Sanity check the first line
+        // FIXME: This is a pretty feeble check that doesn't really work in practice, since top overflow
+        // is not propagated. Sanity check the first line
         // to see if it extended a little above our box. Overflow out the bottom is already handled via
         // overflowHeight(), so we don't need to check that.
         if (m_firstLineBox && m_firstLineBox->topOverflow() < 0)
@@ -1196,41 +1199,16 @@ void RenderBlock::paint(PaintInfo& i, int _tx, int _ty)
             return;
     }
 
-    return RenderBlock::paintObject(i, _tx, _ty);
+    return paintObject(i, _tx, _ty);
 }
 
-void RenderBlock::paintObject(PaintInfo& i, int _tx, int _ty)
+void RenderBlock::paintChildren(PaintInfo& i, int _tx, int _ty)
 {
-    PaintAction paintAction = i.phase;
-
-    // If we're a repositioned run-in, don't paint background/borders.
-    bool inlineFlow = isInlineFlow();
-    bool isPrinting = (i.p->device()->devType() == QInternal::Printer);
-
-    // 1. paint background, borders etc
-    if (!inlineFlow &&
-        (paintAction == PaintActionElementBackground || paintAction == PaintActionChildBackground) &&
-        shouldPaintBackgroundOrBorder() && style()->visibility() == VISIBLE) {
-        paintBoxDecorations(i, _tx, _ty);
-    }
-
-    // We're done.  We don't bother painting any children.
-    if (paintAction == PaintActionElementBackground)
-        return;
     // We don't paint our own background, but we do let the kids paint their backgrounds.
-    if (paintAction == PaintActionChildBackgrounds)
-        paintAction = PaintActionChildBackground;
-    PaintInfo paintInfo(i.p, i.r, paintAction, paintingRootForChildren(i));
-    
-    paintLineBoxBackgroundBorder(paintInfo, _tx, _ty);
+    PaintInfo paintInfo(i.p, i.r, i.phase == PaintActionChildBlockBackgrounds ? PaintActionChildBlockBackground : i.phase,
+                        paintingRootForChildren(i));
+    bool isPrinting = (i.p->device()->devType() == QInternal::Printer);
 
-    // 2. paint contents
-    int scrolledX = _tx;
-    int scrolledY = _ty;
-    if (hasOverflowClip())
-        m_layer->subtractScrollOffset(scrolledX, scrolledY);
-    
-    paintLineBoxDecorations(paintInfo, scrolledX, scrolledY); // Underline/overline
     for (RenderObject *child = firstChild(); child; child = child->nextSibling()) {        
         // Check for page-break-before: always, and if it's set, break and bail.
         if (isPrinting && !childrenInline() && child->style()->pageBreakBefore() == PBALWAYS &&
@@ -1241,7 +1219,7 @@ void RenderBlock::paintObject(PaintInfo& i, int _tx, int _ty)
         }
         
         if (!child->layer() && !child->isFloating())
-            child->paint(paintInfo, scrolledX, scrolledY);
+            child->paint(paintInfo, _tx, _ty);
         
         // Check for page-break-after: always, and if it's set, break and bail.
         if (isPrinting && !childrenInline() && child->style()->pageBreakAfter() == PBALWAYS && 
@@ -1251,28 +1229,55 @@ void RenderBlock::paintObject(PaintInfo& i, int _tx, int _ty)
             return;
         }
     }
-    paintLineBoxDecorations(paintInfo, scrolledX, scrolledY, true); // Strike-through
-    if (!inlineFlow) {
-        paintEllipsisBoxes(paintInfo, scrolledX, scrolledY); // Text overflow ellipsis (...)
-        paintSelection(paintInfo, scrolledX, scrolledY); // Fill in gaps in selection on lines and between blocks.
+}
+
+void RenderBlock::paintObject(PaintInfo& i, int _tx, int _ty)
+{
+    PaintAction paintAction = i.phase;
+
+    // If we're a repositioned run-in or a compact, don't paint background/borders.
+    bool inlineFlow = isInlineFlow();
+
+    // 1. paint background, borders etc
+    if (!inlineFlow &&
+        (paintAction == PaintActionBlockBackground || paintAction == PaintActionChildBlockBackground) &&
+        shouldPaintBackgroundOrBorder() && style()->visibility() == VISIBLE) {
+        paintBoxDecorations(i, _tx, _ty);
     }
 
-    // 3. paint floats.
+    // We're done.  We don't bother painting any children.
+    if (paintAction == PaintActionBlockBackground)
+        return;
+
+    // Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div).s
+    int scrolledX = _tx;
+    int scrolledY = _ty;
+    if (hasOverflowClip())
+        m_layer->subtractScrollOffset(scrolledX, scrolledY);
+
+    // 2. paint contents  
+    if (childrenInline())
+        paintLines(i, scrolledX, scrolledY);
+    else
+        paintChildren(i, scrolledX, scrolledY);
+    
+    // 3. paint selection
+    if (!inlineFlow)
+        paintSelection(i, scrolledX, scrolledY); // Fill in gaps in selection on lines and between blocks.
+
+    // 4. paint floats.
     if (!inlineFlow && (paintAction == PaintActionFloat || paintAction == PaintActionSelection))
-        paintFloats(paintInfo, scrolledX, scrolledY, paintAction == PaintActionSelection);
+        paintFloats(i, scrolledX, scrolledY, paintAction == PaintActionSelection);
 
-    // 4. paint outline.
+    // 5. paint outline.
     if (!inlineFlow && paintAction == PaintActionOutline && 
         style()->outlineWidth() && style()->visibility() == VISIBLE)
         paintOutline(i.p, _tx, _ty, width(), height(), style());
 
-    // 5. paint caret.
-    /*
-        If the caret's node's render object's containing block is this block,
-        and the paint action is PaintActionForeground,
-        then paint the caret.
-    */
-    if (paintAction == PaintActionForeground) {
+    // 6. paint caret.
+    // If the caret's node's render object's containing block is this block, and the paint action is PaintActionForeground,
+    // then paint the caret.
+    if (!inlineFlow && paintAction == PaintActionForeground) {
         const Selection &s = document()->part()->selection();
         NodeImpl *caretNode = s.start().node();
         RenderObject *renderer = caretNode ? caretNode->renderer() : 0;
@@ -1304,12 +1309,12 @@ void RenderBlock::paintFloats(PaintInfo& i, int _tx, int _ty, bool paintSelectio
     for ( ; (r = it.current()); ++it) {
         // Only paint the object if our noPaint flag isn't set.
         if (!r->noPaint && !r->node->layer()) {
-            PaintInfo info(i.p, i.r, paintSelection ? PaintActionSelection : PaintActionElementBackground, i.paintingRoot);
+            PaintInfo info(i.p, i.r, paintSelection ? PaintActionSelection : PaintActionBlockBackground, i.paintingRoot);
             int tx = _tx + r->left - r->node->xPos() + r->node->marginLeft();
             int ty = _ty + r->startY - r->node->yPos() + r->node->marginTop();
             r->node->paint(info, tx, ty);
             if (!paintSelection) {
-                info.phase = PaintActionChildBackgrounds;
+                info.phase = PaintActionChildBlockBackgrounds;
                 r->node->paint(info, tx, ty);
                 info.phase = PaintActionFloat;
                 r->node->paint(info, tx, ty);
@@ -2328,44 +2333,90 @@ bool RenderBlock::isPointInScrollbar(int _x, int _y, int _tx, int _ty)
 }
 
 bool RenderBlock::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
-                              HitTestAction hitTestAction, bool inBox)
+                              HitTestAction hitTestAction)
 {
-    bool inScrollbar = isPointInScrollbar(_x, _y, _tx+xPos(), _ty+yPos());
-    if (inScrollbar && hitTestAction != HitTestChildrenOnly)
-        inBox = true;
+    bool inlineFlow = isInlineFlow();
+
+    int tx = _tx + xPos();
+    int ty = _ty + yPos();
+
+    if (!inlineFlow && !isRoot()) {
+        // Check if we need to do anything at all with this block.
+        // FIXME: This check is limited to only the y-coordinates when it could check x as well.
+        // Compacts keep us from being strict about x-coordinates at the moment.
+        int h = m_overflowHeight;
+        if (m_floatingObjects && floatBottom() > h)
+            h = floatBottom();
+        if (isTableCell())
+            h = kMax(height() + borderTopExtra() + borderBottomExtra(), h);
+        if ((ty > _y) || (ty + h <= _y))
+            return false;
+    }
     
-    if (hitTestAction != HitTestSelfOnly && !inScrollbar) {
-        int stx = _tx + xPos();
-        int sty = _ty + yPos();
-        
-        if (m_floatingObjects) {
-            if (hasOverflowClip())
-                m_layer->subtractScrollOffset(stx, sty);
-            if (isCanvas()) {
-                stx += static_cast<RenderCanvas*>(this)->view()->contentsX();
-                sty += static_cast<RenderCanvas*>(this)->view()->contentsY();
-            }
-            FloatingObject* o;
-            QPtrListIterator<FloatingObject> it(*m_floatingObjects);
-            for (it.toLast(); (o = it.current()); --it)
-                if (!o->noPaint && !o->node->layer())
-                    inBox |= o->node->nodeAtPoint(info, _x, _y,
-                                                  stx+o->left + o->node->marginLeft() - o->node->xPos(),
-                                                  sty+o->startY + o->node->marginTop() - o->node->yPos());
+    if (isTableCell())
+        ty += borderTopExtra();
+
+    // See if we're inside the scrollbar (if we're overflow:scroll/auto).
+    if (isPointInScrollbar(_x, _y, tx, ty)) {
+        if (hitTestAction == HitTestBlockBackground) {
+            setInnerNode(info);
+            return true;
         }
+        return false;
+    }
 
-        if (hasMarkupTruncation()) {
-            for (RootInlineBox* box = lastRootBox(); box; box = box->prevRootBox()) {
-                if (box->ellipsisBox()) {
-                    inBox |= box->hitTestEllipsisBox(info, _x, _y, stx, sty, hitTestAction, inBox);
-                    break;
-                }
+    // Hit test descendants first.
+    int scrolledX = tx;
+    int scrolledY = ty;
+    if (hasOverflowClip())
+        m_layer->subtractScrollOffset(scrolledX, scrolledY);
+    if (childrenInline() && !isTable()) {
+        // We have to hit-test our line boxes.
+        if (hitTestLines(info, _x, _y, scrolledX, scrolledY, hitTestAction)) {
+            setInnerNode(info);
+            return true;
+        }
+    }
+    else {
+        // Hit test our children.
+        HitTestAction childHitTest = hitTestAction;
+        if (hitTestAction == HitTestChildBlockBackgrounds)
+            childHitTest = HitTestChildBlockBackground;
+        for (RenderObject* child = lastChild(); child; child = child->previousSibling())
+            if (!child->layer() && !child->isFloating() && child->nodeAtPoint(info, _x, _y, scrolledX, scrolledY, childHitTest)) {
+                setInnerNode(info);
+                return true;
+            }
+    }
+    
+    // Hit test floats.
+    if (hitTestAction == HitTestFloat && m_floatingObjects) {
+        if (isCanvas()) {
+            scrolledX += static_cast<RenderCanvas*>(this)->view()->contentsX();
+            scrolledY += static_cast<RenderCanvas*>(this)->view()->contentsY();
+        }
+        
+        FloatingObject* o;
+        QPtrListIterator<FloatingObject> it(*m_floatingObjects);
+        for (it.toLast(); (o = it.current()); --it)
+            if (!o->noPaint && !o->node->layer() && o->node->hitTest(info, _x, _y,
+                                     scrolledX + o->left + o->node->marginLeft() - o->node->xPos(),
+                                     scrolledY + o->startY + o->node->marginTop() - o->node->yPos())) {
+                setInnerNode(info);
+                return true;
             }
+    }
+
+    // Now hit test our background.
+    if (!inlineFlow && (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground)) {
+        QRect boundsRect(tx, ty, m_width, m_height);
+        if (isRoot() || (style()->visibility() == VISIBLE && boundsRect.contains(_x, _y))) {
+            setInnerNode(info);
+            return true;
         }
     }
 
-    inBox |= RenderFlow::nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inBox);
-    return inBox;
+    return false;
 }
 
 Position RenderBlock::positionForBox(InlineBox *box, bool start) const
index 7e934d5754f15e6302d90d4362a2fd89c406ee13..3394758d856e55efb2655b373b6e19963aacb7c3 100644 (file)
@@ -135,6 +135,7 @@ public:
     virtual void paint(PaintInfo& i, int tx, int ty);
     void paintObject(PaintInfo& i, int tx, int ty);
     void paintFloats(PaintInfo& i, int _tx, int _ty, bool paintSelection = false);
+    void paintChildren(PaintInfo& i, int _tx, int _ty);
     void paintEllipsisBoxes(PaintInfo& i, int _tx, int _ty);
     void paintSelection(PaintInfo& i, int _tx, int _ty);
     
@@ -175,7 +176,7 @@ public:
     int leftOffset(int y) const { return leftRelOffset(y, leftOffset(), true); }
 
     virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty,
-                             HitTestAction hitTestAction = HitTestAll, bool inside=false);
+                             HitTestAction hitTestAction);
 
     bool isPointInScrollbar(int x, int y, int tx, int ty);
 
index ccd9fd7df3d1e0addd188f17f77b548d6215e380..cfb573b70c63297e09d1166d395c0c382fb5e425 100644 (file)
@@ -199,6 +199,32 @@ int RenderBox::height() const
     return m_height;
 }
 
+// Hit Testing
+bool RenderBox::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
+                            HitTestAction hitTestAction)
+{
+    // Check kids first.
+    _tx += m_x;
+    _ty += m_y;
+    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
+        if (child->nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction)) {
+            setInnerNode(info);
+            return true;
+        }
+    }
+    
+    // Check our bounds next.  For this purpose always assume that we can only be hit in the
+    // foreground phase (which is true for replaced elements like images).
+    if (hitTestAction != HitTestForeground)
+        return false;
+    
+    QRect boundsRect(_tx, _ty, m_width, m_height);
+    if (boundsRect.contains(_x, _y)) {
+        setInnerNode(info);
+        return true;
+    }
+    return false;
+}
 
 // --------------------- painting stuff -------------------------------
 
index 62602b7880e9e607fdd3c97f66eb28bd36db9cb2..200761f4db207c86d93db1f97281e99874d5396b 100644 (file)
@@ -49,6 +49,7 @@ public:
 
     virtual void setStyle(RenderStyle *style);
     virtual void paint(PaintInfo& i, int _tx, int _ty);
+    virtual bool nodeAtPoint(NodeInfo& i, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction);
 
     virtual void detach();
     
index 0e9c533130ff1e1099a23197fa0a43f9779ef822..0e54c4b884a889a484a5cd6532097dfa35f06749 100644 (file)
@@ -44,8 +44,6 @@ public:
  
     virtual QRect selectionRect() { return QRect(); }
 
-    virtual void paint(PaintInfo& i, int tx, int ty) {};
-
     virtual unsigned int width(unsigned int, unsigned int, const Font *) const { return 0; }
     virtual unsigned int width( unsigned int, unsigned int, bool) const { return 0; }
 
index fe90a49be0daabc7ca96ff6a2385c1f907116ec6..a4a55e8ff31fad74eb50cfc75a193054ff74d1fd 100644 (file)
@@ -202,7 +202,7 @@ void RenderCanvas::paint(PaintInfo& i, int _tx, int _ty)
     kdDebug( 6040 ) << renderName() << "(RenderCanvas) " << this << " ::paintObject() w/h = (" << width() << "/" << height() << ")" << endl;
 #endif
     // 1. paint background, borders etc
-    if (i.phase == PaintActionElementBackground) {
+    if (i.phase == PaintActionBlockBackground) {
         paintBoxDecorations(i, _tx, _ty);
         return;
     }
index 8129961d789b22c0f4bfadd4ed065c3b1aefe8a2..0f388e5ffb7f53b102031fd442d01335c9fb833d 100644 (file)
@@ -335,64 +335,105 @@ InlineBox* RenderFlow::createInlineBox(bool makePlaceHolderBox, bool isRootLineB
     return flowBox;
 }
 
-void RenderFlow::paintLineBoxBackgroundBorder(PaintInfo& i, int _tx, int _ty)
+void RenderFlow::paintLines(PaintInfo& i, int _tx, int _ty)
 {
-    if (!shouldPaintWithinRoot(i))
+    // Only paint during the foreground/selection phases.
+    if (i.phase != PaintActionForeground && i.phase != PaintActionSelection && i.phase != PaintActionOutline)
         return;
 
+    bool inlineFlow = isInlineFlow();
+    if (inlineFlow)
+        KHTMLAssert(m_layer); // The only way a compact/run-in/inline could paint like this is if it has a layer.
+
+    // If we have no lines then we have no work to do.
     if (!firstLineBox())
         return;
-    if (style()->visibility() == VISIBLE && i.phase == PaintActionForeground) {
-        // We can check the first box and last box and avoid painting if we don't
-        // intersect.
-        int yPos = _ty + firstLineBox()->yPos();
-        int h = lastLineBox()->yPos() + lastLineBox()->height() - firstLineBox()->yPos();
-        if( (yPos >= i.r.y() + i.r.height()) || (yPos + h <= i.r.y()))
-            return;
-
-        // See if our boxes intersect with the dirty rect.  If so, then we paint
-        // them.  Note that boxes can easily overlap, so we can't make any assumptions
-        // based off positions of our first line box or our last line box.
-        int xOffsetWithinLineBoxes = 0;
-        for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
-            yPos = _ty + curr->yPos();
-            h = curr->height();
-            if ((yPos < i.r.y() + i.r.height()) && (yPos + h > i.r.y()))
-                curr->paintBackgroundAndBorder(i, _tx, _ty, xOffsetWithinLineBoxes);
-            xOffsetWithinLineBoxes += curr->width();
+
+    // We can check the first box and last box and avoid painting if we don't
+    // intersect.  This is a quick short-circuit that we can take to avoid walking any lines.
+    // FIXME: This check is flawed in two extremely obscure ways.
+    // (1) If some line in the middle has a huge overflow, it might actually extend below the last line.
+    // (2) The overflow from an inline block on a line is not reported to the line.
+    int yPos = firstLineBox()->root()->selectionTop() - maximalOutlineSize(i.phase);
+    int h = maximalOutlineSize(i.phase) + lastLineBox()->root()->selectionTop() + lastLineBox()->root()->selectionHeight() - yPos;
+    yPos += _ty;
+    if ((yPos >= i.r.y() + i.r.height()) || (yPos + h <= i.r.y()))
+        return;
+
+    // See if our root lines intersect with the dirty rect.  If so, then we paint
+    // them.  Note that boxes can easily overlap, so we can't make any assumptions
+    // based off positions of our first line box or our last line box.
+    bool isPrinting = (i.p->device()->devType() == QInternal::Printer);
+    for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextFlowBox()) {
+        if (isPrinting) {
+            // FIXME: This is a feeble effort to avoid splitting a line across two pages.
+            // It is utterly inadequate, and this should not be done at paint time at all.
+            // The whole way objects break across pages needs to be redone.
+            if (_ty + curr->root()->bottomOverflow() > i.r.y() + i.r.height()) {
+                RenderCanvas* canvasObj = canvas();
+                if (_ty + curr->root()->topOverflow() < canvasObj->truncatedAt())
+                    canvasObj->setBestTruncatedAt(_ty + curr->root()->topOverflow(), this);
+                // Let's stop here.
+                break;
+            }
+        }
+
+        yPos = _ty + curr->root()->selectionTop() - maximalOutlineSize(i.phase);
+        h = curr->root()->selectionHeight() + 2 * maximalOutlineSize(i.phase);
+        if ((yPos < i.r.y() + i.r.height()) && (yPos + h > i.r.y()))
+            curr->paint(i, _tx, _ty);
+    }
+
+    if (i.phase == PaintActionOutline && i.outlineObjects) {
+        // FIXME: Will the order in which we added objects to the dictionary be preserved? Probably not.
+        // This means the paint order of outlines will be wrong, although this is a minor issue.
+        QPtrDictIterator<RenderFlow> objects(*i.outlineObjects);
+        for (objects.toFirst(); objects.current(); ++objects) {
+#ifdef APPLE_CHANGES
+            if (objects.current()->style()->outlineStyleIsAuto())
+                objects.current()->paintFocusRing(i.p, _tx, _ty);
+            else
+#endif
+                objects.current()->paintOutlines(i.p, _tx, _ty);
         }
     }
 }
 
-void RenderFlow::paintLineBoxDecorations(PaintInfo& i, int _tx, int _ty, bool paintedChildren)
+bool RenderFlow::hitTestLines(NodeInfo& i, int x, int y, int tx, int ty, HitTestAction hitTestAction)
 {
-    if (!shouldPaintWithinRoot(i))
-        return;
+    if (hitTestAction != HitTestForeground)
+        return false;
 
-    // We only paint line box decorations in strict or almost strict mode.
-    // Otherwise we let the InlineTextBoxes paint their own decorations.
-    if (style()->htmlHacks() || !firstLineBox())
-        return;
+    bool inlineFlow = isInlineFlow();
+    if (inlineFlow)
+        KHTMLAssert(m_layer); // The only way a compact/run-in/inline could paint like this is if it has a layer.
 
-    if (style()->visibility() == VISIBLE && i.phase == PaintActionForeground) {
-        // We can check the first box and last box and avoid painting if we don't
-        // intersect.
-        int yPos = _ty + firstLineBox()->yPos();;
-        int h = lastLineBox()->yPos() + lastLineBox()->height() - firstLineBox()->yPos();
-        if( (yPos >= i.r.y() + i.r.height()) || (yPos + h <= i.r.y()))
-            return;
-
-        // See if our boxes intersect with the dirty rect.  If so, then we paint
-        // them.  Note that boxes can easily overlap, so we can't make any assumptions
-        // based off positions of our first line box or our last line box.
-        for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
-            yPos = _ty + curr->yPos();
-            h = curr->height();
-            if ((yPos < i.r.y() + i.r.height()) && (yPos + h > i.r.y()))
-                curr->paintDecorations(i, _tx, _ty, paintedChildren);
+    // If we have no lines then we have no work to do.
+    if (!firstLineBox())
+        return false;
+
+    // We can check the first box and last box and avoid hit testing if we don't
+    // contain the point.  This is a quick short-circuit that we can take to avoid walking any lines.
+    // FIXME: This check is flawed in two extremely obscure ways.
+    // (1) If some line in the middle has a huge overflow, it might actually extend below the last line.
+    // (2) The overflow from an inline block on a line is not reported to the line.
+    if ((y >= ty + lastLineBox()->root()->bottomOverflow()) || (y < ty + firstLineBox()->root()->topOverflow()))
+        return false;
+
+    // See if our root lines contain the point.  If so, then we hit test
+    // them further.  Note that boxes can easily overlap, so we can't make any assumptions
+    // based off positions of our first line box or our last line box.
+    for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevFlowBox()) {
+        if (y >= ty + curr->root()->topOverflow() && y < ty + curr->root()->bottomOverflow()) {
+            bool inside = curr->nodeAtPoint(i, x, y, tx, ty);
+            if (inside) {
+                setInnerNode(i);
+                return true;
+            }
         }
     }
+    
+    return false;
 }
 
 QRect RenderFlow::getAbsoluteRepaintRect()
@@ -587,3 +628,141 @@ QRect RenderFlow::caretRect(int offset, EAffinity affinity, int *extraWidthToEnd
 
     return QRect(_x, _y, width, height);
 }
+
+#if APPLE_CHANGES
+void RenderFlow::addFocusRingRects(QPainter *p, int _tx, int _ty)
+{
+    for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
+        p->addFocusRingRect(_tx + curr->xPos(), 
+                            _ty + curr->yPos(), 
+                            curr->width(), 
+                            curr->height());
+    }
+    
+    for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+        if (!curr->isText())
+            curr->addFocusRingRects(p, _tx + curr->xPos(), _ty + curr->yPos());
+    }
+    
+    if (continuation())
+        continuation()->addFocusRingRects(p, 
+                                          _tx - containingBlock()->xPos() + continuation()->xPos(),
+                                          _ty - containingBlock()->yPos() + continuation()->yPos());
+}
+
+void RenderFlow::paintFocusRing(QPainter *p, int tx, int ty)
+{
+    int ow = style()->outlineWidth();
+    QColor oc = style()->outlineColor();
+    if (!oc.isValid())
+        oc = style()->color();
+    
+    p->initFocusRing(ow,  style()->outlineOffset(), oc);
+    addFocusRingRects(p, tx, ty);
+    p->drawFocusRing();
+    p->clearFocusRing();
+}
+#endif
+
+void RenderFlow::paintOutlines(QPainter *p, int _tx, int _ty)
+{
+    if (style()->outlineStyle() <= BHIDDEN)
+        return;
+    
+    QPtrList <QRect> rects;
+    rects.setAutoDelete(true);
+    
+    rects.append(new QRect(0,0,0,0));
+    for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
+        rects.append(new QRect(curr->xPos(), curr->yPos(), curr->width(), curr->height()));
+    }
+    rects.append(new QRect(0,0,0,0));
+    
+    for (unsigned int i = 1; i < rects.count() - 1; i++)
+        paintOutlineForLine(p, _tx, _ty, *rects.at(i-1), *rects.at(i), *rects.at(i+1));
+}
+
+void RenderFlow::paintOutlineForLine(QPainter *p, int tx, int ty, const QRect &lastline, const QRect &thisline, const QRect &nextline)
+{
+    int ow = style()->outlineWidth();
+    EBorderStyle os = style()->outlineStyle();
+    QColor oc = style()->outlineColor();
+    if (!oc.isValid())
+        oc = style()->color();
+    
+    int offset = style()->outlineOffset();
+    
+    int t = ty + thisline.top() - offset;
+    int l = tx + thisline.left() - offset;
+    int b = ty + thisline.bottom() + offset + 1;
+    int r = tx + thisline.right() + offset + 1;
+    
+    // left edge
+    drawBorder(p,
+               l - ow,
+               t - (lastline.isEmpty() || thisline.left() < lastline.left() || lastline.right() <= thisline.left() ? ow : 0),
+               l,
+               b + (nextline.isEmpty() || thisline.left() <= nextline.left() || nextline.right() <= thisline.left() ? ow : 0),
+               BSLeft,
+               oc, style()->color(), os,
+               (lastline.isEmpty() || thisline.left() < lastline.left() || lastline.right() <= thisline.left() ? ow : -ow),
+               (nextline.isEmpty() || thisline.left() <= nextline.left() || nextline.right() <= thisline.left() ? ow : -ow),
+               true);
+    
+    // right edge
+    drawBorder(p,
+               r,
+               t - (lastline.isEmpty() || lastline.right() < thisline.right() || thisline.right() <= lastline.left() ? ow : 0),
+               r + ow,
+               b + (nextline.isEmpty() || nextline.right() <= thisline.right() || thisline.right() <= nextline.left() ? ow : 0),
+               BSRight,
+               oc, style()->color(), os,
+               (lastline.isEmpty() || lastline.right() < thisline.right() || thisline.right() <= lastline.left() ? ow : -ow),
+               (nextline.isEmpty() || nextline.right() <= thisline.right() || thisline.right() <= nextline.left() ? ow : -ow),
+               true);
+    // upper edge
+    if ( thisline.left() < lastline.left())
+        drawBorder(p,
+                   l - ow,
+                   t - ow,
+                   QMIN(r+ow, (lastline.isValid()? tx+lastline.left() : 1000000)),
+                   t ,
+                   BSTop, oc, style()->color(), os,
+                   ow,
+                   (lastline.isValid() && tx+lastline.left()+1<r+ow ? -ow : ow),
+                   true);
+    
+    if (lastline.right() < thisline.right())
+        drawBorder(p,
+                   QMAX(lastline.isValid()?tx + lastline.right() + 1:-1000000, l - ow),
+                   t - ow,
+                   r + ow,
+                   t ,
+                   BSTop, oc, style()->color(), os,
+                   (lastline.isValid() && l-ow < tx+lastline.right()+1 ? -ow : ow),
+                   ow,
+                   true);
+    
+    // lower edge
+    if ( thisline.left() < nextline.left())
+        drawBorder(p,
+                   l - ow,
+                   b,
+                   QMIN(r+ow, nextline.isValid()? tx+nextline.left()+1 : 1000000),
+                   b + ow,
+                   BSBottom, oc, style()->color(), os,
+                   ow,
+                   (nextline.isValid() && tx+nextline.left()+1<r+ow? -ow : ow),
+                   true);
+    
+    if (nextline.right() < thisline.right())
+        drawBorder(p,
+                   QMAX(nextline.isValid()?tx+nextline.right()+1:-1000000 , l-ow),
+                   b,
+                   r + ow,
+                   b + ow,
+                   BSBottom, oc, style()->color(), os,
+                   (nextline.isValid() && l-ow < tx+nextline.right()+1? -ow : ow),
+                   ow,
+                   true);
+}
index 19696bddc82dcf51884ca53618f2b33bb00d55dd..a64a57de0eae98eaffe857cb55861aeb24681781 100644 (file)
@@ -72,8 +72,8 @@ public:
     virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun=false);
     virtual void dirtyLineBoxes(bool fullLayout, bool isRootLineBox = false);
     
-    void paintLineBoxBackgroundBorder(PaintInfo& i, int _tx, int _ty);
-    void paintLineBoxDecorations(PaintInfo& i, int _tx, int _ty, bool paintedChildren = false);
+    void paintLines(PaintInfo& i, int _tx, int _ty);
+    bool hitTestLines(NodeInfo& i, int x, int y, int tx, int ty, HitTestAction hitTestAction);
 
     virtual QRect getAbsoluteRepaintRect();
     
@@ -83,6 +83,13 @@ public:
     
     virtual QRect caretRect(int offset, EAffinity affinity = UPSTREAM, int *extraWidthToEndOfLine = 0);
 
+#ifdef APPLE_CHANGES
+    virtual void addFocusRingRects(QPainter *painter, int _tx, int _ty);
+    void paintFocusRing(QPainter *p, int tx, int ty);
+#endif
+    void paintOutlineForLine(QPainter *p, int tx, int ty, const QRect &prevLine, const QRect &thisLine, const QRect &nextLine);
+    void paintOutlines(QPainter *p, int tx, int ty);
+
 protected:
     // An inline can be split with blocks occurring in between the inline content.
     // When this occurs we need a pointer to our next object.  We can basically be
index 6736f8d3a4c46ce4a3f2da385809b3b35e22c876..c1901dfaa2037e84f7feb1fd0ccd893439e25e0c 100644 (file)
@@ -87,13 +87,14 @@ RenderFrameSet::~RenderFrameSet()
 }
 
 bool RenderFrameSet::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
-                                 HitTestAction hitTestAction, bool inside)
+                                 HitTestAction hitTestAction)
 {
-    RenderContainer::nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inside);
+    if (hitTestAction != HitTestForeground)
+        return false;
 
-    inside = m_resizing || canResize(_x, _y);
-
-    if ( inside && element() && !element()->noResize() && !info.readonly()){
+    bool inside = RenderContainer::nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction) || 
+                  m_resizing || canResize(_x, _y);
+    if (inside && element() && !element()->noResize() && !info.readonly()){
         info.setInnerNode(element());
         info.setInnerNonSharedNode(element());
     }
index 57eefd4f8cdf5883525d451efe756b1f6d80223b..ad6940151f5c286e50e0a9e0ec332a9ae9908abd 100644 (file)
@@ -62,7 +62,7 @@ public:
   void setResizing(bool e);
 
   bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty,
-                   HitTestAction hitTestAction = HitTestAll, bool inside=false);
+                   HitTestAction hitTestAction);
 
     DOM::HTMLFrameSetElementImpl *element() const
     { return static_cast<DOM::HTMLFrameSetElementImpl*>(RenderObject::element()); }
index 059bec1c879559544bbb97d414abd8055c1f9a98..2ce7ec5fed7a4387f92381bcd1413903965e7b13 100644 (file)
@@ -481,9 +481,9 @@ HTMLMapElementImpl* RenderImage::imageMap()
 }
 
 bool RenderImage::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
-                              HitTestAction hitTestAction, bool inside)
+                              HitTestAction hitTestAction)
 {
-    inside |= RenderReplaced::nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inside);
+    bool inside = RenderReplaced::nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction);
 
     if (inside && element()) {
         int tx = _tx + m_x;
index 2fd4391ddabc1baec35d8df1c34dd9d4ac60f31f..94af5b6c9872724312326567f170a68a010d8bdb 100644 (file)
@@ -69,7 +69,7 @@ public:
     CachedImage* getImage() const { return image; }
     
     virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty,
-                             HitTestAction hitTestAction = HitTestAll, bool inside=false);
+                             HitTestAction hitTestAction);
     
     virtual int calcReplacedWidth() const;
     virtual int calcReplacedHeight() const;
index 8eeef9c8ce8f54541266f007581df963ebb7747a..a8e19c0c85c6103cbb041f3dff35b4adfc91eb96 100644 (file)
@@ -252,37 +252,7 @@ void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox
 
 void RenderInline::paint(PaintInfo& i, int _tx, int _ty)
 {
-#ifdef DEBUG_LAYOUT
-    //    kdDebug( 6040 ) << renderName() << "(RenderInline) " << this << " ::paintObject() w/h = (" << width() << "/" << height() << ")" << endl;
-#endif
-    
-    // We're done.  We don't bother painting any children.
-    if (i.phase == PaintActionElementBackground)
-        return;
-    
-    // We don't paint our own background, but we do let the kids paint their backgrounds.
-    PaintInfo paintInfo(i.p, i.r, i.phase, paintingRootForChildren(i));
-    if (i.phase == PaintActionChildBackgrounds)
-        paintInfo.phase = PaintActionChildBackground;
-
-    paintLineBoxBackgroundBorder(paintInfo, _tx, _ty);
-    
-    paintLineBoxDecorations(paintInfo, _tx, _ty); // Underline/overline
-    
-    for (RenderObject *child = firstChild(); child; child = child->nextSibling())
-        if(!child->layer() && !child->isFloating())
-            child->paint(paintInfo, _tx, _ty);
-
-    paintLineBoxDecorations(paintInfo, _tx, _ty, true); // Strike-through
-    
-    if (style()->visibility() == VISIBLE && paintInfo.phase == PaintActionOutline) {
-#if APPLE_CHANGES
-        if (style()->outlineStyleIsAuto())
-            paintFocusRing(paintInfo.p, _tx, _ty);
-        else
-#endif
-        paintOutlines(paintInfo.p, _tx, _ty);
-    }
+    paintLines(i, _tx, _ty);
 }
 
 void RenderInline::absoluteRects(QValueList<QRect>& rects, int _tx, int _ty)
@@ -300,150 +270,6 @@ void RenderInline::absoluteRects(QValueList<QRect>& rects, int _tx, int _ty)
                                       _ty - containingBlock()->yPos() + continuation()->yPos());
 }
 
-#if APPLE_CHANGES
-void RenderInline::addFocusRingRects(QPainter *p, int _tx, int _ty)
-{
-    for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
-        p->addFocusRingRect(_tx + curr->xPos(), 
-                            _ty + curr->yPos(), 
-                            curr->width(), 
-                            curr->height());
-    }
-    
-    for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
-        if (!curr->isText())
-            curr->addFocusRingRects(p, _tx + curr->xPos(), _ty + curr->yPos());
-    }
-    
-    if (continuation())
-        continuation()->addFocusRingRects(p, 
-                                          _tx - containingBlock()->xPos() + continuation()->xPos(),
-                                          _ty - containingBlock()->yPos() + continuation()->yPos());
-}
-
-void RenderInline::paintFocusRing(QPainter *p, int tx, int ty)
-{
-    int ow = style()->outlineWidth();
-    if (ow == 0 || m_isContinuation) // Continuations get painted by the original inline.
-        return;
-
-    QColor oc = style()->outlineColor();
-    if (!oc.isValid())
-        oc = style()->color();
-
-    p->initFocusRing(ow,  style()->outlineOffset(), oc);
-    addFocusRingRects(p, tx, ty);
-    p->drawFocusRing();
-    p->clearFocusRing();
-}
-#endif
-
-void RenderInline::paintOutlines(QPainter *p, int _tx, int _ty)
-{
-    if (style()->outlineWidth() == 0 || style()->outlineStyle() <= BHIDDEN)
-        return;
-    
-    QPtrList <QRect> rects;
-    rects.setAutoDelete(true);
-
-    rects.append(new QRect(0,0,0,0));
-    for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
-        rects.append(new QRect(curr->xPos(), curr->yPos(), curr->width(), curr->height()));
-    }
-    rects.append(new QRect(0,0,0,0));
-
-    for (unsigned int i = 1; i < rects.count() - 1; i++)
-        paintOutline(p, _tx, _ty, *rects.at(i-1), *rects.at(i), *rects.at(i+1));
-}
-
-void RenderInline::paintOutline(QPainter *p, int tx, int ty, const QRect &lastline, const QRect &thisline, const QRect &nextline)
-{
-    int ow = style()->outlineWidth();
-    if (ow == 0 || m_isContinuation) // Continuations get painted by the original inline.
-        return;
-    
-    EBorderStyle os = style()->outlineStyle();
-    QColor oc = style()->outlineColor();
-    if (!oc.isValid())
-        oc = style()->color();
-    
-    int offset = style()->outlineOffset();
-    
-    int t = ty + thisline.top() - offset;
-    int l = tx + thisline.left() - offset;
-    int b = ty + thisline.bottom() + offset + 1;
-    int r = tx + thisline.right() + offset + 1;
-    
-    // left edge
-    drawBorder(p,
-               l - ow,
-               t - (lastline.isEmpty() || thisline.left() < lastline.left() || lastline.right() <= thisline.left() ? ow : 0),
-               l,
-               b + (nextline.isEmpty() || thisline.left() <= nextline.left() || nextline.right() <= thisline.left() ? ow : 0),
-               BSLeft,
-               oc, style()->color(), os,
-               (lastline.isEmpty() || thisline.left() < lastline.left() || lastline.right() <= thisline.left() ? ow : -ow),
-               (nextline.isEmpty() || thisline.left() <= nextline.left() || nextline.right() <= thisline.left() ? ow : -ow),
-               true);
-    
-    // right edge
-    drawBorder(p,
-               r,
-               t - (lastline.isEmpty() || lastline.right() < thisline.right() || thisline.right() <= lastline.left() ? ow : 0),
-               r + ow,
-               b + (nextline.isEmpty() || nextline.right() <= thisline.right() || thisline.right() <= nextline.left() ? ow : 0),
-               BSRight,
-               oc, style()->color(), os,
-               (lastline.isEmpty() || lastline.right() < thisline.right() || thisline.right() <= lastline.left() ? ow : -ow),
-               (nextline.isEmpty() || nextline.right() <= thisline.right() || thisline.right() <= nextline.left() ? ow : -ow),
-               true);
-    // upper edge
-    if ( thisline.left() < lastline.left())
-        drawBorder(p,
-                   l - ow,
-                   t - ow,
-                   QMIN(r+ow, (lastline.isValid()? tx+lastline.left() : 1000000)),
-                   t ,
-                   BSTop, oc, style()->color(), os,
-                   ow,
-                   (lastline.isValid() && tx+lastline.left()+1<r+ow ? -ow : ow),
-                   true);
-    
-    if (lastline.right() < thisline.right())
-        drawBorder(p,
-                   QMAX(lastline.isValid()?tx + lastline.right() + 1:-1000000, l - ow),
-                   t - ow,
-                   r + ow,
-                   t ,
-                   BSTop, oc, style()->color(), os,
-                   (lastline.isValid() && l-ow < tx+lastline.right()+1 ? -ow : ow),
-                   ow,
-                   true);
-    
-    // lower edge
-    if ( thisline.left() < nextline.left())
-        drawBorder(p,
-                   l - ow,
-                   b,
-                   QMIN(r+ow, nextline.isValid()? tx+nextline.left()+1 : 1000000),
-                   b + ow,
-                   BSBottom, oc, style()->color(), os,
-                   ow,
-                   (nextline.isValid() && tx+nextline.left()+1<r+ow? -ow : ow),
-                   true);
-    
-    if (nextline.right() < thisline.right())
-        drawBorder(p,
-                   QMAX(nextline.isValid()?tx+nextline.right()+1:-1000000 , l-ow),
-                   b,
-                   r + ow,
-                   b + ow,
-                   BSBottom, oc, style()->color(), os,
-                   (nextline.isValid() && l-ow < tx+nextline.right()+1? -ow : ow),
-                   ow,
-                   true);
-}
-
 void RenderInline::calcMinMaxWidth()
 {
     KHTMLAssert( !minMaxKnown() );
@@ -512,46 +338,9 @@ const char *RenderInline::renderName() const
 }
 
 bool RenderInline::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
-                               HitTestAction hitTestAction, bool inside)
+                               HitTestAction hitTestAction)
 {
-    // Check our kids if our HitTestAction says to.
-    if (hitTestAction != HitTestSelfOnly) {
-        for (RenderObject* child = lastChild(); child; child = child->previousSibling())
-            if (!child->layer() && !child->isFloating() && child->nodeAtPoint(info, _x, _y, _tx, _ty))
-                inside = true;
-    }
-    
-    // Check our line boxes if we're still not inside.
-    if (hitTestAction != HitTestChildrenOnly && !inside && style()->visibility() != HIDDEN) {
-        // See if we're inside one of our line boxes.
-        for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
-            if((_y >=_ty + curr->m_y) && (_y < _ty + curr->m_y + curr->m_height) &&
-               (_x >= _tx + curr->m_x) && (_x <_tx + curr->m_x + curr->m_width) ) {
-                inside = true;
-                break;
-            }
-        }
-    }
-
-    if (inside && element()) {
-        if (info.innerNode() && info.innerNode()->renderer() &&
-            !info.innerNode()->renderer()->isInline()) {
-            // Within the same layer, inlines are ALWAYS fully above blocks.  Change inner node.
-            info.setInnerNode(element());
-
-            // Clear everything else.
-            info.setInnerNonSharedNode(0);
-            info.setURLElement(0);
-        }
-
-        if (!info.innerNode())
-            info.setInnerNode(element());
-
-        if(!info.innerNonSharedNode())
-            info.setInnerNonSharedNode(element());
-    }
-
-    return inside;
+    return hitTestLines(info, _x, _y, _tx, _ty, hitTestAction);
 }
 
 Position RenderInline::positionForCoordinates(int x, int y, EAffinity *affinity)
index fb8d11ed71888f5a2de1cf7372bfb25d14cc2270..3582b0b4e250ab1a2d336d79b9c1b140c46fbecc 100644 (file)
@@ -60,7 +60,7 @@ public:
     virtual void paint(PaintInfo& i, int tx, int ty);
 
     virtual bool nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
-                             HitTestAction hitTestAction = HitTestAll, bool inside=false);
+                             HitTestAction hitTestAction);
     
     virtual void calcMinMaxWidth();
 
@@ -78,17 +78,10 @@ public:
     void absoluteRects(QValueList<QRect>& rects, int _tx, int _ty);
 
     virtual DOM::Position positionForCoordinates(int x, int y, EAffinity * = 0);
-
-#ifdef APPLE_CHANGES
-    virtual void addFocusRingRects(QPainter *painter, int _tx, int _ty);
-    void paintFocusRing(QPainter *p, int tx, int ty);
-#endif
     
 protected:
     static RenderInline* cloneInline(RenderFlow* src);
-    void paintOutline(QPainter *p, int tx, int ty, const QRect &prevLine, const QRect &thisLine, const QRect &nextLine);
-    void paintOutlines(QPainter *p, int tx, int ty);
-    
+
 private:
     bool m_isContinuation : 1; // Whether or not we're a continuation of an inline.
 };
index f247cd588693248feb6daca7358cac483b32d57f..e722c3cdfbea1aa1f5aa7fe083cbd908201c3849 100644 (file)
@@ -825,7 +825,7 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, QPainter *p,
         setClip(p, paintDirtyRect, damageRect);
 
         // Paint the background.
-        RenderObject::PaintInfo info(p, damageRect, PaintActionElementBackground, paintingRootForRenderer);
+        RenderObject::PaintInfo info(p, damageRect, PaintActionBlockBackground, paintingRootForRenderer);
         renderer()->paint(info, x - renderer()->xPos(), y - renderer()->yPos());        
 #if APPLE_CHANGES
         // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
@@ -860,7 +860,7 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, QPainter *p,
         int tx = x - renderer()->xPos();
         int ty = y - renderer()->yPos();
         RenderObject::PaintInfo info(p, clipRectToApply, 
-                                     selectionOnly ? PaintActionSelection : PaintActionChildBackgrounds,
+                                     selectionOnly ? PaintActionSelection : PaintActionChildBlockBackgrounds,
                                      paintingRootForRenderer);
         renderer()->paint(info, tx, ty);
         if (!selectionOnly) {
@@ -895,7 +895,7 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, QPainter *p,
 }
 
 bool
-RenderLayer::nodeAtPoint(RenderObject::NodeInfo& info, int x, int y)
+RenderLayer::hitTest(RenderObject::NodeInfo& info, int x, int y)
 {
 #if APPLE_CHANGES
     // Clear our our scrollbar variable
@@ -903,7 +903,7 @@ RenderLayer::nodeAtPoint(RenderObject::NodeInfo& info, int x, int y)
 #endif
     
     QRect damageRect(m_x, m_y, width(), height());
-    RenderLayer* insideLayer = nodeAtPointForLayer(this, info, x, y, damageRect);
+    RenderLayer* insideLayer = hitTestLayer(this, info, x, y, damageRect);
 
     // Now determine if the result is inside an anchor; make sure an image map wins if
     // it already set URLElement and only use the innermost.
@@ -923,8 +923,8 @@ RenderLayer::nodeAtPoint(RenderObject::NodeInfo& info, int x, int y)
 }
 
 RenderLayer*
-RenderLayer::nodeAtPointForLayer(RenderLayer* rootLayer, RenderObject::NodeInfo& info,
-                                 int xMousePos, int yMousePos, const QRect& hitTestRect)
+RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderObject::NodeInfo& info,
+                          int xMousePos, int yMousePos, const QRect& hitTestRect)
 {
     // Calculate the clip rects we should use.
     QRect layerBounds, bgRect, fgRect;
@@ -943,43 +943,38 @@ RenderLayer::nodeAtPointForLayer(RenderLayer* rootLayer, RenderObject::NodeInfo&
         uint count = m_posZOrderList->count();
         for (int i = count-1; i >= 0; i--) {
             RenderLayer* child = m_posZOrderList->at(i);
-            insideLayer = child->nodeAtPointForLayer(rootLayer, info, xMousePos, yMousePos, hitTestRect);
+            insideLayer = child->hitTestLayer(rootLayer, info, xMousePos, yMousePos, hitTestRect);
             if (insideLayer)
                 return insideLayer;
         }
     }
 
     // Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
-    if (containsPoint(xMousePos, yMousePos, fgRect) &&
-        renderer()->nodeAtPoint(info, xMousePos, yMousePos,
-                                layerBounds.x() - renderer()->xPos(),
-                                layerBounds.y() - renderer()->yPos(),
-                                HitTestChildrenOnly)) {
-
-       // for positioned generated content, we might still not have a
-       // node by the time we get to the layer level, since none of
-       // the content in the layer has an element. So just walk up
-       // the tree.
-         if (!info.innerNode()) {
-           for (RenderObject *r = renderer(); r != NULL; r = r->parent()) { 
-               if (r->element()) {
-                   info.setInnerNode(r->element());
-                   break;
-               }
-           }
-        }
-
-        if (!info.innerNonSharedNode()) {
-            for (RenderObject *r = renderer(); r != NULL; r = r->parent()) { 
-                if (r->element()) {
-                    info.setInnerNonSharedNode(r->element());
-                    break;
-                }
-            }
-        }
-
-
+    if (containsPoint(xMousePos, yMousePos, fgRect) && 
+        renderer()->hitTest(info, xMousePos, yMousePos,
+                            layerBounds.x() - renderer()->xPos(),
+                            layerBounds.y() - renderer()->yPos(), HitTestDescendants)) {
+        // for positioned generated content, we might still not have a
+        // node by the time we get to the layer level, since none of
+        // the content in the layer has an element. So just walk up
+        // the tree.
+        if (!info.innerNode()) {
+            for (RenderObject *r = renderer(); r != NULL; r = r->parent()) { 
+                if (r->element()) {
+                    info.setInnerNode(r->element());
+                    break;
+                }
+            }
+        }
 
+        if (!info.innerNonSharedNode()) {
+             for (RenderObject *r = renderer(); r != NULL; r = r->parent()) { 
+                 if (r->element()) {
+                     info.setInnerNonSharedNode(r->element());
+                     break;
+                 }
+             }
+        }
         return this;
     }
         
@@ -988,7 +983,7 @@ RenderLayer::nodeAtPointForLayer(RenderLayer* rootLayer, RenderObject::NodeInfo&
         uint count = m_negZOrderList->count();
         for (int i = count-1; i >= 0; i--) {
             RenderLayer* child = m_negZOrderList->at(i);
-            insideLayer = child->nodeAtPointForLayer(rootLayer, info, xMousePos, yMousePos, hitTestRect);
+            insideLayer = child->hitTestLayer(rootLayer, info, xMousePos, yMousePos, hitTestRect);
             if (insideLayer)
                 return insideLayer;
         }
@@ -996,10 +991,10 @@ RenderLayer::nodeAtPointForLayer(RenderLayer* rootLayer, RenderObject::NodeInfo&
 
     // Next we want to see if the mouse pos is inside this layer but not any of its children.
     if (containsPoint(xMousePos, yMousePos, bgRect) &&
-        renderer()->nodeAtPoint(info, xMousePos, yMousePos,
-                                layerBounds.x() - renderer()->xPos(),
-                                layerBounds.y() - renderer()->yPos(),
-                                HitTestSelfOnly))
+        renderer()->hitTest(info, xMousePos, yMousePos,
+                            layerBounds.x() - renderer()->xPos(),
+                            layerBounds.y() - renderer()->yPos(),
+                            HitTestSelf))
         return this;
 
     // No luck.
index 50ef0e1dfbf1053e9957c8a90603b06e227c8607..6b15d9bd63d5a4fd44979b2a3cd020caeddeb5bc 100644 (file)
@@ -233,10 +233,10 @@ public:
 
     // The two main functions that use the layer system.  The paint method
     // paints the layers that intersect the damage rect from back to
-    // front.  The nodeAtPoint method looks for mouse events by walking
+    // front.  The hitTest method looks for mouse events by walking
     // layers that intersect the point from front to back.
     void paint(QPainter *p, const QRect& damageRect, bool selectionOnly=false, RenderObject *paintingRoot=0);
-    bool nodeAtPoint(RenderObject::NodeInfo& info, int x, int y);
+    bool hitTest(RenderObject::NodeInfo& info, int x, int y);
 
     // This method figures out our layerBounds in coordinates relative to
     // |rootLayer}.  It also computes our background and foreground clip rects
@@ -277,9 +277,8 @@ private:
 
     void paintLayer(RenderLayer* rootLayer, QPainter *p, const QRect& paintDirtyRect, 
                     bool haveTransparency, bool selectionOnly, RenderObject *paintingRoot);
-    RenderLayer* nodeAtPointForLayer(RenderLayer* rootLayer, RenderObject::NodeInfo& info,
-                                     int x, int y, const QRect& hitTestRect);
-
+    RenderLayer* hitTestLayer(RenderLayer* rootLayer, RenderObject::NodeInfo& info,
+                              int x, int y, const QRect& hitTestRect);
     void computeScrollDimensions(bool* needHBar = 0, bool* needVBar = 0);
     
 protected:   
index e2cd3b7f83c1f2da8fcaf045b873c123f3dba144..bd75409d51109683a4c1607c0afbdde981cab8fc 100644 (file)
@@ -63,9 +63,8 @@ public:
         m_markupBox = markupBox;
     }
     
-    void paint(RenderObject::PaintInfo& i, int _tx, int _ty);
-    bool nodeAtPoint(RenderObject::NodeInfo& info, int _x, int _y, int _tx, int _ty,
-                     HitTestAction hitTestAction, bool inBox);
+    virtual void paint(RenderObject::PaintInfo& i, int _tx, int _ty);
+    virtual bool nodeAtPoint(RenderObject::NodeInfo& info, int _x, int _y, int _tx, int _ty);
 
 private:
     DOM::AtomicString m_str;
@@ -153,6 +152,37 @@ void InlineBox::adjustPosition(int dx, int dy)
         m_object->setPos(m_object->xPos() + dx, m_object->yPos() + dy);
 }
 
+void InlineBox::paint(RenderObject::PaintInfo& i, int tx, int ty)
+{
+    if (!object()->shouldPaintWithinRoot(i) || i.phase == PaintActionOutline)
+        return;
+
+    // Paint all phases of replaced elements atomically, as though the replaced element established its
+    // own stacking context.  (See Appendix E.2, section 6.4 on inline block/table elements in the CSS2.1
+    // specification.)
+    bool paintSelectionOnly = i.phase == PaintActionSelection;
+    RenderObject::PaintInfo info(i.p, i.r, paintSelectionOnly ? i.phase : PaintActionBlockBackground, i.paintingRoot);
+    object()->paint(info, tx, ty);
+    if (!paintSelectionOnly) {
+        info.phase = PaintActionChildBlockBackgrounds;
+        object()->paint(info, tx, ty);
+        info.phase = PaintActionFloat;
+        object()->paint(info, tx, ty);
+        info.phase = PaintActionForeground;
+        object()->paint(info, tx, ty);
+        info.phase = PaintActionOutline;
+        object()->paint(info, tx, ty);
+    }
+}
+
+bool InlineBox::nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty)
+{
+    // Hit test all phases of replaced elements atomically, as though the replaced element established its
+    // own stacking context.  (See Appendix E.2, section 6.4 on inline block/table elements in the CSS2.1
+    // specification.)
+    return object()->hitTest(i, x, y, tx, ty);
+}
+
 RootInlineBox* InlineBox::root()
 { 
     if (m_parent)
@@ -240,6 +270,11 @@ int InlineBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool
     return -1;
 }
 
+RenderFlow* InlineFlowBox::flowObject()
+{
+    return static_cast<RenderFlow*>(m_object);
+}
+
 int InlineFlowBox::marginLeft()
 {
     if (!includeLeftEdge())
@@ -691,17 +726,77 @@ void InlineFlowBox::shrinkBoxesWithNoTextChildren(int topPos, int bottomPos)
     }
 }
 
+bool InlineFlowBox::nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty)
+{
+    // Check children first.
+    for (InlineBox* curr = lastChild(); curr; curr = curr->prevOnLine()) {
+        if (!curr->object()->layer() && curr->nodeAtPoint(i, x, y, tx, ty)) {
+            object()->setInnerNode(i);
+            return true;
+        }
+    }
+
+    // Now check ourselves.
+    QRect rect(tx + m_x, ty + m_y, m_width, m_height);
+    if (object()->style()->visibility() == VISIBLE && rect.contains(x, y)) {
+        object()->setInnerNode(i);
+        return true;
+    }
+    
+    return false;
+}
+
+void InlineFlowBox::paint(RenderObject::PaintInfo& i, int tx, int ty)
+{
+    bool intersectsDamageRect = true;
+    int xPos = tx + m_x - object()->maximalOutlineSize(i.phase);
+    int w = width() + 2 * object()->maximalOutlineSize(i.phase);
+    if ((xPos >= i.r.x() + i.r.width()) || (xPos + w <= i.r.x()))
+        intersectsDamageRect = false;
+    
+    if (intersectsDamageRect) {
+        if (i.phase == PaintActionOutline) {
+            // Add ourselves to the paint info struct's list of inlines that need to paint their
+            // outlines.
+            if (object()->style()->visibility() == VISIBLE && object()->style()->outlineWidth() > 0 &&
+                !object()->isInlineContinuation()) {
+                if (!i.outlineObjects)
+                    i.outlineObjects = new QPtrDict<RenderFlow>;
+                if (!i.outlineObjects->find(flowObject()))
+                    i.outlineObjects->insert(flowObject(), flowObject());
+            }
+        }
+        else {
+            // 1. Paint our background and border.
+            paintBackgroundAndBorder(i, tx, ty);
+            
+            // 2. Paint our underline and overline.
+            paintDecorations(i, tx, ty, false);
+        }
+    }
+
+    // 3. Paint our children.
+    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+        if (!curr->object()->layer())
+            curr->paint(i, tx, ty);
+    }
+
+    // 4. Paint our strike-through
+    if (intersectsDamageRect && i.phase != PaintActionOutline)
+        paintDecorations(i, tx, ty, true);
+}
+
 void InlineFlowBox::paintBackgrounds(QPainter* p, const QColor& c, const BackgroundLayer* bgLayer,
-                                     int my, int mh, int _tx, int _ty, int w, int h, int xoff)
+                                     int my, int mh, int _tx, int _ty, int w, int h)
 {
     if (!bgLayer)
         return;
-    paintBackgrounds(p, c, bgLayer->next(), my, mh, _tx, _ty, w, h, xoff);
-    paintBackground(p, c, bgLayer, my, mh, _tx, _ty, w, h, xoff);
+    paintBackgrounds(p, c, bgLayer->next(), my, mh, _tx, _ty, w, h);
+    paintBackground(p, c, bgLayer, my, mh, _tx, _ty, w, h);
 }
 
 void InlineFlowBox::paintBackground(QPainter* p, const QColor& c, const BackgroundLayer* bgLayer,
-                                    int my, int mh, int _tx, int _ty, int w, int h, int xOffsetOnLine)
+                                    int my, int mh, int _tx, int _ty, int w, int h)
 {
     CachedImage* bg = bgLayer->backgroundImage();
     bool hasBackgroundImage = bg && (bg->pixmap_size() == bg->valid_rect().size()) &&
@@ -715,6 +810,9 @@ void InlineFlowBox::paintBackground(QPainter* p, const QColor& c, const Backgrou
         // strip.  Even though that strip has been broken up across multiple lines, you still paint it
         // as though you had one single line.  This means each line has to pick up the background where
         // the previous line left off.
+        int xOffsetOnLine = 0;
+        for (InlineRunBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
+            xOffsetOnLine += curr->width();
         int startX = _tx - xOffsetOnLine;
         int totalWidth = xOffsetOnLine;
         for (InlineRunBox* curr = this; curr; curr = curr->nextLineBox())
@@ -729,8 +827,12 @@ void InlineFlowBox::paintBackground(QPainter* p, const QColor& c, const Backgrou
     }
 }
 
-void InlineFlowBox::paintBackgroundAndBorder(RenderObject::PaintInfo& i, int _tx, int _ty, int xOffsetOnLine)
+void InlineFlowBox::paintBackgroundAndBorder(RenderObject::PaintInfo& i, int _tx, int _ty)
 {
+    if (!object()->shouldPaintWithinRoot(i) || object()->style()->visibility() != VISIBLE ||
+        i.phase != PaintActionForeground)
+        return;
+
     // Move x/y to our coordinates.
     _tx += m_x;
     _ty += m_y;
@@ -753,7 +855,7 @@ void InlineFlowBox::paintBackgroundAndBorder(RenderObject::PaintInfo& i, int _tx
     if ((!parent() && m_firstLine && styleToUse != object()->style()) || 
         (parent() && object()->shouldPaintBackgroundOrBorder())) {
         QColor c = styleToUse->backgroundColor();
-        paintBackgrounds(p, c, styleToUse->backgroundLayers(), my, mh, _tx, _ty, w, h, xOffsetOnLine);
+        paintBackgrounds(p, c, styleToUse->backgroundLayers(), my, mh, _tx, _ty, w, h);
 
         // :first-line cannot be used to put borders on a line. Always paint borders with our
         // non-first-line style.
@@ -782,8 +884,12 @@ static bool shouldDrawDecoration(RenderObject* obj)
 
 void InlineFlowBox::paintDecorations(RenderObject::PaintInfo& i, int _tx, int _ty, bool paintedChildren)
 {
-    // Now paint our text decorations. We only do this if we aren't in quirks mode (i.e., in
+    // Paint text decorations like underlines/overlines. We only do this if we aren't in quirks mode (i.e., in
     // almost-strict mode or strict mode).
+    if (object()->style()->htmlHacks() || !object()->shouldPaintWithinRoot(i) ||
+        object()->style()->visibility() != VISIBLE)
+        return;
+
     QPainter* p = i.p;
     _tx += m_x;
     _ty += m_y;
@@ -967,20 +1073,28 @@ void EllipsisBox::paint(RenderObject::PaintInfo& i, int _tx, int _ty)
         // Paint the markup box
         _tx += m_x + m_width - m_markupBox->xPos();
         _ty += m_y + m_baseline - (m_markupBox->yPos() + m_markupBox->baseline());
-        m_markupBox->object()->paint(i, _tx, _ty);
+        m_markupBox->paint(i, _tx, _ty);
     }
 }
 
-bool EllipsisBox::nodeAtPoint(RenderObject::NodeInfo& info, int _x, int _y, int _tx, int _ty,
-                              HitTestAction hitTestAction, bool inBox)
+bool EllipsisBox::nodeAtPoint(RenderObject::NodeInfo& info, int _x, int _y, int _tx, int _ty)
 {
+    // Hit test the markup box.
     if (m_markupBox) {
         _tx += m_x + m_width - m_markupBox->xPos();
         _ty += m_y + m_baseline - (m_markupBox->yPos() + m_markupBox->baseline());
-        inBox |= m_markupBox->object()->nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inBox);
+        if (m_markupBox->nodeAtPoint(info, _x, _y, _tx, _ty)) {
+            object()->setInnerNode(info);
+            return true;
+        }
     }
-    
-    return inBox;
+
+    QRect rect(_tx + m_x, _ty + m_y, m_width, m_height);
+    if (object()->style()->visibility() == VISIBLE && rect.contains(_x, _y)) {
+        object()->setInnerNode(info);
+        return true;
+    }
+    return false;
 }
 
 void RootInlineBox::detach(RenderArena* arena)
@@ -1048,16 +1162,26 @@ int RootInlineBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth,
 
 void RootInlineBox::paintEllipsisBox(RenderObject::PaintInfo& i, int _tx, int _ty) const
 {
-    if (m_ellipsisBox)
+    if (m_ellipsisBox && object()->shouldPaintWithinRoot(i) && object()->style()->visibility() == VISIBLE &&
+        i.phase == PaintActionForeground)
         m_ellipsisBox->paint(i, _tx, _ty);
 }
 
-bool RootInlineBox::hitTestEllipsisBox(RenderObject::NodeInfo& info, int _x, int _y, int _tx, int _ty,
-                                       HitTestAction hitTestAction, bool inBox)
+void RootInlineBox::paint(RenderObject::PaintInfo& i, int tx, int ty)
+{
+    InlineFlowBox::paint(i, tx, ty);
+    paintEllipsisBox(i, tx, ty);
+}
+
+bool RootInlineBox::nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty)
 {
-    if (m_ellipsisBox)
-        inBox |= m_ellipsisBox->nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inBox);
-    return inBox;
+    if (m_ellipsisBox && object()->style()->visibility() == VISIBLE) {
+        if (m_ellipsisBox->nodeAtPoint(i, x, y, tx, ty)) {
+            object()->setInnerNode(i);
+            return true;
+        }
+    }
+    return InlineFlowBox::nodeAtPoint(i, x, y, tx, ty);
 }
 
 void RootInlineBox::adjustPosition(int dx, int dy)
index 5bacc6451576a1f79775138c9e1fa3a88e214f6d..9611e7d475ae893fdc1b43366eb41c1a5a077090 100644 (file)
@@ -34,6 +34,7 @@ class EllipsisBox;
 class InlineFlowBox;
 class RootInlineBox;
 class RenderBlock;
+class RenderFlow;
 
 // InlineBox represents a rectangle that occurs on a line.  It corresponds to
 // some RenderObject (i.e., it represents a portion of that RenderObject).
@@ -59,6 +60,9 @@ public:
 
     virtual void adjustPosition(int dx, int dy);
 
+    virtual void paint(RenderObject::PaintInfo& i, int _tx, int _ty);
+    virtual bool nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty);
+    
     // Overloaded new operator.
     void* operator new(size_t sz, RenderArena* renderArena) throw();
 
@@ -183,7 +187,7 @@ public:
     void setNextLineBox(InlineRunBox* n) { m_nextLine = n; }
     void setPreviousLineBox(InlineRunBox* p) { m_prevLine = p; }
 
-    virtual void paintBackgroundAndBorder(RenderObject::PaintInfo& i, int _tx, int _ty, int xOffsetOnLine) {};
+    virtual void paintBackgroundAndBorder(RenderObject::PaintInfo& i, int _tx, int _ty) {};
     virtual void paintDecorations(RenderObject::PaintInfo& i, int _tx, int _ty, bool paintedChildren = false) {};
     
 protected:
@@ -203,6 +207,8 @@ public:
         m_hasTextChildren = false;
     }
 
+    RenderFlow* flowObject();
+
     virtual bool isInlineFlowBox() { return true; }
 
     InlineFlowBox* prevFlowBox() const { return static_cast<InlineFlowBox*>(m_prevLine); }
@@ -231,13 +237,15 @@ public:
 
     virtual void clearTruncation();
     
-    virtual void paintBackgroundAndBorder(RenderObject::PaintInfo& i, int _tx, int _ty, int xOffsetOnLine);
+    virtual void paintBackgroundAndBorder(RenderObject::PaintInfo& i, int _tx, int _ty);
     void paintBackgrounds(QPainter* p, const QColor& c, const BackgroundLayer* bgLayer,
-                          int my, int mh, int _tx, int _ty, int w, int h, int xoff);
+                          int my, int mh, int _tx, int _ty, int w, int h);
     void paintBackground(QPainter* p, const QColor& c, const BackgroundLayer* bgLayer,
-                         int my, int mh, int _tx, int _ty, int w, int h, int xoff);
+                         int my, int mh, int _tx, int _ty, int w, int h);
     virtual void paintDecorations(RenderObject::PaintInfo& i, int _tx, int _ty, bool paintedChildren = false);
-    
+    virtual void paint(RenderObject::PaintInfo& i, int _tx, int _ty);
+    virtual bool nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty);
+
     int marginBorderPaddingLeft();
     int marginBorderPaddingRight();
     int marginLeft();
@@ -332,6 +340,9 @@ public:
     
     virtual void clearTruncation();
 
+    virtual void paint(RenderObject::PaintInfo& i, int _tx, int _ty);
+    virtual bool nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty);
+
     bool hasSelectedChildren() const { return m_hasSelectedChildren; }
     void setHasSelectedChildren(bool b);
     
index 9151c3204fefc8189955c6c3a884202a15edc534..676787a8c4e5c6481b32812fb4fd8678999f30f5 100644 (file)
@@ -1885,67 +1885,51 @@ void RenderObject::updateDragState(bool dragOn)
         continuation()->updateDragState(dragOn);
 }
 
-bool RenderObject::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
-                               HitTestAction hitTestAction, bool inside)
+bool RenderObject::hitTest(NodeInfo& info, int x, int y, int tx, int ty, HitTestFilter hitTestFilter)
 {
-    int tx = _tx + xPos();
-    int ty = _ty + yPos();
+    bool inside = false;
+    if (hitTestFilter != HitTestSelf) {
+        // First test the foreground layer (lines and inlines).
+        inside = nodeAtPoint(info, x, y, tx, ty, HitTestForeground);
+        
+        // Test floats next.
+        if (!inside)
+            inside = nodeAtPoint(info, x, y, tx, ty, HitTestFloat);
 
-    QRect boundsRect(tx, ty, width(), height());
-    inside |= (style()->visibility() != HIDDEN && boundsRect.contains(_x, _y)) || isBody() || isRoot();
-    bool inOverflowRect = inside;
-    if (!inOverflowRect) {
-        QRect overflowRect(tx, ty, overflowWidth(false), overflowHeight(false));
-        inOverflowRect = overflowRect.contains(_x, _y);
+        // Finally test to see if the mouse is in the background (within a child block's background).
+        if (!inside)
+            inside = nodeAtPoint(info, x, y, tx, ty, HitTestChildBlockBackgrounds);
     }
     
-    // ### table should have its own, more performant method
-    if (hitTestAction != HitTestSelfOnly &&
-        ((!isRenderBlock() ||
-         !static_cast<RenderBlock*>(this)->isPointInScrollbar(_x, _y, _tx, _ty)) &&
-        (inOverflowRect || isInline() || isCanvas() ||
-         isTableRow() || isTableSection() || inside || mouseInside() ||
-         (childrenInline() && firstChild() && firstChild()->isCompact())))) {
-        if (hitTestAction == HitTestChildrenOnly)
-            inside = false;
-        int stx = _tx + xPos();
-        int sty = _ty + yPos();
-        if (hasOverflowClip())
-            layer()->subtractScrollOffset(stx, sty);
-        for (RenderObject* child = lastChild(); child; child = child->previousSibling())
-            if (!child->layer() && !child->isFloating() &&
-                child->nodeAtPoint(info, _x, _y, stx, sty))
-                inside = true;
-    }
-
-    if (inside) {
-        if (!info.innerNode() && !isInline() && continuation()) {
-            // We are in the margins of block elements that are part of a continuation.  In
-            // this case we're actually still inside the enclosing inline element that was
-            // split.  Go ahead and set our inner node accordingly.
-            info.setInnerNode(continuation()->element());
-            if (!info.innerNonSharedNode())
-                info.setInnerNonSharedNode(continuation()->element());
-        }
-            
-        if (info.innerNode() && info.innerNode()->renderer() && 
-            !info.innerNode()->renderer()->isInline() && element() && isInline()) {
-            // Within the same layer, inlines are ALWAYS fully above blocks.  Change inner node.
-            info.setInnerNode(element());
-            
-            // Clear everything else.
-            info.setInnerNonSharedNode(0);
-            info.setURLElement(0);
-        }
+    // See if the mouse is inside us but not any of our descendants
+    if (hitTestFilter != HitTestDescendants && !inside)
+        inside = nodeAtPoint(info, x, y, tx, ty, HitTestBlockBackground);
         
-        if (!info.innerNode() && element())
-            info.setInnerNode(element());
+    return inside;
+}
 
-        if(!info.innerNonSharedNode() && element())
-            info.setInnerNonSharedNode(element());
+void RenderObject::setInnerNode(NodeInfo& info)
+{
+    if (!info.innerNode() && !isInline() && continuation()) {
+        // We are in the margins of block elements that are part of a continuation.  In
+        // this case we're actually still inside the enclosing inline element that was
+        // split.  Go ahead and set our inner node accordingly.
+        info.setInnerNode(continuation()->element());
+        if (!info.innerNonSharedNode())
+            info.setInnerNonSharedNode(continuation()->element());
     }
 
-    return inside;
+    if (!info.innerNode() && element())
+        info.setInnerNode(element());
+            
+    if(!info.innerNonSharedNode() && element())
+        info.setInnerNonSharedNode(element());
+}
+
+bool RenderObject::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
+                               HitTestAction hitTestAction)
+{
+    return false;
 }
 
 short RenderObject::verticalPositionHint( bool firstLine ) const
index 8b5fb98dd1996196dacbd89afaa47e94d89ca3f9..cb5da8888ef535f34b89ccf3aa88ed04c488829d 100644 (file)
@@ -66,9 +66,9 @@ class RenderArena;
  */
 
 typedef enum {
-    PaintActionElementBackground = 0,
-    PaintActionChildBackground,
-    PaintActionChildBackgrounds,
+    PaintActionBlockBackground,
+    PaintActionChildBlockBackground,
+    PaintActionChildBlockBackgrounds,
     PaintActionFloat,
     PaintActionForeground,
     PaintActionOutline,
@@ -77,9 +77,17 @@ typedef enum {
 } PaintAction;
 
 typedef enum {
-    HitTestAll = 0,
-    HitTestSelfOnly = 1,
-    HitTestChildrenOnly = 2
+    HitTestAll,
+    HitTestSelf,
+    HitTestDescendants
+} HitTestFilter;
+
+typedef enum {
+    HitTestBlockBackground,
+    HitTestChildBlockBackground,
+    HitTestChildBlockBackgrounds,
+    HitTestFloat,
+    HitTestForeground
 } HitTestAction;
 
 namespace DOM {
@@ -384,11 +392,13 @@ public:
      */
     struct PaintInfo {
         PaintInfo(QPainter* _p, const QRect& _r, PaintAction _phase, RenderObject *_paintingRoot)
-        : p(_p), r(_r), phase(_phase), paintingRoot(_paintingRoot) {}
+        : p(_p), r(_r), phase(_phase), paintingRoot(_paintingRoot), outlineObjects(0) {}
+        ~PaintInfo() { delete outlineObjects; }
         QPainter* p;
         QRect     r;
         PaintAction phase;
         RenderObject *paintingRoot;      // used to draw just one element and its visual kids
+        QPtrDict<RenderFlow>* outlineObjects; // used to list which outlines should be painted by a block with inline children
     };
     virtual void paint(PaintInfo& i, int tx, int ty);
     void paintBorder(QPainter *p, int _tx, int _ty, int w, int h, const RenderStyle* style, bool begin=true, bool end=true);
@@ -505,9 +515,11 @@ public:
         RepaintInfo(RenderObject* o, const QRect& r) :m_object(o), m_repaintRect(r) {}
     };
     
+    bool hitTest(NodeInfo& info, int x, int y, int tx, int ty, HitTestFilter hitTestFilter = HitTestAll);
     virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty,
-                             HitTestAction hitTestAction = HitTestAll, bool inside=false);
-    
+                             HitTestAction hitTestAction);
+    void setInnerNode(NodeInfo& info);
+
     virtual DOM::Position positionForCoordinates(int x, int y, EAffinity * = 0);
     
     virtual void dirtyLinesFromChangedChild(RenderObject* child, bool adding = true);
@@ -819,6 +831,15 @@ public:
 
     virtual void selectionStartEnd(int& spos, int& epos);
 
+    RenderObject* paintingRootForChildren(PaintInfo &i) const {
+        // if we're the painting root, kids draw normally, and see root of 0
+        return (!i.paintingRoot || i.paintingRoot == this) ? 0 : i.paintingRoot;
+    }
+
+    bool shouldPaintWithinRoot(PaintInfo &i) const {
+        return !i.paintingRoot || i.paintingRoot == this;
+    }
+    
 protected:
 
     virtual void printBoxDecorations(QPainter* /*p*/, int /*_x*/, int /*_y*/,
@@ -835,14 +856,6 @@ protected:
     
     void arenaDelete(RenderArena *arena);
 
-    RenderObject *paintingRootForChildren(PaintInfo &i) const {
-        // if we're the painting root, kids draw normally, and see root of 0
-        return (!i.paintingRoot || i.paintingRoot == this) ? 0 : i.paintingRoot;
-    }
-    bool shouldPaintWithinRoot(PaintInfo &i) const {
-        return !i.paintingRoot || i.paintingRoot == this;
-    }
-
 private:
     RenderStyle* m_style;
 
index 5415606a05535f5af3b7478aeff0e4d6c2299e06..3d7869c9b0d6494137f80bfa090206435913caf4 100644 (file)
@@ -347,6 +347,8 @@ void RenderTable::layout()
     if (checkForRepaint)
         repaintAfterLayoutIfNeeded(oldBounds, oldFullBounds);
     
+    m_overflowHeight = kMax(m_overflowHeight, m_height);
+
     setNeedsLayout(false);
 }
 
@@ -377,33 +379,32 @@ void RenderTable::paint(PaintInfo& i, int _tx, int _ty)
 #ifdef TABLE_PRINT
     kdDebug( 6040 ) << "RenderTable::paint() w/h = (" << width() << "/" << height() << ")" << endl;
 #endif
-    if (!isRelPositioned() && !isPositioned()) {
-        int os = 2*maximalOutlineSize(paintAction);
-        if ((_ty >= i.r.y() + i.r.height() + os) || (_ty + height() <= i.r.y() - os)) return;
-        if ((_tx >= i.r.x() + i.r.width() + os) || (_tx + width() <= i.r.x() - os)) return;
-    }
+    
+    int os = 2*maximalOutlineSize(paintAction);
+    if ((_ty >= i.r.y() + i.r.height() + os) || (_ty + height() <= i.r.y() - os)) return;
+    if ((_tx >= i.r.x() + i.r.width() + os) || (_tx + width() <= i.r.x() - os)) return;
 
 #ifdef TABLE_PRINT
     kdDebug( 6040 ) << "RenderTable::paint(2) " << _tx << "/" << _ty << " (" << _y << "/" << _h << ")" << endl;
 #endif
 
-    if ((paintAction == PaintActionElementBackground || paintAction == PaintActionChildBackground)
+    if ((paintAction == PaintActionBlockBackground || paintAction == PaintActionChildBlockBackground)
         && shouldPaintBackgroundOrBorder() && style()->visibility() == VISIBLE)
         paintBoxDecorations(i, _tx, _ty);
 
     // We're done.  We don't bother painting any children.
-    if (paintAction == PaintActionElementBackground)
+    if (paintAction == PaintActionBlockBackground)
         return;
     // We don't paint our own background, but we do let the kids paint their backgrounds.
-    if (paintAction == PaintActionChildBackgrounds)
-        paintAction = PaintActionChildBackground;
+    if (paintAction == PaintActionChildBlockBackgrounds)
+        paintAction = PaintActionChildBlockBackground;
     PaintInfo paintInfo(i.p, i.r, paintAction, paintingRootForChildren(i));
     
     for (RenderObject *child = firstChild(); child; child = child->nextSibling())
         if (child->isTableSection() || child == tCaption)
            child->paint(paintInfo, _tx, _ty);
 
-    if (collapseBorders() && paintAction == PaintActionChildBackground && style()->visibility() == VISIBLE) {
+    if (collapseBorders() && paintAction == PaintActionChildBlockBackground && style()->visibility() == VISIBLE) {
         // Collect all the unique border styles that we want to paint in a sorted list.  Once we
         // have all the styles sorted, we then do individual passes, painting each style of border
         // from lowest precedence to highest precedence.
index 1d67d13e05a40efc8a4b6e7665d01153f53388d1..b18920458d83db3be248354a1db56a607fa368ae 100644 (file)
@@ -235,12 +235,238 @@ int InlineTextBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth,
     return -1;
 }
 
-void InlineTextBox::paintSelection(const Font *f, RenderText *text, QPainter *p, RenderStyle* style, int tx, int ty, int startPos, int endPos)
+static int
+simpleDifferenceBetweenColors(QColor c1, QColor c2)
 {
-    int offset = m_start;
-    int sPos = kMax(startPos - offset, 0);
-    int ePos = kMin(endPos - offset, (int)m_len);
+    // a distance could be computed by squaring the differences between components, but
+    // this is faster and so far seems good enough for our purposes.
+    return abs(c1.red() - c2.red()) + abs(c1.green() - c2.green()) + abs(c1.blue() - c2.blue());
+}
+
+static QColor 
+correctedTextColor(QColor textColor, QColor backgroundColor) 
+{
+    // Adjust the text color if it is too close to the background color,
+    // by darkening or lightening it to move it further away.
+    
+    int d = simpleDifferenceBetweenColors(textColor, backgroundColor);
+    // semi-arbitrarily chose 255 value here after a few tests; 
+    if (d > 255) {
+        return textColor;
+    }
+    
+    int distanceFromWhite = simpleDifferenceBetweenColors(textColor, Qt::white);
+    int distanceFromBlack = simpleDifferenceBetweenColors(textColor, Qt::black);
+
+    if (distanceFromWhite < distanceFromBlack) {
+        return textColor.dark();
+    }
+    
+    return textColor.light();
+}
+
+bool InlineTextBox::nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty)
+{
+    if (object()->isBR())
+        return false;
+
+    QRect rect(tx + m_x, ty + m_y, m_width, m_height);
+    if (m_truncation != cFullTruncation && 
+        object()->style()->visibility() == VISIBLE && rect.contains(x, y)) {
+        object()->setInnerNode(i);
+        return true;
+    }
+    return false;
+}
+
+void InlineTextBox::paint(RenderObject::PaintInfo& i, int tx, int ty)
+{
+    if (object()->isBR() || !object()->shouldPaintWithinRoot(i) || object()->style()->visibility() != VISIBLE ||
+        m_truncation == cFullTruncation || i.phase == PaintActionOutline)
+        return;
+
+    int xPos = tx + m_x;
+    int w = width();
+    if ((xPos >= i.r.x() + i.r.width()) || (xPos + w <= i.r.x()))
+        return;
+        
+    bool isPrinting = (i.p->device()->devType() == QInternal::Printer);
+
+    // Determine whether or not we're selected.
+    bool haveSelection = !isPrinting && selectionState() != RenderObject::SelectionNone;
+    if (!haveSelection && i.phase == PaintActionSelection)
+        // When only painting the selection, don't bother to paint if there is none.
+        return;
+
+    // Determine whether or not we have marked text.
+    Range markedTextRange = KWQ(object()->document()->part())->markedTextRange();
+    bool haveMarkedText = markedTextRange.handle() != 0 && markedTextRange.startContainer() == object()->node();
+
+    // Set our font.
+    RenderStyle* styleToUse = object()->style(m_firstLine);
+    int d = styleToUse->textDecorationsInEffect();
+    if (styleToUse->font() != i.p->font())
+        i.p->setFont(styleToUse->font());
+    const Font *font = &styleToUse->htmlFont();
+
+    // 1. Paint backgrounds behind text if needed.  Examples of such backgrounds include selection
+    // and marked text.
+    if ((haveSelection || haveMarkedText) && i.phase != PaintActionSelection && !isPrinting) {
+        if (haveMarkedText)
+            paintMarkedTextBackground(i.p, tx, ty, styleToUse, font, markedTextRange.startOffset(), markedTextRange.endOffset());
+
+        if (haveSelection)
+            paintSelection(i.p, tx, ty, styleToUse, font);
+    }
+
+    // 2. Now paint the foreground, including text and decorations like underline/overline (in quirks mode only).
+    if (m_len <= 0) return;
+    QValueList<DocumentMarker> markers = object()->document()->markersForNode(object()->node());
+    QValueListIterator <DocumentMarker> markerIt = markers.begin();
+
+    QColor textColor = styleToUse->color();
+    if (styleToUse->shouldCorrectTextColor())
+        textColor = correctedTextColor(textColor, styleToUse->backgroundColor());
+
+    if (textColor != i.p->pen().color())
+        i.p->setPen(textColor);
+
+    // Set a text shadow if we have one.
+    // FIXME: Support multiple shadow effects.  Need more from the CG API before
+    // we can do this.
+    bool setShadow = false;
+    if (styleToUse->textShadow()) {
+        i.p->setShadow(styleToUse->textShadow()->x, styleToUse->textShadow()->y,
+                        styleToUse->textShadow()->blur, styleToUse->textShadow()->color);
+        setShadow = true;
+    }
+
+    bool paintSelectedTextOnly = (i.phase == PaintActionSelection);
+    bool paintSelectedTextSeparately = false; // Whether or not we have to do multiple paints.  Only
+                                              // necessary when a custom ::selection foreground color is applied.
+    QColor selectionColor = i.p->pen().color();
+    ShadowData* selectionTextShadow = 0;
+    if (haveSelection) {
+        RenderStyle* pseudoStyle = object()->getPseudoStyle(RenderStyle::SELECTION);
+        if (pseudoStyle) {
+            if (pseudoStyle->color() != selectionColor || pseudoStyle->textShadow()) {
+                if (!paintSelectedTextOnly)
+                    paintSelectedTextSeparately = true;
+                if (pseudoStyle->color() != selectionColor)
+                    selectionColor = pseudoStyle->color();
+                if (pseudoStyle->textShadow())
+                    selectionTextShadow = pseudoStyle->textShadow();
+            }
+        }
+    }
+
+    if (!paintSelectedTextOnly && !paintSelectedTextSeparately) {
+        // paint all the text
+        // FIXME: Handle RTL direction, handle reversed strings.  For now truncation can only be turned on
+        // for non-reversed LTR strings.
+        int endPoint = m_len;
+        if (m_truncation != cNoTruncation)
+            endPoint = m_truncation - m_start;
+        font->drawText(i.p, m_x + tx, m_y + ty + m_baseline,
+                       textObject()->string()->s, textObject()->string()->l, m_start, endPoint,
+                       m_toAdd, m_reversed ? QPainter::RTL : QPainter::LTR, styleToUse->visuallyOrdered());
+    } else {
+        int sPos, ePos;
+        selectionStartEnd(sPos, ePos);
+        if (paintSelectedTextSeparately) {
+            // paint only the text that is not selected
+            if (sPos >= ePos) {
+                font->drawText(i.p, m_x + tx, m_y + ty + m_baseline,
+                               textObject()->string()->s, textObject()->string()->l, m_start, m_len,
+                               m_toAdd, m_reversed ? QPainter::RTL : QPainter::LTR, styleToUse->visuallyOrdered());
+            } else {
+                if (sPos - 1 >= 0) {
+                    font->drawText(i.p, m_x + tx, m_y + ty + m_baseline, textObject()->string()->s,
+                                   textObject()->string()->l, m_start, m_len,
+                                   m_toAdd, m_reversed ? QPainter::RTL : QPainter::LTR, styleToUse->visuallyOrdered(), 0, sPos);
+                }
+                if (ePos < m_start + m_len) {
+                    font->drawText(i.p, m_x + tx, m_y + ty + m_baseline, textObject()->string()->s,
+                                   textObject()->string()->l, m_start, m_len,
+                                   m_toAdd, m_reversed ? QPainter::RTL : QPainter::LTR, styleToUse->visuallyOrdered(), ePos, -1);
+                }
+            }
+        }
+            
+        if (sPos < ePos) {
+            // paint only the text that is selected
+            if (selectionColor != i.p->pen().color())
+                i.p->setPen(selectionColor);
+            
+            if (selectionTextShadow)
+                i.p->setShadow(selectionTextShadow->x,
+                               selectionTextShadow->y,
+                               selectionTextShadow->blur,
+                               selectionTextShadow->color);
+            font->drawText(i.p, m_x + tx, m_y + ty + m_baseline, textObject()->string()->s,
+                           textObject()->string()->l, m_start, m_len,
+                           m_toAdd, m_reversed ? QPainter::RTL : QPainter::LTR, styleToUse->visuallyOrdered(), sPos, ePos);
+            if (selectionTextShadow)
+                i.p->clearShadow();
+        }
+    }
+
+    // Paint decorations
+    if (d != TDNONE && i.phase != PaintActionSelection && styleToUse->htmlHacks()) {
+        i.p->setPen(styleToUse->color());
+        paintDecoration(i.p, tx, ty, d);
+    }
+
+    // Draw any doc markers that touch this run
+    // Note end() points at the last char, not one past it like endOffset and ranges do
+    if (i.phase != PaintActionSelection) {
+        for ( ; markerIt != markers.end(); markerIt++) {
+            DocumentMarker marker = *markerIt;
+
+            if (marker.endOffset <= start())
+                // marker is completely before this run.  This might be a marker that sits before the
+                // first run we draw, or markers that were within runs we skipped due to truncation.
+                continue;
+            
+            if (marker.startOffset <= end()) {
+                // marker intersects this run.  Paint it.
+                paintMarker(i.p, tx, ty, marker);
+                if (marker.endOffset > end() + 1)
+                    // marker also runs into the next run. Bail now, no more marker advancement.
+                    break;
+            } else
+                // marker is completely after this run, bail.  A later run will paint it.
+                break;
+        }
+    }
+
+    if (setShadow)
+        i.p->clearShadow();
+}
+
+void InlineTextBox::selectionStartEnd(int& sPos, int& ePos)
+{
+    int startPos, endPos;
+    if (object()->selectionState() == RenderObject::SelectionInside) {
+        startPos = 0;
+        endPos = textObject()->string()->l;
+    } else {
+        textObject()->selectionStartEnd(startPos, endPos);
+        if (object()->selectionState() == RenderObject::SelectionStart)
+            endPos = textObject()->string()->l;
+        else if (object()->selectionState() == RenderObject::SelectionEnd)
+            startPos = 0;
+    }
+
+    sPos = kMax(startPos - m_start, 0);
+    ePos = kMin(endPos - m_start, (int)m_len);
+}
 
+void InlineTextBox::paintSelection(QPainter* p, int tx, int ty, RenderStyle* style, const Font* f)
+{
+    // See if we have a selection to paint at all.
+    int sPos, ePos;
+    selectionStartEnd(sPos, ePos);
     if (sPos >= ePos)
         return;
 
@@ -262,13 +488,12 @@ void InlineTextBox::paintSelection(const Font *f, RenderText *text, QPainter *p,
     int y = r->selectionTop();
     int h = r->selectionHeight();
     f->drawHighlightForText(p, x, y + ty, h,
-                            text->str->s, text->str->l, m_start, m_len,
+                            textObject()->str->s, textObject()->str->l, m_start, m_len,
                             m_toAdd, m_reversed ? QPainter::RTL : QPainter::LTR, style->visuallyOrdered(), sPos, ePos, c);
     p->restore();
 }
 
-#if APPLE_CHANGES
-void InlineTextBox::paintMarkedTextBackground(const Font *f, RenderText *text, QPainter *p, RenderStyle* style, int tx, int ty, int startPos, int endPos)
+void InlineTextBox::paintMarkedTextBackground(QPainter* p, int tx, int ty, RenderStyle* style, const Font* f, int startPos, int endPos)
 {
     int offset = m_start;
     int sPos = kMax(startPos - offset, 0);
@@ -287,13 +512,11 @@ void InlineTextBox::paintMarkedTextBackground(const Font *f, RenderText *text, Q
     int x = m_x + tx;
     int y = r->selectionTop();
     int h = r->selectionHeight();
-    f->drawHighlightForText(p, x, y + ty, h, text->str->s, text->str->l, m_start, m_len,
+    f->drawHighlightForText(p, x, y + ty, h, textObject()->str->s, textObject()->str->l, m_start, m_len,
                m_toAdd, m_reversed ? QPainter::RTL : QPainter::LTR, style->visuallyOrdered(), sPos, ePos, c);
     p->restore();
 }
-#endif
 
-#ifdef APPLE_CHANGES
 void InlineTextBox::paintDecoration( QPainter *pt, int _tx, int _ty, int deco)
 {
     _tx += m_x;
@@ -323,36 +546,6 @@ void InlineTextBox::paintDecoration( QPainter *pt, int _tx, int _ty, int deco)
         pt->drawLineForText(_tx, _ty, 2*m_baseline/3, width);
     }
 }
-#else
-void InlineTextBox::paintDecoration( QPainter *pt, int _tx, int _ty, int decoration)
-{
-    _tx += m_x;
-    _ty += m_y;
-
-    int width = m_width - 1;
-
-    QColor underline, overline, linethrough;
-    object()->getTextDecorationColors(decoration, underline, overline, linethrough, true);
-    
-    int underlineOffset = ( pt->fontMetrics().height() + m_baseline ) / 2;
-    if(underlineOffset <= m_baseline) underlineOffset = m_baseline+1;
-
-    if(deco & UNDERLINE){
-        pt->setPen(underline);
-        pt->drawLine(_tx, _ty + underlineOffset, _tx + width, _ty + underlineOffset );
-    }
-    if (deco & OVERLINE) {
-        pt->setPen(overline);
-        pt->drawLine(_tx, _ty, _tx + width, _ty );
-    }
-    if(deco & LINE_THROUGH) {
-        pt->setPen(linethrough);
-        pt->drawLine(_tx, _ty + 2*m_baseline/3, _tx + width, _ty + 2*m_baseline/3 );
-    }
-    // NO! Do NOT add BLINK! It is the most annouing feature of Netscape, and IE has a reason not to
-    // support it. Lars
-}
-#endif
 
 void InlineTextBox::paintMarker(QPainter *pt, int _tx, int _ty, DocumentMarker marker)
 {
@@ -589,43 +782,6 @@ InlineTextBox* RenderText::findNextInlineTextBox(int offset, int &pos)
     return s;
 }
 
-bool RenderText::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
-                             HitTestAction hitTestAction, bool inside)
-{
-    assert(parent());
-
-    if (style()->visibility() == HIDDEN)
-        return inside;
-
-    for (InlineTextBox *s = m_firstTextBox; s; s = s->nextTextBox()) {
-        if((_y >=_ty + s->m_y) && (_y < _ty + s->m_y + s->height()) &&
-           (_x >= _tx + s->m_x) && (_x <_tx + s->m_x + s->m_width) ) {
-            inside = true;
-            break;
-        }
-    }
-
-    if (inside && element()) {
-        if (info.innerNode() && info.innerNode()->renderer() && 
-            !info.innerNode()->renderer()->isInline()) {
-            // Within the same layer, inlines are ALWAYS fully above blocks.  Change inner node.
-            info.setInnerNode(element());
-            
-            // Clear everything else.
-            info.setInnerNonSharedNode(0);
-            info.setURLElement(0);
-        }
-        
-        if (!info.innerNode())
-            info.setInnerNode(element());
-
-        if (!info.innerNonSharedNode())
-            info.setInnerNonSharedNode(element());
-    }
-
-    return inside;
-}
-
 Position RenderText::positionForCoordinates(int _x, int _y, EAffinity *affinity)
 {
     if (affinity)
@@ -789,311 +945,6 @@ void RenderText::posOfChar(int chr, int &x, int &y)
     }
 }
 
-static int
-simpleDifferenceBetweenColors(QColor c1, QColor c2)
-{
-    // a distance could be computed by squaring the differences between components, but
-    // this is faster and so far seems good enough for our purposes.
-    return abs(c1.red() - c2.red()) + abs(c1.green() - c2.green()) + abs(c1.blue() - c2.blue());
-}
-
-static QColor 
-correctedTextColor(QColor textColor, QColor backgroundColor) 
-{
-    // Adjust the text color if it is too close to the background color,
-    // by darkening or lightening it to move it further away.
-    
-    int d = simpleDifferenceBetweenColors(textColor, backgroundColor);
-    // semi-arbitrarily chose 255 value here after a few tests; 
-    if (d > 255) {
-        return textColor;
-    }
-    
-    int distanceFromWhite = simpleDifferenceBetweenColors(textColor, Qt::white);
-    int distanceFromBlack = simpleDifferenceBetweenColors(textColor, Qt::black);
-
-    if (distanceFromWhite < distanceFromBlack) {
-        return textColor.dark();
-    }
-    
-    return textColor.light();
-}
-
-void RenderText::paint(PaintInfo& i, int tx, int ty)
-{
-    if (i.phase != PaintActionForeground && i.phase != PaintActionSelection)
-        return;
-    
-    if (!shouldPaintWithinRoot(i))
-        return;
-        
-    if (style()->visibility() != VISIBLE || !firstTextBox())
-        return;
-    
-    // Selection paints all the way up to the previous line's bottomOverflow.  We need to check
-    // for this when doing our dirty rect intersection tests.
-    int topY = firstTextBox()->yPos();
-    if (firstTextBox()->root()->hasSelectedChildren())
-        topY = kMin(topY, firstTextBox()->root()->selectionTop());
-    int bottomY = lastTextBox()->yPos() + lastTextBox()->height();
-    if (lastTextBox()->root()->hasSelectedChildren())
-        bottomY = kMax(bottomY, lastTextBox()->root()->bottomOverflow());
-
-    if (ty + topY >= i.r.y() + i.r.height()) 
-        return;
-
-    if (ty + bottomY <= i.r.y()) 
-        return;
-    
-    QPainter* p = i.p;
-    RenderStyle* pseudoStyle = style(true);
-    if (pseudoStyle == style()) pseudoStyle = 0;
-    int d = style()->textDecorationsInEffect();
-    bool isPrinting = (p->device()->devType() == QInternal::Printer);
-    
-    // Walk forward until we hit the first line that needs to be painted.
-    InlineTextBox* s = firstTextBox();
-    for (; s && !s->checkVerticalPoint(i.r.y(), ty, i.r.height()); s = s->nextTextBox());
-    if (!s) return;
-    
-    // Now calculate startPos and endPos, for painting selection.
-    // We paint selection while endPos > 0
-    int endPos, startPos;
-    if (!isPrinting && (selectionState() != SelectionNone)) {
-        if (selectionState() == SelectionInside) {
-            //kdDebug(6040) << this << " SelectionInside -> 0 to end" << endl;
-            startPos = 0;
-            endPos = str->l;
-        } else {
-            selectionStartEnd(startPos, endPos);
-            if(selectionState() == SelectionStart)
-                endPos = str->l;
-            else if(selectionState() == SelectionEnd)
-                startPos = 0;
-        }
-        //kdDebug(6040) << this << " Selection from " << startPos << " to " << endPos << endl;
-    }
-
-    const Font *font = &style()->htmlFont();
-
-#if APPLE_CHANGES
-    // We will iterate over the text boxes in two passes. First we
-    // paint all the backgrounds, then the foregrounds.
-
-    InlineTextBox* startBox = s;
-
-    // Pass 1: paint backgrounds for selection or marked text, if we have any
-
-    bool haveSelection = startPos != endPos && !isPrinting && selectionState() != SelectionNone;
-    if (!haveSelection && i.phase == PaintActionSelection) {
-        // When only painting the selection, don't bother to paint if there is none.
-        return;
-    }
-
-    Range markedTextRange = KWQ(document()->part())->markedTextRange();
-    bool haveMarkedText = markedTextRange.handle() != 0 && markedTextRange.startContainer() == node();
-
-    if ((haveSelection || haveMarkedText) && i.phase != PaintActionSelection && !isPrinting) {
-        s = startBox;
-
-        // run until we find a text box that is outside the range, then we know we can stop
-        do {
-            if (s->m_truncation == cFullTruncation)
-                continue;
-
-            RenderStyle* _style = pseudoStyle && s->m_firstLine ? pseudoStyle : style();
-
-            if (_style->font() != p->font())
-                p->setFont(_style->font());
-
-            font = &_style->htmlFont(); // Always update, since smallCaps is not stored in the QFont.
-
-            if (haveMarkedText)
-                s->paintMarkedTextBackground(font, this, p, _style, tx, ty, markedTextRange.startOffset(), markedTextRange.endOffset());
-
-            if (haveSelection)
-                s->paintSelection(font, this, p, _style, tx, ty, startPos, endPos);
-
-        } while (((s = s->nextTextBox()) != 0) && s->checkVerticalPoint(i.r.y(), ty, i.r.height()));
-    }
-
-
-    // Pass 2: now paint the foreground, including text and decorations
-
-    QValueList<DocumentMarker> markers = document()->markersForNode(node());
-    QValueListIterator <DocumentMarker> markerIt = markers.begin();
-
-    s = startBox;
-
-    // run until we find a text box that is outside the range, then we know we can stop
-    do {
-        if (isPrinting) {
-            if (ty+s->m_y+s->height() > i.r.y() + i.r.height()) {
-                RenderCanvas* canvasObj = canvas();
-                if (ty+s->m_y < canvasObj->truncatedAt())
-                    canvasObj->setBestTruncatedAt(ty+s->m_y, this);
-                // Let's stop here.
-                break;
-            }
-        }
-
-        if (s->m_truncation == cFullTruncation)
-            continue;
-        
-        RenderStyle* _style = pseudoStyle && s->m_firstLine ? pseudoStyle : style();
-
-        if (_style->font() != p->font())
-            p->setFont(_style->font());
-
-        font = &_style->htmlFont(); // Always update, since smallCaps is not stored in the QFont.
-
-        QColor textColor = _style->color();
-        if (_style->shouldCorrectTextColor()) {
-            textColor = correctedTextColor(textColor, _style->backgroundColor());
-        }
-
-        if(textColor != p->pen().color())
-            p->setPen(textColor);
-
-        // Set a text shadow if we have one.
-        // FIXME: Support multiple shadow effects.  Need more from the CG API before
-        // we can do this.
-        bool setShadow = false;
-        if (_style->textShadow()) {
-            p->setShadow(_style->textShadow()->x, _style->textShadow()->y,
-                         _style->textShadow()->blur, _style->textShadow()->color);
-            setShadow = true;
-        }
-        
-        if (s->m_len > 0) {
-            bool paintSelectedTextOnly = (i.phase == PaintActionSelection);
-            bool paintSelectedTextSeparately = false; // Whether or not we have to do multiple paints.  Only
-            // necessary when a custom ::selection foreground color is applied.
-            QColor selectionColor = p->pen().color();
-            ShadowData* selectionTextShadow = 0;
-            if (haveSelection) {
-                RenderStyle* pseudoStyle = getPseudoStyle(RenderStyle::SELECTION);
-                if (pseudoStyle) {
-                    if (pseudoStyle->color() != selectionColor || pseudoStyle->textShadow()) {
-                        if (!paintSelectedTextOnly)
-                            paintSelectedTextSeparately = true;
-                        if (pseudoStyle->color() != selectionColor)
-                            selectionColor = pseudoStyle->color();
-                        if (pseudoStyle->textShadow())
-                            selectionTextShadow = pseudoStyle->textShadow();
-                    }
-                }
-            }
-
-            if (!paintSelectedTextOnly && !paintSelectedTextSeparately) {
-                // paint all the text
-
-                // FIXME: Handle RTL direction, handle reversed strings.  For now truncation can only be turned on
-                // for non-reversed LTR strings.
-                int endPoint = s->m_len;
-                if (s->m_truncation != cNoTruncation)
-                    endPoint = s->m_truncation - s->m_start;
-                font->drawText(p, s->m_x + tx, s->m_y + ty + s->m_baseline,
-                               str->s, str->l, s->m_start, endPoint,
-                               s->m_toAdd, s->m_reversed ? QPainter::RTL : QPainter::LTR, style()->visuallyOrdered());
-            } else {
-                int offset = s->m_start;
-                int sPos = QMAX( startPos - offset, 0 );
-                int ePos = QMIN( endPos - offset, s->m_len );
-                if (paintSelectedTextSeparately) {
-                    // paint only the text that is not selected
-
-                    if (sPos >= ePos) {
-                        font->drawText(p, s->m_x + tx, s->m_y + ty + s->m_baseline,
-                                       str->s, str->l, s->m_start, s->m_len,
-                                       s->m_toAdd, s->m_reversed ? QPainter::RTL : QPainter::LTR, style()->visuallyOrdered());
-                    } else {
-                        if (sPos-1 >= 0) {
-                            font->drawText(p, s->m_x + tx, s->m_y + ty + s->m_baseline, str->s,
-                                           str->l, s->m_start, s->m_len,
-                                           s->m_toAdd, s->m_reversed ? QPainter::RTL : QPainter::LTR, style()->visuallyOrdered(), 0, sPos);
-                        }
-                        if (ePos < s->m_start+s->m_len) {
-                            font->drawText(p, s->m_x + tx, s->m_y + ty + s->m_baseline, str->s,
-                                           str->l, s->m_start, s->m_len,
-                                           s->m_toAdd, s->m_reversed ? QPainter::RTL : QPainter::LTR, style()->visuallyOrdered(), ePos, -1);
-                        }
-                    }
-                }
-                
-                if ( sPos < ePos ) {
-                    // paint only the text that is selected
-                    if (selectionColor != p->pen().color())
-                        p->setPen(selectionColor);
-                    
-                    if (selectionTextShadow)
-                        p->setShadow(selectionTextShadow->x,
-                                     selectionTextShadow->y,
-                                     selectionTextShadow->blur,
-                                     selectionTextShadow->color);
-                    font->drawText(p, s->m_x + tx, s->m_y + ty + s->m_baseline, str->s,
-                                   str->l, s->m_start, s->m_len,
-                                   s->m_toAdd, s->m_reversed ? QPainter::RTL : QPainter::LTR, style()->visuallyOrdered(), sPos, ePos);
-                    if (selectionTextShadow)
-                        p->clearShadow();
-                }
-            } 
-        }
-
-        // paint decorations
-
-        if (d != TDNONE && i.phase != PaintActionSelection &&
-            style()->htmlHacks()) {
-            p->setPen(_style->color());
-            s->paintDecoration(p, tx, ty, d);
-        }
-
-        // Draw any doc markers that touch this run
-        // Note s->end() points at the last char, not one past it like endOffset and ranges do
-        
-        if (i.phase != PaintActionSelection) {
-            for ( ; markerIt != markers.end(); markerIt++) {
-                DocumentMarker marker = *markerIt;
-
-                if (marker.endOffset <= s->start()) {
-                    // marker is completely before this run.  This might be a marker that sits before the
-                    // first run we draw, or markers that were within runs we skipped due to truncation.
-                    continue;
-                }
-                
-                if (marker.startOffset <= s->end()) {
-                    // marker intersects this run.  Paint it.
-                    s->paintMarker(p, tx, ty, marker);
-                    if (marker.endOffset > s->end()+1) {
-                        // marker also runs into the next run. Bail now, no more marker advancement.
-                        break;
-                    }
-                } else {
-                    // marker is completely after this run, bail.  A later run will paint it.
-                    break;
-                }
-            }
-        }
-
-        if (setShadow)
-            p->clearShadow();
-        
-#ifdef BIDI_DEBUG
-        {
-            int h = lineHeight( false ) + paddingTop() + paddingBottom() + borderTop() + borderBottom();
-            QColor c2 = QColor("#0000ff");
-            drawBorder(p, tx, ty, tx+1, ty + h,
-                       RenderObject::BSLeft, c2, c2, SOLID, 1, 1);
-            drawBorder(p, tx + s->m_width, ty, tx + s->m_width + 1, ty + h,
-                       RenderObject::BSRight, c2, c2, SOLID, 1, 1);
-        }
-#endif
-    } while (((s = s->nextTextBox()) != 0) && s->checkVerticalPoint(i.r.y(), ty, i.r.height()));
-#else
-#error This file no longer works without Apple changes
-#endif
-}
-
 #ifdef APPLE_CHANGES
 
 bool RenderText::allAscii() const
index 5d661a03150533ced5016f339be6dc00af62bac9..00ae2a2800f6d50a13796155bb2ad1fb68ddbd3f 100644 (file)
@@ -79,7 +79,11 @@ public:
     
     QRect selectionRect(int absx, int absy, int startPos, int endPos);
     bool isSelected(int startPos, int endPos) const;
+    void selectionStartEnd(int& sPos, int& ePos);
     
+    virtual void paint(RenderObject::PaintInfo& i, int tx, int ty);
+    virtual bool nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty);
+
     RenderText* textObject();
     
     virtual void deleteLine(RenderArena* arena);
@@ -110,12 +114,10 @@ public:
     virtual bool isText() const { return m_treatAsText; }
     void setIsText(bool b) { m_treatAsText = b; }
     
-    void paintDecoration( QPainter *pt, int _tx, int _ty, int decoration);
-    void paintSelection(const Font *f, RenderText *text, QPainter *p, RenderStyle* style, int tx, int ty, int startPos, int endPos);
-#if APPLE_CHANGES
-    void paintMarkedTextBackground(const Font *f, RenderText *text, QPainter *p, RenderStyle* style, int tx, int ty, int startPos, int endPos);
-#endif
-    void paintMarker(QPainter *pt, int _tx, int _ty, DOM::DocumentMarker marker);
+    void paintDecoration(QPainter* p, int _tx, int _ty, int decoration);
+    void paintSelection(QPainter* p, int tx, int ty, RenderStyle* style, const Font* font);
+    void paintMarkedTextBackground(QPainter* p, int tx, int ty, RenderStyle* style, const Font* font, int startPos, int endPos);
+    void paintMarker(QPainter* p, int _tx, int _ty, DOM::DocumentMarker marker);
 
     virtual long caretMinOffset() const;
     virtual long caretMaxOffset() const;
@@ -158,8 +160,6 @@ public:
     virtual const char *renderName() const { return "RenderText"; }
 
     virtual void setStyle(RenderStyle *style);
-    
-    virtual void paint(PaintInfo& i, int tx, int ty);
 
     void extractTextBox(InlineTextBox* textBox);
     void attachTextBox(InlineTextBox* textBox);
@@ -173,10 +173,11 @@ public:
     virtual InlineBox* createInlineBox(bool,bool, bool isOnlyRun = false);
     virtual void dirtyLineBoxes(bool fullLayout, bool isRootInlineBox = false);
     
-    virtual void layout() {assert(false);}
+    virtual void paint(PaintInfo& i, int tx, int ty) { assert(false); }
+    virtual void layout() { assert(false); }
 
     virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty,
-                             HitTestAction hitTestAction = HitTestAll, bool inside=false);
+                             HitTestAction hitTestAction) { assert(false); return false; }
 
     virtual void absoluteRects(QValueList<QRect>& rects, int _tx, int _ty);
 
index b64ebc09dd29f8629451ba522ac055ed575a3aa2..5a41d1e42fd98f60c87e2e128b916bd9b4d460fc 100644 (file)
@@ -399,7 +399,7 @@ void MouseEventImpl::computeLayerPos()
     }
 
     khtml::RenderObject::NodeInfo renderInfo(true, false);
-    doc->renderer()->layer()->nodeAtPoint(renderInfo, m_clientX, m_clientY);
+    doc->renderer()->layer()->hitTest(renderInfo, m_clientX, m_clientY);
 
     NodeImpl *node = renderInfo.innerNonSharedNode();
     while (node && !node->renderer()) {
index 2343eed96a2d6e651303cd1080e9f7f76382c554..4b21d06e09153e8957e6c75c433f4d9978a0a190 100644 (file)
@@ -1900,7 +1900,7 @@ bool DocumentImpl::prepareMouseEvent( bool readonly, int _x, int _y, MouseEvent
     if ( m_render ) {
         assert(m_render->isCanvas());
         RenderObject::NodeInfo renderInfo(readonly, ev->type == MousePress);
-        bool isInside = m_render->layer()->nodeAtPoint(renderInfo, _x, _y);
+        bool isInside = m_render->layer()->hitTest(renderInfo, _x, _y);
         ev->innerNode = renderInfo.innerNode();
 
         if (renderInfo.URLElement()) {
index a62c695cbabb57184f6adc46af0bfbeae882f557..cdea37052cac0b92f664f8d91ba445c6ecd2ed1f 100644 (file)
@@ -659,7 +659,7 @@ static QRect boundingBoxRect(RenderObject* obj)
         return self;
     
     RenderObject::NodeInfo nodeInfo(true, true);
-    m_renderer->layer()->nodeAtPoint(nodeInfo, (int)point.x, (int)point.y);
+    m_renderer->layer()->hitTest(nodeInfo, (int)point.x, (int)point.y);
     if (!nodeInfo.innerNode())
         return self;
     RenderObject* obj = nodeInfo.innerNode()->renderer();
index 09a209547a547d36850a192e92d2e5a89fa1e6a6..bce69edae16c47af7c9d3276dbbc522bde31c507 100644 (file)
@@ -1041,7 +1041,7 @@ bool KWQKHTMLPart::scrollOverflowWithScrollWheelEvent(NSEvent *event)
     
     NSPoint point = [d->m_view->getDocumentView() convertPoint:[event locationInWindow] fromView:nil];
     RenderObject::NodeInfo nodeInfo(true, true);
-    r->layer()->nodeAtPoint(nodeInfo, (int)point.x, (int)point.y);    
+    r->layer()->hitTest(nodeInfo, (int)point.x, (int)point.y);    
     
     NodeImpl *node = nodeInfo.innerNode();
     if (node == 0) {
@@ -2206,7 +2206,7 @@ bool KWQKHTMLPart::eventMayStartDrag(NSEvent *event) const
     int mouseDownX, mouseDownY;
     d->m_view->viewportToContents((int)loc.x, (int)loc.y, mouseDownX, mouseDownY);
     RenderObject::NodeInfo nodeInfo(true, false);
-    renderer()->layer()->nodeAtPoint(nodeInfo, mouseDownX, mouseDownY);
+    renderer()->layer()->hitTest(nodeInfo, mouseDownX, mouseDownY);
     bool srcIsDHTML;
     Node possibleSrc = nodeInfo.innerNode()->renderer()->draggableNode(DHTMLFlag, UAFlag, mouseDownX, mouseDownY, srcIsDHTML);
     return !possibleSrc.isNull();
@@ -2241,7 +2241,7 @@ void KWQKHTMLPart::khtmlMouseMoveEvent(MouseMoveEvent *event)
         if (_mouseDownMayStartDrag && _dragSrc.isNull()) {
             // try to find an element that wants to be dragged
             RenderObject::NodeInfo nodeInfo(true, false);
-            renderer()->layer()->nodeAtPoint(nodeInfo, _mouseDownX, _mouseDownY);
+            renderer()->layer()->hitTest(nodeInfo, _mouseDownX, _mouseDownY);
             _dragSrc = nodeInfo.innerNode()->renderer()->draggableNode(_dragSrcMayBeDHTML, _dragSrcMayBeUA, _mouseDownX, _mouseDownY, _dragSrcIsDHTML);
             if (_dragSrc.isNull()) {
                 _mouseDownMayStartDrag = false;     // no element is draggable
index 067122b6379cb331723741750c8c7dda683c720f..9113ec2d3f4afa0a70da2b61d90a6baa8295caf6 100644 (file)
@@ -971,7 +971,7 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
         return nil;
     }
     RenderObject::NodeInfo nodeInfo(true, true);
-    renderer->layer()->nodeAtPoint(nodeInfo, (int)point.x, (int)point.y);
+    renderer->layer()->hitTest(nodeInfo, (int)point.x, (int)point.y);
     
     NSMutableDictionary *element = [NSMutableDictionary dictionary];
     [element setObject:[NSNumber numberWithBool:_part->isPointInsideSelection((int)point.x, (int)point.y)]
@@ -1652,7 +1652,7 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
     }
     
     RenderObject::NodeInfo nodeInfo(true, true);
-    renderer->layer()->nodeAtPoint(nodeInfo, (int)point.x, (int)point.y);
+    renderer->layer()->hitTest(nodeInfo, (int)point.x, (int)point.y);
     NodeImpl *node = nodeInfo.innerNode();
     if (!node->renderer())
         return Position();