Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/paint/PaintInvalidator.h" | 5 #include "core/paint/PaintInvalidator.h" |
| 6 | 6 |
| 7 #include "core/editing/FrameSelection.h" | |
| 7 #include "core/frame/FrameView.h" | 8 #include "core/frame/FrameView.h" |
| 9 #include "core/frame/LocalFrame.h" | |
| 10 #include "core/frame/Settings.h" | |
| 8 #include "core/layout/LayoutObject.h" | 11 #include "core/layout/LayoutObject.h" |
| 12 #include "core/layout/LayoutTable.h" | |
| 13 #include "core/layout/svg/SVGLayoutSupport.h" | |
| 14 #include "core/paint/PaintLayer.h" | |
| 15 #include "core/paint/PaintLayerScrollableArea.h" | |
| 9 | 16 |
| 10 namespace blink { | 17 namespace blink { |
| 11 | 18 |
| 12 void PaintInvalidator::invalidatePaintIfNeeded(FrameView& frameView, const Paint PropertyTreeBuilderContext& treeContext, Optional<PaintInvalidatorContext>& pain tInvalidatorContext) | 19 void PaintInvalidatorContext::mapLocalRectToPaintInvalidationBacking(const Layou tObject& object, LayoutRect& rect) const |
| 13 { | 20 { |
| 14 paintInvalidatorContext.emplace(*frameView.layoutView(), m_pendingDelayedPai ntInvalidations); | 21 // TODO(wangxianzhu): For now this is the same as the slow path in PaintInva lidationState.cpp |
| 15 frameView.invalidatePaintIfNeeded(*paintInvalidatorContext); | 22 // (slowMapToVisualRectInAncestorSpace()). Should implement this with Geomet ryMapper. |
| 16 } | 23 if (object.isBox()) |
| 17 | 24 toLayoutBox(object).flipForWritingMode(rect); |
| 18 void PaintInvalidator::invalidatePaintIfNeeded(const LayoutObject& layoutObject, const PaintPropertyTreeBuilderContext& treeContext, const PaintInvalidatorConte xt& parentPaintInvalidatorContext, Optional<PaintInvalidatorContext>& paintInval idatorContext) | 25 |
| 19 { | 26 if (object.isLayoutView()) |
| 20 if (!layoutObject.shouldCheckForPaintInvalidation(parentPaintInvalidatorCont ext)) | 27 toLayoutView(object).mapToVisualRectInAncestorSpace(paintInvalidationCon tainer, rect, InputIsInFrameCoordinates, DefaultVisualRectFlags); |
| 28 else | |
| 29 object.mapToVisualRectInAncestorSpace(paintInvalidationContainer, rect); | |
| 30 } | |
| 31 | |
| 32 static LayoutRect computePaintInvalidationRectInBacking(const LayoutObject& obje ct, const PaintInvalidatorContext& context) | |
| 33 { | |
| 34 if (object.isSVG() && !object.isSVGRoot()) { | |
| 35 // TODO(wangxianzhu): For now this is the same as the slow path in Paint InvalidationState.cpp | |
| 36 // (PaintInvalidationState::computePaintInvalidationRectInBackingForSVG( )). Should implement this with GeometryMapper. | |
| 37 LayoutRect rect = SVGLayoutSupport::clippedOverflowRectForPaintInvalidat ion(object, *context.paintInvalidationContainer); | |
| 38 if (context.paintInvalidationContainer->layer()->groupedMapping()) | |
| 39 PaintLayer::mapRectInPaintInvalidationContainerToBacking(*context.pa intInvalidationContainer, rect); | |
| 40 return rect; | |
| 41 } | |
| 42 | |
| 43 LayoutRect rect = object.localOverflowRectForPaintInvalidation(); | |
| 44 context.mapLocalRectToPaintInvalidationBacking(object, rect); | |
| 45 return rect; | |
| 46 } | |
| 47 | |
| 48 static LayoutPoint computeLocationFromPaintInvalidationBacking(const LayoutObjec t& object, const PaintInvalidatorContext& context) | |
| 49 { | |
| 50 // TODO(wangxianzhu): For now this is the same as the slow path in PaintInva lidationState.cpp | |
| 51 // (slowLocalToAncestorPoint()). Should implement this with GeometryMapper. | |
| 52 FloatPoint point; | |
| 53 if (object != context.paintInvalidationContainer) { | |
| 54 if (object.isLayoutView()) | |
| 55 point = toLayoutView(object).localToAncestorPoint(point, context.pai ntInvalidationContainer, TraverseDocumentBoundaries | InputIsInFrameCoordinates) ; | |
| 56 else | |
| 57 point = object.localToAncestorPoint(point, context.paintInvalidation Container, TraverseDocumentBoundaries); | |
|
chrishtr
2016/08/11 00:14:50
I think you'll need this code:
if (ancestor.isBo
Xianzhu
2016/08/11 01:27:08
Done.
| |
| 58 } | |
| 59 | |
| 60 if (context.paintInvalidationContainer->layer()->groupedMapping()) | |
| 61 PaintLayer::mapPointInPaintInvalidationContainerToBacking(*context.paint InvalidationContainer, point); | |
| 62 | |
| 63 return LayoutPoint(point); | |
| 64 } | |
| 65 | |
| 66 static void updatePaintingLayer(const LayoutObject& object, PaintInvalidatorCont ext& context) | |
| 67 { | |
| 68 if (object.hasLayer() && toLayoutBoxModelObject(object).hasSelfPaintingLayer ()) | |
| 69 context.paintingLayer = toLayoutBoxModelObject(object).layer(); | |
| 70 | |
| 71 if (object.isLayoutBlockFlow() && toLayoutBlockFlow(object).containsFloats() ) | |
| 72 context.paintingLayer->setNeedsPaintPhaseFloat(); | |
| 73 | |
| 74 if (object == context.paintingLayer->layoutObject()) | |
| 21 return; | 75 return; |
| 22 | 76 |
| 23 paintInvalidatorContext.emplace(parentPaintInvalidatorContext, layoutObject) ; | 77 if (object.styleRef().hasOutline()) |
| 24 | 78 context.paintingLayer->setNeedsPaintPhaseDescendantOutlines(); |
| 25 if (layoutObject.mayNeedPaintInvalidationSubtree()) | 79 |
| 26 paintInvalidatorContext->setForceSubtreeInvalidationCheckingWithinContai ner(); | 80 if (object.hasBoxDecorationBackground() |
| 27 | 81 // We also paint overflow controls in background phase. |
| 28 PaintInvalidationReason reason = layoutObject.getMutableForPainting().invali datePaintIfNeeded(*paintInvalidatorContext); | 82 || (object.hasOverflowClip() && toLayoutBox(object).getScrollableArea()- >hasOverflowControls())) { |
| 29 layoutObject.getMutableForPainting().clearPaintInvalidationFlags(*paintInval idatorContext); | 83 context.paintingLayer->setNeedsPaintPhaseDescendantBlockBackgrounds(); |
| 30 | 84 } |
| 31 paintInvalidatorContext->updateForChildren(reason); | 85 |
| 86 if (object.isTable()) { | |
| 87 const LayoutTable& table = toLayoutTable(object); | |
| 88 if (table.collapseBorders() && !table.collapsedBorders().isEmpty()) | |
| 89 context.paintingLayer->setNeedsPaintPhaseDescendantBlockBackgrounds( ); | |
| 90 } | |
| 91 } | |
| 92 | |
| 93 static void updateContext(const LayoutObject& object, PaintInvalidatorContext& c ontext) | |
| 94 { | |
| 95 if (object.isPaintInvalidationContainer()) { | |
| 96 context.paintInvalidationContainer = toLayoutBoxModelObject(&object); | |
| 97 if (object.styleRef().isStackingContext()) | |
| 98 context.paintInvalidationContainerForStackedContents = toLayoutBoxMo delObject(&object); | |
| 99 } else if (object.isLayoutView()) { | |
| 100 // paintInvalidationContainerForStackedContents is only for stacked desc endants in its own frame, | |
| 101 // because it doesn't establish stacking context for stacked contents in sub-frames. | |
| 102 // Contents stacked in the root stacking context in this frame should us e this frame's paintInvalidationContainer. | |
| 103 context.paintInvalidationContainerForStackedContents = context.paintInva lidationContainer; | |
| 104 } else if (object.styleRef().isStacked() | |
| 105 // This is to exclude some objects (e.g. LayoutText) inheriting stacked style from parent but aren't actually stacked. | |
| 106 && object.hasLayer() | |
| 107 && context.paintInvalidationContainer != context.paintInvalidationContai nerForStackedContents) { | |
| 108 // The current object is stacked, so we should use m_paintInvalidationCo ntainerForStackedContents as its | |
| 109 // paint invalidation container on which the current object is painted. | |
| 110 context.paintInvalidationContainer = context.paintInvalidationContainerF orStackedContents; | |
| 111 if (context.forcedSubtreeInvalidationFlags & PaintInvalidatorContext::Fo rcedSubtreeFullInvalidationForStackedContents) | |
| 112 context.forcedSubtreeInvalidationFlags |= PaintInvalidatorContext::F orcedSubtreeFullInvalidation; | |
| 113 } | |
| 114 | |
| 115 if (object == context.paintInvalidationContainer) { | |
| 116 // When we hit a new paint invalidation container, we don't need to | |
| 117 // continue forcing a check for paint invalidation, since we're | |
| 118 // descending into a different invalidation container. (For instance if | |
| 119 // our parents were moved, the entire container will just move.) | |
| 120 if (object != context.paintInvalidationContainerForStackedContents) { | |
| 121 // However, we need to keep the ForcedSubtreeFullInvalidationForStac kedContents flag | |
| 122 // if the current object isn't the paint invalidation container of s tacked contents. | |
| 123 context.forcedSubtreeInvalidationFlags &= PaintInvalidatorContext::F orcedSubtreeFullInvalidationForStackedContents; | |
| 124 } else { | |
| 125 context.forcedSubtreeInvalidationFlags = 0; | |
| 126 } | |
| 127 } | |
| 128 | |
| 129 DCHECK(context.paintInvalidationContainer == object.containerForPaintInvalid ation()); | |
| 130 DCHECK(context.paintingLayer == object.paintingLayer()); | |
| 131 | |
| 132 if (object.mayNeedPaintInvalidationSubtree()) | |
| 133 context.forcedSubtreeInvalidationFlags |= PaintInvalidatorContext::Force dSubtreeInvalidationChecking; | |
| 134 | |
| 135 context.oldBounds = object.previousPaintInvalidationRect(); | |
| 136 context.oldLocation = object.previousPositionFromPaintInvalidationBacking(); | |
| 137 context.newBounds = computePaintInvalidationRectInBacking(object, context); | |
| 138 context.newLocation = computeLocationFromPaintInvalidationBacking(object, co ntext); | |
| 139 | |
| 140 IntSize adjustment = object.scrollAdjustmentForPaintInvalidation(*context.pa intInvalidationContainer); | |
| 141 context.newLocation.move(adjustment); | |
| 142 context.newBounds.move(adjustment); | |
| 143 | |
| 144 object.getMutableForPainting().setPreviousPaintInvalidationRect(context.newB ounds); | |
| 145 object.getMutableForPainting().setPreviousPositionFromPaintInvalidationBacki ng(context.newLocation); | |
| 146 } | |
| 147 | |
| 148 void PaintInvalidator::invalidatePaintIfNeeded(FrameView& frameView, PaintInvali datorContext& context) | |
| 149 { | |
| 150 LayoutView* layoutView = frameView.layoutView(); | |
| 151 CHECK(layoutView); | |
| 152 | |
| 153 context.paintInvalidationContainer = context.paintInvalidationContainerForSt ackedContents = &layoutView->containerForPaintInvalidation(); | |
| 154 context.paintingLayer = layoutView->layer(); | |
| 155 | |
| 156 if (!frameView.frame().settings() || !frameView.frame().settings()->rootLaye rScrolls()) | |
| 157 frameView.invalidatePaintOfScrollControlsIfNeeded(context); | |
| 158 | |
| 159 if (frameView.frame().selection().isCaretBoundsDirty()) | |
| 160 frameView.frame().selection().invalidateCaretRect(); | |
| 161 | |
| 162 // Temporary callback for crbug.com/487345,402044 | |
| 163 // TODO(ojan): Make this more general to be used by PositionObserver | |
| 164 // and rAF throttling. | |
| 165 IntRect visibleRect = frameView.rootFrameToContents(frameView.computeVisible Area()); | |
| 166 layoutView->sendMediaPositionChangeNotifications(visibleRect); | |
| 167 } | |
| 168 | |
| 169 void PaintInvalidator::invalidatePaintIfNeeded(const LayoutObject& object, Paint InvalidatorContext& context) | |
| 170 { | |
| 171 object.getMutableForPainting().ensureIsReadyForPaintInvalidation(); | |
| 172 | |
| 173 if (!context.forcedSubtreeInvalidationFlags && !object.shouldCheckForPaintIn validationRegardlessOfPaintInvalidationState()) | |
| 174 return; | |
| 175 | |
| 176 updatePaintingLayer(object, context); | |
| 177 | |
| 178 if (object.document().printing()) | |
| 179 return; // Don't invalidate paints if we're printing. | |
| 180 | |
| 181 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), "PaintInvalida tor::invalidatePaintIfNeeded()", "object", object.debugName().ascii()); | |
| 182 | |
| 183 updateContext(object, context); | |
| 184 | |
| 185 if (!object.shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationStat e() && context.forcedSubtreeInvalidationFlags == PaintInvalidatorContext::Forced SubtreeInvalidationRectUpdate) { | |
| 186 // We are done updating the paint invalidation rect. No other paint inva lidation work to do for this object. | |
| 187 return; | |
| 188 } | |
| 189 | |
| 190 switch (object.invalidatePaintIfNeeded(context)) { | |
| 191 case PaintInvalidationDelayedFull: | |
| 192 m_pendingDelayedPaintInvalidations.append(&object); | |
| 193 break; | |
| 194 case PaintInvalidationSubtree: | |
| 195 context.forcedSubtreeInvalidationFlags |= (PaintInvalidatorContext::Forc edSubtreeFullInvalidation | PaintInvalidatorContext::ForcedSubtreeFullInvalidati onForStackedContents); | |
| 196 break; | |
| 197 case PaintInvalidationSVGResourceChange: | |
| 198 context.forcedSubtreeInvalidationFlags |= PaintInvalidatorContext::Force dSubtreeInvalidationChecking; | |
| 199 break; | |
| 200 default: | |
| 201 break; | |
| 202 } | |
| 203 | |
| 204 if (context.oldLocation != context.newLocation) | |
| 205 context.forcedSubtreeInvalidationFlags |= PaintInvalidatorContext::Force dSubtreeInvalidationChecking; | |
| 206 | |
| 207 object.getMutableForPainting().clearPaintInvalidationFlags(); | |
| 32 } | 208 } |
| 33 | 209 |
| 34 void PaintInvalidator::processPendingDelayedPaintInvalidations() | 210 void PaintInvalidator::processPendingDelayedPaintInvalidations() |
| 35 { | 211 { |
| 36 for (auto target : m_pendingDelayedPaintInvalidations) | 212 for (auto target : m_pendingDelayedPaintInvalidations) |
| 37 target->getMutableForPainting().setShouldDoDelayedFullPaintInvalidation( ); | 213 target->getMutableForPainting().setShouldDoFullPaintInvalidation(PaintIn validationDelayedFull); |
| 38 } | 214 } |
| 39 | 215 |
| 40 } // namespace blink | 216 } // namespace blink |
| OLD | NEW |