WebCore:

        Reviewed by Hyatt.

        Fix for <rdar://problem/5399614> anchor tag is not rendered without 
        text content, works in Firefox with CSS background-image (13237)

        This patch allows empty inlines that have box decorations or width 
        from border/padding/margin to have line boxes.

        * rendering/bidi.cpp:
        (WebCore::inlineFlowAllowsLineBox): Convenience function that 
        defines when we allow an inline flow to have a line box.
        (WebCore::requiresLineBox): Call inlineFlowAllowsLineBox.
        (WebCore::shouldSkipWhitespaceAfterStartObject): New function to 
        merge some shared code between list markers and empty inline flows 
        that fall at the beginning of a line.
        (WebCore::RenderBlock::findNextLineBreak): Make flows more like 
        list markers.

        One interesting side effect of this bug appeared in our xhtml/svg 
        tests that generate parser error tags. The tag we generate was 
        actually an empty inline with box decorations. This patch causes 
        those inlines to draw now, and the parser errors looked strange. So 
        I changed it so that the parsererror tag is display:block. This 
        matches Firefox, and I think was the original intent of the tag 
        since that causes its red background and border to show up.
        * dom/XMLTokenizer.cpp:
        (WebCore::createXHTMLParserErrorHeader):

LayoutTests:

        Reviewed by Hyatt.

        New tests and new results for old tests for <rdar://problem/
        5399614> anchor tag is not rendered without text content, works in 
        Firefox with CSS background-image (13237)

        New tests:
        * fast/inline/drawStyledEmptyInlines.html: Added.
        * fast/inline/drawStyledEmptyInlinesWithWS.html: Added.
        * fast/inline/emptyInlinesWithinLists.html: Added.
        * fast/inline/styledEmptyInlinesWithBRs.html: Added.
        * platform/mac/fast/inline/drawStyledEmptyInlines-expected.checksum: Added.
        * platform/mac/fast/inline/drawStyledEmptyInlines-expected.png: Added.
        * platform/mac/fast/inline/drawStyledEmptyInlines-expected.txt: Added.
        * platform/mac/fast/inline/drawStyledEmptyInlinesWithWS-expected.checksum: Added.
        * platform/mac/fast/inline/drawStyledEmptyInlinesWithWS-expected.png: Added.
        * platform/mac/fast/inline/drawStyledEmptyInlinesWithWS-expected.txt: Added.
        * platform/mac/fast/inline/emptyInlinesWithinLists-expected.checksum: Added.
        * platform/mac/fast/inline/emptyInlinesWithinLists-expected.png: Added.
        * platform/mac/fast/inline/emptyInlinesWithinLists-expected.txt: Added.
        * platform/mac/fast/inline/styledEmptyInlinesWithBRs-expected.checksum: Added.
        * platform/mac/fast/inline/styledEmptyInlinesWithBRs-expected.png: Added.
        * platform/mac/fast/inline/styledEmptyInlinesWithBRs-expected.txt: Added.
        
        New results for tests with <paserererrors> since <parsererror> is 
        now block.
        * platform/mac/fast/invalid/junk-data-expected.checksum: Replaced.
        * platform/mac/fast/invalid/junk-data-expected.png: Replaced.
        * platform/mac/fast/invalid/junk-data-expected.txt:
        * platform/mac/fast/invalid/missing-end-tag-expected.checksum: Replaced.
        * platform/mac/fast/invalid/missing-end-tag-expected.png: Replaced.
        * platform/mac/fast/invalid/missing-end-tag-expected.txt:
        * platform/mac/fast/parser/xhtml-alternate-entities-expected.checksum: Replaced.
        * platform/mac/fast/parser/xhtml-alternate-entities-expected.png: Replaced.
        * platform/mac/fast/parser/xhtml-alternate-entities-expected.txt:
        * platform/mac/fast/xsl/xslt-extra-content-at-end-expected.checksum: Replaced.
        * platform/mac/fast/xsl/xslt-extra-content-at-end-expected.png: Replaced.
        * platform/mac/fast/xsl/xslt-extra-content-at-end-expected.txt: Removed.
        * platform/mac/svg/custom/junk-data-expected.checksum: Replaced.
        * platform/mac/svg/custom/junk-data-expected.png: Replaced.
        * platform/mac/svg/custom/junk-data-expected.txt:
        * platform/mac/svg/custom/missing-xlink-expected.checksum: Replaced.
        * platform/mac/svg/custom/missing-xlink-expected.png: Replaced.
        * platform/mac/svg/custom/missing-xlink-expected.txt:
        * platform/mac/svg/hixie/error/012-expected.checksum: Replaced.
        * platform/mac/svg/hixie/error/012-expected.png: Replaced.
        * platform/mac/svg/hixie/error/012-expected.txt:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@27254 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/rendering/bidi.cpp b/WebCore/rendering/bidi.cpp
index eb3766f..97bfe1d 100644
--- a/WebCore/rendering/bidi.cpp
+++ b/WebCore/rendering/bidi.cpp
@@ -1244,10 +1244,32 @@
     return object->style()->preserveNewline();
 }
 
+static bool inlineFlowRequiresLineBox(RenderObject* flow)
+{
+    // FIXME: Right now, we only allow line boxes for inlines that are truly empty.
+    // We need to fix this, though, because at the very least, inlines with only text
+    // children that is all whitespace should should also have line boxes. 
+    if (!flow->isInlineFlow() || flow->firstChild())
+        return false;
+
+    bool hasPaddingOrMargin = !(flow->paddingLeft() == 0 && flow->paddingRight() == 0
+        && flow->paddingTop() == 0 && flow->paddingBottom() == 0 
+        && flow->marginLeft() == 0 && flow->marginRight() == 0
+        && flow->marginTop() == 0 && flow->marginBottom() == 0);
+    if (flow->hasBoxDecorations() || hasPaddingOrMargin)
+        return true;
+
+    return false;
+}
+
 static inline bool requiresLineBox(BidiIterator& it)
 {
-    if (it.obj->isFloatingOrPositioned() || it.obj->isInlineFlow())
+    if (it.obj->isFloatingOrPositioned())
         return false;
+
+    if (it.obj->isInlineFlow() && !inlineFlowRequiresLineBox(it.obj))
+        return false;
+
     if (!shouldCollapseWhiteSpace(it.obj->style()) || it.obj->isBR())
         return true;
 
@@ -1320,6 +1342,24 @@
     return w;
 }
 
+// This is currently just used for list markers and inline flows that have line boxes. Neither should 
+// have an effect on whitespace at the start of the line. 
+static bool shouldSkipWhitespaceAfterStartObject(RenderBlock* block, RenderObject* o, BidiState &bidi)
+{
+    RenderObject* next = bidiNext(block, o, bidi);
+    if (next && !next->isBR() && next->isText() && static_cast<RenderText*>(next)->textLength() > 0) {
+        RenderText* nextText = static_cast<RenderText*>(next);
+        UChar nextChar = nextText->characters()[0];
+        if (nextText->style()->isCollapsibleWhiteSpace(nextChar)) {
+            BidiIterator endMid(0, o, 0);
+            addMidpoint(endMid);
+            return true;
+        }
+    }
+
+    return false;
+}
+
 BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi)
 {
     // eliminate spaces at beginning of line
@@ -1448,8 +1488,28 @@
                 }
             }
         } else if (o->isInlineFlow()) {
-            // Only empty inlines matter.  We treat those similarly to replaced elements.
+            // Right now, we should only encounter empty inlines here.
             ASSERT(!o->firstChild());
+    
+            // Now that some inline flows have line boxes, if we are already ignoring spaces, we need 
+            // to make sure that we stop to include this object and then start ignoring spaces again. 
+            // If this object is at the start of the line, we need to behave like list markers and 
+            // start ignoring spaces.
+            if (inlineFlowRequiresLineBox(o)) {
+                if (ignoringSpaces) {
+                    trailingSpaceObject = 0;
+                    addMidpoint(BidiIterator(0, o, 0)); // Stop ignoring spaces.
+                    addMidpoint(BidiIterator(0, o, 0)); // Start ignoring again.
+                } else if (style()->collapseWhiteSpace() && start.obj == o
+                    && shouldSkipWhitespaceAfterStartObject(start.block, o, bidi)) {
+                    // Like with list markers, we start ignoring spaces to make sure that any 
+                    // additional spaces we see will be discarded.
+                    currentCharacterIsSpace = true;
+                    currentCharacterIsWS = true;
+                    ignoringSpaces = true;
+                }
+            }
+
             if (static_cast<RenderFlow*>(o)->isWordBreak()) {
                 w += tmpW;
                 tmpW = 0;
@@ -1477,24 +1537,15 @@
             currentCharacterIsWS = false;
             trailingSpaceObject = 0;
             
+            // Optimize for a common case. If we can't find whitespace after the list
+            // item, then this is all moot. -dwh
             if (o->isListMarker() && !static_cast<RenderListMarker*>(o)->isInside()) {
-                // The marker must not have an effect on whitespace at the start
-                // of the line.  We start ignoring spaces to make sure that any additional
-                // spaces we see will be discarded. 
-                //
-                // Optimize for a common case. If we can't find whitespace after the list
-                // item, then this is all moot. -dwh
-                RenderObject* next = bidiNext(start.block, o, bidi);
-                if (style()->collapseWhiteSpace() && next && !next->isBR() && next->isText() && static_cast<RenderText*>(next)->textLength() > 0) {
-                    RenderText *nextText = static_cast<RenderText*>(next);
-                    UChar nextChar = nextText->characters()[0];
-                    if (nextText->style()->isCollapsibleWhiteSpace(nextChar)) {
-                        currentCharacterIsSpace = true;
-                        currentCharacterIsWS = true;
-                        ignoringSpaces = true;
-                        BidiIterator endMid( 0, o, 0 );
-                        addMidpoint(endMid);
-                    }
+                if (style()->collapseWhiteSpace() && shouldSkipWhitespaceAfterStartObject(start.block, o, bidi)) {
+                    // Like with inline flows, we start ignoring spaces to make sure that any 
+                    // additional spaces we see will be discarded.
+                    currentCharacterIsSpace = true;
+                    currentCharacterIsWS = true;
+                    ignoringSpaces = true;
                 }
             } else
                 tmpW += o->width() + o->marginLeft() + o->marginRight() + inlineWidth(o);