void RenderTreeUpdater::createRenderer(Element& element, RenderStyle&& style) { auto computeInsertionPosition = [this, &element, &style] () { #if ENABLE(CSS_REGIONS) if (element.shouldMoveToFlowThread(style)) return RenderTreePosition::insertionPositionForFlowThread(renderTreePosition().parent().element(), element, style); #endif renderTreePosition().computeNextSibling(element); return renderTreePosition(); }; if (!shouldCreateRenderer(element, renderTreePosition().parent())) return; #if ENABLE(CSS_REGIONS) // Even display: none elements need to be registered in FlowThreadController. registerElementForFlowThreadIfNeeded(element, style); #endif if (!element.rendererIsNeeded(style)) return; RenderTreePosition insertionPosition = computeInsertionPosition(); RenderElement* newRenderer = element.createElementRenderer(WTFMove(style), insertionPosition).leakPtr(); if (!newRenderer) return; if (!insertionPosition.canInsert(*newRenderer)) { newRenderer->destroy(); return; } // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail. newRenderer->setFlowThreadState(insertionPosition.parent().flowThreadState()); element.setRenderer(newRenderer); auto& initialStyle = newRenderer->style(); std::unique_ptr<RenderStyle> animatedStyle; newRenderer->animation().updateAnimations(*newRenderer, initialStyle, animatedStyle); if (animatedStyle) newRenderer->setStyleInternal(WTFMove(*animatedStyle)); newRenderer->initializeStyle(); #if ENABLE(FULLSCREEN_API) if (m_document.webkitIsFullScreen() && m_document.webkitCurrentFullScreenElement() == &element) { newRenderer = RenderFullScreen::wrapRenderer(newRenderer, &insertionPosition.parent(), m_document); if (!newRenderer) return; } #endif // Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer. insertionPosition.insert(*newRenderer); if (AXObjectCache* cache = m_document.axObjectCache()) cache->updateCacheAfterNodeIsAttached(&element); }
static void createTextRenderer(Text& textNode, RenderTreePosition& renderTreePosition) { ASSERT(!textNode.renderer()); auto newRenderer = textNode.createTextRenderer(renderTreePosition.parent().style()); ASSERT(newRenderer); renderTreePosition.computeNextSibling(textNode); if (!renderTreePosition.canInsert(*newRenderer)) return; textNode.setRenderer(newRenderer.get()); renderTreePosition.insert(*newRenderer.leakPtr()); }
static void createTextRenderer(Text& textNode, RenderTreePosition& renderTreePosition) { ASSERT(!textNode.renderer()); auto newRenderer = textNode.createTextRenderer(renderTreePosition.parent().style()); ASSERT(newRenderer); renderTreePosition.computeNextSibling(textNode); if (!renderTreePosition.canInsert(*newRenderer)) return; // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail. newRenderer->setFlowThreadState(renderTreePosition.parent().flowThreadState()); textNode.setRenderer(newRenderer.get()); renderTreePosition.insert(*newRenderer.leakPtr()); }
static bool textRendererIsNeeded(const Text& textNode, const RenderTreePosition& renderTreePosition) { const RenderElement& parentRenderer = renderTreePosition.parent(); if (!parentRenderer.canHaveChildren()) return false; if (parentRenderer.element() && !parentRenderer.element()->childShouldCreateRenderer(textNode)) return false; if (textNode.isEditingText()) return true; if (!textNode.length()) return false; if (!textNode.containsOnlyWhitespace()) return true; // This text node has nothing but white space. We may still need a renderer in some cases. if (parentRenderer.isTable() || parentRenderer.isTableRow() || parentRenderer.isTableSection() || parentRenderer.isRenderTableCol() || parentRenderer.isFrameSet()) return false; if (parentRenderer.style().preserveNewline()) // pre/pre-wrap/pre-line always make renderers. return true; RenderObject* previousRenderer = renderTreePosition.previousSiblingRenderer(textNode); if (previousRenderer && previousRenderer->isBR()) // <span><br/> <br/></span> return false; if (parentRenderer.isRenderInline()) { // <span><div/> <div/></span> if (previousRenderer && !previousRenderer->isInline()) return false; } else { if (parentRenderer.isRenderBlock() && !parentRenderer.childrenInline() && (!previousRenderer || !previousRenderer->isInline())) return false; RenderObject* first = parentRenderer.firstChild(); while (first && first->isFloatingOrOutOfFlowPositioned()) first = first->nextSibling(); RenderObject* nextRenderer = renderTreePosition.nextSiblingRenderer(textNode); if (!first || nextRenderer == 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; }