Chromium Code Reviews| Index: Source/core/paint/ViewPainter.cpp |
| diff --git a/Source/core/paint/ViewPainter.cpp b/Source/core/paint/ViewPainter.cpp |
| index 63e19a5021ef6bff5dc723919e232cf5ae1a4717..5fce8b8d706fdda0c2bb9c1cb86bf7fa6e75b28e 100644 |
| --- a/Source/core/paint/ViewPainter.cpp |
| +++ b/Source/core/paint/ViewPainter.cpp |
| @@ -6,9 +6,12 @@ |
| #include "core/paint/ViewPainter.h" |
| #include "core/frame/FrameView.h" |
| +#include "core/frame/Settings.h" |
| #include "core/layout/LayoutBox.h" |
| #include "core/layout/LayoutView.h" |
| #include "core/paint/BlockPainter.h" |
| +#include "core/paint/BoxPainter.h" |
| +#include "core/paint/DeprecatedPaintLayer.h" |
| #include "core/paint/LayoutObjectDrawingRecorder.h" |
| #include "core/paint/PaintInfo.h" |
| #include "platform/RuntimeEnabledFeatures.h" |
| @@ -34,69 +37,89 @@ void ViewPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffs |
| BlockPainter(m_layoutView).paintOverflowControlsIfNeeded(paintInfo, paintOffset); |
| } |
| -static inline bool layoutObjectObscuresBackground(LayoutBox* rootBox) |
| -{ |
| - ASSERT(rootBox); |
| - const ComputedStyle& style = rootBox->styleRef(); |
| - if (style.visibility() != VISIBLE |
| - || style.opacity() != 1 |
| - || style.hasFilter() |
| - || style.hasTransform()) |
| - return false; |
| - |
| - if (rootBox->compositingState() == PaintsIntoOwnBacking) |
| - return false; |
| - |
| - const LayoutObject* rootLayoutObject = rootBox->layoutObjectForRootBackground(); |
| - if (rootLayoutObject->style()->backgroundClip() == TextFillBox) |
| - return false; |
| - |
| - return true; |
| -} |
| - |
| void ViewPainter::paintBoxDecorationBackground(const PaintInfo& paintInfo) |
| { |
| - if (m_layoutView.document().ownerElement() || !m_layoutView.view()) |
| + if (paintInfo.skipRootBackground()) |
| return; |
| - if (paintInfo.skipRootBackground()) |
| + GraphicsContext& context = *paintInfo.context; |
| + IntRect documentRect = m_layoutView.unscaledDocumentRect(); |
| + const Document& document = m_layoutView.document(); |
| + const FrameView& frameView = *m_layoutView.frameView(); |
| + bool isMainFrame = !document.ownerElement(); |
| + bool paintsBaseBackground = isMainFrame && !frameView.isTransparent(); |
| + bool shouldClearCanvas = paintsBaseBackground && (document.settings() && document.settings()->shouldClearDocumentBackground()); |
| + Color baseBackgroundColor = paintsBaseBackground ? frameView.baseBackgroundColor() : Color(); |
| + const LayoutObject* rootObject = document.documentElement() ? document.documentElement()->layoutObject() : nullptr; |
| + |
| + LayoutObjectDrawingRecorder recorder(context, m_layoutView, DisplayItem::BoxDecorationBackground, documentRect); |
| + if (recorder.canUseCachedDrawing()) |
| return; |
| - bool shouldPaintBackground = true; |
| - Node* documentElement = m_layoutView.document().documentElement(); |
| - if (LayoutBox* rootBox = documentElement ? toLayoutBox(documentElement->layoutObject()) : 0) |
| - shouldPaintBackground = !rootFillsViewportBackground(rootBox) || !layoutObjectObscuresBackground(rootBox); |
| + bool backgroundRenderable = true; |
| + TransformationMatrix transform; |
| + IntRect paintRect = documentRect; |
| + if (!rootObject || !rootObject->isBox()) { |
| + backgroundRenderable = false; |
| + } else if (rootObject->hasLayer()) { |
| + const DeprecatedPaintLayer& rootLayer = *toLayoutBoxModelObject(rootObject)->layer(); |
| + LayoutPoint offset; |
| + rootLayer.convertToLayerCoords(nullptr, offset); |
| + transform.translate(offset.x(), offset.y()); |
| + 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
|
| + |
| + if (!transform.isInvertible()) { |
| + backgroundRenderable = false; |
| + } else { |
| + bool isClamped; |
| + paintRect = transform.inverse().projectQuad(FloatQuad(documentRect), &isClamped).enclosingBoundingBox(); |
| + backgroundRenderable = !isClamped; |
| + } |
| + } |
| - // If painting will entirely fill the view, no need to fill the background. |
| - if (!shouldPaintBackground) |
| + if (!backgroundRenderable) { |
| + if (baseBackgroundColor.alpha()) |
| + context.fillRect(documentRect, baseBackgroundColor, shouldClearCanvas ? SkXfermode::kSrc_Mode : SkXfermode::kSrcOver_Mode); |
| + else if (shouldClearCanvas) |
| + context.fillRect(documentRect, Color(), SkXfermode::kClear_Mode); |
| return; |
| + } |
| - // This code typically only executes if the root element's visibility has been set to hidden, |
| - // if there is a transform on the <html>, or if there is a page scale factor less than 1. |
| - // Only fill with the base background color (typically white) if we're the root document, |
| - // since iframes/frames with no background in the child document should show the parent's background. |
| - if (!m_layoutView.frameView()->isTransparent()) { |
| - LayoutRect paintRect(paintInfo.rect); |
| - if (RuntimeEnabledFeatures::slimmingPaintEnabled()) |
| - paintRect = m_layoutView.viewRect(); |
| - |
| - LayoutObjectDrawingRecorder recorder(*paintInfo.context, m_layoutView, DisplayItem::BoxDecorationBackground, m_layoutView.viewRect()); |
| - if (!recorder.canUseCachedDrawing()) { |
| - Color baseColor = m_layoutView.frameView()->baseBackgroundColor(); |
| - paintInfo.context->fillRect(paintRect, baseColor, baseColor.alpha() ? |
| - SkXfermode::kSrc_Mode : SkXfermode::kClear_Mode); |
| - } |
| + Vector<const FillLayer*, 8> reversedPaintList; |
| + bool shouldDrawBackgroundInSeparateBuffer = BoxPainter(m_layoutView).calculateFillLayerOcclusionCulling(reversedPaintList, m_layoutView.style()->backgroundLayers()); |
| + ASSERT(reversedPaintList.size()); |
| + Color rootBackgroundColor = m_layoutView.style()->visitedDependentColor(CSSPropertyBackgroundColor); |
| + if (!rootBackgroundColor.hasAlpha()) |
| + shouldDrawBackgroundInSeparateBuffer = false; |
| + |
| + if (!baseBackgroundColor.alpha() && shouldClearCanvas) |
| + shouldDrawBackgroundInSeparateBuffer = false; |
| + |
| + if (shouldDrawBackgroundInSeparateBuffer) { |
| + if (baseBackgroundColor.alpha()) |
| + context.fillRect(documentRect, baseBackgroundColor, shouldClearCanvas ? SkXfermode::kSrc_Mode : SkXfermode::kSrcOver_Mode); |
| + context.beginLayer(); |
| } |
| -} |
| -bool ViewPainter::rootFillsViewportBackground(LayoutBox* rootBox) const |
| -{ |
| - ASSERT(rootBox); |
| - // CSS Boxes always fill the viewport background (see paintRootBoxFillLayers) |
| - if (!rootBox->isSVG()) |
| - return true; |
| + Color combinedBackgroundColor = shouldDrawBackgroundInSeparateBuffer ? rootBackgroundColor : baseBackgroundColor.blend(rootBackgroundColor); |
| + if (combinedBackgroundColor.alpha()) |
| + context.fillRect(documentRect, combinedBackgroundColor, (shouldDrawBackgroundInSeparateBuffer || shouldClearCanvas) ? SkXfermode::kSrc_Mode : SkXfermode::kSrcOver_Mode); |
| + else if (shouldClearCanvas && !shouldDrawBackgroundInSeparateBuffer) |
| + context.fillRect(documentRect, Color(), SkXfermode::kClear_Mode); |
| + |
| + { |
| + GraphicsContextStateSaver stateSaver(context); |
| + // TODO(trchen): We should be able to handle 3D-transformed root |
| + // background with slimming paint by using transform display items. |
| + context.concatCTM(transform.toAffineTransform()); |
| + for (auto it = reversedPaintList.rbegin(); it != reversedPaintList.rend(); ++it) { |
| + ASSERT((*it)->clip() == BorderFillBox); |
| + BoxPainter::paintFillLayerExtended(m_layoutView, paintInfo, Color(), **it, LayoutRect(paintRect), BackgroundBleedNone); |
| + } |
| + } |
| - return rootBox->frameRect().contains(m_layoutView.frameRect()); |
| + if (shouldDrawBackgroundInSeparateBuffer) |
| + context.endLayer(); |
| } |
| } // namespace blink |