OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/BlockPainter.h" | 5 #include "core/paint/BlockPainter.h" |
6 | 6 |
7 #include "core/editing/DragCaretController.h" | 7 #include "core/editing/DragCaretController.h" |
8 #include "core/editing/FrameSelection.h" | 8 #include "core/editing/FrameSelection.h" |
9 #include "core/frame/Settings.h" | 9 #include "core/frame/Settings.h" |
10 #include "core/layout/LayoutBlockFlow.h" | 10 #include "core/layout/LayoutBlockFlow.h" |
(...skipping 24 matching lines...) Expand all Loading... |
35 LayoutPoint adjustedPaintOffset = paintOffset + m_layoutBlock.location(); | 35 LayoutPoint adjustedPaintOffset = paintOffset + m_layoutBlock.location(); |
36 PaintInfo localPaintInfo(paintInfo); | 36 PaintInfo localPaintInfo(paintInfo); |
37 PaintPhase originalPhase = localPaintInfo.phase; | 37 PaintPhase originalPhase = localPaintInfo.phase; |
38 | 38 |
39 // There are some cases where not all clipped visual overflow is accounted f
or. | 39 // There are some cases where not all clipped visual overflow is accounted f
or. |
40 // FIXME: reduce the number of such cases. | 40 // FIXME: reduce the number of such cases. |
41 ContentsClipBehavior contentsClipBehavior = ForceContentsClip; | 41 ContentsClipBehavior contentsClipBehavior = ForceContentsClip; |
42 if (m_layoutBlock.hasOverflowClip() && !m_layoutBlock.hasControlClip() && !(
m_layoutBlock.shouldPaintSelectionGaps() && originalPhase == PaintPhaseForegroun
d) && !m_layoutBlock.hasCaret()) | 42 if (m_layoutBlock.hasOverflowClip() && !m_layoutBlock.hasControlClip() && !(
m_layoutBlock.shouldPaintSelectionGaps() && originalPhase == PaintPhaseForegroun
d) && !m_layoutBlock.hasCaret()) |
43 contentsClipBehavior = SkipContentsClipIfPossible; | 43 contentsClipBehavior = SkipContentsClipIfPossible; |
44 | 44 |
45 if (localPaintInfo.phase == PaintPhaseOutline) { | 45 if (originalPhase == PaintPhaseOutline) { |
46 localPaintInfo.phase = PaintPhaseDescendantOutlines; | 46 localPaintInfo.phase = PaintPhaseDescendantOutlinesOnly; |
47 } else if (localPaintInfo.phase == PaintPhaseBlockBackground) { | 47 } else if (shouldPaintSelfBlockBackground(originalPhase)) { |
48 localPaintInfo.phase = PaintPhaseSelfBlockBackground; | 48 localPaintInfo.phase = PaintPhaseSelfBlockBackgroundOnly; |
49 m_layoutBlock.paintObject(localPaintInfo, adjustedPaintOffset); | 49 m_layoutBlock.paintObject(localPaintInfo, adjustedPaintOffset); |
50 localPaintInfo.phase = PaintPhaseDescendantBlockBackgrounds; | 50 if (shouldPaintDescendantBlockBackgrounds(originalPhase)) |
| 51 localPaintInfo.phase = PaintPhaseDescendantBlockBackgroundsOnly; |
51 } | 52 } |
52 | 53 |
53 { | 54 if (originalPhase != PaintPhaseSelfBlockBackgroundOnly && originalPhase != P
aintPhaseSelfOutlineOnly) { |
54 BoxClipper boxClipper(m_layoutBlock, localPaintInfo, adjustedPaintOffset
, contentsClipBehavior); | 55 BoxClipper boxClipper(m_layoutBlock, localPaintInfo, adjustedPaintOffset
, contentsClipBehavior); |
55 m_layoutBlock.paintObject(localPaintInfo, adjustedPaintOffset); | 56 m_layoutBlock.paintObject(localPaintInfo, adjustedPaintOffset); |
56 } | 57 } |
57 | 58 |
58 if (originalPhase == PaintPhaseOutline) { | 59 if (shouldPaintSelfOutline(originalPhase)) { |
59 localPaintInfo.phase = PaintPhaseSelfOutline; | 60 localPaintInfo.phase = PaintPhaseSelfOutlineOnly; |
60 m_layoutBlock.paintObject(localPaintInfo, adjustedPaintOffset); | 61 m_layoutBlock.paintObject(localPaintInfo, adjustedPaintOffset); |
61 localPaintInfo.phase = originalPhase; | |
62 } else if (originalPhase == PaintPhaseBlockBackground) { | |
63 localPaintInfo.phase = originalPhase; | |
64 } | 62 } |
65 | 63 |
66 // Our scrollbar widgets paint exactly when we tell them to, so that they wo
rk properly with | 64 // Our scrollbar widgets paint exactly when we tell them to, so that they wo
rk properly with |
67 // z-index. We paint after we painted the background/border, so that the scr
ollbars will | 65 // z-index. We paint after we painted the background/border, so that the scr
ollbars will |
68 // sit above the background/border. | 66 // sit above the background/border. |
| 67 localPaintInfo.phase = originalPhase; |
69 paintOverflowControlsIfNeeded(localPaintInfo, adjustedPaintOffset); | 68 paintOverflowControlsIfNeeded(localPaintInfo, adjustedPaintOffset); |
70 } | 69 } |
71 | 70 |
72 void BlockPainter::paintOverflowControlsIfNeeded(const PaintInfo& paintInfo, con
st LayoutPoint& paintOffset) | 71 void BlockPainter::paintOverflowControlsIfNeeded(const PaintInfo& paintInfo, con
st LayoutPoint& paintOffset) |
73 { | 72 { |
74 PaintPhase phase = paintInfo.phase; | 73 if (m_layoutBlock.hasOverflowClip() |
75 if (m_layoutBlock.hasOverflowClip() && m_layoutBlock.style()->visibility() =
= VISIBLE && (phase == PaintPhaseSelfBlockBackground || phase == PaintPhaseBlock
Background) && paintInfo.shouldPaintWithinRoot(&m_layoutBlock) && !paintInfo.pai
ntRootBackgroundOnly()) { | 74 && m_layoutBlock.style()->visibility() == VISIBLE |
| 75 && shouldPaintSelfBlockBackground(paintInfo.phase) |
| 76 && paintInfo.shouldPaintWithinRoot(&m_layoutBlock) |
| 77 && !paintInfo.paintRootBackgroundOnly()) { |
76 Optional<ClipRecorder> clipRecorder; | 78 Optional<ClipRecorder> clipRecorder; |
77 if (!m_layoutBlock.layer()->isSelfPaintingLayer()) { | 79 if (!m_layoutBlock.layer()->isSelfPaintingLayer()) { |
78 LayoutRect clipRect = m_layoutBlock.borderBoxRect(); | 80 LayoutRect clipRect = m_layoutBlock.borderBoxRect(); |
79 clipRect.moveBy(paintOffset); | 81 clipRect.moveBy(paintOffset); |
80 clipRecorder.emplace(paintInfo.context, m_layoutBlock, DisplayItem::
ClipScrollbarsToBoxBounds, clipRect); | 82 clipRecorder.emplace(paintInfo.context, m_layoutBlock, DisplayItem::
ClipScrollbarsToBoxBounds, clipRect); |
81 } | 83 } |
82 ScrollableAreaPainter(*m_layoutBlock.layer()->scrollableArea()).paintOve
rflowControls(paintInfo.context, roundedIntPoint(paintOffset), paintInfo.cullRec
t(), false /* paintingOverlayControls */); | 84 ScrollableAreaPainter(*m_layoutBlock.layer()->scrollableArea()).paintOve
rflowControls(paintInfo.context, roundedIntPoint(paintOffset), paintInfo.cullRec
t(), false /* paintingOverlayControls */); |
83 } | 85 } |
84 } | 86 } |
85 | 87 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 paintInfo.context.paintController().invalidatePaintOffset(m_layoutBl
ock); | 131 paintInfo.context.paintController().invalidatePaintOffset(m_layoutBl
ock); |
130 } | 132 } |
131 // Set previousPaintOffset here in case that m_layoutBlock paints nothin
g and no | 133 // Set previousPaintOffset here in case that m_layoutBlock paints nothin
g and no |
132 // LayoutObjectDrawingRecorder updates its previousPaintOffset. | 134 // LayoutObjectDrawingRecorder updates its previousPaintOffset. |
133 // TODO(wangxianzhu): Integrate paint offset checking into new paint inv
alidation. | 135 // TODO(wangxianzhu): Integrate paint offset checking into new paint inv
alidation. |
134 m_layoutBlock.mutableForPainting().setPreviousPaintOffset(paintOffset); | 136 m_layoutBlock.mutableForPainting().setPreviousPaintOffset(paintOffset); |
135 } | 137 } |
136 | 138 |
137 const PaintPhase paintPhase = paintInfo.phase; | 139 const PaintPhase paintPhase = paintInfo.phase; |
138 | 140 |
139 if ((paintPhase == PaintPhaseSelfBlockBackground || paintPhase == PaintPhase
BlockBackground) | 141 if (shouldPaintSelfBlockBackground(paintPhase)) { |
140 && m_layoutBlock.style()->visibility() == VISIBLE | 142 if (m_layoutBlock.style()->visibility() == VISIBLE && m_layoutBlock.hasB
oxDecorationBackground()) |
141 && m_layoutBlock.hasBoxDecorationBackground()) | 143 m_layoutBlock.paintBoxDecorationBackground(paintInfo, paintOffset); |
142 m_layoutBlock.paintBoxDecorationBackground(paintInfo, paintOffset); | 144 // We're done. We don't bother painting any children. |
| 145 if (paintPhase == PaintPhaseSelfBlockBackgroundOnly) |
| 146 return; |
| 147 } |
| 148 |
| 149 if (paintInfo.paintRootBackgroundOnly()) |
| 150 return; |
143 | 151 |
144 if (paintPhase == PaintPhaseMask && m_layoutBlock.style()->visibility() == V
ISIBLE) { | 152 if (paintPhase == PaintPhaseMask && m_layoutBlock.style()->visibility() == V
ISIBLE) { |
145 m_layoutBlock.paintMask(paintInfo, paintOffset); | 153 m_layoutBlock.paintMask(paintInfo, paintOffset); |
146 return; | 154 return; |
147 } | 155 } |
148 | 156 |
149 if (paintPhase == PaintPhaseClippingMask && m_layoutBlock.style()->visibilit
y() == VISIBLE) { | 157 if (paintPhase == PaintPhaseClippingMask && m_layoutBlock.style()->visibilit
y() == VISIBLE) { |
150 BoxPainter(m_layoutBlock).paintClippingMask(paintInfo, paintOffset); | 158 BoxPainter(m_layoutBlock).paintClippingMask(paintInfo, paintOffset); |
151 return; | 159 return; |
152 } | 160 } |
153 | 161 |
154 // FIXME: When Skia supports annotation rect covering (https://code.google.c
om/p/skia/issues/detail?id=3872), | 162 // FIXME: When Skia supports annotation rect covering (https://code.google.c
om/p/skia/issues/detail?id=3872), |
155 // this rect may be covered by foreground and descendant drawings. Then we m
ay need a dedicated paint phase. | 163 // this rect may be covered by foreground and descendant drawings. Then we m
ay need a dedicated paint phase. |
156 if (paintPhase == PaintPhaseForeground && paintInfo.isPrinting()) | 164 if (paintPhase == PaintPhaseForeground && paintInfo.isPrinting()) |
157 ObjectPainter(m_layoutBlock).addPDFURLRectIfNeeded(paintInfo, paintOffse
t); | 165 ObjectPainter(m_layoutBlock).addPDFURLRectIfNeeded(paintInfo, paintOffse
t); |
158 | 166 |
159 { | 167 if (paintPhase != PaintPhaseSelfOutlineOnly) { |
160 Optional<ScrollRecorder> scrollRecorder; | 168 Optional<ScrollRecorder> scrollRecorder; |
161 Optional<PaintInfo> scrolledPaintInfo; | 169 Optional<PaintInfo> scrolledPaintInfo; |
162 if (m_layoutBlock.hasOverflowClip()) { | 170 if (m_layoutBlock.hasOverflowClip()) { |
163 IntSize scrollOffset = m_layoutBlock.scrolledContentOffset(); | 171 IntSize scrollOffset = m_layoutBlock.scrolledContentOffset(); |
164 if (m_layoutBlock.layer()->scrollsOverflow() || !scrollOffset.isZero
()) { | 172 if (m_layoutBlock.layer()->scrollsOverflow() || !scrollOffset.isZero
()) { |
165 scrollRecorder.emplace(paintInfo.context, m_layoutBlock, paintPh
ase, scrollOffset); | 173 scrollRecorder.emplace(paintInfo.context, m_layoutBlock, paintPh
ase, scrollOffset); |
166 scrolledPaintInfo.emplace(paintInfo); | 174 scrolledPaintInfo.emplace(paintInfo); |
167 AffineTransform transform; | 175 AffineTransform transform; |
168 transform.translate(-scrollOffset.width(), -scrollOffset.height(
)); | 176 transform.translate(-scrollOffset.width(), -scrollOffset.height(
)); |
169 scrolledPaintInfo->updateCullRect(transform); | 177 scrolledPaintInfo->updateCullRect(transform); |
170 } | 178 } |
171 } | 179 } |
172 | 180 |
173 // We're done. We don't bother painting any children. | |
174 if (paintPhase == PaintPhaseSelfBlockBackground || paintInfo.paintRootBa
ckgroundOnly()) | |
175 return; | |
176 | |
177 const PaintInfo& contentsPaintInfo = scrolledPaintInfo ? *scrolledPaintI
nfo : paintInfo; | 181 const PaintInfo& contentsPaintInfo = scrolledPaintInfo ? *scrolledPaintI
nfo : paintInfo; |
178 | 182 |
179 if (paintPhase != PaintPhaseSelfOutline) | 183 paintContents(contentsPaintInfo, paintOffset); |
180 paintContents(contentsPaintInfo, paintOffset); | |
181 | 184 |
182 if (paintPhase == PaintPhaseForeground && !paintInfo.isPrinting()) | 185 if (paintPhase == PaintPhaseForeground && !paintInfo.isPrinting()) |
183 m_layoutBlock.paintSelection(contentsPaintInfo, paintOffset); // Fil
l in gaps in selection on lines and between blocks. | 186 m_layoutBlock.paintSelection(contentsPaintInfo, paintOffset); // Fil
l in gaps in selection on lines and between blocks. |
184 | 187 |
185 if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection |
| paintPhase == PaintPhaseTextClip) | 188 if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection |
| paintPhase == PaintPhaseTextClip) |
186 m_layoutBlock.paintFloats(contentsPaintInfo, paintOffset); | 189 m_layoutBlock.paintFloats(contentsPaintInfo, paintOffset); |
187 } | 190 } |
188 | 191 |
189 if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline)
&& m_layoutBlock.style()->hasOutline() && m_layoutBlock.style()->visibility() =
= VISIBLE) | 192 if (shouldPaintSelfOutline(paintPhase)) |
190 ObjectPainter(m_layoutBlock).paintOutline(paintInfo, paintOffset); | 193 ObjectPainter(m_layoutBlock).paintOutline(paintInfo, paintOffset); |
191 | 194 |
192 // If the caret's node's layout object's containing block is this block, and
the paint action is PaintPhaseForeground, | 195 // If the caret's node's layout object's containing block is this block, and
the paint action is PaintPhaseForeground, |
193 // then paint the caret. | 196 // then paint the caret. |
194 if (paintPhase == PaintPhaseForeground && m_layoutBlock.hasCaret() && !Layou
tObjectDrawingRecorder::useCachedDrawingIfPossible(paintInfo.context, m_layoutBl
ock, DisplayItem::Caret, paintOffset)) { | 197 if (paintPhase == PaintPhaseForeground && m_layoutBlock.hasCaret() && !Layou
tObjectDrawingRecorder::useCachedDrawingIfPossible(paintInfo.context, m_layoutBl
ock, DisplayItem::Caret, paintOffset)) { |
195 LayoutRect bounds = m_layoutBlock.visualOverflowRect(); | 198 LayoutRect bounds = m_layoutBlock.visualOverflowRect(); |
196 bounds.moveBy(paintOffset); | 199 bounds.moveBy(paintOffset); |
197 LayoutObjectDrawingRecorder recorder(paintInfo.context, m_layoutBlock, D
isplayItem::Caret, bounds, paintOffset); | 200 LayoutObjectDrawingRecorder recorder(paintInfo.context, m_layoutBlock, D
isplayItem::Caret, bounds, paintOffset); |
198 paintCarets(paintInfo, paintOffset); | 201 paintCarets(paintInfo, paintOffset); |
199 } | 202 } |
(...skipping 24 matching lines...) Expand all Loading... |
224 | 227 |
225 void BlockPainter::paintContents(const PaintInfo& paintInfo, const LayoutPoint&
paintOffset) | 228 void BlockPainter::paintContents(const PaintInfo& paintInfo, const LayoutPoint&
paintOffset) |
226 { | 229 { |
227 // Avoid painting descendants of the root element when stylesheets haven't l
oaded. This eliminates FOUC. | 230 // Avoid painting descendants of the root element when stylesheets haven't l
oaded. This eliminates FOUC. |
228 // It's ok not to draw, because later on, when all the stylesheets do load,
styleResolverChanged() on the Document | 231 // It's ok not to draw, because later on, when all the stylesheets do load,
styleResolverChanged() on the Document |
229 // will do a full paint invalidation. | 232 // will do a full paint invalidation. |
230 if (m_layoutBlock.document().didLayoutWithPendingStylesheets() && !m_layoutB
lock.isLayoutView()) | 233 if (m_layoutBlock.document().didLayoutWithPendingStylesheets() && !m_layoutB
lock.isLayoutView()) |
231 return; | 234 return; |
232 | 235 |
233 if (m_layoutBlock.childrenInline()) { | 236 if (m_layoutBlock.childrenInline()) { |
234 if (paintInfo.phase == PaintPhaseDescendantOutlines) | 237 if (shouldPaintDescendantOutlines(paintInfo.phase)) |
235 ObjectPainter(m_layoutBlock).paintInlineChildrenOutlines(paintInfo,
paintOffset); | 238 ObjectPainter(m_layoutBlock).paintInlineChildrenOutlines(paintInfo,
paintOffset); |
236 else | 239 else |
237 LineBoxListPainter(m_layoutBlock.lineBoxes()).paint(m_layoutBlock, p
aintInfo, paintOffset); | 240 LineBoxListPainter(m_layoutBlock.lineBoxes()).paint(m_layoutBlock, p
aintInfo, paintOffset); |
238 } else { | 241 } else { |
239 PaintPhase newPhase = (paintInfo.phase == PaintPhaseDescendantOutlines)
? PaintPhaseOutline : paintInfo.phase; | 242 PaintInfo paintInfoForDescendants = paintInfo.forDescendants(); |
240 newPhase = (newPhase == PaintPhaseDescendantBlockBackgrounds) ? PaintPha
seBlockBackground : newPhase; | 243 paintInfoForDescendants.updatePaintingRootForChildren(&m_layoutBlock); |
241 | 244 m_layoutBlock.paintChildren(paintInfoForDescendants, paintOffset); |
242 // We don't paint our own background, but we do let the kids paint their
backgrounds. | |
243 PaintInfo paintInfoForChild(paintInfo); | |
244 paintInfoForChild.phase = newPhase; | |
245 paintInfoForChild.updatePaintingRootForChildren(&m_layoutBlock); | |
246 m_layoutBlock.paintChildren(paintInfoForChild, paintOffset); | |
247 } | 245 } |
248 } | 246 } |
249 | 247 |
250 } // namespace blink | 248 } // namespace blink |
OLD | NEW |