First step at getting rid of anonymous blocks and continuations. -Add RenderParagraph and display:paragraph. This is the only render type that's allowed to contain inlines or text. -If you put text nodes directly in a non-paragraph, wrap them in an anonymous paragraph. This may not be the place we want to end up, but it's a good stopgap to make it so we don't crash in this case. -Make StyleAdjuster force that non-paragraph blocks only contain RenderBlock subclasses and that paragraphs and inlines only contain inlines. -Considerably simplify addChildIgnoringAnonymousColumnBlocks now that we only create anonymous blocks for the case of text nodes in non-paragraphs. Also get rid of the behavior where we try to group multiple nodes into a single anonymous block. R=esprehn@chromium.org Review URL: https://codereview.chromium.org/729693003
diff --git a/sky/engine/core/core.gni b/sky/engine/core/core.gni index c445c43..e21dd08 100644 --- a/sky/engine/core/core.gni +++ b/sky/engine/core/core.gni
@@ -1231,6 +1231,8 @@ "rendering/RenderObjectChildList.h", "rendering/RenderObjectInlines.h", "rendering/RenderOverflow.h", + "rendering/RenderParagraph.cpp", + "rendering/RenderParagraph.h", "rendering/RenderReplaced.cpp", "rendering/RenderReplaced.h", "rendering/RenderSelectionInfo.h",
diff --git a/sky/engine/core/css/CSSPrimitiveValueMappings.h b/sky/engine/core/css/CSSPrimitiveValueMappings.h index e27eedc..1a086ba 100644 --- a/sky/engine/core/css/CSSPrimitiveValueMappings.h +++ b/sky/engine/core/css/CSSPrimitiveValueMappings.h
@@ -926,6 +926,9 @@ case INLINE: m_value.valueID = CSSValueInline; break; + case PARAGRAPH: + m_value.valueID = CSSValueParagraph; + break; case BLOCK: m_value.valueID = CSSValueBlock; break;
diff --git a/sky/engine/core/css/CSSValueKeywords.in b/sky/engine/core/css/CSSValueKeywords.in index 15d7cf9..3840c85 100644 --- a/sky/engine/core/css/CSSValueKeywords.in +++ b/sky/engine/core/css/CSSValueKeywords.in
@@ -259,6 +259,9 @@ // The order here must match the order of the EDisplay enum in RenderStyleConstants.h. // inline +// Contains only inline content. +paragraph +// Contains only block content. block inline-block flex
diff --git a/sky/engine/core/css/resolver/StyleAdjuster.cpp b/sky/engine/core/css/resolver/StyleAdjuster.cpp index 2e21d56..0977f9b 100644 --- a/sky/engine/core/css/resolver/StyleAdjuster.cpp +++ b/sky/engine/core/css/resolver/StyleAdjuster.cpp
@@ -41,24 +41,68 @@ namespace blink { +static bool requiresOnlyBlockChildren(RenderStyle* parentStyle) +{ + switch (parentStyle->display()) { + case PARAGRAPH: + case INLINE: + return false; + + case BLOCK: + case FLEX: + case INLINE_FLEX: + case INLINE_BLOCK: + return true; + + case NONE: + ASSERT_NOT_REACHED(); + return false; + } +} + +static EDisplay equivalentInlineDisplay(EDisplay display) +{ + switch (display) { + // TODO(ojan): Do we need an INLINE_PARAGRAPH display? + case PARAGRAPH: + return INLINE; + + case BLOCK: + return INLINE_BLOCK; + + case FLEX: + return INLINE_FLEX; + + case INLINE: + case INLINE_FLEX: + case INLINE_BLOCK: + return display; + + case NONE: + ASSERT_NOT_REACHED(); + return NONE; + } +} + static EDisplay equivalentBlockDisplay(EDisplay display) { switch (display) { + case PARAGRAPH: case BLOCK: case FLEX: return display; + case INLINE_FLEX: return FLEX; case INLINE: case INLINE_BLOCK: return BLOCK; + case NONE: ASSERT_NOT_REACHED(); return NONE; } - ASSERT_NOT_REACHED(); - return BLOCK; } // CSS requires text-decoration to be reset at each DOM element for tables, @@ -108,7 +152,10 @@ if (style->hasOutOfFlowPosition() || element.document().documentElement() == element) style->setDisplay(equivalentBlockDisplay(style->display())); - adjustStyleForDisplay(style, parentStyle); + if (requiresOnlyBlockChildren(parentStyle)) + style->setDisplay(equivalentBlockDisplay(style->display())); + else + style->setDisplay(equivalentInlineDisplay(style->display())); } // Make sure our z-index value is only applied if the object is positioned. @@ -226,11 +273,4 @@ } } -void StyleAdjuster::adjustStyleForDisplay(RenderStyle* style, RenderStyle* parentStyle) -{ - if (parentStyle->isDisplayFlexibleBox()) { - style->setDisplay(equivalentBlockDisplay(style->display())); - } -} - }
diff --git a/sky/engine/core/css/resolver/StyleAdjuster.h b/sky/engine/core/css/resolver/StyleAdjuster.h index 75a3220..cd1996d 100644 --- a/sky/engine/core/css/resolver/StyleAdjuster.h +++ b/sky/engine/core/css/resolver/StyleAdjuster.h
@@ -41,7 +41,6 @@ void adjustRenderStyle(RenderStyle* styleToAdjust, RenderStyle* parentStyle, Element&); private: - void adjustStyleForDisplay(RenderStyle* styleToAdjust, RenderStyle* parentStyle); void adjustOverflow(RenderStyle* styleToAdjust); void adjustStyleForAlignment(RenderStyle& styleToAdjust, const RenderStyle& parentStyle); };
diff --git a/sky/engine/core/rendering/RenderBlock.cpp b/sky/engine/core/rendering/RenderBlock.cpp index a59cb17..6977729 100644 --- a/sky/engine/core/rendering/RenderBlock.cpp +++ b/sky/engine/core/rendering/RenderBlock.cpp
@@ -44,6 +44,7 @@ #include "core/rendering/RenderInline.h" #include "core/rendering/RenderLayer.h" #include "core/rendering/RenderObjectInlines.h" +#include "core/rendering/RenderParagraph.h" #include "core/rendering/RenderView.h" #include "core/rendering/style/RenderStyle.h" #include "platform/geometry/FloatQuad.h" @@ -87,8 +88,6 @@ , m_hasMarkupTruncation(false) , m_hasBorderOrPaddingLogicalWidthChanged(false) { - // RenderBlockFlow calls setChildrenInline(true). - // By default, subclasses do not have inline children. } static void removeBlockFromDescendantAndContainerMaps(RenderBlock* block, TrackedDescendantsMap*& descendantMap, TrackedContainerMap*& containerMap) @@ -442,70 +441,23 @@ { if (beforeChild && beforeChild->parent() != this) { RenderObject* beforeChildContainer = beforeChild->parent(); - while (beforeChildContainer->parent() != this) - beforeChildContainer = beforeChildContainer->parent(); - ASSERT(beforeChildContainer); - - if (beforeChildContainer->isAnonymous()) { - // If the requested beforeChild is not one of our children, then this is because - // there is an anonymous container within this object that contains the beforeChild. - RenderObject* beforeChildAnonymousContainer = beforeChildContainer; - if (beforeChildAnonymousContainer->isAnonymousBlock() - // Full screen renderers and full screen placeholders act as anonymous blocks, not tables: - ) { - // Insert the child into the anonymous block box instead of here. - if (newChild->isInline() || newChild->isFloatingOrOutOfFlowPositioned() || beforeChild->parent()->slowFirstChild() != beforeChild) - beforeChild->parent()->addChild(newChild, beforeChild); - else - addChild(newChild, beforeChild->parent()); - return; - } - - // This used to ASSERT(beforeChildAnonymousContainer->isTable()); - ASSERT_NOT_REACHED(); - } + ASSERT(beforeChildContainer->parent() == this); + ASSERT(beforeChildContainer->isAnonymousBlock()); + addChild(newChild, beforeChildContainer); + return; } - bool madeBoxesNonInline = false; - - // A block has to either have all of its children inline, or all of its children as blocks. - // So, if our children are currently inline and a block child has to be inserted, we move all our - // inline children into anonymous block boxes. - if (childrenInline() && !newChild->isInline() && !newChild->isFloatingOrOutOfFlowPositioned()) { - // This is a block with inline content. Wrap the inline content in anonymous blocks. - makeChildrenNonInline(beforeChild); - madeBoxesNonInline = true; - - if (beforeChild && beforeChild->parent() != this) { - beforeChild = beforeChild->parent(); - ASSERT(beforeChild->isAnonymousBlock()); - ASSERT(beforeChild->parent() == this); - } - } else if (!childrenInline() && (newChild->isFloatingOrOutOfFlowPositioned() || newChild->isInline())) { - // If we're inserting an inline child but all of our children are blocks, then we have to make sure - // it is put into an anomyous block box. We try to use an existing anonymous box if possible, otherwise - // a new one is created and inserted into our list of children in the appropriate position. - RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : lastChild(); - - if (afterChild && afterChild->isAnonymousBlock()) { - afterChild->addChild(newChild); - return; - } - - if (newChild->isInline()) { - // No suitable existing anonymous box - create a new one. - RenderBlock* newBox = createAnonymousBlock(); - RenderBox::addChild(newBox, beforeChild); - newBox->addChild(newChild); - return; - } + // TODO(ojan): What should we do in this case? For now we insert an anonymous paragraph. + // This only happens if we have a text node directly inside a non-paragraph. + if (!childrenInline() && newChild->isInline()) { + RenderBlock* newBox = createAnonymousBlock(); + ASSERT(newBox->childrenInline()); + RenderBox::addChild(newBox, beforeChild); + newBox->addChild(newChild); + return; } RenderBox::addChild(newChild, beforeChild); - - if (madeBoxesNonInline && parent() && isAnonymousBlock() && parent()->isRenderBlock()) - toRenderBlock(parent())->removeLeftoverAnonymousBlock(this); - // this object may be dead here } void RenderBlock::addChild(RenderObject* newChild, RenderObject* beforeChild) @@ -521,46 +473,6 @@ addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild); } -static void getInlineRun(RenderObject* start, RenderObject* boundary, - RenderObject*& inlineRunStart, - RenderObject*& inlineRunEnd) -{ - // Beginning at |start| we find the largest contiguous run of inlines that - // we can. We denote the run with start and end points, |inlineRunStart| - // and |inlineRunEnd|. Note that these two values may be the same if - // we encounter only one inline. - // - // We skip any non-inlines we encounter as long as we haven't found any - // inlines yet. - // - // |boundary| indicates a non-inclusive boundary point. Regardless of whether |boundary| - // is inline or not, we will not include it in a run with inlines before it. It's as though we encountered - // a non-inline. - - // Start by skipping as many non-inlines as we can. - RenderObject * curr = start; - bool sawInline; - do { - while (curr && !(curr->isInline() || curr->isFloatingOrOutOfFlowPositioned())) - curr = curr->nextSibling(); - - inlineRunStart = inlineRunEnd = curr; - - if (!curr) - return; // No more inline children to be found. - - sawInline = curr->isInline(); - - curr = curr->nextSibling(); - while (curr && (curr->isInline() || curr->isFloatingOrOutOfFlowPositioned()) && (curr != boundary)) { - inlineRunEnd = curr; - if (curr->isInline()) - sawInline = true; - curr = curr->nextSibling(); - } - } while (!sawInline); -} - void RenderBlock::deleteLineBoxTree() { ASSERT(!m_lineBoxes.firstLineBox()); @@ -568,93 +480,8 @@ void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint) { - // makeChildrenNonInline takes a block whose children are *all* inline and it - // makes sure that inline children are coalesced under anonymous - // blocks. If |insertionPoint| is defined, then it represents the insertion point for - // the new block child that is causing us to have to wrap all the inlines. This - // means that we cannot coalesce inlines before |insertionPoint| with inlines following - // |insertionPoint|, because the new child is going to be inserted in between the inlines, - // splitting them. - ASSERT(isInlineBlock() || !isInline()); - ASSERT(!insertionPoint || insertionPoint->parent() == this); - - setChildrenInline(false); - - RenderObject *child = firstChild(); - if (!child) - return; - - deleteLineBoxTree(); - - while (child) { - RenderObject *inlineRunStart, *inlineRunEnd; - getInlineRun(child, insertionPoint, inlineRunStart, inlineRunEnd); - - if (!inlineRunStart) - break; - - child = inlineRunEnd->nextSibling(); - - RenderBlock* block = createAnonymousBlock(); - children()->insertChildNode(this, block, inlineRunStart); - moveChildrenTo(block, inlineRunStart, child); - } - -#if ENABLE(ASSERT) - for (RenderObject *c = firstChild(); c; c = c->nextSibling()) - ASSERT(!c->isInline()); -#endif - - setShouldDoFullPaintInvalidation(true); -} - -void RenderBlock::removeLeftoverAnonymousBlock(RenderBlock* child) -{ - ASSERT(child->isAnonymousBlock()); - ASSERT(!child->childrenInline()); - - if (child->continuation()) - return; - - RenderObject* firstAnChild = child->m_children.firstChild(); - RenderObject* lastAnChild = child->m_children.lastChild(); - if (firstAnChild) { - RenderObject* o = firstAnChild; - while (o) { - o->setParent(this); - o = o->nextSibling(); - } - firstAnChild->setPreviousSibling(child->previousSibling()); - lastAnChild->setNextSibling(child->nextSibling()); - if (child->previousSibling()) - child->previousSibling()->setNextSibling(firstAnChild); - if (child->nextSibling()) - child->nextSibling()->setPreviousSibling(lastAnChild); - - if (child == m_children.firstChild()) - m_children.setFirstChild(firstAnChild); - if (child == m_children.lastChild()) - m_children.setLastChild(lastAnChild); - } else { - if (child == m_children.firstChild()) - m_children.setFirstChild(child->nextSibling()); - if (child == m_children.lastChild()) - m_children.setLastChild(child->previousSibling()); - - if (child->previousSibling()) - child->previousSibling()->setNextSibling(child->nextSibling()); - if (child->nextSibling()) - child->nextSibling()->setPreviousSibling(child->previousSibling()); - } - - child->children()->setFirstChild(0); - child->m_next = nullptr; - - child->setParent(0); - child->setPreviousSibling(0); - child->setNextSibling(0); - - child->destroy(); + ASSERT_NOT_REACHED(); + // FIXME(sky): Remove } static bool canMergeContiguousAnonymousBlocks(RenderObject* oldChild, RenderObject* prev, RenderObject* next) @@ -2609,10 +2436,8 @@ void RenderBlock::childBecameNonInline(RenderObject*) { - makeChildrenNonInline(); - if (isAnonymousBlock() && parent() && parent()->isRenderBlock()) - toRenderBlock(parent())->removeLeftoverAnonymousBlock(this); - // |this| may be dead here + ASSERT_NOT_REACHED(); + // FIXME(sky): Remove } void RenderBlock::updateHitTestResult(HitTestResult& result, const LayoutPoint& point) @@ -2719,20 +2544,11 @@ return "RenderBlock"; } -RenderBlock* RenderBlock::createAnonymousWithParentRendererAndDisplay(const RenderObject* parent, EDisplay display) +// FIXME(sky): Clean up callers now that we no longer use the EDisplay argument. +RenderBlock* RenderBlock::createAnonymousWithParentRendererAndDisplay(const RenderObject* parent, EDisplay) { - // FIXME: Do we need to convert all our inline displays to block-type in the anonymous logic ? - EDisplay newDisplay; - RenderBlock* newBox = 0; - if (display == FLEX || display == INLINE_FLEX) { - newBox = RenderFlexibleBox::createAnonymous(&parent->document()); - newDisplay = FLEX; - } else { - newBox = RenderBlockFlow::createAnonymous(&parent->document()); - newDisplay = BLOCK; - } - - RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), newDisplay); + RenderBlock* newBox = RenderParagraph::createAnonymous(parent->document()); + RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), PARAGRAPH); parent->updateAnonymousChildStyle(newBox, newStyle.get()); newBox->setStyle(newStyle.release()); return newBox;
diff --git a/sky/engine/core/rendering/RenderBlock.h b/sky/engine/core/rendering/RenderBlock.h index 21c95b2..758cd5c 100644 --- a/sky/engine/core/rendering/RenderBlock.h +++ b/sky/engine/core/rendering/RenderBlock.h
@@ -175,8 +175,8 @@ using RenderBoxModelObject::continuation; using RenderBoxModelObject::setContinuation; - static RenderBlock* createAnonymousWithParentRendererAndDisplay(const RenderObject*, EDisplay = BLOCK); - RenderBlock* createAnonymousBlock(EDisplay display = BLOCK) const { return createAnonymousWithParentRendererAndDisplay(this, display); } + static RenderBlock* createAnonymousWithParentRendererAndDisplay(const RenderObject*, EDisplay = PARAGRAPH); + RenderBlock* createAnonymousBlock(EDisplay display = PARAGRAPH) const { return createAnonymousWithParentRendererAndDisplay(this, display); } virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const override; @@ -298,7 +298,6 @@ virtual bool isRenderBlock() const override final { return true; } void makeChildrenNonInline(RenderObject* insertionPoint = 0); - virtual void removeLeftoverAnonymousBlock(RenderBlock* child); static void collapseAnonymousBlockChild(RenderBlock* parent, RenderBlock* child);
diff --git a/sky/engine/core/rendering/RenderBlockFlow.cpp b/sky/engine/core/rendering/RenderBlockFlow.cpp index 6be0823..c84afbe 100644 --- a/sky/engine/core/rendering/RenderBlockFlow.cpp +++ b/sky/engine/core/rendering/RenderBlockFlow.cpp
@@ -46,7 +46,6 @@ RenderBlockFlow::RenderBlockFlow(ContainerNode* node) : RenderBlock(node) { - setChildrenInline(true); } RenderBlockFlow::~RenderBlockFlow()
diff --git a/sky/engine/core/rendering/RenderBox.cpp b/sky/engine/core/rendering/RenderBox.cpp index d74981f..6f6a079 100644 --- a/sky/engine/core/rendering/RenderBox.cpp +++ b/sky/engine/core/rendering/RenderBox.cpp
@@ -3473,47 +3473,6 @@ || style()->logicalMaxHeight().isPercent(); } -static void markBoxForRelayoutAfterSplit(RenderBox* box) -{ - box->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); -} - -RenderObject* RenderBox::splitAnonymousBoxesAroundChild(RenderObject* beforeChild) -{ - bool didSplitParentAnonymousBoxes = false; - - while (beforeChild->parent() != this) { - RenderBox* boxToSplit = toRenderBox(beforeChild->parent()); - if (boxToSplit->slowFirstChild() != beforeChild && boxToSplit->isAnonymous()) { - didSplitParentAnonymousBoxes = true; - - // We have to split the parent box into two boxes and move children - // from |beforeChild| to end into the new post box. - RenderBox* postBox = boxToSplit->createAnonymousBoxWithSameTypeAs(this); - postBox->setChildrenInline(boxToSplit->childrenInline()); - RenderBox* parentBox = toRenderBox(boxToSplit->parent()); - // We need to invalidate the |parentBox| before inserting the new node - // so that the table paint invalidation logic knows the structure is dirty. - // See for example RenderTableCell:clippedOverflowRectForPaintInvalidation. - markBoxForRelayoutAfterSplit(parentBox); - parentBox->virtualChildren()->insertChildNode(parentBox, postBox, boxToSplit->nextSibling()); - boxToSplit->moveChildrenTo(postBox, beforeChild, 0, true); - - markBoxForRelayoutAfterSplit(boxToSplit); - markBoxForRelayoutAfterSplit(postBox); - - beforeChild = postBox; - } else - beforeChild = boxToSplit; - } - - if (didSplitParentAnonymousBoxes) - markBoxForRelayoutAfterSplit(this); - - ASSERT(beforeChild->parent() == this); - return beforeChild; -} - void RenderBox::savePreviousBorderBoxSizeIfNeeded() { // If m_rareData is already created, always save.
diff --git a/sky/engine/core/rendering/RenderObject.cpp b/sky/engine/core/rendering/RenderObject.cpp index f1ffdeb..1d85606 100644 --- a/sky/engine/core/rendering/RenderObject.cpp +++ b/sky/engine/core/rendering/RenderObject.cpp
@@ -52,6 +52,7 @@ #include "core/rendering/RenderInline.h" #include "core/rendering/RenderLayer.h" #include "core/rendering/RenderObjectInlines.h" +#include "core/rendering/RenderParagraph.h" #include "core/rendering/RenderText.h" #include "core/rendering/RenderTheme.h" #include "core/rendering/RenderView.h" @@ -141,6 +142,8 @@ case BLOCK: case INLINE_BLOCK: return new RenderBlockFlow(element); + case PARAGRAPH: + return new RenderParagraph(element); case FLEX: case INLINE_FLEX: return new RenderFlexibleBox(element); @@ -1645,21 +1648,13 @@ void RenderObject::handleDynamicFloatPositionChange() { + // FIXME(sky): Inline this function. + // We have gone from not affecting the inline status of the parent flow to suddenly // having an impact. See if there is a mismatch between the parent flow's // childrenInline() state and our state. setInline(style()->isDisplayInlineType()); - if (isInline() != parent()->childrenInline()) { - if (!isInline()) - toRenderBoxModelObject(parent())->childBecameNonInline(this); - else { - // An anonymous block must be made to wrap this inline. - RenderBlock* block = toRenderBlock(parent())->createAnonymousBlock(); - RenderObjectChildList* childlist = parent()->virtualChildren(); - childlist->insertChildNode(parent(), block, this); - block->children()->appendChildNode(block, childlist->removeChildNode(parent(), this)); - } - } + ASSERT(isInline() == parent()->childrenInline()); } StyleDifference RenderObject::adjustStyleDifference(StyleDifference diff) const
diff --git a/sky/engine/core/rendering/RenderObject.h b/sky/engine/core/rendering/RenderObject.h index f80848e..7ee9de9 100644 --- a/sky/engine/core/rendering/RenderObject.h +++ b/sky/engine/core/rendering/RenderObject.h
@@ -326,6 +326,7 @@ virtual bool isMedia() const { return false; } virtual bool isRenderBlock() const { return false; } virtual bool isRenderBlockFlow() const { return false; } + virtual bool isRenderParagraph() const { return false; } virtual bool isRenderImage() const { return false; } virtual bool isRenderInline() const { return false; } virtual bool isRenderView() const { return false; } @@ -335,7 +336,8 @@ bool everHadLayout() const { return m_bitfields.everHadLayout(); } - bool childrenInline() const { return m_bitfields.childrenInline(); } + // FIXME(sky): Remove this concept. + bool childrenInline() const { return isRenderParagraph(); } void setChildrenInline(bool b) { m_bitfields.setChildrenInline(b); } bool alwaysCreateLineBoxesForRenderInline() const @@ -400,7 +402,7 @@ // This function is kept in sync with anonymous block creation conditions in // RenderBlock::createAnonymousBlock(). This includes creating an anonymous // RenderBlock having a BLOCK or BOX display. See https://bugs.webkit.org/show_bug.cgi?id=56709. - return isAnonymous() && style()->display() == BLOCK && style()->styleType() == NOPSEUDO && isRenderBlock(); + return isAnonymous() && style()->display() == PARAGRAPH; } bool isElementContinuation() const { return node() && node()->renderer() != this; }
diff --git a/sky/engine/core/rendering/RenderParagraph.cpp b/sky/engine/core/rendering/RenderParagraph.cpp new file mode 100644 index 0000000..bd6e0e8 --- /dev/null +++ b/sky/engine/core/rendering/RenderParagraph.cpp
@@ -0,0 +1,27 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/rendering/RenderParagraph.h" + +namespace blink { + +RenderParagraph::RenderParagraph(ContainerNode* node) + : RenderBlockFlow(node) +{ + setChildrenInline(true); +} + +RenderParagraph::~RenderParagraph() +{ +} + +RenderParagraph* RenderParagraph::createAnonymous(Document& document) +{ + RenderParagraph* renderer = new RenderParagraph(0); + renderer->setDocumentForAnonymous(&document); + return renderer; +} + +} // namespace blink
diff --git a/sky/engine/core/rendering/RenderParagraph.h b/sky/engine/core/rendering/RenderParagraph.h new file mode 100644 index 0000000..ed7a552 --- /dev/null +++ b/sky/engine/core/rendering/RenderParagraph.h
@@ -0,0 +1,29 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RenderParagraph_h +#define RenderParagraph_h + +#include "core/dom/ContainerNode.h" +#include "core/rendering/RenderBlockFlow.h" + +namespace blink { + +class ContainerNode; + +class RenderParagraph final : public RenderBlockFlow { +public: + explicit RenderParagraph(ContainerNode*); + virtual ~RenderParagraph(); + + static RenderParagraph* createAnonymous(Document&); + + bool isRenderParagraph() const override { return true; } +}; + +DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderParagraph, isRenderParagraph()); + +} // namespace blink + +#endif // RenderParagraph_h
diff --git a/sky/engine/core/rendering/style/RenderStyleConstants.h b/sky/engine/core/rendering/style/RenderStyleConstants.h index 5fbad43..0e7cbb1 100644 --- a/sky/engine/core/rendering/style/RenderStyleConstants.h +++ b/sky/engine/core/rendering/style/RenderStyleConstants.h
@@ -367,7 +367,7 @@ // The order of this enum must match the order of the display values in CSSValueKeywords.in. enum EDisplay { - INLINE, + INLINE, PARAGRAPH, BLOCK, INLINE_BLOCK, FLEX, INLINE_FLEX, NONE,
diff --git a/sky/examples/city-list/city-list.sky b/sky/examples/city-list/city-list.sky index 92b3aa5..c1ecc67 100644 --- a/sky/examples/city-list/city-list.sky +++ b/sky/examples/city-list/city-list.sky
@@ -14,6 +14,7 @@ color: #FFF; background-color: #333; padding: 4px 4px 4px 12px; + display: paragraph; } </style> <div>{{ state }}</div> @@ -35,6 +36,7 @@ font-weight: bold; padding: 2px 4px 4px 12px; background-color: #DDD; + display: paragraph; } </style> <div>{{ letter }}</div> @@ -60,6 +62,10 @@ overflow: hidden; } + div { + display: paragraph; + } + span { display: inline; }
diff --git a/sky/tests/framework/flights-app-expected.txt b/sky/tests/framework/flights-app-expected.txt index bc0efc8..f383adb 100644 --- a/sky/tests/framework/flights-app-expected.txt +++ b/sky/tests/framework/flights-app-expected.txt
@@ -6,8 +6,9 @@ RenderFlexibleBox {app-header} at (0,0) size 800x47 [color=#FFFFFF] [border: none (1px solid #3E77B7) none] RenderFlexibleBox {app-title} at (16,8) size 746x30 RenderBlock {t} at (0,2) size 69.72x26 - RenderText {#text} at (0,0) size 70x25 - text run at (0,0) width 70: "Search" + RenderBlock (anonymous) at (0,0) size 69.72x26 + RenderText {#text} at (0,0) size 70x25 + text run at (0,0) width 70: "Search" RenderFlexibleBox {app-menu-button} at (762,8) size 30x30 RenderImage {img} at (6,15) size 18x0 RenderBlock {app-toolbar} at (0,47) size 800x30 [bgcolor=#F6F6F6] @@ -16,143 +17,146 @@ RenderImage {img} at (0,0) size 16x0 RenderBlock {span} at (28,4) size 221.84x22 RenderBlock {t} at (0,0) size 221.84x22 - RenderText {#text} at (0,0) size 222x21 - text run at (0,0) width 222: "flights today to dc by price" + RenderBlock (anonymous) at (0,0) size 221.84x22 + RenderText {#text} at (0,0) size 222x21 + text run at (0,0) width 222: "flights today to dc by price" layer at (0,77) size 800x474 RenderBlock {app-scrollable} at (0,77) size 800x474 RenderFlexibleBox {app-panel} at (16,16) size 768x246 [bgcolor=#FFFFFF] RenderFlexibleBox {app-panel-header} at (0,0) size 768x46 [bgcolor=#DEDEDE] RenderBlock {div} at (8,14) size 722x18 - RenderInline {t} at (0,0) size 89x17 - RenderText {#text} at (0,0) size 89x17 - text run at (0,0) width 89: "SFO to DCA" - RenderText {#text} at (0,0) size 0x0 + RenderBlock {t} at (0,0) size 722x18 + RenderBlock (anonymous) at (0,0) size 722x18 + RenderText {#text} at (0,0) size 89x17 + text run at (0,0) width 89: "SFO to DCA" RenderFlexibleBox {app-menu-button} at (730,8) size 30x30 RenderImage {img} at (8,15) size 14x0 RenderFlexibleBox {app-panel-content} at (0,46) size 768x50 RenderBlock {div} at (8,25) size 50x0 RenderImage {img} at (0,0) size 50x0 RenderBlock {div} at (58,8) size 650.41x34 - RenderInline {t} at (0,0) size 105x17 - RenderText {#text} at (8,8) size 105x17 - text run at (8,8) width 105: "Virgin America" - RenderText {#text} at (0,0) size 0x0 + RenderBlock {t} at (8,8) size 634.41x18 + RenderBlock (anonymous) at (0,0) size 634.41x18 + RenderText {#text} at (0,0) size 105x17 + text run at (0,0) width 105: "Virgin America" RenderBlock {div} at (708.41,8) size 51.59x34 [color=#ABB4B6] - RenderInline {t} at (0,0) size 36x17 - RenderInline {a} at (0,0) size 36x17 [color=#1155CC] - RenderText {#text} at (8,8) size 36x17 - text run at (8,8) width 36: "$800" - RenderText {#text} at (0,0) size 0x0 + RenderBlock {t} at (8,8) size 35.59x18 + RenderBlock {a} at (0,0) size 35.59x18 [color=#1155CC] + RenderBlock (anonymous) at (0,0) size 35.59x18 + RenderText {#text} at (0,0) size 36x17 + text run at (0,0) width 36: "$800" RenderFlexibleBox {app-panel-content} at (0,96) size 768x50 RenderBlock {div} at (8,25) size 50x0 RenderImage {img} at (0,0) size 50x0 RenderBlock {div} at (58,8) size 650.41x34 - RenderInline {t} at (0,0) size 105x17 - RenderText {#text} at (8,8) size 105x17 - text run at (8,8) width 105: "British Airways" - RenderText {#text} at (0,0) size 0x0 + RenderBlock {t} at (8,8) size 634.41x18 + RenderBlock (anonymous) at (0,0) size 634.41x18 + RenderText {#text} at (0,0) size 105x17 + text run at (0,0) width 105: "British Airways" RenderBlock {div} at (708.41,8) size 51.59x34 [color=#ABB4B6] - RenderInline {t} at (0,0) size 36x17 - RenderInline {a} at (0,0) size 36x17 [color=#1155CC] - RenderText {#text} at (8,8) size 36x17 - text run at (8,8) width 36: "$700" - RenderText {#text} at (0,0) size 0x0 + RenderBlock {t} at (8,8) size 35.59x18 + RenderBlock {a} at (0,0) size 35.59x18 [color=#1155CC] + RenderBlock (anonymous) at (0,0) size 35.59x18 + RenderText {#text} at (0,0) size 36x17 + text run at (0,0) width 36: "$700" RenderFlexibleBox {app-panel-content} at (0,146) size 768x50 RenderBlock {div} at (8,25) size 50x0 RenderImage {img} at (0,0) size 50x0 RenderBlock {div} at (58,8) size 650.41x34 - RenderInline {t} at (0,0) size 47x17 - RenderText {#text} at (8,8) size 47x17 - text run at (8,8) width 47: "United" - RenderText {#text} at (0,0) size 0x0 + RenderBlock {t} at (8,8) size 634.41x18 + RenderBlock (anonymous) at (0,0) size 634.41x18 + RenderText {#text} at (0,0) size 47x17 + text run at (0,0) width 47: "United" RenderBlock {div} at (708.41,8) size 51.59x34 [color=#ABB4B6] - RenderInline {t} at (0,0) size 36x17 - RenderInline {a} at (0,0) size 36x17 [color=#1155CC] - RenderText {#text} at (8,8) size 36x17 - text run at (8,8) width 36: "$667" - RenderText {#text} at (0,0) size 0x0 + RenderBlock {t} at (8,8) size 35.59x18 + RenderBlock {a} at (0,0) size 35.59x18 [color=#1155CC] + RenderBlock (anonymous) at (0,0) size 35.59x18 + RenderText {#text} at (0,0) size 36x17 + text run at (0,0) width 36: "$667" RenderFlexibleBox {app-panel-content} at (0,196) size 768x50 RenderBlock {div} at (8,25) size 50x0 RenderImage {img} at (0,0) size 50x0 RenderBlock {div} at (58,8) size 650.41x34 - RenderInline {t} at (0,0) size 38x17 - RenderText {#text} at (8,8) size 38x17 - text run at (8,8) width 38: "Delta" - RenderText {#text} at (0,0) size 0x0 + RenderBlock {t} at (8,8) size 634.41x18 + RenderBlock (anonymous) at (0,0) size 634.41x18 + RenderText {#text} at (0,0) size 38x17 + text run at (0,0) width 38: "Delta" RenderBlock {div} at (708.41,8) size 51.59x34 [color=#ABB4B6] - RenderInline {t} at (0,0) size 36x17 - RenderInline {a} at (0,0) size 36x17 [color=#1155CC] - RenderText {#text} at (8,8) size 36x17 - text run at (8,8) width 36: "$450" - RenderText {#text} at (0,0) size 0x0 + RenderBlock {t} at (8,8) size 35.59x18 + RenderBlock {a} at (0,0) size 35.59x18 [color=#1155CC] + RenderBlock (anonymous) at (0,0) size 35.59x18 + RenderText {#text} at (0,0) size 36x17 + text run at (0,0) width 36: "$450" RenderFlexibleBox {app-panel} at (16,278) size 768x196 [bgcolor=#FFFFFF] RenderFlexibleBox {app-panel-header} at (0,0) size 768x46 [bgcolor=#DEDEDE] RenderBlock {div} at (8,14) size 722x18 - RenderInline {t} at (0,0) size 87x17 - RenderText {#text} at (0,0) size 87x17 - text run at (0,0) width 87: "SJC to DCA" - RenderText {#text} at (0,0) size 0x0 + RenderBlock {t} at (0,0) size 722x18 + RenderBlock (anonymous) at (0,0) size 722x18 + RenderText {#text} at (0,0) size 87x17 + text run at (0,0) width 87: "SJC to DCA" RenderFlexibleBox {app-menu-button} at (730,8) size 30x30 RenderImage {img} at (8,15) size 14x0 RenderFlexibleBox {app-panel-content} at (0,46) size 768x50 RenderBlock {div} at (8,25) size 50x0 RenderImage {img} at (0,0) size 50x0 RenderBlock {div} at (58,8) size 641.50x34 - RenderInline {t} at (0,0) size 105x17 - RenderText {#text} at (8,8) size 105x17 - text run at (8,8) width 105: "Virgin America" - RenderText {#text} at (0,0) size 0x0 + RenderBlock {t} at (8,8) size 625.50x18 + RenderBlock (anonymous) at (0,0) size 625.50x18 + RenderText {#text} at (0,0) size 105x17 + text run at (0,0) width 105: "Virgin America" RenderBlock {div} at (699.50,8) size 60.50x34 [color=#ABB4B6] - RenderInline {t} at (0,0) size 45x17 - RenderInline {a} at (0,0) size 45x17 [color=#1155CC] - RenderText {#text} at (8,8) size 45x17 - text run at (8,8) width 45: "$1500" - RenderText {#text} at (0,0) size 0x0 + RenderBlock {t} at (8,8) size 44.50x18 + RenderBlock {a} at (0,0) size 44.50x18 [color=#1155CC] + RenderBlock (anonymous) at (0,0) size 44.50x18 + RenderText {#text} at (0,0) size 45x17 + text run at (0,0) width 45: "$1500" RenderFlexibleBox {app-panel-content} at (0,96) size 768x50 RenderBlock {div} at (8,25) size 50x0 RenderImage {img} at (0,0) size 50x0 RenderBlock {div} at (58,8) size 650.41x34 - RenderInline {t} at (0,0) size 49x17 - RenderText {#text} at (8,8) size 49x17 - text run at (8,8) width 49: "jetBlue" - RenderText {#text} at (0,0) size 0x0 + RenderBlock {t} at (8,8) size 634.41x18 + RenderBlock (anonymous) at (0,0) size 634.41x18 + RenderText {#text} at (0,0) size 49x17 + text run at (0,0) width 49: "jetBlue" RenderBlock {div} at (708.41,8) size 51.59x34 [color=#ABB4B6] - RenderInline {t} at (0,0) size 36x17 - RenderInline {a} at (0,0) size 36x17 [color=#1155CC] - RenderText {#text} at (8,8) size 36x17 - text run at (8,8) width 36: "$650" - RenderText {#text} at (0,0) size 0x0 + RenderBlock {t} at (8,8) size 35.59x18 + RenderBlock {a} at (0,0) size 35.59x18 [color=#1155CC] + RenderBlock (anonymous) at (0,0) size 35.59x18 + RenderText {#text} at (0,0) size 36x17 + text run at (0,0) width 36: "$650" RenderFlexibleBox {app-panel-content} at (0,146) size 768x50 RenderBlock {div} at (8,25) size 50x0 RenderImage {img} at (0,0) size 50x0 RenderBlock {div} at (58,8) size 650.41x34 - RenderInline {t} at (0,0) size 47x17 - RenderText {#text} at (8,8) size 47x17 - text run at (8,8) width 47: "United" - RenderText {#text} at (0,0) size 0x0 + RenderBlock {t} at (8,8) size 634.41x18 + RenderBlock (anonymous) at (0,0) size 634.41x18 + RenderText {#text} at (0,0) size 47x17 + text run at (0,0) width 47: "United" RenderBlock {div} at (708.41,8) size 51.59x34 [color=#ABB4B6] - RenderInline {t} at (0,0) size 36x17 - RenderInline {a} at (0,0) size 36x17 [color=#1155CC] - RenderText {#text} at (8,8) size 36x17 - text run at (8,8) width 36: "$367" - RenderText {#text} at (0,0) size 0x0 -layer at (514,522) size 254x46 - RenderFlexibleBox {app-toast} at (513.98,522) size 254.02x46 [bgcolor=#B0281A] [border: (1px solid #AEA477)] - RenderBlock {div} at (7,7) size 32x32 + RenderBlock {t} at (8,8) size 35.59x18 + RenderBlock {a} at (0,0) size 35.59x18 [color=#1155CC] + RenderBlock (anonymous) at (0,0) size 35.59x18 + RenderText {#text} at (0,0) size 36x17 + text run at (0,0) width 36: "$367" +layer at (609,509) size 159x59 + RenderFlexibleBox {app-toast} at (609.31,509) size 158.69x59 [bgcolor=#B0281A] [border: (1px solid #AEA477)] + RenderBlock {div} at (7,13.50) size 32x32 RenderBlock {div} at (0,0) size 32x32 [border: (2px solid #000000)] - RenderInline {t} at (0,0) size 16x27 - RenderText {#text} at (8,3) size 16x27 - text run at (8,3) width 16: "?" - RenderText {#text} at (0,0) size 0x0 - RenderBlock {div} at (45,15.50) size 202.02x15 - RenderBlock {div} at (0,0) size 202.02x15 - RenderInline {t} at (0,0) size 203x15 - RenderText {#text} at (0,0) size 64x15 - text run at (0,0) width 64: "Flights are " - RenderInline {span} at (0,0) size 29x15 - RenderText {#text} at (63,0) size 29x15 - text run at (63,0) width 29: "$200" - RenderText {#text} at (91,0) size 112x15 - text run at (91,0) width 112: " cheaper tomorrow." - RenderText {#text} at (0,0) size 0x0 + RenderBlock {t} at (2,2) size 28x30 + RenderBlock (anonymous) at (0,0) size 28x30 + RenderText {#text} at (6,1) size 16x27 + text run at (6,1) width 16: "?" + RenderBlock {div} at (45,7) size 106.69x45 + RenderBlock {div} at (0,0) size 106.69x45 + RenderBlock {t} at (0,0) size 106.69x45 + RenderBlock (anonymous) at (0,0) size 106.69x15 + RenderText {#text} at (0,0) size 60x15 + text run at (0,0) width 60: "Flights are" + RenderBlock {span} at (0,15) size 106.69x15 + RenderBlock (anonymous) at (0,0) size 106.69x15 + RenderText {#text} at (0,0) size 29x15 + text run at (0,0) width 29: "$200" + RenderBlock (anonymous) at (0,30) size 106.69x15 + RenderText {#text} at (0,0) size 107x15 + text run at (0,0) width 107: "cheaper tomorrow."
diff --git a/sky/tests/layout/continuations-expected.txt b/sky/tests/layout/continuations-expected.txt new file mode 100644 index 0000000..c88d5e8 --- /dev/null +++ b/sky/tests/layout/continuations-expected.txt
@@ -0,0 +1,13 @@ +layer at (0,0) size 800x600 + RenderView {#document} at (0,0) size 800x600 +layer at (0,0) size 800x19 + RenderBlock {sky} at (0,0) size 800x19 + RenderBlock {div} at (0,0) size 800x19 + RenderBlock {span} at (0,0) size 800x19 + RenderBlock {div} at (0,0) size 25.22x19 + RenderBlock (anonymous) at (0,0) size 25.22x19 + RenderText {#text} at (0,0) size 26x19 + text run at (0,0) width 26: "foo" + RenderText {#text} at (25,0) size 27x19 + text run at (25,0) width 27: "bar" +
diff --git a/sky/tests/layout/continuations.sky b/sky/tests/layout/continuations.sky new file mode 100644 index 0000000..2c04baa --- /dev/null +++ b/sky/tests/layout/continuations.sky
@@ -0,0 +1,4 @@ +<sky> + <import src="../resources/dump-as-render-tree.sky" /> + <div><span style="display: paragraph"><div>foo</div>bar</span></div> +</sky>
diff --git a/sky/tests/lowlevel/abarth.sky b/sky/tests/lowlevel/abarth.sky index f604ce2..2af8f28 100644 --- a/sky/tests/lowlevel/abarth.sky +++ b/sky/tests/lowlevel/abarth.sky
@@ -19,6 +19,13 @@ background-size: cover; } +.line, +.link, +.name, +.photograph-credit { + display: paragraph; +} + .photograph-credit { position: absolute; right: 0;
diff --git a/sky/tests/lowlevel/hello-world-expected.txt b/sky/tests/lowlevel/hello-world-expected.txt index 99b8286..573c2e6 100644 --- a/sky/tests/lowlevel/hello-world-expected.txt +++ b/sky/tests/lowlevel/hello-world-expected.txt
@@ -2,6 +2,7 @@ RenderView {#document} at (0,0) size 800x600 layer at (0,0) size 800x19 RenderBlock {foo} at (0,0) size 800x19 - RenderText {#text} at (0,0) size 99x19 - text run at (0,0) width 99: "Hello World!" + RenderBlock (anonymous) at (0,0) size 800x19 + RenderText {#text} at (0,0) size 99x19 + text run at (0,0) width 99: "Hello World!"
diff --git a/sky/tests/lowlevel/iframe-expected.txt b/sky/tests/lowlevel/iframe-expected.txt index 6495ab1..0cd4429 100644 --- a/sky/tests/lowlevel/iframe-expected.txt +++ b/sky/tests/lowlevel/iframe-expected.txt
@@ -10,8 +10,9 @@ RenderText {#text} at (0,0) size 72x19 text run at (0,0) width 72: "element." RenderBlock {div} at (0,228) size 800x200 - RenderText {#text} at (0,0) size 99x19 - text run at (0,0) width 99: "Placeholder." + RenderBlock (anonymous) at (0,0) size 800x19 + RenderText {#text} at (0,0) size 99x19 + text run at (0,0) width 99: "Placeholder." RenderBlock {div} at (0,428) size 800x78 RenderBlock (anonymous) at (0,0) size 800x19 RenderText {#text} at (0,0) size 218x19
diff --git a/sky/tests/lowlevel/scrollbar-expected.txt b/sky/tests/lowlevel/scrollbar-expected.txt index 28369d9..0756a1f 100644 --- a/sky/tests/lowlevel/scrollbar-expected.txt +++ b/sky/tests/lowlevel/scrollbar-expected.txt
@@ -5,48 +5,63 @@ layer at (0,0) size 800x400 scrollHeight 1500 RenderBlock {scroller} at (0,0) size 800x400 RenderBlock {div} at (0,0) size 800x100 - RenderText {#text} at (0,0) size 10x19 - text run at (0,0) width 10: "a" + RenderBlock (anonymous) at (0,0) size 800x19 + RenderText {#text} at (0,0) size 10x19 + text run at (0,0) width 10: "a" RenderBlock {div} at (0,100) size 800x100 - RenderText {#text} at (0,0) size 11x19 - text run at (0,0) width 11: "b" + RenderBlock (anonymous) at (0,0) size 800x19 + RenderText {#text} at (0,0) size 11x19 + text run at (0,0) width 11: "b" RenderBlock {div} at (0,200) size 800x100 - RenderText {#text} at (0,0) size 9x19 - text run at (0,0) width 9: "c" + RenderBlock (anonymous) at (0,0) size 800x19 + RenderText {#text} at (0,0) size 9x19 + text run at (0,0) width 9: "c" RenderBlock {div} at (0,300) size 800x100 - RenderText {#text} at (0,0) size 11x19 - text run at (0,0) width 11: "d" + RenderBlock (anonymous) at (0,0) size 800x19 + RenderText {#text} at (0,0) size 11x19 + text run at (0,0) width 11: "d" RenderBlock {div} at (0,400) size 800x100 - RenderText {#text} at (0,0) size 10x19 - text run at (0,0) width 10: "e" + RenderBlock (anonymous) at (0,0) size 800x19 + RenderText {#text} at (0,0) size 10x19 + text run at (0,0) width 10: "e" RenderBlock {div} at (0,500) size 800x100 - RenderText {#text} at (0,0) size 6x19 - text run at (0,0) width 6: "f" + RenderBlock (anonymous) at (0,0) size 800x19 + RenderText {#text} at (0,0) size 6x19 + text run at (0,0) width 6: "f" RenderBlock {div} at (0,600) size 800x100 - RenderText {#text} at (0,0) size 11x19 - text run at (0,0) width 11: "g" + RenderBlock (anonymous) at (0,0) size 800x19 + RenderText {#text} at (0,0) size 11x19 + text run at (0,0) width 11: "g" RenderBlock {div} at (0,700) size 800x100 - RenderText {#text} at (0,0) size 11x19 - text run at (0,0) width 11: "h" + RenderBlock (anonymous) at (0,0) size 800x19 + RenderText {#text} at (0,0) size 11x19 + text run at (0,0) width 11: "h" RenderBlock {div} at (0,800) size 800x100 - RenderText {#text} at (0,0) size 5x19 - text run at (0,0) width 5: "i" + RenderBlock (anonymous) at (0,0) size 800x19 + RenderText {#text} at (0,0) size 5x19 + text run at (0,0) width 5: "i" RenderBlock {div} at (0,900) size 800x100 - RenderText {#text} at (0,0) size 5x19 - text run at (0,0) width 5: "j" + RenderBlock (anonymous) at (0,0) size 800x19 + RenderText {#text} at (0,0) size 5x19 + text run at (0,0) width 5: "j" RenderBlock {div} at (0,1000) size 800x100 - RenderText {#text} at (0,0) size 10x19 - text run at (0,0) width 10: "k" + RenderBlock (anonymous) at (0,0) size 800x19 + RenderText {#text} at (0,0) size 10x19 + text run at (0,0) width 10: "k" RenderBlock {div} at (0,1100) size 800x100 - RenderText {#text} at (0,0) size 5x19 - text run at (0,0) width 5: "l" + RenderBlock (anonymous) at (0,0) size 800x19 + RenderText {#text} at (0,0) size 5x19 + text run at (0,0) width 5: "l" RenderBlock {div} at (0,1200) size 800x100 - RenderText {#text} at (0,0) size 16x19 - text run at (0,0) width 16: "m" + RenderBlock (anonymous) at (0,0) size 800x19 + RenderText {#text} at (0,0) size 16x19 + text run at (0,0) width 16: "m" RenderBlock {div} at (0,1300) size 800x100 - RenderText {#text} at (0,0) size 11x19 - text run at (0,0) width 11: "n" + RenderBlock (anonymous) at (0,0) size 800x19 + RenderText {#text} at (0,0) size 11x19 + text run at (0,0) width 11: "n" RenderBlock {div} at (0,1400) size 800x100 - RenderText {#text} at (0,0) size 10x19 - text run at (0,0) width 10: "o" + RenderBlock (anonymous) at (0,0) size 800x19 + RenderText {#text} at (0,0) size 10x19 + text run at (0,0) width 10: "o"