Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: Source/core/paint/ViewPainter.cpp

Issue 1145993002: Refactor root element background painting (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: rebase, adding back TestExpectation Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/paint/ViewPainter.h ('k') | Source/core/style/FillLayer.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 m_layoutView.paintObject(paintInfo, paintOffset); 28 m_layoutView.paintObject(paintInfo, paintOffset);
26 BlockPainter(m_layoutView).paintOverflowControlsIfNeeded(paintInfo, paintOff set); 29 BlockPainter(m_layoutView).paintOverflowControlsIfNeeded(paintInfo, paintOff set);
27 } 30 }
28 31
29 static inline bool layoutObjectObscuresBackground(LayoutBox* rootBox)
30 {
31 ASSERT(rootBox);
32 const ComputedStyle& style = rootBox->styleRef();
33 if (style.visibility() != VISIBLE
34 || style.opacity() != 1
35 || style.hasFilter()
36 || style.hasTransform())
37 return false;
38
39 if (rootBox->compositingState() == PaintsIntoOwnBacking)
40 return false;
41
42 const LayoutObject* rootLayoutObject = rootBox->layoutObjectForRootBackgroun d();
43 if (rootLayoutObject->style()->backgroundClip() == TextFillBox)
44 return false;
45
46 return true;
47 }
48
49 void ViewPainter::paintBoxDecorationBackground(const PaintInfo& paintInfo) 32 void ViewPainter::paintBoxDecorationBackground(const PaintInfo& paintInfo)
50 { 33 {
51 if (m_layoutView.document().ownerElement() || !m_layoutView.view())
52 return;
53
54 if (paintInfo.skipRootBackground()) 34 if (paintInfo.skipRootBackground())
55 return; 35 return;
56 36
57 bool shouldPaintBackground = true; 37 // This function overrides background painting for the LayoutView.
58 Node* documentElement = m_layoutView.document().documentElement(); 38 // View background painting is special in the following ways:
59 if (LayoutBox* rootBox = documentElement ? toLayoutBox(documentElement->layo utObject()) : 0) 39 // 1. The view paints background for the root element, the background positi oning respects
60 shouldPaintBackground = !rootFillsViewportBackground(rootBox) || !layout ObjectObscuresBackground(rootBox); 40 // the positioning and transformation of the root element.
41 // 2. CSS background-clip is ignored, the background layers always expand to cover the whole
42 // canvas. None of the stacking context effects (except transformation) o n the root element
43 // affects the background.
44 // 3. The main frame is also responsible for painting the user-agent-defined base background
45 // color. Conceptually it should be painted by the embedder but painting it here allows
46 // culling and pre-blending optimization when possible.
61 47
62 // If painting will entirely fill the view, no need to fill the background. 48 GraphicsContext& context = *paintInfo.context;
63 if (!shouldPaintBackground) 49 IntRect documentRect = m_layoutView.unscaledDocumentRect();
50 const Document& document = m_layoutView.document();
51 const FrameView& frameView = *m_layoutView.frameView();
52 bool isMainFrame = !document.ownerElement();
53 bool paintsBaseBackground = isMainFrame && !frameView.isTransparent();
54 bool shouldClearCanvas = paintsBaseBackground && (document.settings() && doc ument.settings()->shouldClearDocumentBackground());
55 Color baseBackgroundColor = paintsBaseBackground ? frameView.baseBackgroundC olor() : Color();
56 const LayoutObject* rootObject = document.documentElement() ? document.docum entElement()->layoutObject() : nullptr;
57
58 LayoutObjectDrawingRecorder recorder(context, m_layoutView, DisplayItem::Box DecorationBackground, documentRect);
59 if (recorder.canUseCachedDrawing())
64 return; 60 return;
65 61
66 // This code typically only executes if the root element's visibility has be en set to hidden, 62 // Compute the enclosing rect of the view, in root element space.
67 // if there is a transform on the <html>, or if there is a page scale factor less than 1. 63 //
68 // Only fill with the base background color (typically white) if we're the r oot document, 64 // For background colors we can simply paint the document rect in the defaul t space.
69 // since iframes/frames with no background in the child document should show the parent's background. 65 // However for background image, the root element transform applies. The str ategy is to apply
70 if (!m_layoutView.frameView()->isTransparent()) { 66 // root element transform on the context and issue draw commands in the loca l space, therefore
71 LayoutRect paintRect(paintInfo.rect); 67 // we need to apply inverse transform on the document rect to get to the roo t element space.
72 if (RuntimeEnabledFeatures::slimmingPaintEnabled()) 68 bool backgroundRenderable = true;
73 paintRect = m_layoutView.viewRect(); 69 TransformationMatrix transform;
70 IntRect paintRect = documentRect;
71 if (!rootObject || !rootObject->isBox()) {
72 backgroundRenderable = false;
73 } else if (rootObject->hasLayer()) {
74 const DeprecatedPaintLayer& rootLayer = *toLayoutBoxModelObject(rootObje ct)->layer();
75 LayoutPoint offset;
76 rootLayer.convertToLayerCoords(nullptr, offset);
77 transform.translate(offset.x(), offset.y());
78 transform.multiply(rootLayer.renderableTransform(paintInfo.paintBehavior ));
74 79
75 LayoutObjectDrawingRecorder recorder(*paintInfo.context, m_layoutView, D isplayItem::BoxDecorationBackground, m_layoutView.viewRect()); 80 if (!transform.isInvertible()) {
76 if (!recorder.canUseCachedDrawing()) { 81 backgroundRenderable = false;
77 Color baseColor = m_layoutView.frameView()->baseBackgroundColor(); 82 } else {
78 paintInfo.context->fillRect(paintRect, baseColor, baseColor.alpha() ? 83 bool isClamped;
79 SkXfermode::kSrc_Mode : SkXfermode::kClear_Mode); 84 paintRect = transform.inverse().projectQuad(FloatQuad(documentRect), &isClamped).enclosingBoundingBox();
85 backgroundRenderable = !isClamped;
80 } 86 }
81 } 87 }
82 }
83 88
84 bool ViewPainter::rootFillsViewportBackground(LayoutBox* rootBox) const 89 if (!backgroundRenderable) {
85 { 90 if (baseBackgroundColor.alpha())
86 ASSERT(rootBox); 91 context.fillRect(documentRect, baseBackgroundColor, shouldClearCanva s ? SkXfermode::kSrc_Mode : SkXfermode::kSrcOver_Mode);
87 // CSS Boxes always fill the viewport background (see paintRootBoxFillLayers ) 92 else if (shouldClearCanvas)
88 if (!rootBox->isSVG()) 93 context.fillRect(documentRect, Color(), SkXfermode::kClear_Mode);
89 return true; 94 return;
95 }
90 96
91 return rootBox->frameRect().contains(m_layoutView.frameRect()); 97 BoxPainter::FillLayerOcclusionOutputList reversedPaintList;
98 bool shouldDrawBackgroundInSeparateBuffer = BoxPainter(m_layoutView).calcula teFillLayerOcclusionCulling(reversedPaintList, m_layoutView.style()->backgroundL ayers());
99 ASSERT(reversedPaintList.size());
100 Color rootBackgroundColor = m_layoutView.style()->visitedDependentColor(CSSP ropertyBackgroundColor);
101
102 // If the root background color is opaque, isolation group can be skipped be cause the canvas
103 // will be cleared by root background color.
104 if (!rootBackgroundColor.hasAlpha())
105 shouldDrawBackgroundInSeparateBuffer = false;
106
107 // We are going to clear the canvas with transparent pixels, isolation group can be skipped.
108 if (!baseBackgroundColor.alpha() && shouldClearCanvas)
109 shouldDrawBackgroundInSeparateBuffer = false;
110
111 if (shouldDrawBackgroundInSeparateBuffer) {
112 if (baseBackgroundColor.alpha())
113 context.fillRect(documentRect, baseBackgroundColor, shouldClearCanva s ? SkXfermode::kSrc_Mode : SkXfermode::kSrcOver_Mode);
114 context.beginLayer();
115 }
116
117 Color combinedBackgroundColor = shouldDrawBackgroundInSeparateBuffer ? rootB ackgroundColor : baseBackgroundColor.blend(rootBackgroundColor);
118 if (combinedBackgroundColor.alpha())
119 context.fillRect(documentRect, combinedBackgroundColor, (shouldDrawBackg roundInSeparateBuffer || shouldClearCanvas) ? SkXfermode::kSrc_Mode : SkXfermode ::kSrcOver_Mode);
120 else if (shouldClearCanvas && !shouldDrawBackgroundInSeparateBuffer)
121 context.fillRect(documentRect, Color(), SkXfermode::kClear_Mode);
122
123 context.save();
124 // TODO(trchen): We should be able to handle 3D-transformed root
125 // background with slimming paint by using transform display items.
126 context.concatCTM(transform.toAffineTransform());
127 for (auto it = reversedPaintList.rbegin(); it != reversedPaintList.rend(); + +it) {
128 ASSERT((*it)->clip() == BorderFillBox);
129 BoxPainter::paintFillLayerExtended(m_layoutView, paintInfo, Color(), **i t, LayoutRect(paintRect), BackgroundBleedNone);
130 }
131 context.restore();
132
133 if (shouldDrawBackgroundInSeparateBuffer)
134 context.endLayer();
92 } 135 }
93 136
94 } // namespace blink 137 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/paint/ViewPainter.h ('k') | Source/core/style/FillLayer.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698