Make sure <br>s always get line boxes. Also prevent the creation of RenderTexts...
authorhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 29 Sep 2004 17:55:00 +0000 (17:55 +0000)
committerhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 29 Sep 2004 17:55:00 +0000 (17:55 +0000)
that follow <br>s.

        Reviewed by kocienda

        * khtml/editing/visible_position.cpp:
        (khtml::VisiblePosition::isCandidate):
        * khtml/rendering/render_br.cpp:
        (RenderBR::RenderBR):
        (RenderBR::createInlineBox):
        (RenderBR::baselinePosition):
        (RenderBR::lineHeight):
        * khtml/rendering/render_br.h:
        * khtml/rendering/render_line.cpp:
        (khtml::InlineFlowBox::placeBoxesVertically):
        * khtml/rendering/render_line.h:
        (khtml::InlineBox::isText):
        (khtml::InlineFlowBox::addToLine):
        * khtml/rendering/render_text.cpp:
        (RenderText::detach):
        * khtml/rendering/render_text.h:
        (khtml::InlineTextBox:::InlineRunBox):
        (khtml::InlineTextBox::isInlineTextBox):
        (khtml::InlineTextBox::isText):
        (khtml::InlineTextBox::setIsText):
        * khtml/xml/dom_textimpl.cpp:
        (TextImpl::rendererIsNeeded):
        * kwq/KWQRenderTreeDebug.cpp:
        (operator<<):

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

WebCore/ChangeLog-2005-08-23
WebCore/khtml/editing/visible_position.cpp
WebCore/khtml/rendering/render_br.cpp
WebCore/khtml/rendering/render_br.h
WebCore/khtml/rendering/render_line.cpp
WebCore/khtml/rendering/render_line.h
WebCore/khtml/rendering/render_text.cpp
WebCore/khtml/rendering/render_text.h
WebCore/khtml/xml/dom_textimpl.cpp
WebCore/kwq/KWQRenderTreeDebug.cpp

index bac317fdd65fd9cff6caa11a2c07fc8f15d98a2c..c321ef853d19909e54f8a08879c2efbf99d9a114 100644 (file)
@@ -1,3 +1,35 @@
+2004-09-29  David Hyatt  <hyatt@apple.com>
+
+       Make sure <br>s always get line boxes.  Also prevent the creation of RenderTexts for whitespace normal/nowrap nodes
+       that follow <br>s.
+       
+        Reviewed by kocienda
+
+        * khtml/editing/visible_position.cpp:
+        (khtml::VisiblePosition::isCandidate):
+        * khtml/rendering/render_br.cpp:
+        (RenderBR::RenderBR):
+        (RenderBR::createInlineBox):
+        (RenderBR::baselinePosition):
+        (RenderBR::lineHeight):
+        * khtml/rendering/render_br.h:
+        * khtml/rendering/render_line.cpp:
+        (khtml::InlineFlowBox::placeBoxesVertically):
+        * khtml/rendering/render_line.h:
+        (khtml::InlineBox::isText):
+        (khtml::InlineFlowBox::addToLine):
+        * khtml/rendering/render_text.cpp:
+        (RenderText::detach):
+        * khtml/rendering/render_text.h:
+        (khtml::InlineTextBox:::InlineRunBox):
+        (khtml::InlineTextBox::isInlineTextBox):
+        (khtml::InlineTextBox::isText):
+        (khtml::InlineTextBox::setIsText):
+        * khtml/xml/dom_textimpl.cpp:
+        (TextImpl::rendererIsNeeded):
+        * kwq/KWQRenderTreeDebug.cpp:
+        (operator<<):
+
 2004-09-29  Ken Kocienda  <kocienda@apple.com>
 
         Reviewed by John
index 77b7e7e3a5c1da516917af16d4d2415cade6ba12..b7b35b95f434a7d9f089a9ebaf5071332232ec5e 100644 (file)
@@ -259,9 +259,18 @@ bool VisiblePosition::isCandidate(const Position &pos)
         // return true for replaced elements
         return pos.offset() == 0 || pos.offset() == 1;
 
-    if (renderer->isBR() && static_cast<RenderText *>(renderer)->firstTextBox())
-        // return true for offset 0 into BR element on a line by itself
-        return pos.offset() == 0;
+    if (renderer->isBR()) {
+        if (pos.offset() == 0) {
+            InlineBox* box = static_cast<RenderText*>(renderer)->firstTextBox();
+            if (box) {
+                // return true for offset 0 into BR element on a line by itself
+                RootInlineBox* root = box->root();
+                if (root)
+                    return root->firstLeafChild() == box && root->lastLeafChild() == box;
+            }
+        }   
+        return false;
+    }
     
     if (renderer->isText()) {
         RenderText *textRenderer = static_cast<RenderText *>(renderer);
index 3f4dd8365ce8f115cdb20d761a349a2d71adadba..2b3c455515f0d03172151ecc86ad80c251ff09c3 100644 (file)
@@ -29,7 +29,7 @@ using namespace khtml;
 using DOM::Position;
 
 RenderBR::RenderBR(DOM::NodeImpl* node)
-    : RenderText(node, new DOM::DOMStringImpl(QChar('\n'))), m_x(0), m_y(0), m_height(0),
+    : RenderText(node, new DOM::DOMStringImpl(QChar('\n'))),
       m_lineHeight(-1)
 {
 }
@@ -38,33 +38,27 @@ RenderBR::~RenderBR()
 {
 }
 
-void RenderBR::setPos(int xPos, int yPos)
-{
-    m_x = xPos;
-    m_y = yPos;
-}
-
 InlineBox* RenderBR::createInlineBox(bool makePlaceholder, bool isRootLineBox, bool isOnlyRun)
 {
-    // We only make a box for a <br> if we are on a line by ourself or in strict mode
-    // (Note the use of strict mode.  In "almost strict" mode, we don't make a box for <br>.)
-    if (isOnlyRun || document()->inStrictMode())
-        return RenderText::createInlineBox(makePlaceholder, isRootLineBox, isOnlyRun);
-    return 0;
+    // We only treat a box as text for a <br> if we are on a line by ourself or in strict mode
+    // (Note the use of strict mode.  In "almost strict" mode, we don't treat the box for <br> as text.)
+    InlineTextBox* box = static_cast<InlineTextBox*>(RenderText::createInlineBox(makePlaceholder, isRootLineBox, isOnlyRun));
+    box->setIsText(isOnlyRun || document()->inStrictMode());
+    return box;
 }
 
-void RenderBR::position(InlineBox* box, int from, int len, bool reverse)
+short RenderBR::baselinePosition( bool firstLine, bool isRootLineBox) const
 {
-    InlineTextBox *s = static_cast<InlineTextBox*>(box);
-    
-    // We want the box to be destroyed, but get the position of it first.
-    m_x = s->xPos();
-    m_y = s->yPos();
-    m_height = s->height();
+    if (firstTextBox() && !firstTextBox()->isText())
+        return 0;
+    return RenderText::baselinePosition(firstLine, isRootLineBox);
 }
 
 short RenderBR::lineHeight(bool firstLine, bool isRootLineBox) const
 {
+    if (firstTextBox() && !firstTextBox()->isText())
+        return 0;
+
     if (firstLine) {
         RenderStyle* s = style(firstLine);
         Length lh = s->lineHeight();
index 7ccd3d67ab8fe8f49b82baa74d195f01a2fd3416..480acb867368cc76d5b523abcb3c76f9b4b22d18 100644 (file)
@@ -47,11 +47,11 @@ public:
     // FIXME: This is just temporary.
     virtual QRect selectionRect();
 
-    virtual void position(InlineBox* box, int from, int len, bool reverse);
     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; }
 
     virtual short lineHeight(bool firstLine, bool isRootLineBox=false) const;
+    virtual short baselinePosition( bool firstLine, bool isRootLineBox=false) const;
     virtual void setStyle(RenderStyle* _style);
 
     // overrides
@@ -60,11 +60,6 @@ public:
     virtual int minWidth() const { return 0; }
     virtual int maxWidth() const { return 0; }
 
-    virtual int xPos() const { return m_x; }
-    virtual int yPos() const { return m_y; }
-    virtual int height() const { return m_height; }
-    virtual void setPos(int xPos, int yPos);
-    
     virtual bool isBR() const { return true; }
 
     virtual long caretMinOffset() const;
@@ -77,9 +72,6 @@ public:
     virtual InlineBox *inlineBox(long offset);
     
 private:
-    int m_x;
-    int m_y;
-    int m_height;
     mutable short m_lineHeight;
 
 };
index 29a10569ddc92b6e9bb805358cfdcb537829e521..cef49287575e0ad073e1221e0bde5accecd6ff7b 100644 (file)
@@ -599,7 +599,7 @@ void InlineFlowBox::placeBoxesVertically(int y, int maxHeight, int maxAscent, bo
         int newY = curr->yPos();
         int newHeight = curr->height();
         int newBaseline = curr->baseline();
-        if (curr->isInlineTextBox() || curr->isInlineFlowBox()) {
+        if (curr->isText() || curr->isInlineFlowBox()) {
             const QFontMetrics &fm = curr->object()->fontMetrics( m_firstLine );
             newBaseline = fm.ascent();
             newY += curr->baseline() - newBaseline;
@@ -611,7 +611,7 @@ void InlineFlowBox::placeBoxesVertically(int y, int maxHeight, int maxAscent, bo
                 newBaseline += curr->object()->borderTop() + curr->object()->paddingTop();
             }  
         }
-        else {
+        else if (!curr->object()->isBR()) {
             newY += curr->object()->marginTop();
             newHeight = curr->height() - (curr->object()->marginTop() + curr->object()->marginBottom());
         }
index 3b2feafdc6b58a0bad60d51144efd68ded96ff8a..f81ef8797d2cae75d756756b08d6dd4d99b59ea4 100644 (file)
@@ -75,6 +75,8 @@ public:
     virtual bool isInlineTextBox() { return false; }
     virtual bool isRootInlineBox() { return false; }
     
+    virtual bool isText() const { return false; }
+
     bool isConstructed() { return m_constructed; }
     virtual void setConstructed() {
         m_constructed = true;
@@ -223,7 +225,7 @@ public:
         }
         child->setFirstLineStyleBit(m_firstLine);
         child->setParent(this);
-        if (child->isInlineTextBox())
+        if (child->isText())
             m_hasTextChildren = true;
     }
 
index 1eb8b9347943f88e6f80159980c4a0b7cf797408..5dcbee1015ca7303c8442d982f7287338c31c317 100644 (file)
@@ -488,11 +488,17 @@ RenderText::~RenderText()
 void RenderText::detach()
 {
     if (!documentBeingDestroyed()) {
-        if (firstTextBox())
+        if (firstTextBox()) {
+            if (isBR()) {
+                RootInlineBox* next = firstTextBox()->root()->nextRootBox();
+                if (next)
+                    next->markDirty();
+            }
             for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
                 box->remove();
-        else if (parent() && isBR())
-            parent()->dirtyLinesFromChangedChild(this);
+        }
+        else if (parent())
+            parent()->dirtyLinesFromChangedChild(this, false);
     }
     deleteTextBoxes();
     RenderObject::detach();
index d53d73a8c6059b40c8295d752b402ff038d32af7..22ad68522a241800159faf7ae2446472246686dc 100644 (file)
@@ -61,6 +61,7 @@ public:
         m_start = 0;
         m_len = 0;
         m_reversed = false;
+        m_treatAsText = true;
         m_toAdd = 0;
         m_truncation = cNoTruncation;
     }
@@ -102,7 +103,9 @@ public:
     void setSpaceAdd(int add) { m_width -= m_toAdd; m_toAdd = add; m_width += m_toAdd; }
     int spaceAdd() { return m_toAdd; }
 
-    virtual bool isInlineTextBox() { return true; }
+    virtual bool isInlineTextBox() { return true; }    
+    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);
@@ -132,7 +135,9 @@ public:
                       // denote no truncation (the whole run paints) and full truncation (nothing paints at all).
 
     bool m_reversed : 1;
+    bool m_treatAsText : 1; // Whether or not to treat a <br> as text for the purposes of line height.
     int m_toAdd : 14; // for justified text
+
 private:
     friend class RenderText;
 };
index d06c1b75e8e3f9200eeae6a01188a870146f1a9b..fdadf66d8801e7fed0dd583e98f89aee763c5cee 100644 (file)
@@ -411,43 +411,39 @@ NodeImpl *TextImpl::cloneNode(bool /*deep*/)
 
 bool TextImpl::rendererIsNeeded(RenderStyle *style)
 {
-    if (!CharacterDataImpl::rendererIsNeeded(style)) {
+    if (!CharacterDataImpl::rendererIsNeeded(style))
         return false;
-    }
+
     bool onlyWS = containsOnlyWhitespace();
-    if (!onlyWS) {
+    if (!onlyWS)
         return true;
-    }
 
     RenderObject *par = parentNode()->renderer();
     
-    if (par->isTable() || par->isTableRow() || par->isTableSection() || par->isTableCol()) {
+    if (par->isTable() || par->isTableRow() || par->isTableSection() || par->isTableCol())
         return false;
-    }
     
-    if (style->whiteSpace() == PRE) {
+    if (style->whiteSpace() == PRE)
         return true;
-    }
     
+    RenderObject *prev = previousRenderer();
+    if (prev && prev->isBR()) // <span><br/> <br/></span>
+        return false;
+        
     if (par->isInline()) {
         // <span><div/> <div/></span>
-        RenderObject *prev = previousRenderer();
-        if (prev && prev->isRenderBlock()) {
+        if (prev && prev->isRenderBlock())
             return false;
-        }
     } else {
-        RenderObject *prev = previousRenderer();
-        if (par->isRenderBlock() && !par->childrenInline() && (!prev || !prev->isInline())) {
+        if (par->isRenderBlock() && !par->childrenInline() && (!prev || !prev->isInline()))
             return false;
-        }
         
         RenderObject *first = par->firstChild();
         RenderObject *next = nextRenderer();
-        if (!first || next == first) {
+        if (!first || next == first)
             // Whitespace at the start of a block just goes away.  Don't even
             // make a render object for this text.
             return false;
-        }
     }
     
     return true;
index 5087d30508113fca2184c343b0c9177b8df316e9..44ca2edf5b041658138dcf94bd54344ee3868ce9 100644 (file)
@@ -33,6 +33,7 @@
 #include "render_replaced.h"
 #include "render_table.h"
 #include "render_text.h"
+#include "render_br.h"
 #include "selection.h"
 
 #include "KWQKHTMLPart.h"
@@ -51,6 +52,7 @@ using khtml::RenderTableCell;
 using khtml::RenderWidget;
 using khtml::RenderText;
 using khtml::RenderCanvas;
+using khtml::RenderBR;
 using khtml::Selection;
 using khtml::transparentColor;
 
@@ -122,7 +124,14 @@ static QTextStream &operator<<(QTextStream &ts, const RenderObject &o)
         }
     }
     
-    QRect r(o.xPos(), o.yPos(), o.width(), o.height());
+    // FIXME: Will remove this <br> code once all layout tests pass.  Until then, we can't really change
+    // all the results easily.
+    bool usePositions = true;
+    if (o.isBR()) {
+        const RenderBR* br = static_cast<const RenderBR*>(&o);
+        usePositions = (br->firstTextBox() && br->firstTextBox()->isText());
+    }
+    QRect r(usePositions ? o.xPos() : 0, usePositions ? o.yPos() : 0, o.width(), o.height());
     ts << " " << r;
     
     if (!o.isText()) {