[New Block-Inside-Inline Model] Create anonymous inline blocks to hold blocks-inside...
authorhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 30 Mar 2015 18:02:37 +0000 (18:02 +0000)
committerhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 30 Mar 2015 18:02:37 +0000 (18:02 +0000)
https://bugs.webkit.org/show_bug.cgi?id=143145

Reviewed by Dean Jackson.

Source/WebCore:

Added fast/block/inside-inlines/ tests.

* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::renderName):
Add support for labeling anonymous inline-blocks when dumped by the render tree.

* rendering/RenderInline.cpp:
(WebCore::RenderInline::addChildIgnoringContinuation):
When the pref is set to use the new block-inside-inline model, create an anonymous inline block to
hold block children of RenderInlines instead of splitting flows or creating continuations.

* rendering/RenderObject.h:
(WebCore::RenderObject::isAnonymousInlineBlock):
Add the definition of isAnonymousInlineBlock (note the exclusion of Ruby, since Ruby creates anonymous
inline-blocks also).

LayoutTests:

* fast/block/inside-inlines: Added.
* fast/block/inside-inlines/empty-block-expected.html: Added.
* fast/block/inside-inlines/empty-block.html: Added.
* fast/block/inside-inlines/new-model: Added.
* fast/block/inside-inlines/new-model/empty-block-expected.html: Added.
* fast/block/inside-inlines/new-model/empty-block.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/fast/block/inside-inlines/empty-block-expected.html [new file with mode: 0644]
LayoutTests/fast/block/inside-inlines/empty-block.html [new file with mode: 0644]
LayoutTests/fast/block/inside-inlines/new-model/empty-block-expected.html [new file with mode: 0644]
LayoutTests/fast/block/inside-inlines/new-model/empty-block.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderBlock.cpp
Source/WebCore/rendering/RenderInline.cpp
Source/WebCore/rendering/RenderObject.h

index 953050e..91f3b57 100644 (file)
@@ -1,3 +1,17 @@
+2015-03-27  David Hyatt  <hyatt@apple.com>
+
+        [New Block-Inside-Inline Model] Create anonymous inline blocks to hold blocks-inside-inlines.
+        https://bugs.webkit.org/show_bug.cgi?id=143145
+
+        Reviewed by Dean Jackson.
+
+        * fast/block/inside-inlines: Added.
+        * fast/block/inside-inlines/empty-block-expected.html: Added.
+        * fast/block/inside-inlines/empty-block.html: Added.
+        * fast/block/inside-inlines/new-model: Added.
+        * fast/block/inside-inlines/new-model/empty-block-expected.html: Added.
+        * fast/block/inside-inlines/new-model/empty-block.html: Added.
+
 2015-03-30  Chris Dumez  <cdumez@apple.com>
 
         [WK2][NetworkCache] Add support for "Cache-Control: max-stale" request header
 2015-03-30  Chris Dumez  <cdumez@apple.com>
 
         [WK2][NetworkCache] Add support for "Cache-Control: max-stale" request header
diff --git a/LayoutTests/fast/block/inside-inlines/empty-block-expected.html b/LayoutTests/fast/block/inside-inlines/empty-block-expected.html
new file mode 100644 (file)
index 0000000..be38bc7
--- /dev/null
@@ -0,0 +1,9 @@
+<!doctype html>
+
+The two lines below should look identical.
+
+<div>
+
+<a style="line-height:2; background-color:green; padding:0 100px">&nbsp;&nbsp;<br>
+&nbsp;&nbsp;</a>
+</div>
\ No newline at end of file
diff --git a/LayoutTests/fast/block/inside-inlines/empty-block.html b/LayoutTests/fast/block/inside-inlines/empty-block.html
new file mode 100644 (file)
index 0000000..cd1fbd1
--- /dev/null
@@ -0,0 +1,10 @@
+<!doctype html>
+
+The two lines below should look identical.
+
+<div>
+
+<a style="line-height:2; background-color:green; padding:0 100px">&nbsp;&nbsp;
+<div></div>
+&nbsp;&nbsp;</a>
+</div>
\ No newline at end of file
diff --git a/LayoutTests/fast/block/inside-inlines/new-model/empty-block-expected.html b/LayoutTests/fast/block/inside-inlines/new-model/empty-block-expected.html
new file mode 100644 (file)
index 0000000..be38bc7
--- /dev/null
@@ -0,0 +1,9 @@
+<!doctype html>
+
+The two lines below should look identical.
+
+<div>
+
+<a style="line-height:2; background-color:green; padding:0 100px">&nbsp;&nbsp;<br>
+&nbsp;&nbsp;</a>
+</div>
\ No newline at end of file
diff --git a/LayoutTests/fast/block/inside-inlines/new-model/empty-block.html b/LayoutTests/fast/block/inside-inlines/new-model/empty-block.html
new file mode 100644 (file)
index 0000000..0b608ce
--- /dev/null
@@ -0,0 +1,14 @@
+<!doctype html>
+<head>
+<script>
+window.internals.settings.setNewBlockInsideInlineModelEnabled(true)
+</script>
+</head>
+
+The two lines below should look identical.
+
+<div>
+
+<a style="line-height:2; background-color:green; padding:0 100px">&nbsp;&nbsp;<br>
+<div></div>&nbsp;&nbsp;</a>
+</div>
\ No newline at end of file
index 1334834..14f20f3 100644 (file)
@@ -1,3 +1,26 @@
+2015-03-27  David Hyatt  <hyatt@apple.com>
+
+        [New Block-Inside-Inline Model] Create anonymous inline blocks to hold blocks-inside-inlines.
+        https://bugs.webkit.org/show_bug.cgi?id=143145
+
+        Reviewed by Dean Jackson.
+
+        Added fast/block/inside-inlines/ tests.
+
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::renderName):
+        Add support for labeling anonymous inline-blocks when dumped by the render tree.
+
+        * rendering/RenderInline.cpp:
+        (WebCore::RenderInline::addChildIgnoringContinuation):
+        When the pref is set to use the new block-inside-inline model, create an anonymous inline block to
+        hold block children of RenderInlines instead of splitting flows or creating continuations.
+
+        * rendering/RenderObject.h:
+        (WebCore::RenderObject::isAnonymousInlineBlock):
+        Add the definition of isAnonymousInlineBlock (note the exclusion of Ruby, since Ruby creates anonymous
+        inline-blocks also).
+
 2015-03-30  Chris Dumez  <cdumez@apple.com>
 
         [WK2][NetworkCache] Add support for "Cache-Control: max-stale" request header
 2015-03-30  Chris Dumez  <cdumez@apple.com>
 
         [WK2][NetworkCache] Add support for "Cache-Control: max-stale" request header
index 6456975..3e58a6b 100644 (file)
@@ -3656,6 +3656,8 @@ const char* RenderBlock::renderName() const
         return "RenderBlock (positioned)";
     if (isAnonymousBlock())
         return "RenderBlock (anonymous)";
         return "RenderBlock (positioned)";
     if (isAnonymousBlock())
         return "RenderBlock (anonymous)";
+    if (isAnonymousInlineBlock())
+        return "RenderBlock (anonymous inline-block)";
     // FIXME: Temporary hack while the new generated content system is being implemented.
     if (isPseudoElement())
         return "RenderBlock (generated)";
     // FIXME: Temporary hack while the new generated content system is being implemented.
     if (isPseudoElement())
         return "RenderBlock (generated)";
index 7e26f57..7cd3304 100644 (file)
@@ -41,6 +41,7 @@
 #include "RenderNamedFlowThread.h"
 #include "RenderTheme.h"
 #include "RenderView.h"
 #include "RenderNamedFlowThread.h"
 #include "RenderTheme.h"
 #include "RenderView.h"
+#include "Settings.h"
 #include "StyleInheritedData.h"
 #include "TransformState.h"
 #include "VisiblePosition.h"
 #include "StyleInheritedData.h"
 #include "TransformState.h"
 #include "VisiblePosition.h"
@@ -306,8 +307,11 @@ void RenderInline::addChildIgnoringContinuation(RenderObject* newChild, RenderOb
     // Make sure we don't append things after :after-generated content if we have it.
     if (!beforeChild && isAfterContent(lastChild()))
         beforeChild = lastChild();
     // Make sure we don't append things after :after-generated content if we have it.
     if (!beforeChild && isAfterContent(lastChild()))
         beforeChild = lastChild();
-
-    if (!newChild->isInline() && !newChild->isFloatingOrOutOfFlowPositioned()) {
+    
+    bool useNewBlockInsideInlineModel = document().settings()->newBlockInsideInlineModelEnabled();
+    
+    // This code is for the old block-inside-inline model that uses continuations.
+    if (!useNewBlockInsideInlineModel && !newChild->isInline() && !newChild->isFloatingOrOutOfFlowPositioned()) {
         // We are placing a block inside an inline. We have to perform a split of this
         // inline into continuations.  This involves creating an anonymous block box to hold
         // |newChild|.  We then make that block box a continuation of this inline.  We take all of
         // We are placing a block inside an inline. We have to perform a split of this
         // inline into continuations.  This involves creating an anonymous block box to hold
         // |newChild|.  We then make that block box a continuation of this inline.  We take all of
@@ -327,6 +331,65 @@ void RenderInline::addChildIgnoringContinuation(RenderObject* newChild, RenderOb
         splitFlow(beforeChild, newBox, newChild, oldContinuation);
         return;
     }
         splitFlow(beforeChild, newBox, newChild, oldContinuation);
         return;
     }
+    
+    if (!useNewBlockInsideInlineModel) {
+        RenderBoxModelObject::addChild(newChild, beforeChild);
+        newChild->setNeedsLayoutAndPrefWidthsRecalc();
+        return;
+    }
+
+    // This code is for the new block-inside-inline model that uses anonymous inline blocks.
+    // If the requested beforeChild is not one of our children, then this is most likely because
+    // there is an anonymous inline-block box within this object that contains the beforeChild.
+    // Insert the child into the anonymous inline-block box instead of here.
+    // A second possibility is that the beforeChild is an anonymous block inside the anonymous inline block.
+    // This can happen if inlines are inserted in between two of the anonymous inline block's block-level
+    // children after it has been created.
+    if (beforeChild && beforeChild->parent() != this) {
+        ASSERT(beforeChild->parent());
+        ASSERT(beforeChild->parent()->isAnonymousInlineBlock() || beforeChild->parent()->isAnonymousBlock());
+        if (beforeChild->parent()->isAnonymousInlineBlock()) {
+            if (!newChild->isInline() || (newChild->isInline() && beforeChild->parent()->firstChild() != beforeChild))
+                beforeChild->parent()->addChild(newChild, beforeChild);
+            else
+                addChild(newChild, beforeChild->parent());
+        } else if (beforeChild->parent()->isAnonymousBlock()) {
+            ASSERT(!beforeChild->parent()->parent() || beforeChild->parent()->parent()->isAnonymousInlineBlock());
+            ASSERT(beforeChild->isInline());
+            if (newChild->isInline() || (!newChild->isInline() && beforeChild->parent()->firstChild() != beforeChild))
+                beforeChild->parent()->addChild(newChild, beforeChild);
+            else
+                addChild(newChild, beforeChild->parent());
+        }
+        return;
+    }
+
+    if (!newChild->isInline()) {
+        // We are placing a block inside an inline. We have to place the block inside an anonymous inline-block.
+        // This inline-block can house a sequence of contiguous block-level children, and they will all sit on the
+        // same "line" together. We try to reuse an existing inline-block if possible.
+        if (beforeChild) {
+            if (beforeChild->previousSibling() && beforeChild->previousSibling()->isAnonymousInlineBlock()) {
+                downcast<RenderBlockFlow>(beforeChild->previousSibling())->addChild(newChild);
+                return;
+            }
+        } else {
+            if (lastChild() && lastChild()->isAnonymousInlineBlock()) {
+                downcast<RenderBlockFlow>(lastChild())->addChild(newChild);
+                return;
+            }
+        }
+        if (!newChild->isFloatingOrOutOfFlowPositioned()) {
+            // There was no suitable existing anonymous inline-block. Create a new one.
+            RenderBlockFlow* anonymousInlineBlock = new RenderBlockFlow(document(), RenderStyle::createAnonymousStyleWithDisplay(&style(), INLINE_BLOCK));
+            anonymousInlineBlock->initializeStyle();
+    
+            RenderBoxModelObject::addChild(anonymousInlineBlock, beforeChild);
+            anonymousInlineBlock->addChild(newChild);
+            return;
+        }
+    }
 
     RenderBoxModelObject::addChild(newChild, beforeChild);
 
 
     RenderBoxModelObject::addChild(newChild, beforeChild);
 
index d985874..c9a96e7 100644 (file)
@@ -489,6 +489,11 @@ public:
 #endif
             ;
     }
 #endif
             ;
     }
+    bool isAnonymousInlineBlock() const
+    {
+        return isAnonymous() && style().display() == INLINE_BLOCK && style().styleType() == NOPSEUDO && isRenderBlockFlow() && !isRubyRun() && !isRubyBase();
+    }
+
     bool isElementContinuation() const { return node() && node()->renderer() != this; }
     bool isInlineElementContinuation() const { return isElementContinuation() && isInline(); }
     bool isBlockElementContinuation() const { return isElementContinuation() && !isInline(); }
     bool isElementContinuation() const { return node() && node()->renderer() != this; }
     bool isInlineElementContinuation() const { return isElementContinuation() && isInline(); }
     bool isBlockElementContinuation() const { return isElementContinuation() && !isInline(); }