| 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 |