void RenderSVGShape::layout() { bool updateCachedBoundariesInParents = false; if (m_needsShapeUpdate || m_needsBoundariesUpdate) { updateShapeFromElement(); m_needsShapeUpdate = false; updatePaintInvalidationBoundingBox(); m_needsBoundariesUpdate = false; updateCachedBoundariesInParents = true; } if (m_needsTransformUpdate) { m_localTransform = toSVGGraphicsElement(element())->animatedLocalTransform(); m_needsTransformUpdate = false; updateCachedBoundariesInParents = true; } // Invalidate all resources of this client if our layout changed. if (everHadLayout() && selfNeedsLayout()) SVGResourcesCache::clientLayoutChanged(this); // If our bounds changed, notify the parents. if (updateCachedBoundariesInParents) RenderSVGModelObject::setNeedsBoundariesUpdate(); clearNeedsLayout(); }
void RenderSVGShape::layout() { StackStats::LayoutCheckPoint layoutCheckPoint; LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(this) && selfNeedsLayout()); bool updateCachedBoundariesInParents = false; if (m_needsShapeUpdate || m_needsBoundariesUpdate) { updateShapeFromElement(); m_needsShapeUpdate = false; updateRepaintBoundingBox(); m_needsBoundariesUpdate = false; updateCachedBoundariesInParents = true; } if (m_needsTransformUpdate) { m_localTransform = graphicsElement().animatedLocalTransform(); m_needsTransformUpdate = false; updateCachedBoundariesInParents = true; } // Invalidate all resources of this client if our layout changed. if (everHadLayout() && selfNeedsLayout()) SVGResourcesCache::clientLayoutChanged(*this); // If our bounds changed, notify the parents. if (updateCachedBoundariesInParents) RenderSVGModelObject::setNeedsBoundariesUpdate(); repainter.repaintAfterLayout(); clearNeedsLayout(); }
void LayoutSVGImage::layout() { ASSERT(needsLayout()); LayoutAnalyzer::Scope analyzer(*this); updateBoundingBox(); bool transformOrBoundariesUpdate = m_needsTransformUpdate || m_needsBoundariesUpdate; if (m_needsTransformUpdate) { m_localTransform = toSVGImageElement(element())->calculateAnimatedLocalTransform(); m_needsTransformUpdate = false; } if (m_needsBoundariesUpdate) { m_paintInvalidationBoundingBox = m_objectBoundingBox; SVGLayoutSupport::intersectPaintInvalidationRectWithResources(this, m_paintInvalidationBoundingBox); m_needsBoundariesUpdate = false; } // Invalidate all resources of this client if our layout changed. if (everHadLayout() && selfNeedsLayout()) SVGResourcesCache::clientLayoutChanged(this); // If our bounds changed, notify the parents. if (transformOrBoundariesUpdate) LayoutSVGModelObject::setNeedsBoundariesUpdate(); clearNeedsLayout(); }
void RenderSVGImage::layout() { StackStats::LayoutCheckPoint layoutCheckPoint; ASSERT(needsLayout()); LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsLayout()); updateImageViewport(); bool transformOrBoundariesUpdate = m_needsTransformUpdate || m_needsBoundariesUpdate; if (m_needsTransformUpdate) { m_localTransform = static_cast<SVGImageElement*>(node())->animatedLocalTransform(); m_needsTransformUpdate = false; } if (m_needsBoundariesUpdate) { m_repaintBoundingBox = m_objectBoundingBox; SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBox); m_needsBoundariesUpdate = false; } // Invalidate all resources of this client if our layout changed. if (everHadLayout() && selfNeedsLayout()) SVGResourcesCache::clientLayoutChanged(this); // If our bounds changed, notify the parents. if (transformOrBoundariesUpdate) RenderSVGModelObject::setNeedsBoundariesUpdate(); repainter.repaintAfterLayout(); setNeedsLayout(false); }
void RenderSVGContainer::layout() { ASSERT(needsLayout()); // Allow RenderSVGViewportContainer to update its viewport. calcViewport(); // Allow RenderSVGTransformableContainer to update its transform. bool updatedTransform = calculateLocalTransform(); // RenderSVGViewportContainer needs to set the 'layout size changed' flag. determineIfLayoutSizeChanged(); SVGRenderSupport::layoutChildren(this, selfNeedsLayout() || SVGRenderSupport::filtersForceContainerLayout(this)); // Invalidate all resources of this client if our layout changed. if (everHadLayout() && needsLayout()) SVGResourcesCache::clientLayoutChanged(this); if (m_needsBoundariesUpdate || updatedTransform) { updateCachedBoundaries(); m_needsBoundariesUpdate = false; // If our bounds changed, notify the parents. RenderSVGModelObject::setNeedsBoundariesUpdate(); } clearNeedsLayout(); }
void LayoutSVGShape::layout() { bool updateCachedBoundariesInParents = false; LayoutAnalyzer::Scope analyzer(*this); if (m_needsShapeUpdate || m_needsBoundariesUpdate) { updateShapeFromElement(); m_needsShapeUpdate = false; updatePaintInvalidationBoundingBox(); m_needsBoundariesUpdate = false; updateCachedBoundariesInParents = true; } if (m_needsTransformUpdate) { updateLocalTransform(); m_needsTransformUpdate = false; updateCachedBoundariesInParents = true; } // Invalidate all resources of this client if our layout changed. if (everHadLayout() && selfNeedsLayout()) SVGResourcesCache::clientLayoutChanged(this); // If our bounds changed, notify the parents. if (updateCachedBoundariesInParents) LayoutSVGModelObject::setNeedsBoundariesUpdate(); clearNeedsLayout(); }
void RenderSVGContainer::layout() { ASSERT(needsLayout()); // RenderSVGRoot disables layoutState for the SVG rendering tree. ASSERT(!view()->layoutStateEnabled()); LayoutRepainter repainter(*this, checkForRepaintDuringLayout() || selfWillPaint()); // Allow RenderSVGViewportContainer to update its viewport. calcViewport(); // Allow RenderSVGTransformableContainer to update its transform. bool updatedTransform = calculateLocalTransform(); SVGRenderSupport::layoutChildren(this, selfNeedsLayout() || SVGRenderSupport::filtersForceContainerLayout(this)); // Invalidate all resources of this client if our layout changed. if (everHadLayout() && needsLayout()) SVGResourcesCache::clientLayoutChanged(this); // At this point LayoutRepainter already grabbed the old bounds, // recalculate them now so repaintAfterLayout() uses the new bounds. if (m_needsBoundariesUpdate || updatedTransform) { updateCachedBoundaries(); m_needsBoundariesUpdate = false; // If our bounds changed, notify the parents. RenderSVGModelObject::setNeedsBoundariesUpdate(); } repainter.repaintAfterLayout(); setNeedsLayout(false); }
void RenderSVGText::subtreeTextDidChange(RenderSVGInlineText* text) { ASSERT(text); ASSERT(!beingDestroyed()); if (!everHadLayout()) { ASSERT(m_layoutAttributes.isEmpty()); ASSERT(!m_layoutAttributesBuilder.numberOfTextPositioningElements()); return; } // Text transforms can cause text change to be signaled during addChild before m_layoutAttributes has been updated. if (!m_layoutAttributes.contains(text->layoutAttributes())) { ASSERT(!text->everHadLayout()); return; } // Always protect the cache before clearing text positioning elements when the cache will subsequently be rebuilt. FontCachePurgePreventer fontCachePurgePreventer; // The positioning elements cache depends on the size of each text renderer in the // subtree. If this changes, clear the cache. It's going to be rebuilt below. m_layoutAttributesBuilder.clearTextPositioningElements(); checkLayoutAttributesConsistency(this, m_layoutAttributes); for (RenderObject* descendant = text; descendant; descendant = descendant->nextInPreOrder(text)) { if (descendant->isSVGInlineText()) m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(toRenderSVGInlineText(*descendant)); } }
void LayoutSVGImage::layout() { ASSERT(needsLayout()); LayoutAnalyzer::Scope analyzer(*this); // Invalidate all resources of this client if our layout changed. if (everHadLayout() && selfNeedsLayout()) SVGResourcesCache::clientLayoutChanged(this); updateBoundingBox(); bool updateParentBoundaries = false; if (m_needsTransformUpdate) { m_localTransform = toSVGImageElement(element())->calculateTransform( SVGElement::IncludeMotionTransform); m_needsTransformUpdate = false; updateParentBoundaries = true; } if (m_needsBoundariesUpdate) { m_localVisualRect = m_objectBoundingBox; SVGLayoutSupport::adjustVisualRectWithResources(this, m_localVisualRect); m_needsBoundariesUpdate = false; updateParentBoundaries = true; } // If our bounds changed, notify the parents. if (updateParentBoundaries) LayoutSVGModelObject::setNeedsBoundariesUpdate(); ASSERT(!m_needsBoundariesUpdate); ASSERT(!m_needsTransformUpdate); clearNeedsLayout(); }
void RenderSVGResourceContainer::layout() { // Invalidate all resources if our layout changed. if (everHadLayout() && selfNeedsLayout()) RenderSVGRoot::addResourceForClientInvalidation(this); RenderSVGHiddenContainer::layout(); }
void RenderSVGResourceContainer::layout() { // Invalidate all resources if our layout changed. if (everHadLayout() && selfNeedsLayout()) removeAllClientsFromCache(); RenderSVGHiddenContainer::layout(); }
void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect) { if (documentBeingDestroyed()) return; if (!m_imageResource) return; if (newImage != m_imageResource->imagePtr()) return; // Per the spec, we let the server-sent header override srcset/other sources of dpr. // https://github.com/igrigorik/http-client-hints/blob/master/draft-grigorik-http-client-hints-01.txt#L255 if (m_imageResource->cachedImage() && m_imageResource->cachedImage()->hasDevicePixelRatioHeaderValue()) m_imageDevicePixelRatio = 1 / m_imageResource->cachedImage()->devicePixelRatioHeaderValue(); // If the RenderImage was just created we don't have style() or a parent() // yet so all we can do is update our intrinsic size. Once we're inserted // the resulting layout will do the rest of the work. if (!parent()) { updateIntrinsicSizeIfNeeded(m_imageResource->intrinsicSize()); return; } RenderReplaced::imageChanged(newImage, rect); ASSERT(isRooted()); LayoutSize oldIntrinsicSize = intrinsicSize(); LayoutSize newIntrinsicSize = m_imageResource->intrinsicSize(); updateIntrinsicSizeIfNeeded(newIntrinsicSize); bool imageSourceHasChangedSize = oldIntrinsicSize != newIntrinsicSize; if (imageSourceHasChangedSize) setPreferredLogicalWidthsDirty(); // If the actual area occupied by the image has changed and it is not constrained by style then a layout is required. bool imageSizeIsConstrained = style()->logicalWidth().isSpecified() && style()->logicalHeight().isSpecified(); // FIXME: We only need to recompute the containing block's preferred size if the containing block's size // depends on the image's size (i.e., the container uses shrink-to-fit sizing). // There's no easy way to detect that shrink-to-fit is needed, always force a layout. bool containingBlockNeedsToRecomputePreferredSize = style()->logicalWidth().isPercent() || style()->logicalMaxWidth().isPercent() || style()->logicalMinWidth().isPercent(); if (imageSourceHasChangedSize && (!imageSizeIsConstrained || containingBlockNeedsToRecomputePreferredSize)) { setNeedsLayout(); return; } // The image hasn't changed in size or its style constrains its size, so a paint invalidation will suffice. if (everHadLayout() && !selfNeedsLayout()) { // The inner content rectangle is calculated during layout, but may need an update now // (unless the box has already been scheduled for layout). In order to calculate it, we // may need values from the containing block, though, so make sure that we're not too // early. It may be that layout hasn't even taken place once yet. updateInnerContentRect(); } }
void RenderFlowThread::layout() { m_pageLogicalSizeChanged = m_regionsInvalidated && everHadLayout(); CurrentRenderFlowThreadMaintainer currentFlowThreadSetter(this); RenderBlockFlow::layout(); m_pageLogicalSizeChanged = false; }
inline bool RenderSVGText::shouldHandleSubtreeMutations() const { if (beingDestroyed() || !everHadLayout()) { ASSERT(m_layoutAttributes.isEmpty()); ASSERT(!m_layoutAttributesBuilder.numberOfTextPositioningElements()); return false; } return true; }
void LayoutSVGResourceContainer::invalidateCacheAndMarkForLayout(SubtreeLayoutScope* layoutScope) { if (selfNeedsLayout()) return; setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::SvgResourceInvalidated, MarkContainerChain, layoutScope); if (everHadLayout()) removeAllClientsFromCache(); }
void RenderSVGResourceContainer::invalidateCacheAndMarkForLayout(SubtreeLayoutScope* layoutScope) { if (selfNeedsLayout()) return; setNeedsLayoutAndFullPaintInvalidation(MarkContainingBlockChain, layoutScope); if (everHadLayout()) removeAllClientsFromCache(); }
void RenderImage::paintInvalidationOrMarkForLayout(const IntRect* rect) { ASSERT(isRooted()); LayoutSize oldIntrinsicSize = intrinsicSize(); LayoutSize newIntrinsicSize = m_imageResource->intrinsicSize(); updateIntrinsicSizeIfNeeded(newIntrinsicSize); bool imageSourceHasChangedSize = oldIntrinsicSize != newIntrinsicSize; if (imageSourceHasChangedSize) setPreferredLogicalWidthsDirty(); // If the actual area occupied by the image has changed and it is not constrained by style then a layout is required. bool imageSizeIsConstrained = style()->logicalWidth().isSpecified() && style()->logicalHeight().isSpecified(); // FIXME: We only need to recompute the containing block's preferred size if the containing block's size // depends on the image's size (i.e., the container uses shrink-to-fit sizing). // There's no easy way to detect that shrink-to-fit is needed, always force a layout. bool containingBlockNeedsToRecomputePreferredSize = style()->logicalWidth().isPercent() || style()->logicalMaxWidth().isPercent() || style()->logicalMinWidth().isPercent(); if (imageSourceHasChangedSize && (!imageSizeIsConstrained || containingBlockNeedsToRecomputePreferredSize)) { setNeedsLayoutAndFullPaintInvalidation(); return; } // The image hasn't changed in size or its style constrains its size, so a paint invalidation will suffice. if (everHadLayout() && !selfNeedsLayout()) { // The inner content rectangle is calculated during layout, but may need an update now // (unless the box has already been scheduled for layout). In order to calculate it, we // may need values from the containing block, though, so make sure that we're not too // early. It may be that layout hasn't even taken place once yet. updateInnerContentRect(); } LayoutRect paintInvalidationRect; if (rect) { // The image changed rect is in source image coordinates, // so map from the bounds of the image to the contentsBox. paintInvalidationRect = enclosingIntRect(mapRect(*rect, FloatRect(FloatPoint(), m_imageResource->imageSize()), contentBoxRect())); // Guard against too-large changed rects. paintInvalidationRect.intersect(contentBoxRect()); } else { paintInvalidationRect = contentBoxRect(); } { // FIXME: We should not be allowing paint invalidations during layout. crbug.com/339584 AllowPaintInvalidationScope scoper(frameView()); DisableCompositingQueryAsserts disabler; invalidatePaintRectangle(paintInvalidationRect); } // Tell any potential compositing layers that the image needs updating. contentChanged(ImageChanged); }
void RenderSVGResourceMarker::layout() { StackStats::LayoutCheckPoint layoutCheckPoint; // Invalidate all resources if our layout changed. if (everHadLayout() && selfNeedsLayout()) RenderSVGRoot::addResourceForClientInvalidation(this); // RenderSVGHiddenContainer overwrites layout(). We need the // layouting of RenderSVGContainer for calculating local // transformations and repaint. RenderSVGContainer::layout(); }
void LayoutSVGForeignObject::layout() { ASSERT(needsLayout()); SVGForeignObjectElement* foreign = toSVGForeignObjectElement(node()); bool updateCachedBoundariesInParents = false; if (m_needsTransformUpdate) { m_localTransform = foreign->calculateAnimatedLocalTransform(); m_needsTransformUpdate = false; updateCachedBoundariesInParents = true; } FloatRect oldViewport = m_viewport; // Cache viewport boundaries SVGLengthContext lengthContext(foreign); FloatPoint viewportLocation( lengthContext.valueForLength(styleRef().svgStyle().x(), styleRef(), SVGLengthMode::Width), lengthContext.valueForLength(styleRef().svgStyle().y(), styleRef(), SVGLengthMode::Height)); m_viewport = FloatRect( viewportLocation, FloatSize(lengthContext.valueForLength(styleRef().width(), styleRef(), SVGLengthMode::Width), lengthContext.valueForLength(styleRef().height(), styleRef(), SVGLengthMode::Height))); if (!updateCachedBoundariesInParents) updateCachedBoundariesInParents = oldViewport != m_viewport; // Set box origin to the foreignObject x/y translation, so positioned objects // in XHTML content get correct positions. A regular LayoutBoxModelObject // would pull this information from ComputedStyle - in SVG those properties // are ignored for non <svg> elements, so we mimic what happens when // specifying them through CSS. // FIXME: Investigate in location rounding issues - only affects // LayoutSVGForeignObject & LayoutSVGText setLocation(roundedIntPoint(viewportLocation)); bool layoutChanged = everHadLayout() && selfNeedsLayout(); LayoutBlock::layout(); ASSERT(!needsLayout()); // If our bounds changed, notify the parents. if (updateCachedBoundariesInParents) LayoutSVGBlock::setNeedsBoundariesUpdate(); // Invalidate all resources of this client if our layout changed. if (layoutChanged) SVGResourcesCache::clientLayoutChanged(this); }
void RenderSVGForeignObject::layout() { StackStats::LayoutCheckPoint layoutCheckPoint; ASSERT(needsLayout()); ASSERT(!view()->layoutStateEnabled()); // RenderSVGRoot disables layoutState for the SVG rendering tree. LayoutRepainter repainter(*this, checkForRepaintDuringLayout()); SVGForeignObjectElement* foreign = static_cast<SVGForeignObjectElement*>(node()); bool updateCachedBoundariesInParents = false; if (m_needsTransformUpdate) { m_localTransform = foreign->animatedLocalTransform(); m_needsTransformUpdate = false; updateCachedBoundariesInParents = true; } FloatRect oldViewport = m_viewport; // Cache viewport boundaries SVGLengthContext lengthContext(foreign); FloatPoint viewportLocation(foreign->x().value(lengthContext), foreign->y().value(lengthContext)); m_viewport = FloatRect(viewportLocation, FloatSize(foreign->width().value(lengthContext), foreign->height().value(lengthContext))); if (!updateCachedBoundariesInParents) updateCachedBoundariesInParents = oldViewport != m_viewport; // Set box origin to the foreignObject x/y translation, so positioned objects in XHTML content get correct // positions. A regular RenderBoxModelObject would pull this information from RenderStyle - in SVG those // properties are ignored for non <svg> elements, so we mimic what happens when specifying them through CSS. // FIXME: Investigate in location rounding issues - only affects RenderSVGForeignObject & RenderSVGText setLocation(roundedIntPoint(viewportLocation)); bool layoutChanged = everHadLayout() && selfNeedsLayout(); RenderBlock::layout(); ASSERT(!needsLayout()); // If our bounds changed, notify the parents. if (updateCachedBoundariesInParents) RenderSVGBlock::setNeedsBoundariesUpdate(); // Invalidate all resources of this client if our layout changed. if (layoutChanged) SVGResourcesCache::clientLayoutChanged(this); repainter.repaintAfterLayout(); }
void RenderSVGResourceMarker::layout() { ASSERT(needsLayout()); if (m_isInLayout) return; TemporaryChange<bool> inLayoutChange(m_isInLayout, true); // Invalidate all resources if our layout changed. if (everHadLayout() && selfNeedsLayout()) removeAllClientsFromCache(); // RenderSVGHiddenContainer overwrites layout(). We need the // layouting of RenderSVGContainer for calculating local // transformations and repaint. RenderSVGContainer::layout(); }
void RenderFlowThread::layout() { StackStats::LayoutCheckPoint layoutCheckPoint; m_pageLogicalSizeChanged = m_regionsInvalidated && everHadLayout(); validateRegions(); CurrentRenderFlowThreadMaintainer currentFlowThreadSetter(this); RenderBlock::layout(); m_pageLogicalSizeChanged = false; if (lastRegion()) lastRegion()->expandToEncompassFlowThreadContentsIfNeeded(); if (shouldDispatchRegionLayoutUpdateEvent()) dispatchRegionLayoutUpdateEvent(); }
void RenderSVGShape::layout() { LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsLayout()); SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node()); bool updateCachedBoundariesInParents = false; bool needsShapeUpdate = m_needsShapeUpdate; if (needsShapeUpdate || m_needsBoundariesUpdate) { setIsPaintingFallback(false); m_path.clear(); createShape(); m_needsShapeUpdate = false; updateCachedBoundariesInParents = true; } if (m_needsTransformUpdate) { m_localTransform = element->animatedLocalTransform(); m_needsTransformUpdate = false; updateCachedBoundariesInParents = true; } // Invalidate all resources of this client if our layout changed. if (everHadLayout() && selfNeedsLayout()) { SVGResourcesCache::clientLayoutChanged(this); m_markerLayoutInfo.clear(); } // At this point LayoutRepainter already grabbed the old bounds, // recalculate them now so repaintAfterLayout() uses the new bounds. if (needsShapeUpdate || m_needsBoundariesUpdate) { updateCachedBoundaries(); m_needsBoundariesUpdate = false; } // If our bounds changed, notify the parents. if (updateCachedBoundariesInParents) RenderSVGModelObject::setNeedsBoundariesUpdate(); repainter.repaintAfterLayout(); setNeedsLayout(false); }
void RenderMultiColumnBlock::checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight) { // We need to go ahead and set our explicit page height if one exists, so that we can // avoid doing multiple layout passes. computeLogicalHeight(); LayoutUnit newContentLogicalHeight = contentLogicalHeight(); if (newContentLogicalHeight > ZERO_LAYOUT_UNIT) { pageLogicalHeight = newContentLogicalHeight; hasSpecifiedPageLogicalHeight = true; } setLogicalHeight(ZERO_LAYOUT_UNIT); if (columnHeight() != pageLogicalHeight && everHadLayout()) { setColumnHeight(pageLogicalHeight); pageLogicalHeightChanged = true; } // Set up our column sets. ensureColumnSets(); }
void LayoutSVGContainer::layout() { ASSERT(needsLayout()); LayoutAnalyzer::Scope analyzer(*this); // Allow LayoutSVGViewportContainer to update its viewport. calcViewport(); // Allow LayoutSVGTransformableContainer to update its transform. SVGTransformChange transformChange = calculateLocalTransform(); m_didScreenScaleFactorChange = transformChange == SVGTransformChange::Full || SVGLayoutSupport::screenScaleFactorChanged(parent()); // LayoutSVGViewportContainer needs to set the 'layout size changed' flag. determineIfLayoutSizeChanged(); // When hasRelativeLengths() is false, no descendants have relative lengths // (hence no one is interested in viewport size changes). bool layoutSizeChanged = element()->hasRelativeLengths() && SVGLayoutSupport::layoutSizeOfNearestViewportChanged(this); SVGLayoutSupport::layoutChildren( firstChild(), false, m_didScreenScaleFactorChange, layoutSizeChanged); // Invalidate all resources of this client if our layout changed. if (everHadLayout() && needsLayout()) SVGResourcesCache::clientLayoutChanged(this); if (m_needsBoundariesUpdate || transformChange != SVGTransformChange::None) { updateCachedBoundaries(); m_needsBoundariesUpdate = false; // If our bounds changed, notify the parents. LayoutSVGModelObject::setNeedsBoundariesUpdate(); } ASSERT(!m_needsBoundariesUpdate); clearNeedsLayout(); }
void LayoutSVGShape::layout() { LayoutAnalyzer::Scope analyzer(*this); // Invalidate all resources of this client if our layout changed. if (everHadLayout() && selfNeedsLayout()) SVGResourcesCache::clientLayoutChanged(this); bool updateParentBoundaries = false; // updateShapeFromElement() also updates the object & stroke bounds - which // feeds into the visual rect - so we need to call it for both the // shape-update and the bounds-update flag. if (m_needsShapeUpdate || m_needsBoundariesUpdate) { FloatRect oldObjectBoundingBox = objectBoundingBox(); updateShapeFromElement(); if (oldObjectBoundingBox != objectBoundingBox()) setShouldDoFullPaintInvalidation(); m_needsShapeUpdate = false; m_localVisualRect = strokeBoundingBox(); SVGLayoutSupport::adjustVisualRectWithResources(this, m_localVisualRect); m_needsBoundariesUpdate = false; updateParentBoundaries = true; } if (m_needsTransformUpdate) { updateLocalTransform(); m_needsTransformUpdate = false; updateParentBoundaries = true; } // If our bounds changed, notify the parents. if (updateParentBoundaries) LayoutSVGModelObject::setNeedsBoundariesUpdate(); ASSERT(!m_needsShapeUpdate); ASSERT(!m_needsBoundariesUpdate); ASSERT(!m_needsTransformUpdate); clearNeedsLayout(); }
void LayoutSVGText::subtreeTextDidChange(LayoutSVGInlineText* text) { ASSERT(text); ASSERT(!beingDestroyed()); if (!everHadLayout()) { ASSERT(m_layoutAttributes.isEmpty()); ASSERT(!m_layoutAttributesBuilder.numberOfTextPositioningElements()); return; } // Always protect the cache before clearing text positioning elements when the cache will subsequently be rebuilt. FontCachePurgePreventer fontCachePurgePreventer; // The positioning elements cache depends on the size of each text layoutObject in the // subtree. If this changes, clear the cache. It's going to be rebuilt below. m_layoutAttributesBuilder.clearTextPositioningElements(); for (LayoutObject* descendant = text; descendant; descendant = descendant->nextInPreOrder(text)) { if (descendant->isSVGInlineText()) m_layoutAttributesBuilder.buildLayoutAttributesForText(toLayoutSVGInlineText(descendant)); } }
void RenderFlowThread::layout() { StackStats::LayoutCheckPoint layoutCheckPoint; m_pageLogicalHeightChanged = m_regionsInvalidated && everHadLayout(); if (m_regionsInvalidated) { m_regionsInvalidated = false; m_regionsHaveUniformLogicalWidth = true; m_regionsHaveUniformLogicalHeight = true; m_regionRangeMap.clear(); m_breakBeforeToRegionMap.clear(); m_breakAfterToRegionMap.clear(); LayoutUnit previousRegionLogicalWidth = 0; LayoutUnit previousRegionLogicalHeight = 0; bool firstRegionVisited = false; if (hasRegions()) { for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) { RenderRegion* region = *iter; ASSERT(!region->needsLayout()); region->deleteAllRenderBoxRegionInfo(); // In the normal layout phase we need to initialize the overrideLogicalContentHeight for auto-height regions. // See initializeRegionsOverrideLogicalContentHeight for the explanation. // Also, if we have auto-height regions we can't assume m_regionsHaveUniformLogicalHeight to be true in the first phase // because the auto-height regions don't have their height computed yet. if (view()->normalLayoutPhase() && region->hasAutoLogicalHeight()) { region->setOverrideLogicalContentHeight(region->maxPageLogicalHeight()); m_regionsHaveUniformLogicalHeight = false; } LayoutUnit regionLogicalWidth = region->pageLogicalWidth(); LayoutUnit regionLogicalHeight = region->pageLogicalHeight(); if (!firstRegionVisited) firstRegionVisited = true; else { if (m_regionsHaveUniformLogicalWidth && previousRegionLogicalWidth != regionLogicalWidth) m_regionsHaveUniformLogicalWidth = false; if (m_regionsHaveUniformLogicalHeight && previousRegionLogicalHeight != regionLogicalHeight) m_regionsHaveUniformLogicalHeight = false; } previousRegionLogicalWidth = regionLogicalWidth; } updateLogicalWidth(); // Called to get the maximum logical width for the region. updateRegionsFlowThreadPortionRect(); } } CurrentRenderFlowThreadMaintainer currentFlowThreadSetter(this); RenderBlock::layout(); m_pageLogicalHeightChanged = false; if (lastRegion()) lastRegion()->expandToEncompassFlowThreadContentsIfNeeded(); if (shouldDispatchRegionLayoutUpdateEvent()) dispatchRegionLayoutUpdateEvent(); }
void RenderSVGText::layout() { StackStats::LayoutCheckPoint layoutCheckPoint; ASSERT(needsLayout()); LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(*this)); bool updateCachedBoundariesInParents = false; if (m_needsTransformUpdate) { m_localTransform = textElement().animatedLocalTransform(); m_needsTransformUpdate = false; updateCachedBoundariesInParents = true; } if (!everHadLayout()) { // When laying out initially, collect all layout attributes, build the character data map, // and propogate resulting SVGLayoutAttributes to all RenderSVGInlineText children in the subtree. ASSERT(m_layoutAttributes.isEmpty()); collectLayoutAttributes(this, m_layoutAttributes); updateFontInAllDescendants(this); m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(*this); m_needsReordering = true; m_needsTextMetricsUpdate = false; m_needsPositioningValuesUpdate = false; updateCachedBoundariesInParents = true; } else if (m_needsPositioningValuesUpdate) { // When the x/y/dx/dy/rotate lists change, recompute the layout attributes, and eventually // update the on-screen font objects as well in all descendants. if (m_needsTextMetricsUpdate) { updateFontInAllDescendants(this); m_needsTextMetricsUpdate = false; } m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(*this); m_needsReordering = true; m_needsPositioningValuesUpdate = false; updateCachedBoundariesInParents = true; } else if (m_needsTextMetricsUpdate || SVGRenderSupport::findTreeRootObject(*this).isLayoutSizeChanged()) { // If the root layout size changed (eg. window size changes) or the transform to the root // context has changed then recompute the on-screen font size. updateFontInAllDescendants(this, &m_layoutAttributesBuilder); ASSERT(!m_needsReordering); ASSERT(!m_needsPositioningValuesUpdate); m_needsTextMetricsUpdate = false; updateCachedBoundariesInParents = true; } checkLayoutAttributesConsistency(this, m_layoutAttributes); // Reduced version of RenderBlock::layoutBlock(), which only takes care of SVG text. // All if branches that could cause early exit in RenderBlocks layoutBlock() method are turned into assertions. ASSERT(!isInline()); ASSERT(!simplifiedLayout()); ASSERT(!scrollsOverflow()); ASSERT(!hasControlClip()); ASSERT(!multiColumnFlowThread()); ASSERT(!positionedObjects()); ASSERT(!m_overflow); ASSERT(!isAnonymousBlock()); if (!firstChild()) setChildrenInline(true); // FIXME: We need to find a way to only layout the child boxes, if needed. FloatRect oldBoundaries = objectBoundingBox(); ASSERT(childrenInline()); LayoutUnit repaintLogicalTop = 0; LayoutUnit repaintLogicalBottom = 0; rebuildFloatingObjectSetFromIntrudingFloats(); layoutInlineChildren(true, repaintLogicalTop, repaintLogicalBottom); if (m_needsReordering) m_needsReordering = false; if (!updateCachedBoundariesInParents) updateCachedBoundariesInParents = oldBoundaries != objectBoundingBox(); // Invalidate all resources of this client if our layout changed. if (everHadLayout() && selfNeedsLayout()) SVGResourcesCache::clientLayoutChanged(*this); // If our bounds changed, notify the parents. if (updateCachedBoundariesInParents) RenderSVGBlock::setNeedsBoundariesUpdate(); repainter.repaintAfterLayout(); clearNeedsLayout(); }
void RenderFlowThread::layout() { m_pageLogicalHeightChanged = m_regionsInvalidated && everHadLayout(); if (m_regionsInvalidated) { m_regionsInvalidated = false; m_hasValidRegions = false; m_regionsHaveUniformLogicalWidth = true; m_regionsHaveUniformLogicalHeight = true; m_regionRangeMap.clear(); LayoutUnit previousRegionLogicalWidth = 0; LayoutUnit previousRegionLogicalHeight = 0; if (hasRegions()) { for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) { RenderRegion* region = *iter; if (!region->isValid()) continue; ASSERT(!region->needsLayout()); region->deleteAllRenderBoxRegionInfo(); LayoutUnit regionLogicalWidth = region->pageLogicalWidth(); LayoutUnit regionLogicalHeight = region->pageLogicalHeight(); if (!m_hasValidRegions) m_hasValidRegions = true; else { if (m_regionsHaveUniformLogicalWidth && previousRegionLogicalWidth != regionLogicalWidth) m_regionsHaveUniformLogicalWidth = false; if (m_regionsHaveUniformLogicalHeight && previousRegionLogicalHeight != regionLogicalHeight) m_regionsHaveUniformLogicalHeight = false; } previousRegionLogicalWidth = regionLogicalWidth; } updateLogicalWidth(); // Called to get the maximum logical width for the region. LayoutUnit logicalHeight = 0; for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) { RenderRegion* region = *iter; if (!region->isValid()) continue; LayoutUnit regionLogicalWidth = region->pageLogicalWidth(); LayoutUnit regionLogicalHeight = region->logicalHeightOfAllFlowThreadContent(); LayoutRect regionRect(style()->direction() == LTR ? ZERO_LAYOUT_UNIT : logicalWidth() - regionLogicalWidth, logicalHeight, regionLogicalWidth, regionLogicalHeight); region->setFlowThreadPortionRect(isHorizontalWritingMode() ? regionRect : regionRect.transposedRect()); logicalHeight += regionLogicalHeight; } } } CurrentRenderFlowThreadMaintainer currentFlowThreadSetter(this); RenderBlock::layout(); m_pageLogicalHeightChanged = false; if (lastRegion()) lastRegion()->expandToEncompassFlowThreadContentsIfNeeded(); if (shouldDispatchRegionLayoutUpdateEvent()) dispatchRegionLayoutUpdateEvent(); }