Fix for 3674601, "Read More..." links should trail articles in Emerson.
authorhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 17 Jun 2004 18:09:49 +0000 (18:09 +0000)
committerhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 17 Jun 2004 18:09:49 +0000 (18:09 +0000)
        Reviewed by darin

        * khtml/rendering/bidi.cpp:
        (khtml::RenderBlock::layoutInlineChildren):
        (khtml::RenderBlock::deleteEllipsisLineBoxes):
        (khtml::RenderBlock::checkLinesForTextOverflow):
        * khtml/rendering/render_block.cpp:
        (khtml:::RenderFlow):
        (khtml::RenderBlock::paintEllipsisBoxes):
        (khtml::RenderBlock::nodeAtPoint):
        (khtml::shouldCheckLines):
        (khtml::getLineAtIndex):
        (khtml::getHeightForLineCount):
        (khtml::RenderBlock::lineAtIndex):
        (khtml::RenderBlock::lineCount):
        (khtml::RenderBlock::heightForLineCount):
        (khtml::RenderBlock::clearTruncation):
        * khtml/rendering/render_block.h:
        (khtml::RenderBlock::setHasMarkupTruncation):
        (khtml::RenderBlock::hasMarkupTruncation):
        * khtml/rendering/render_flexbox.cpp:
        (khtml::RenderFlexibleBox::layoutVerticalBox):
        * khtml/rendering/render_line.cpp:
        (khtml::EllipsisBox::m_str):
        (khtml::InlineBox::adjustPosition):
        (khtml::InlineFlowBox::adjustPosition):
        (khtml::InlineFlowBox::clearTruncation):
        (khtml::EllipsisBox::paint):
        (khtml::EllipsisBox::nodeAtPoint):
        (khtml::RootInlineBox::clearTruncation):
        (khtml::RootInlineBox::placeEllipsis):
        (khtml::RootInlineBox::paintEllipsisBox):
        (khtml::RootInlineBox::hitTestEllipsisBox):
        (khtml::RootInlineBox::adjustPosition):
        (khtml::RootInlineBox::childRemoved):
        * khtml/rendering/render_line.h:
        (khtml::InlineBox::clearTruncation):
        * khtml/rendering/render_text.cpp:
        * khtml/rendering/render_text.h:
        (khtml::InlineTextBox::clearTruncation):

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

WebCore/ChangeLog-2005-08-23
WebCore/khtml/rendering/bidi.cpp
WebCore/khtml/rendering/render_block.cpp
WebCore/khtml/rendering/render_block.h
WebCore/khtml/rendering/render_flexbox.cpp
WebCore/khtml/rendering/render_line.cpp
WebCore/khtml/rendering/render_line.h
WebCore/khtml/rendering/render_text.cpp
WebCore/khtml/rendering/render_text.h

index 07658eb..271ae1e 100644 (file)
@@ -1,3 +1,48 @@
+2004-06-17  David Hyatt  <hyatt@apple.com>
+
+       Fix for 3674601, "Read More..." links should trail articles in Emerson.
+       
+        Reviewed by darin
+
+        * khtml/rendering/bidi.cpp:
+        (khtml::RenderBlock::layoutInlineChildren):
+        (khtml::RenderBlock::deleteEllipsisLineBoxes):
+        (khtml::RenderBlock::checkLinesForTextOverflow):
+        * khtml/rendering/render_block.cpp:
+        (khtml:::RenderFlow):
+        (khtml::RenderBlock::paintEllipsisBoxes):
+        (khtml::RenderBlock::nodeAtPoint):
+        (khtml::shouldCheckLines):
+        (khtml::getLineAtIndex):
+        (khtml::getHeightForLineCount):
+        (khtml::RenderBlock::lineAtIndex):
+        (khtml::RenderBlock::lineCount):
+        (khtml::RenderBlock::heightForLineCount):
+        (khtml::RenderBlock::clearTruncation):
+        * khtml/rendering/render_block.h:
+        (khtml::RenderBlock::setHasMarkupTruncation):
+        (khtml::RenderBlock::hasMarkupTruncation):
+        * khtml/rendering/render_flexbox.cpp:
+        (khtml::RenderFlexibleBox::layoutVerticalBox):
+        * khtml/rendering/render_line.cpp:
+        (khtml::EllipsisBox::m_str):
+        (khtml::InlineBox::adjustPosition):
+        (khtml::InlineFlowBox::adjustPosition):
+        (khtml::InlineFlowBox::clearTruncation):
+        (khtml::EllipsisBox::paint):
+        (khtml::EllipsisBox::nodeAtPoint):
+        (khtml::RootInlineBox::clearTruncation):
+        (khtml::RootInlineBox::placeEllipsis):
+        (khtml::RootInlineBox::paintEllipsisBox):
+        (khtml::RootInlineBox::hitTestEllipsisBox):
+        (khtml::RootInlineBox::adjustPosition):
+        (khtml::RootInlineBox::childRemoved):
+        * khtml/rendering/render_line.h:
+        (khtml::InlineBox::clearTruncation):
+        * khtml/rendering/render_text.cpp:
+        * khtml/rendering/render_text.h:
+        (khtml::InlineTextBox::clearTruncation):
+
 2004-06-17  Trey Matteson  <trey@apple.com>
 
        3698514 - coordinates in ondragstart and ondrag events are wrong
index 3285d27..576ba79 100644 (file)
@@ -1369,8 +1369,6 @@ QRect RenderBlock::layoutInlineChildren(bool relayoutChildren)
             else if (o->isText() || (o->isInlineFlow() && !endOfInline)) {
                 if (fullLayout || o->selfNeedsLayout())
                     o->dirtyLineBoxes(fullLayout);
-                if (hasTextOverflow && isText())
-                    static_cast<RenderText*>(o)->clearTextOverflowTruncation();
                 o->setNeedsLayout(false);
             }
             o = Bidinext( this, o, bidi, false, &endOfInline);
@@ -1517,7 +1515,7 @@ QRect RenderBlock::layoutInlineChildren(bool relayoutChildren)
                 int delta = m_height - endLineYPos;
                 if (delta)
                     for (RootInlineBox* line = endLine; line; line = line->nextRootBox())
-                        line->adjustVerticalPosition(delta);
+                        line->adjustPosition(0, delta);
 
                 // Now set our height and check for overflow.
                 int currYPos = m_height;
@@ -2252,16 +2250,15 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi
 
 void RenderBlock::deleteEllipsisLineBoxes()
 {
-    RenderArena* arena = renderArena();
     for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox())
-        curr->detachEllipsisBox(arena);
+        curr->clearTruncation();
 }
 
 void RenderBlock::checkLinesForTextOverflow()
 {
     // Determine the width of the ellipsis using the current font.
     QChar ellipsis = 0x2026; // FIXME: CSS3 says this is configurable, also need to use 0x002E (FULL STOP) if 0x2026 not renderable
-    AtomicString ellipsisStr(ellipsis);
+    static AtomicString ellipsisStr(ellipsis);
     const Font& firstLineFont = style(true)->htmlFont();
     const Font& font = style()->htmlFont();
     int firstLineEllipsisWidth = firstLineFont.width(&ellipsis, 1, 0);
@@ -2272,11 +2269,8 @@ void RenderBlock::checkLinesForTextOverflow()
     // check the left edge of the line box to see if it is less
     // Include the scrollbar for overflow blocks, which means we want to use "contentWidth()"
     bool ltr = style()->direction() == LTR;
-    int blockEdge = ltr ? 
-                    borderLeft() + paddingLeft() + contentWidth() :
-                    borderLeft() + paddingLeft(); // FIXME: In theory we will one day do RTL scrollbars, and then this
-                                                  // RTL computation will want to add in the vertical scroller's width.
     for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
+        int blockEdge = ltr ? rightOffset(curr->yPos()) : leftOffset(curr->yPos());
         int lineBoxEdge = ltr ? curr->xPos() + curr->width() : curr->xPos();
         if ((ltr && lineBoxEdge > blockEdge) || (!ltr && lineBoxEdge < blockEdge)) {
             // This line spills out of our box in the appropriate direction.  Now we need to see if the line
index 629c504..99c2d77 100644 (file)
@@ -55,6 +55,7 @@ RenderBlock::RenderBlock(DOM::NodeImpl* node)
     m_pre = false;
     m_firstLine = false;
     m_linesAppended = false;
+    m_hasMarkupTruncation = false;
     m_clearStatus = CNONE;
     m_maxTopPosMargin = m_maxTopNegMargin = m_maxBottomPosMargin = m_maxBottomNegMargin = 0;
     m_topMarginQuirk = m_bottomMarginQuirk = false;
@@ -1377,7 +1378,7 @@ void RenderBlock::paintEllipsisBoxes(PaintInfo& i, int _tx, int _ty)
             yPos = _ty + curr->yPos();
             h = curr->height();
             if (curr->ellipsisBox() && (yPos < i.r.y() + i.r.height()) && (yPos + h > i.r.y()))
-                curr->ellipsisBox()->paint(i, _tx, _ty);
+                curr->paintEllipsisBox(i, _tx, _ty);
         }
     }
 }
@@ -2043,22 +2044,34 @@ bool RenderBlock::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
     if (inScrollbar && hitTestAction != HitTestChildrenOnly)
         inBox = true;
     
-    if (hitTestAction != HitTestSelfOnly && m_floatingObjects && !inScrollbar) {
+    if (hitTestAction != HitTestSelfOnly && !inScrollbar) {
         int stx = _tx + xPos();
         int sty = _ty + yPos();
-        if (hasOverflowClip())
-            m_layer->subtractScrollOffset(stx, sty);
-        if (isCanvas()) {
-            stx += static_cast<RenderCanvas*>(this)->view()->contentsX();
-            sty += static_cast<RenderCanvas*>(this)->view()->contentsY();
+        
+        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 (hasMarkupTruncation()) {
+            for (RootInlineBox* box = lastRootBox(); box; box = box->prevRootBox()) {
+                if (box->ellipsisBox()) {
+                    inBox |= box->hitTestEllipsisBox(info, _x, _y, stx, sty, hitTestAction, inBox);
+                    break;
+                }
+            }
         }
-        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());
     }
 
     inBox |= RenderFlow::nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inBox);
@@ -2824,7 +2837,66 @@ bool RenderBlock::inRootBlockContext() const
     return containingBlock()->inRootBlockContext();
 }
 
-// Helper methods for computing line counts and heights for line counts.
+// Helper methods for obtaining the last line, computing line counts and heights for line counts
+// (crawling into blocks).
+static bool shouldCheckLines(RenderObject* obj)
+{
+    return !obj->isFloatingOrPositioned() && !obj->isCompact() && !obj->isRunIn() &&
+            obj->isBlockFlow() && obj->style()->height().isVariable() &&
+            (!obj->isFlexibleBox() || obj->style()->boxOrient() == VERTICAL);
+}
+
+static RootInlineBox* getLineAtIndex(RenderBlock* block, int i, int& count)
+{
+    if (block->style()->visibility() == VISIBLE) {
+        if (block->childrenInline()) {
+            for (RootInlineBox* box = block->firstRootBox(); box; box = box->nextRootBox()) {
+                if (count++ == i)
+                    return box;
+            }
+        }
+        else {
+            for (RenderObject* obj = block->firstChild(); obj; obj = obj->nextSibling()) {
+                if (shouldCheckLines(obj)) {
+                    RootInlineBox *box = getLineAtIndex(static_cast<RenderBlock*>(obj), i, count);
+                    if (box)
+                        return box;
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+int getHeightForLineCount(RenderBlock* block, int l, bool includeBottom, int& count)
+{
+    if (block->style()->visibility() == VISIBLE) {
+        if (block->childrenInline()) {
+            for (RootInlineBox* box = block->firstRootBox(); box; box = box->nextRootBox()) {
+                if (++count == l)
+                    return box->bottomOverflow() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0);
+            }
+        }
+        else {
+            for (RenderObject* obj = block->firstChild(); obj; obj = obj->nextSibling()) {
+                if (shouldCheckLines(obj)) {
+                    int result = getHeightForLineCount(static_cast<RenderBlock*>(obj), l, false, count);
+                    if (result != -1)
+                        return result + obj->yPos() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0);
+                }
+            }
+        }
+    }
+    
+    return -1;
+}
+
+RootInlineBox* RenderBlock::lineAtIndex(int i)
+{
+    int count = 0;
+    return getLineAtIndex(this, i, count);
+}
+
 int RenderBlock::lineCount()
 {
     int count = 0;
@@ -2834,35 +2906,31 @@ int RenderBlock::lineCount()
                 count++;
         else
             for (RenderObject* obj = firstChild(); obj; obj = obj->nextSibling())
-                if (!obj->isFloatingOrPositioned() && !obj->isCompact() && !obj->isRunIn() &&
-                    obj->isBlockFlow() && obj->style()->height().isVariable())
+                if (shouldCheckLines(obj))
                     count += static_cast<RenderBlock*>(obj)->lineCount();
     }
     return count;
 }
 
-int RenderBlock::heightForLineCount(int l, bool includeBottom)
+int RenderBlock::heightForLineCount(int l)
+{
+    int count = 0;
+    return getHeightForLineCount(this, l, true, count);
+}
+
+void RenderBlock::clearTruncation()
 {
     if (style()->visibility() == VISIBLE) {
-        int c = 0;
-        if (childrenInline())
-            for (RootInlineBox* box = firstRootBox(); c < l && box; box = box->nextRootBox()) {
-                if (++c == l)
-                    return box->bottomOverflow() + (includeBottom ? (borderBottom() + paddingBottom()) : 0);
-            }
+        if (childrenInline() && hasMarkupTruncation()) {
+            setHasMarkupTruncation(false);
+            for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox())
+                box->clearTruncation();
+        }
         else
             for (RenderObject* obj = firstChild(); obj; obj = obj->nextSibling())
-                if (!obj->isFloatingOrPositioned() && !obj->isCompact() && !obj->isRunIn() &&
-                    obj->isBlockFlow() && obj->style()->height().isVariable()) {
-                    int childCount = static_cast<RenderBlock*>(obj)->lineCount();
-                    if (c + childCount >= l)
-                        return obj->yPos() + static_cast<RenderBlock*>(obj)->heightForLineCount(l - c, false) +
-                               (includeBottom ? (borderBottom() + paddingBottom()) : 0);
-                    else
-                        c += childCount;
-                }
+                if (shouldCheckLines(obj))
+                    static_cast<RenderBlock*>(obj)->clearTruncation();
     }
-    return m_height;
 }
 
 const char *RenderBlock::renderName() const
index 82cb783..9cb16eb 100644 (file)
@@ -197,15 +197,20 @@ public:
     void setLinesAppended(bool b=true) { m_linesAppended = b; }
     bool linesAppended() const { return m_linesAppended; }
 
+    void setHasMarkupTruncation(bool b=true) { m_hasMarkupTruncation = b; }
+    bool hasMarkupTruncation() const { return m_hasMarkupTruncation; }
+
 #ifndef NDEBUG
     virtual void printTree(int indent=0) const;
     virtual void dump(QTextStream *stream, QString ind = "") const;
 #endif
 
     // Helper methods for computing line counts and heights for line counts.
+    RootInlineBox* lineAtIndex(int i);
     int lineCount();
-    int heightForLineCount(int l, bool includeBottom = true);
-    
+    int heightForLineCount(int l);
+    void clearTruncation();
+
 protected:
     void newLine();
     void removeChildrenFromLineBoxes();
@@ -251,6 +256,7 @@ protected:
     bool m_topMarginQuirk : 1;
     bool m_bottomMarginQuirk : 1;
     bool m_linesAppended : 1; // Whether or not a block with inline children has had lines appended.
+    bool m_hasMarkupTruncation : 1;
 
     short m_maxTopPosMargin;
     short m_maxTopNegMargin;
index 57d9762..fed151b 100644 (file)
@@ -705,6 +705,7 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
                     
                     // Dirty all the positioned objects.
                     static_cast<RenderBlock*>(child)->markPositionedObjectsForLayout();
+                    static_cast<RenderBlock*>(child)->clearTruncation();
                 }
                 child->layoutIfNeeded();
                 if (child->style()->height().isVariable() && child->isBlockFlow())
@@ -715,23 +716,67 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
         
         // Get the # of lines and then alter all block flow children with auto height to use the
         // specified height.
-        int numLines = int(maxLineCount*style()->lineClamp()/100.0 + 1.0);
-        if (numLines < maxLineCount) {
-            child = iterator.first();
-            while (child) {
-                if (!child->isPositioned() && child->style()->height().isVariable() && child->isBlockFlow() &&
-                    static_cast<RenderBlock*>(child)->lineCount() > numLines) {
-                    int newHeight = static_cast<RenderBlock*>(child)->heightForLineCount(numLines);
-                    if (newHeight != child->height()) {
-                        child->setChildNeedsLayout(true);
-                        child->setOverrideSize(newHeight);
-                        m_flexingChildren = true;
-                        child->layoutIfNeeded();
-                        m_flexingChildren = false;
-                        child->setOverrideSize(-1);
-                    }
-                }
-                child = iterator.next();
+        int numVisibleLines = int(maxLineCount*style()->lineClamp()/100.0 + 1.0);
+        if (numVisibleLines < maxLineCount) {
+            for (child = iterator.first(); child; child = iterator.next()) {
+                if (child->isPositioned() || !child->style()->height().isVariable() || !child->isBlockFlow())
+                    continue;
+                
+                RenderBlock* blockChild = static_cast<RenderBlock*>(child);
+                int lineCount = blockChild->lineCount();
+                if (lineCount <= numVisibleLines) continue;
+                
+                int newHeight = blockChild->heightForLineCount(numVisibleLines);
+                if (newHeight == child->height()) continue;
+                
+                child->setChildNeedsLayout(true);
+                child->setOverrideSize(newHeight);
+                m_flexingChildren = true;
+                child->layoutIfNeeded();
+                m_flexingChildren = false;
+                child->setOverrideSize(-1);
+                
+                // FIXME: For now don't support RTL.
+                if (style()->direction() != LTR) continue;
+                
+                // Get the last line
+                RootInlineBox* lastLine = blockChild->lineAtIndex(lineCount-1);
+                if (!lastLine) continue;
+                
+                // See if the last item is an anchor
+                InlineBox* anchorBox = lastLine->lastChild();
+                if (!anchorBox) continue;
+                if (!anchorBox->object()->element()) continue;
+                if (!anchorBox->object()->element()->hasAnchor()) continue;
+                
+                RootInlineBox* lastVisibleLine = blockChild->lineAtIndex(numVisibleLines-1);
+                if (!lastVisibleLine) continue;
+
+                const unsigned short ellipsisAndSpace[2] = { 0x2026, ' ' };
+                static AtomicString ellipsisAndSpaceStr(ellipsisAndSpace, 2);
+                const Font& font = style(numVisibleLines == 1)->htmlFont();
+                int ellipsisAndSpaceWidth = font.width(const_cast<QChar*>(ellipsisAndSpaceStr.unicode()), 2, 0, 2);
+
+                // Get ellipsis width + " " + anchor width
+                int totalWidth = ellipsisAndSpaceWidth + anchorBox->width();
+                
+                // See if this width can be accommodated on the last visible line
+                RenderBlock* destBlock = static_cast<RenderBlock*>(lastVisibleLine->object());
+                RenderBlock* srcBlock = static_cast<RenderBlock*>(lastLine->object());
+                
+                // FIXME: Directions of src/destBlock could be different from our direction and from one another.
+                if (srcBlock->style()->direction() != LTR) continue;
+                if (destBlock->style()->direction() != LTR) continue;
+
+                int blockEdge = destBlock->rightOffset(lastVisibleLine->yPos());
+                if (!lastVisibleLine->canAccommodateEllipsis(true, blockEdge, 
+                                                             lastVisibleLine->xPos() + lastVisibleLine->width(),
+                                                             totalWidth))
+                    continue;
+
+                // Let the truncation code kick in.
+                lastVisibleLine->placeEllipsis(ellipsisAndSpaceStr, true, blockEdge, totalWidth, anchorBox);
+                destBlock->setHasMarkupTruncation(true);
             }
         }
     }
index 99d72f4..29a1056 100644 (file)
 #include "htmltags.h"
 
 using namespace DOM;
-using namespace khtml;
 
 #ifndef NDEBUG
 static bool inInlineBoxDetach;
 #endif
 
+namespace khtml {
+    
+class EllipsisBox : public InlineBox
+{
+public:
+    EllipsisBox(RenderObject* obj, const DOM::AtomicString& ellipsisStr, InlineFlowBox* p,
+                int w, int y, int h, int b, bool firstLine, InlineBox* markupBox)
+    :InlineBox(obj), m_str(ellipsisStr) {
+        m_parent = p;
+        m_width = w;
+        m_y = y;
+        m_height = h;
+        m_baseline = b;
+        m_firstLine = firstLine;
+        m_constructed = true;
+        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);
+
+private:
+    DOM::AtomicString m_str;
+    InlineBox* m_markupBox;
+};
+
 void InlineBox::remove()
 { 
     if (parent())
@@ -119,11 +145,12 @@ void InlineBox::attachLine()
     m_object->setInlineBoxWrapper(this);
 }
 
-void InlineBox::adjustVerticalPosition(int delta)
+void InlineBox::adjustPosition(int dx, int dy)
 {
-    m_y += delta;
+    m_x += dx;
+    m_y += dy;
     if (m_object->isReplaced() || m_object->isBR())
-        m_object->setPos(m_object->xPos(), m_object->yPos() + delta);
+        m_object->setPos(m_object->xPos() + dx, m_object->yPos() + dy);
 }
 
 RootInlineBox* InlineBox::root()
@@ -291,11 +318,11 @@ void InlineFlowBox::attachLine()
         child->attachLine();
 }
 
-void InlineFlowBox::adjustVerticalPosition(int delta)
+void InlineFlowBox::adjustPosition(int dx, int dy)
 {
-    InlineRunBox::adjustVerticalPosition(delta);
+    InlineRunBox::adjustPosition(dx, dy);
     for (InlineBox* child = m_firstChild; child; child = child->nextOnLine())
-        child->adjustVerticalPosition(delta);
+        child->adjustPosition(dx, dy);
 }
 
 bool InlineFlowBox::onEndChain(RenderObject* endObject)
@@ -857,7 +884,13 @@ int InlineFlowBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth,
     return result;
 }
 
-void EllipsisBox::paint(const RenderObject::PaintInfo& i, int _tx, int _ty)
+void InlineFlowBox::clearTruncation()
+{
+    for (InlineBox *box = firstChild(); box; box = box->nextOnLine())
+        box->clearTruncation();
+}
+
+void EllipsisBox::paint(RenderObject::PaintInfo& i, int _tx, int _ty)
 {
     QPainter* p = i.p;
     RenderStyle* _style = m_firstLine ? m_object->style(true) : m_object->style();
@@ -885,6 +918,25 @@ void EllipsisBox::paint(const RenderObject::PaintInfo& i, int _tx, int _ty)
                       
     if (setShadow)
         p->clearShadow();
+    
+    if (m_markupBox) {
+        // 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);
+    }
+}
+
+bool EllipsisBox::nodeAtPoint(RenderObject::NodeInfo& info, int _x, int _y, int _tx, int _ty,
+                              HitTestAction hitTestAction, bool inBox)
+{
+    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);
+    }
+    
+    return inBox;
 }
 
 void RootInlineBox::detach(RenderArena* arena)
@@ -901,6 +953,14 @@ void RootInlineBox::detachEllipsisBox(RenderArena* arena)
     }
 }
 
+void RootInlineBox::clearTruncation()
+{
+    if (m_ellipsisBox) {
+        detachEllipsisBox(m_object->renderArena());
+        InlineFlowBox::clearTruncation();
+    }
+}
+
 bool RootInlineBox::canAccommodateEllipsis(bool ltr, int blockEdge, int lineBoxEdge, int ellipsisWidth)
 {
     // First sanity-check the unoverflowed width of the whole line to see if there is sufficient room.
@@ -913,11 +973,19 @@ bool RootInlineBox::canAccommodateEllipsis(bool ltr, int blockEdge, int lineBoxE
     return InlineFlowBox::canAccommodateEllipsis(ltr, blockEdge, ellipsisWidth);
 }
 
-void RootInlineBox::placeEllipsis(const AtomicString& ellipsisStr,  bool ltr, int blockEdge, int ellipsisWidth)
+void RootInlineBox::placeEllipsis(const AtomicString& ellipsisStr,  bool ltr, int blockEdge, int ellipsisWidth,
+                                  InlineBox* markupBox)
 {
     // Create an ellipsis box.
-    m_ellipsisBox = new (m_object->renderArena()) EllipsisBox(m_object, ellipsisStr, this, ellipsisWidth,
-                                                              yPos(), height(), baseline(), !prevRootBox());
+    m_ellipsisBox = new (m_object->renderArena()) EllipsisBox(m_object, ellipsisStr, this, 
+                                                              ellipsisWidth - (markupBox ? markupBox->width() : 0),
+                                                              yPos(), height(), baseline(), !prevRootBox(),
+                                                              markupBox);
+
+    if (ltr && (xPos() + width() + ellipsisWidth) <= blockEdge) {
+        m_ellipsisBox->m_x = xPos() + width();
+        return;
+    }
 
     // Now attempt to find the nearest glyph horizontally and place just to the right (or left in RTL)
     // of that glyph.  Mark all of the objects that intersect the ellipsis box as not painting (as being
@@ -934,12 +1002,26 @@ int RootInlineBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth,
     return result;
 }
 
-void RootInlineBox::adjustVerticalPosition(int delta)
+void RootInlineBox::paintEllipsisBox(RenderObject::PaintInfo& i, int _tx, int _ty) const
 {
-    InlineFlowBox::adjustVerticalPosition(delta);
-    m_topOverflow += delta;
-    m_bottomOverflow += delta;
-    m_blockHeight += delta;
+    if (m_ellipsisBox)
+        m_ellipsisBox->paint(i, _tx, _ty);
+}
+
+bool RootInlineBox::hitTestEllipsisBox(RenderObject::NodeInfo& info, int _x, int _y, int _tx, int _ty,
+                                       HitTestAction hitTestAction, bool inBox)
+{
+    if (m_ellipsisBox)
+        inBox |= m_ellipsisBox->nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inBox);
+    return inBox;
+}
+
+void RootInlineBox::adjustPosition(int dx, int dy)
+{
+    InlineFlowBox::adjustPosition(dx, dy);
+    m_topOverflow += dy;
+    m_bottomOverflow += dy;
+    m_blockHeight += dy;
 }
 
 void RootInlineBox::childRemoved(InlineBox* box)
@@ -953,3 +1035,5 @@ void RootInlineBox::childRemoved(InlineBox* box)
         prev->markDirty();
     }
 }
+
+}
index 4336ed1..3b2feaf 100644 (file)
@@ -30,6 +30,7 @@ class AtomicString;
 
 namespace khtml {
 
+class EllipsisBox;
 class InlineFlowBox;
 class RootInlineBox;
 
@@ -55,7 +56,7 @@ public:
     virtual void extractLine();
     virtual void attachLine();
 
-    virtual void adjustVerticalPosition(int delta);
+    virtual void adjustPosition(int dx, int dy);
 
     // Overloaded new operator.
     void* operator new(size_t sz, RenderArena* renderArena) throw();
@@ -129,6 +130,8 @@ public:
     virtual long caretMaxOffset() const;
     virtual unsigned long caretMaxRenderedOffset() const;
     
+    virtual void clearTruncation() {};
+
     bool isDirty() const { return m_dirty; }
     void markDirty(bool dirty=true) { m_dirty = dirty; }
 
@@ -227,8 +230,10 @@ public:
     virtual void deleteLine(RenderArena* arena);
     virtual void extractLine();
     virtual void attachLine();
-    virtual void adjustVerticalPosition(int delta);
+    virtual void adjustPosition(int dx, int dy);
 
+    virtual void clearTruncation();
+    
     virtual void paintBackgroundAndBorder(RenderObject::PaintInfo& i, int _tx, int _ty, int xOffsetOnLine);
     virtual void paintDecorations(RenderObject::PaintInfo& i, int _tx, int _ty, bool paintedChildren = false);
     
@@ -278,27 +283,6 @@ protected:
     bool m_hasTextChildren : 1;
 };
 
-class EllipsisBox : public InlineBox
-{
-public:
-    EllipsisBox(RenderObject* obj, const DOM::AtomicString& ellipsisStr, InlineFlowBox* p,
-                int w, int y, int h, int b, bool firstLine)
-    :InlineBox(obj), m_str(ellipsisStr) {
-        m_parent = p;
-        m_width = w;
-        m_y = y;
-        m_height = h;
-        m_baseline = b;
-        m_firstLine = firstLine;
-        m_constructed = true;
-    }
-
-    void paint(const RenderObject::PaintInfo& i, int _tx, int _ty);
-    
-private:
-    DOM::AtomicString m_str;
-};
-
 class RootInlineBox : public InlineFlowBox
 {
 public:
@@ -313,7 +297,7 @@ public:
     RootInlineBox* nextRootBox() { return static_cast<RootInlineBox*>(m_nextLine); }
     RootInlineBox* prevRootBox() { return static_cast<RootInlineBox*>(m_prevLine); }
 
-    virtual void adjustVerticalPosition(int delta);
+    virtual void adjustPosition(int dx, int dy);
     
     virtual bool isRootInlineBox() { return true; }
     virtual int topOverflow() { return m_topOverflow; }
@@ -335,11 +319,16 @@ public:
     void childRemoved(InlineBox* box);
 
     bool canAccommodateEllipsis(bool ltr, int blockEdge, int lineBoxEdge, int ellipsisWidth);
-    void placeEllipsis(const DOM::AtomicString& ellipsisStr, bool ltr, int blockEdge, int ellipsisWidth);
+    void placeEllipsis(const DOM::AtomicString& ellipsisStr, bool ltr, int blockEdge, int ellipsisWidth, InlineBox* markupBox = 0);
     virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool&);
 
     EllipsisBox* ellipsisBox() const { return m_ellipsisBox; }
-        
+    void paintEllipsisBox(RenderObject::PaintInfo& i, int _tx, int _ty) const;
+    bool hitTestEllipsisBox(RenderObject::NodeInfo& info, int _x, int _y, int _tx, int _ty,
+                            HitTestAction hitTestAction, bool inBox);
+    
+    virtual void clearTruncation();
+
 protected:
     // Normally we are only as tall as the style on our block dictates, but we might have content
     // that spills out above the height of our font (e.g, a tall image), or something that extends further
index d600004..d1cfdef 100644 (file)
@@ -1485,13 +1485,6 @@ InlineBox *RenderText::inlineBox(long offset)
     return 0;
 }
 
-void RenderText::clearTextOverflowTruncation()
-{
-    // Walk our text boxes and clear any truncation bits that might be set.
-    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
-        box->clearTruncation();
-}
-   
 RenderTextFragment::RenderTextFragment(DOM::NodeImpl* _node, DOM::DOMStringImpl* _str,
                                        int startOffset, int endOffset)
 :RenderText(_node, _str->substring(startOffset, endOffset)), 
index 9d4ec38..91e0fae 100644 (file)
@@ -79,7 +79,7 @@ public:
     virtual void extractLine();
     virtual void attachLine();
 
-    void clearTruncation() { m_truncation = cNoTruncation; }
+    virtual void clearTruncation() { m_truncation = cNoTruncation; }
     virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox);
 
     // Overloaded new operator.  Derived classes must override operator new
@@ -225,9 +225,7 @@ public:
     InlineTextBox* lastTextBox() const { return m_lastTextBox; }
     
     virtual InlineBox *inlineBox(long offset);
-    
-    void clearTextOverflowTruncation();
-    
+
 #if APPLE_CHANGES
     int widthFromCache(const Font *, int start, int len) const;
     bool shouldUseMonospaceCache(const Font *) const;