void RenderRegion::ensureOverflowForBox(const RenderBox* box, RefPtr<RenderOverflow>& overflow, bool forceCreation) { RenderFlowThread* flowThread = this->flowThread(); ASSERT(flowThread); RenderBoxRegionInfo* boxInfo = renderBoxRegionInfo(box); if (!boxInfo && !forceCreation) return; if (boxInfo && boxInfo->overflow()) { overflow = boxInfo->overflow(); return; } LayoutRect borderBox = box->borderBoxRectInRegion(this); LayoutRect clientBox; ASSERT(flowThread->objectShouldPaintInFlowRegion(box, this)); if (!borderBox.isEmpty()) { borderBox = rectFlowPortionForBox(box, borderBox); clientBox = box->clientBoxRectInRegion(this); clientBox = rectFlowPortionForBox(box, clientBox); flowThread->flipForWritingModeLocalCoordinates(borderBox); flowThread->flipForWritingModeLocalCoordinates(clientBox); } if (boxInfo) { boxInfo->createOverflow(clientBox, borderBox); overflow = boxInfo->overflow(); } else overflow = adoptRef(new RenderOverflow(clientBox, borderBox)); }
void RenderView::pushLayoutState(LayoutState& layoutState) { if (m_flowThreadController) { RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread(); if (currentFlowThread) currentFlowThread->pushFlowThreadLayoutState(layoutState.renderer()); } m_layoutState = &layoutState; }
void RenderView::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { RenderBlock::styleDidChange(diff, oldStyle); for (RenderObject* renderer = firstChild(); renderer; renderer = renderer->nextSibling()) { if (renderer->isRenderFlowThread()) { RenderFlowThread* flowRenderer = toRenderFlowThread(renderer); flowRenderer->setStyle(RenderFlowThread::createFlowThreadStyle(style())); } } }
void RenderView::popLayoutStateForCurrentFlowThread() { if (!m_flowThreadController) return; RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread(); if (!currentFlowThread) return; currentFlowThread->popFlowThreadLayoutState(); }
void RenderView::pushLayoutStateForCurrentFlowThread(const RenderObject* object) { if (!m_flowThreadController) return; RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread(); if (!currentFlowThread) return; currentFlowThread->pushFlowThreadLayoutState(object); }
static inline bool inFlowThread(RenderObject* renderer, RenderNamedFlowThread* flowThread) { if (!renderer) return false; RenderFlowThread* currentFlowThread = renderer->flowThreadContainingBlock(); if (flowThread == currentFlowThread) return true; if (renderer->flowThreadState() != RenderObject::InsideInFlowThread) return false; // An in-flow flow thread can be nested inside an out-of-flow one, so we have to recur up to check. return inFlowThread(currentFlowThread->containingBlock(), flowThread); }
void RenderView::popLayoutState() { ASSERT(m_layoutState); m_layoutState = m_layoutState->next(); if (!m_flowThreadController) return; RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread(); if (!currentFlowThread) return; currentFlowThread->popFlowThreadLayoutState(); }
RenderRegion* RootInlineBox::containingRegion() const { ContainingRegionMap& regionMap = containingRegionMap(blockFlow()); bool hasContainingRegion = regionMap.contains(this); RenderRegion* region = hasContainingRegion ? regionMap.get(this) : nullptr; #ifndef NDEBUG if (hasContainingRegion) { RenderFlowThread* flowThread = blockFlow().flowThreadContainingBlock(); const RenderRegionList& regionList = flowThread->renderRegionList(); ASSERT_WITH_SECURITY_IMPLICATION(regionList.contains(region)); } #endif return region; }
RenderMultiColumnSet::RenderMultiColumnSet(RenderFlowThread& flowThread, PassRef<RenderStyle> style) : RenderRegionSet(flowThread.document(), std::move(style), flowThread) , m_computedColumnCount(1) , m_computedColumnWidth(0) , m_computedColumnHeight(0) , m_maxColumnHeight(RenderFlowThread::maxLogicalHeight()) , m_minSpaceShortage(RenderFlowThread::maxLogicalHeight()) , m_minimumColumnHeight(0) { }
RenderFlowThread* RenderView::renderFlowThreadWithName(const AtomicString& flowThread) { if (!m_renderFlowThreadList) m_renderFlowThreadList = adoptPtr(new RenderFlowThreadList()); else { for (RenderFlowThreadList::iterator iter = m_renderFlowThreadList->begin(); iter != m_renderFlowThreadList->end(); ++iter) { RenderFlowThread* flowRenderer = *iter; if (flowRenderer->flowThread() == flowThread) return flowRenderer; } } RenderFlowThread* flowRenderer = new (renderArena()) RenderFlowThread(document(), flowThread); flowRenderer->setStyle(RenderFlowThread::createFlowThreadStyle(style())); addChild(flowRenderer); m_renderFlowThreadList->add(flowRenderer); setIsRenderFlowThreadOrderDirty(true); return flowRenderer; }
void RenderRegion::computeOverflowFromFlowThread() { ASSERT(isValid()); LayoutRect layoutRect; { // When getting the overflow from the flow thread we need to temporarly reset the current flow thread because // we're changing flows. CurrentRenderFlowThreadMaintainer flowThreadMaintainer(m_flowThread); layoutRect = layoutOverflowRectForBox(m_flowThread); } layoutRect.setLocation(contentBoxRect().location() + (layoutRect.location() - m_flowThreadPortionRect.location())); // FIXME: Correctly adjust the layout overflow for writing modes. addLayoutOverflow(layoutRect); RenderFlowThread* enclosingRenderFlowThread = flowThreadContainingBlock(); if (enclosingRenderFlowThread) enclosingRenderFlowThread->addRegionsLayoutOverflow(this, layoutRect); updateLayerTransform(); updateScrollInfoAfterLayout(); }
void RenderView::layoutRenderFlowThreads() { ASSERT(m_renderFlowThreadList); if (isRenderFlowThreadOrderDirty()) { // Arrange the thread list according to dependencies. RenderFlowThreadList sortedList; for (RenderFlowThreadList::iterator iter = m_renderFlowThreadList->begin(); iter != m_renderFlowThreadList->end(); ++iter) { RenderFlowThread* flowRenderer = *iter; if (sortedList.contains(flowRenderer)) continue; flowRenderer->pushDependencies(sortedList); sortedList.add(flowRenderer); } m_renderFlowThreadList->swap(sortedList); setIsRenderFlowThreadOrderDirty(false); } for (RenderFlowThreadList::iterator iter = m_renderFlowThreadList->begin(); iter != m_renderFlowThreadList->end(); ++iter) { RenderFlowThread* flowRenderer = *iter; flowRenderer->layoutIfNeeded(); } }
static PassRefPtr<InspectorArray> buildObjectForRendererFragments(RenderObject* renderer, const HighlightConfig& config) { RefPtr<InspectorArray> fragmentsArray = InspectorArray::create(); RenderFlowThread* containingFlowThread = renderer->flowThreadContainingBlock(); if (!containingFlowThread) { Highlight highlight; buildRendererHighlight(renderer, nullptr, config, &highlight, InspectorOverlay::CoordinateSystem::View); fragmentsArray->pushObject(buildObjectForHighlight(highlight)); } else { RenderRegion* startRegion = nullptr; RenderRegion* endRegion = nullptr; if (!containingFlowThread->getRegionRangeForBox(&renderer->enclosingBox(), startRegion, endRegion)) { // The flow has no visible regions. The renderer is not visible on screen. return nullptr; } const RenderRegionList& regionList = containingFlowThread->renderRegionList(); for (RenderRegionList::const_iterator iter = regionList.find(startRegion); iter != regionList.end(); ++iter) { RenderRegion* region = *iter; if (region->isValid()) { // Compute the highlight of the fragment inside the current region. Highlight highlight; buildRendererHighlight(renderer, region, config, &highlight, InspectorOverlay::CoordinateSystem::View); RefPtr<InspectorObject> fragmentObject = buildObjectForHighlight(highlight); // Compute the clipping area of the region. fragmentObject->setObject("region", buildObjectForCSSRegionContentClip(region)); fragmentsArray->pushObject(fragmentObject.release()); } if (region == endRegion) break; } } return fragmentsArray.release(); }
static PassRefPtr<InspectorObject> buildObjectForCSSRegionContentClip(RenderRegion* region) { Frame* containingFrame = region->document().frame(); if (!containingFrame) return nullptr; FrameView* containingView = containingFrame->view(); FrameView* mainView = containingFrame->page()->mainFrame().view(); RenderFlowThread* flowThread = region->flowThread(); // Get the clip box of the current region and covert it into an absolute quad. LayoutRect flippedRegionRect(region->flowThreadPortionOverflowRect()); flowThread->flipForWritingMode(flippedRegionRect); // Apply any border or padding of the region. flippedRegionRect.setLocation(region->contentBoxRect().location()); FloatQuad clipQuad = region->localToAbsoluteQuad(FloatRect(flippedRegionRect)); contentsQuadToPage(mainView, containingView, clipQuad); RefPtr<InspectorObject> regionObject = InspectorObject::create(); regionObject->setArray("quad", buildArrayForQuad(clipQuad)); return regionObject.release(); }
static PassRefPtr<InspectorObject> buildObjectForElementInfo(Node* node) { if (!node->isElementNode() || !node->document().frame()) return nullptr; RefPtr<InspectorObject> elementInfo = InspectorObject::create(); Element* element = toElement(node); bool isXHTML = element->document().isXHTMLDocument(); elementInfo->setString("tagName", isXHTML ? element->nodeName() : element->nodeName().lower()); elementInfo->setString("idValue", element->getIdAttribute()); HashSet<AtomicString> usedClassNames; if (element->hasClass() && element->isStyledElement()) { StringBuilder classNames; const SpaceSplitString& classNamesString = toStyledElement(element)->classNames(); size_t classNameCount = classNamesString.size(); for (size_t i = 0; i < classNameCount; ++i) { const AtomicString& className = classNamesString[i]; if (usedClassNames.contains(className)) continue; usedClassNames.add(className); classNames.append('.'); classNames.append(className); } elementInfo->setString("className", classNames.toString()); } RenderElement* renderer = element->renderer(); Frame* containingFrame = node->document().frame(); FrameView* containingView = containingFrame->view(); IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect())); RenderBoxModelObject* modelObject = renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : nullptr; elementInfo->setString("nodeWidth", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetWidth(), *modelObject) : boundingBox.width())); elementInfo->setString("nodeHeight", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetHeight(), *modelObject) : boundingBox.height())); if (renderer->isRenderNamedFlowFragmentContainer()) { RenderNamedFlowFragment* region = toRenderBlockFlow(renderer)->renderNamedFlowFragment(); if (region->isValid()) { RenderFlowThread* flowThread = region->flowThread(); ASSERT(flowThread && flowThread->isRenderNamedFlowThread()); RefPtr<InspectorObject> regionFlowInfo = InspectorObject::create(); regionFlowInfo->setString("name", toRenderNamedFlowThread(flowThread)->flowThreadName()); regionFlowInfo->setArray("regions", buildObjectForCSSRegionsHighlight(region, flowThread)); elementInfo->setObject("regionFlowInfo", regionFlowInfo.release()); } } RenderFlowThread* containingFlowThread = renderer->flowThreadContainingBlock(); if (containingFlowThread && containingFlowThread->isRenderNamedFlowThread()) { RefPtr<InspectorObject> contentFlowInfo = InspectorObject::create(); contentFlowInfo->setString("name", toRenderNamedFlowThread(containingFlowThread)->flowThreadName()); elementInfo->setObject("contentFlowInfo", contentFlowInfo.release()); } #if ENABLE(CSS_SHAPES) if (renderer->isBox()) { RenderBox* renderBox = toRenderBox(renderer); if (RefPtr<InspectorObject> shapeObject = buildObjectForShapeOutside(containingFrame, renderBox)) elementInfo->setObject("shapeOutsideInfo", shapeObject.release()); } #endif // Need to enable AX to get the computed role. if (!WebCore::AXObjectCache::accessibilityEnabled()) WebCore::AXObjectCache::enableAccessibility(); if (AXObjectCache* axObjectCache = node->document().axObjectCache()) { if (AccessibilityObject* axObject = axObjectCache->getOrCreate(node)) elementInfo->setString("role", axObject->computedRoleString()); } return elementInfo.release(); }
static void buildRendererHighlight(RenderObject* renderer, RenderRegion* region, const HighlightConfig& highlightConfig, Highlight* highlight, InspectorOverlay::CoordinateSystem coordinateSystem) { Frame* containingFrame = renderer->document().frame(); if (!containingFrame) return; highlight->setDataFromConfig(highlightConfig); FrameView* containingView = containingFrame->view(); FrameView* mainView = containingFrame->page()->mainFrame().view(); // RenderSVGRoot should be highlighted through the isBox() code path, all other SVG elements should just dump their absoluteQuads(). bool isSVGRenderer = renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot(); if (isSVGRenderer) { highlight->type = HighlightTypeRects; renderer->absoluteQuads(highlight->quads); for (size_t i = 0; i < highlight->quads.size(); ++i) contentsQuadToCoordinateSystem(mainView, containingView, highlight->quads[i], coordinateSystem); } else if (renderer->isBox() || renderer->isRenderInline()) { LayoutRect contentBox; LayoutRect paddingBox; LayoutRect borderBox; LayoutRect marginBox; if (renderer->isBox()) { RenderBox* renderBox = toRenderBox(renderer); LayoutBoxExtent margins(renderBox->marginTop(), renderBox->marginRight(), renderBox->marginBottom(), renderBox->marginLeft()); if (!renderBox->isOutOfFlowPositioned() && region) { RenderBox::LogicalExtentComputedValues computedValues; renderBox->computeLogicalWidthInRegion(computedValues, region); margins.mutableLogicalLeft(renderBox->style().writingMode()) = computedValues.m_margins.m_start; margins.mutableLogicalRight(renderBox->style().writingMode()) = computedValues.m_margins.m_end; } paddingBox = renderBox->clientBoxRectInRegion(region); contentBox = LayoutRect(paddingBox.x() + renderBox->paddingLeft(), paddingBox.y() + renderBox->paddingTop(), paddingBox.width() - renderBox->paddingLeft() - renderBox->paddingRight(), paddingBox.height() - renderBox->paddingTop() - renderBox->paddingBottom()); borderBox = LayoutRect(paddingBox.x() - renderBox->borderLeft(), paddingBox.y() - renderBox->borderTop(), paddingBox.width() + renderBox->borderLeft() + renderBox->borderRight(), paddingBox.height() + renderBox->borderTop() + renderBox->borderBottom()); marginBox = LayoutRect(borderBox.x() - margins.left(), borderBox.y() - margins.top(), borderBox.width() + margins.left() + margins.right(), borderBox.height() + margins.top() + margins.bottom()); } else { RenderInline* renderInline = toRenderInline(renderer); // RenderInline's bounding box includes paddings and borders, excludes margins. borderBox = renderInline->linesBoundingBox(); paddingBox = LayoutRect(borderBox.x() + renderInline->borderLeft(), borderBox.y() + renderInline->borderTop(), borderBox.width() - renderInline->borderLeft() - renderInline->borderRight(), borderBox.height() - renderInline->borderTop() - renderInline->borderBottom()); contentBox = LayoutRect(paddingBox.x() + renderInline->paddingLeft(), paddingBox.y() + renderInline->paddingTop(), paddingBox.width() - renderInline->paddingLeft() - renderInline->paddingRight(), paddingBox.height() - renderInline->paddingTop() - renderInline->paddingBottom()); // Ignore marginTop and marginBottom for inlines. marginBox = LayoutRect(borderBox.x() - renderInline->marginLeft(), borderBox.y(), borderBox.width() + renderInline->horizontalMarginExtent(), borderBox.height()); } FloatQuad absContentQuad; FloatQuad absPaddingQuad; FloatQuad absBorderQuad; FloatQuad absMarginQuad; if (region) { RenderFlowThread* flowThread = region->flowThread(); // Figure out the quads in the space of the RenderFlowThread. absContentQuad = renderer->localToContainerQuad(FloatRect(contentBox), flowThread); absPaddingQuad = renderer->localToContainerQuad(FloatRect(paddingBox), flowThread); absBorderQuad = renderer->localToContainerQuad(FloatRect(borderBox), flowThread); absMarginQuad = renderer->localToContainerQuad(FloatRect(marginBox), flowThread); // Move the quad relative to the space of the current region. LayoutRect flippedRegionRect(region->flowThreadPortionRect()); flowThread->flipForWritingMode(flippedRegionRect); FloatSize delta = region->contentBoxRect().location() - flippedRegionRect.location(); absContentQuad.move(delta); absPaddingQuad.move(delta); absBorderQuad.move(delta); absMarginQuad.move(delta); // Resolve the absolute quads starting from the current region. absContentQuad = region->localToAbsoluteQuad(absContentQuad); absPaddingQuad = region->localToAbsoluteQuad(absPaddingQuad); absBorderQuad = region->localToAbsoluteQuad(absBorderQuad); absMarginQuad = region->localToAbsoluteQuad(absMarginQuad); } else { absContentQuad = renderer->localToAbsoluteQuad(FloatRect(contentBox)); absPaddingQuad = renderer->localToAbsoluteQuad(FloatRect(paddingBox)); absBorderQuad = renderer->localToAbsoluteQuad(FloatRect(borderBox)); absMarginQuad = renderer->localToAbsoluteQuad(FloatRect(marginBox)); } contentsQuadToCoordinateSystem(mainView, containingView, absContentQuad, coordinateSystem); contentsQuadToCoordinateSystem(mainView, containingView, absPaddingQuad, coordinateSystem); contentsQuadToCoordinateSystem(mainView, containingView, absBorderQuad, coordinateSystem); contentsQuadToCoordinateSystem(mainView, containingView, absMarginQuad, coordinateSystem); highlight->type = HighlightTypeNode; highlight->quads.append(absMarginQuad); highlight->quads.append(absBorderQuad); highlight->quads.append(absPaddingQuad); highlight->quads.append(absContentQuad); } }