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