Chromium Code Reviews| 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 "config.h" | 5 #include "config.h" |
| 6 #include "core/paint/ViewPainter.h" | 6 #include "core/paint/ViewPainter.h" |
| 7 | 7 |
| 8 #include "core/frame/FrameView.h" | 8 #include "core/frame/FrameView.h" |
| 9 #include "core/frame/Settings.h" | |
| 9 #include "core/layout/LayoutBox.h" | 10 #include "core/layout/LayoutBox.h" |
| 10 #include "core/layout/LayoutView.h" | 11 #include "core/layout/LayoutView.h" |
| 11 #include "core/paint/BlockPainter.h" | 12 #include "core/paint/BlockPainter.h" |
| 13 #include "core/paint/BoxPainter.h" | |
| 14 #include "core/paint/DeprecatedPaintLayer.h" | |
| 12 #include "core/paint/LayoutObjectDrawingRecorder.h" | 15 #include "core/paint/LayoutObjectDrawingRecorder.h" |
| 13 #include "core/paint/PaintInfo.h" | 16 #include "core/paint/PaintInfo.h" |
| 14 #include "platform/RuntimeEnabledFeatures.h" | 17 #include "platform/RuntimeEnabledFeatures.h" |
| 15 | 18 |
| 16 namespace blink { | 19 namespace blink { |
| 17 | 20 |
| 18 void ViewPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffs et) | 21 void ViewPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffs et) |
| 19 { | 22 { |
| 20 // If we ever require layout but receive a paint anyway, something has gone horribly wrong. | 23 // If we ever require layout but receive a paint anyway, something has gone horribly wrong. |
| 21 ASSERT(!m_layoutView.needsLayout()); | 24 ASSERT(!m_layoutView.needsLayout()); |
| 22 // LayoutViews should never be called to paint with an offset not on device pixels. | 25 // LayoutViews should never be called to paint with an offset not on device pixels. |
| 23 ASSERT(LayoutPoint(IntPoint(paintOffset.x(), paintOffset.y())) == paintOffse t); | 26 ASSERT(LayoutPoint(IntPoint(paintOffset.x(), paintOffset.y())) == paintOffse t); |
| 24 | 27 |
| 25 // This avoids painting garbage between columns if there is a column gap. | 28 // This avoids painting garbage between columns if there is a column gap. |
| 26 // This is legacy WebKit behavior and doesn't work with slimmingpaint. We ca n remove it once region-based columns are launched. | 29 // This is legacy WebKit behavior and doesn't work with slimmingpaint. We ca n remove it once region-based columns are launched. |
| 27 if (!RuntimeEnabledFeatures::regionBasedColumnsEnabled() && m_layoutView.fra meView() && m_layoutView.style()->isOverflowPaged()) { | 30 if (!RuntimeEnabledFeatures::regionBasedColumnsEnabled() && m_layoutView.fra meView() && m_layoutView.style()->isOverflowPaged()) { |
| 28 ASSERT(!RuntimeEnabledFeatures::slimmingPaintEnabled()); | 31 ASSERT(!RuntimeEnabledFeatures::slimmingPaintEnabled()); |
| 29 LayoutRect paintRect(paintInfo.rect); | 32 LayoutRect paintRect(paintInfo.rect); |
| 30 paintInfo.context->fillRect(paintRect, m_layoutView.frameView()->baseBac kgroundColor()); | 33 paintInfo.context->fillRect(paintRect, m_layoutView.frameView()->baseBac kgroundColor()); |
| 31 } | 34 } |
| 32 | 35 |
| 33 m_layoutView.paintObject(paintInfo, paintOffset); | 36 m_layoutView.paintObject(paintInfo, paintOffset); |
| 34 BlockPainter(m_layoutView).paintOverflowControlsIfNeeded(paintInfo, paintOff set); | 37 BlockPainter(m_layoutView).paintOverflowControlsIfNeeded(paintInfo, paintOff set); |
| 35 } | 38 } |
| 36 | 39 |
| 37 static inline bool layoutObjectObscuresBackground(LayoutBox* rootBox) | |
| 38 { | |
| 39 ASSERT(rootBox); | |
| 40 const ComputedStyle& style = rootBox->styleRef(); | |
| 41 if (style.visibility() != VISIBLE | |
| 42 || style.opacity() != 1 | |
| 43 || style.hasFilter() | |
| 44 || style.hasTransform()) | |
| 45 return false; | |
| 46 | |
| 47 if (rootBox->compositingState() == PaintsIntoOwnBacking) | |
| 48 return false; | |
| 49 | |
| 50 const LayoutObject* rootLayoutObject = rootBox->layoutObjectForRootBackgroun d(); | |
| 51 if (rootLayoutObject->style()->backgroundClip() == TextFillBox) | |
| 52 return false; | |
| 53 | |
| 54 return true; | |
| 55 } | |
| 56 | |
| 57 void ViewPainter::paintBoxDecorationBackground(const PaintInfo& paintInfo) | 40 void ViewPainter::paintBoxDecorationBackground(const PaintInfo& paintInfo) |
| 58 { | 41 { |
| 59 if (m_layoutView.document().ownerElement() || !m_layoutView.view()) | |
| 60 return; | |
| 61 | |
| 62 if (paintInfo.skipRootBackground()) | 42 if (paintInfo.skipRootBackground()) |
| 63 return; | 43 return; |
| 64 | 44 |
| 65 bool shouldPaintBackground = true; | 45 GraphicsContext& context = *paintInfo.context; |
| 66 Node* documentElement = m_layoutView.document().documentElement(); | 46 IntRect documentRect = m_layoutView.unscaledDocumentRect(); |
| 67 if (LayoutBox* rootBox = documentElement ? toLayoutBox(documentElement->layo utObject()) : 0) | 47 const Document& document = m_layoutView.document(); |
| 68 shouldPaintBackground = !rootFillsViewportBackground(rootBox) || !layout ObjectObscuresBackground(rootBox); | 48 const FrameView& frameView = *m_layoutView.frameView(); |
| 49 bool isMainFrame = !document.ownerElement(); | |
| 50 bool paintsBaseBackground = isMainFrame && !frameView.isTransparent(); | |
| 51 bool shouldClearCanvas = paintsBaseBackground && (document.settings() && doc ument.settings()->shouldClearDocumentBackground()); | |
| 52 Color baseBackgroundColor = paintsBaseBackground ? frameView.baseBackgroundC olor() : Color(); | |
| 53 const LayoutObject* rootObject = document.documentElement() ? document.docum entElement()->layoutObject() : nullptr; | |
| 69 | 54 |
| 70 // If painting will entirely fill the view, no need to fill the background. | 55 LayoutObjectDrawingRecorder recorder(context, m_layoutView, DisplayItem::Box DecorationBackground, documentRect); |
| 71 if (!shouldPaintBackground) | 56 if (recorder.canUseCachedDrawing()) |
| 72 return; | 57 return; |
| 73 | 58 |
| 74 // This code typically only executes if the root element's visibility has be en set to hidden, | 59 bool backgroundRenderable = true; |
| 75 // if there is a transform on the <html>, or if there is a page scale factor less than 1. | 60 TransformationMatrix transform; |
| 76 // Only fill with the base background color (typically white) if we're the r oot document, | 61 IntRect paintRect = documentRect; |
| 77 // since iframes/frames with no background in the child document should show the parent's background. | 62 if (!rootObject || !rootObject->isBox()) { |
| 78 if (!m_layoutView.frameView()->isTransparent()) { | 63 backgroundRenderable = false; |
| 79 LayoutRect paintRect(paintInfo.rect); | 64 } else if (rootObject->hasLayer()) { |
| 80 if (RuntimeEnabledFeatures::slimmingPaintEnabled()) | 65 const DeprecatedPaintLayer& rootLayer = *toLayoutBoxModelObject(rootObje ct)->layer(); |
| 81 paintRect = m_layoutView.viewRect(); | 66 LayoutPoint offset; |
| 67 rootLayer.convertToLayerCoords(nullptr, offset); | |
| 68 transform.translate(offset.x(), offset.y()); | |
| 69 transform.multiply(rootLayer.renderableTransform(paintInfo.paintBehavior )); | |
|
Xianzhu
2015/06/03 04:40:34
Do we need to invalidate / have we invalidated the
trchen
2015/06/03 23:15:24
Yes we do. Tried with the inspector we are already
Xianzhu
2015/06/03 23:24:19
The paint invalidation rect shown by inspector doe
| |
| 82 | 70 |
| 83 LayoutObjectDrawingRecorder recorder(*paintInfo.context, m_layoutView, D isplayItem::BoxDecorationBackground, m_layoutView.viewRect()); | 71 if (!transform.isInvertible()) { |
| 84 if (!recorder.canUseCachedDrawing()) { | 72 backgroundRenderable = false; |
| 85 Color baseColor = m_layoutView.frameView()->baseBackgroundColor(); | 73 } else { |
| 86 paintInfo.context->fillRect(paintRect, baseColor, baseColor.alpha() ? | 74 bool isClamped; |
| 87 SkXfermode::kSrc_Mode : SkXfermode::kClear_Mode); | 75 paintRect = transform.inverse().projectQuad(FloatQuad(documentRect), &isClamped).enclosingBoundingBox(); |
| 76 backgroundRenderable = !isClamped; | |
| 88 } | 77 } |
| 89 } | 78 } |
| 90 } | |
| 91 | 79 |
| 92 bool ViewPainter::rootFillsViewportBackground(LayoutBox* rootBox) const | 80 if (!backgroundRenderable) { |
| 93 { | 81 if (baseBackgroundColor.alpha()) |
| 94 ASSERT(rootBox); | 82 context.fillRect(documentRect, baseBackgroundColor, shouldClearCanva s ? SkXfermode::kSrc_Mode : SkXfermode::kSrcOver_Mode); |
| 95 // CSS Boxes always fill the viewport background (see paintRootBoxFillLayers ) | 83 else if (shouldClearCanvas) |
| 96 if (!rootBox->isSVG()) | 84 context.fillRect(documentRect, Color(), SkXfermode::kClear_Mode); |
| 97 return true; | 85 return; |
| 86 } | |
| 98 | 87 |
| 99 return rootBox->frameRect().contains(m_layoutView.frameRect()); | 88 Vector<const FillLayer*, 8> reversedPaintList; |
| 89 bool shouldDrawBackgroundInSeparateBuffer = BoxPainter(m_layoutView).calcula teFillLayerOcclusionCulling(reversedPaintList, m_layoutView.style()->backgroundL ayers()); | |
| 90 ASSERT(reversedPaintList.size()); | |
| 91 Color rootBackgroundColor = m_layoutView.style()->visitedDependentColor(CSSP ropertyBackgroundColor); | |
| 92 if (!rootBackgroundColor.hasAlpha()) | |
| 93 shouldDrawBackgroundInSeparateBuffer = false; | |
| 94 | |
| 95 if (!baseBackgroundColor.alpha() && shouldClearCanvas) | |
| 96 shouldDrawBackgroundInSeparateBuffer = false; | |
| 97 | |
| 98 if (shouldDrawBackgroundInSeparateBuffer) { | |
| 99 if (baseBackgroundColor.alpha()) | |
| 100 context.fillRect(documentRect, baseBackgroundColor, shouldClearCanva s ? SkXfermode::kSrc_Mode : SkXfermode::kSrcOver_Mode); | |
| 101 context.beginLayer(); | |
| 102 } | |
| 103 | |
| 104 Color combinedBackgroundColor = shouldDrawBackgroundInSeparateBuffer ? rootB ackgroundColor : baseBackgroundColor.blend(rootBackgroundColor); | |
| 105 if (combinedBackgroundColor.alpha()) | |
| 106 context.fillRect(documentRect, combinedBackgroundColor, (shouldDrawBackg roundInSeparateBuffer || shouldClearCanvas) ? SkXfermode::kSrc_Mode : SkXfermode ::kSrcOver_Mode); | |
| 107 else if (shouldClearCanvas && !shouldDrawBackgroundInSeparateBuffer) | |
| 108 context.fillRect(documentRect, Color(), SkXfermode::kClear_Mode); | |
| 109 | |
| 110 { | |
| 111 GraphicsContextStateSaver stateSaver(context); | |
| 112 // TODO(trchen): We should be able to handle 3D-transformed root | |
| 113 // background with slimming paint by using transform display items. | |
| 114 context.concatCTM(transform.toAffineTransform()); | |
| 115 for (auto it = reversedPaintList.rbegin(); it != reversedPaintList.rend( ); ++it) { | |
| 116 ASSERT((*it)->clip() == BorderFillBox); | |
| 117 BoxPainter::paintFillLayerExtended(m_layoutView, paintInfo, Color(), **it, LayoutRect(paintRect), BackgroundBleedNone); | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 if (shouldDrawBackgroundInSeparateBuffer) | |
| 122 context.endLayer(); | |
| 100 } | 123 } |
| 101 | 124 |
| 102 } // namespace blink | 125 } // namespace blink |
| OLD | NEW |