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 |