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
3 // found in the LICENSE file.
6 #include "core/paint/FramePainter.h"
8 #include "core/dom/DocumentMarkerController.h"
9 #include "core/frame/FrameView.h"
10 #include "core/inspector/InspectorInstrumentation.h"
11 #include "core/inspector/InspectorTraceEvents.h"
12 #include "core/page/Chrome.h"
13 #include "core/page/ChromeClient.h"
14 #include "core/page/Page.h"
15 #include "core/paint/LayerPainter.h"
16 #include "core/paint/ScrollbarPainter.h"
17 #include "core/rendering/RenderLayer.h"
18 #include "core/rendering/RenderView.h"
19 #include "platform/fonts/FontCache.h"
20 #include "platform/graphics/GraphicsContext.h"
21 #include "platform/graphics/GraphicsContextStateSaver.h"
22 #include "platform/scroll/ScrollbarTheme.h"
26 bool FramePainter::s_inPaintContents = false;
28 void FramePainter::paint(GraphicsContext* context, const IntRect& rect)
30 m_frameView.notifyPageThatContentAreaWillPaint();
32 IntRect documentDirtyRect = rect;
33 IntRect visibleAreaWithoutScrollbars(m_frameView.location(), m_frameView.visibleContentRect().size());
34 documentDirtyRect.intersect(visibleAreaWithoutScrollbars);
36 if (!documentDirtyRect.isEmpty()) {
37 GraphicsContextStateSaver stateSaver(*context);
39 context->translate(m_frameView.x() - m_frameView.scrollX(), m_frameView.y() - m_frameView.scrollY());
40 context->clip(m_frameView.visibleContentRect());
42 documentDirtyRect.moveBy(-m_frameView.location() + m_frameView.scrollPosition());
43 paintContents(context, documentDirtyRect);
46 calculateAndPaintOverhangAreas(context, rect);
48 // Now paint the scrollbars.
49 if (!m_frameView.scrollbarsSuppressed() && (m_frameView.horizontalScrollbar() || m_frameView.verticalScrollbar())) {
50 GraphicsContextStateSaver stateSaver(*context);
51 IntRect scrollViewDirtyRect = rect;
52 IntRect visibleAreaWithScrollbars(m_frameView.location(), m_frameView.visibleContentRect(IncludeScrollbars).size());
53 scrollViewDirtyRect.intersect(visibleAreaWithScrollbars);
54 context->translate(m_frameView.x(), m_frameView.y());
55 scrollViewDirtyRect.moveBy(-m_frameView.location());
56 context->clip(IntRect(IntPoint(), visibleAreaWithScrollbars.size()));
58 paintScrollbars(context, scrollViewDirtyRect);
61 // Paint the panScroll Icon
62 if (m_frameView.drawPanScrollIcon())
63 m_frameView.paintPanScrollIcon(context);
66 void FramePainter::paintContents(GraphicsContext* p, const IntRect& rect)
68 Document* document = m_frameView.frame().document();
72 if (document->printing())
73 fillWithRed = false; // Printing, don't fill with red (can't remember why).
74 else if (m_frameView.frame().owner())
75 fillWithRed = false; // Subframe, don't fill with red.
76 else if (m_frameView.isTransparent())
77 fillWithRed = false; // Transparent, don't fill with red.
78 else if (m_frameView.paintBehavior() & PaintBehaviorSelectionOnly)
79 fillWithRed = false; // Selections are transparent, don't fill with red.
80 else if (m_frameView.nodeToDraw())
81 fillWithRed = false; // Element images are transparent, don't fill with red.
86 p->fillRect(rect, Color(0xFF, 0, 0));
89 RenderView* renderView = m_frameView.renderView();
91 WTF_LOG_ERROR("called FramePainter::paint with nil renderer");
95 RELEASE_ASSERT(!m_frameView.needsLayout());
96 ASSERT(document->lifecycle().state() >= DocumentLifecycle::CompositingClean);
98 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Paint", "data", InspectorPaintEvent::data(renderView, rect, 0));
99 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack());
100 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
101 InspectorInstrumentation::willPaint(renderView, 0);
103 bool isTopLevelPainter = !s_inPaintContents;
104 s_inPaintContents = true;
106 FontCachePurgePreventer fontCachePurgePreventer;
108 PaintBehavior oldPaintBehavior = m_frameView.paintBehavior();
110 if (FrameView* parentView = m_frameView.parentFrameView()) {
111 if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
112 m_frameView.setPaintBehavior(m_frameView.paintBehavior() | PaintBehaviorFlattenCompositingLayers);
115 if (m_frameView.paintBehavior() == PaintBehaviorNormal)
116 document->markers().invalidateRenderedRectsForMarkersInRect(rect);
118 if (document->printing())
119 m_frameView.setPaintBehavior(m_frameView.paintBehavior() | PaintBehaviorFlattenCompositingLayers);
121 ASSERT(!m_frameView.isPainting());
122 m_frameView.setIsPainting(true);
124 // m_frameView.nodeToDraw() is used to draw only one element (and its descendants)
125 RenderObject* renderer = m_frameView.nodeToDraw() ? m_frameView.nodeToDraw()->renderer() : 0;
126 RenderLayer* rootLayer = renderView->layer();
129 renderView->assertSubtreeIsLaidOut();
130 RenderObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(*rootLayer->renderer());
133 LayerPainter layerPainter(*rootLayer);
135 layerPainter.paint(p, rect, m_frameView.paintBehavior(), renderer);
137 if (rootLayer->containsDirtyOverlayScrollbars())
138 layerPainter.paintOverlayScrollbars(p, rect, m_frameView.paintBehavior(), renderer);
140 m_frameView.setIsPainting(false);
142 m_frameView.setPaintBehavior(oldPaintBehavior);
143 m_frameView.setLastPaintTime(currentTime());
145 // Regions may have changed as a result of the visibility/z-index of element changing.
146 if (document->annotatedRegionsDirty())
147 m_frameView.updateAnnotatedRegions();
149 if (isTopLevelPainter) {
150 // Everything that happens after paintContents completions is considered
151 // to be part of the next frame.
152 m_frameView.setCurrentFrameTimeStamp(currentTime());
153 s_inPaintContents = false;
156 InspectorInstrumentation::didPaint(renderView, 0, p, rect);
159 void FramePainter::paintScrollbars(GraphicsContext* context, const IntRect& rect)
161 if (m_frameView.horizontalScrollbar() && !m_frameView.layerForHorizontalScrollbar())
162 paintScrollbar(context, m_frameView.horizontalScrollbar(), rect);
163 if (m_frameView.verticalScrollbar() && !m_frameView.layerForVerticalScrollbar())
164 paintScrollbar(context, m_frameView.verticalScrollbar(), rect);
166 if (m_frameView.layerForScrollCorner())
168 paintScrollCorner(context, m_frameView.scrollCornerRect());
171 void FramePainter::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
173 if (m_frameView.scrollCorner()) {
174 bool needsBackground = m_frameView.frame().isMainFrame();
176 context->fillRect(cornerRect, m_frameView.baseBackgroundColor());
177 ScrollbarPainter::paintIntoRect(m_frameView.scrollCorner(), context, cornerRect.location(), cornerRect);
181 ScrollbarTheme::theme()->paintScrollCorner(context, cornerRect);
184 void FramePainter::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect)
186 bool needsBackground = bar->isCustomScrollbar() && m_frameView.frame().isMainFrame();
187 if (needsBackground) {
188 IntRect toFill = bar->frameRect();
189 toFill.intersect(rect);
190 context->fillRect(toFill, m_frameView.baseBackgroundColor());
193 bar->paint(context, rect);
196 void FramePainter::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect)
198 if (m_frameView.frame().document()->printing())
201 if (m_frameView.frame().isMainFrame()) {
202 if (m_frameView.frame().page()->chrome().client().paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect))
206 paintOverhangAreasInternal(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect);
209 void FramePainter::paintOverhangAreasInternal(GraphicsContext* context, const IntRect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect& dirtyRect)
211 ScrollbarTheme::theme()->paintOverhangBackground(context, horizontalOverhangRect, verticalOverhangRect, dirtyRect);
212 ScrollbarTheme::theme()->paintOverhangShadows(context, m_frameView.scrollOffset(), horizontalOverhangRect, verticalOverhangRect, dirtyRect);
215 void FramePainter::calculateAndPaintOverhangAreas(GraphicsContext* context, const IntRect& dirtyRect)
217 IntRect horizontalOverhangRect;
218 IntRect verticalOverhangRect;
219 m_frameView.calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRect);
221 if (dirtyRect.intersects(horizontalOverhangRect) || dirtyRect.intersects(verticalOverhangRect))
222 paintOverhangAreas(context, horizontalOverhangRect, verticalOverhangRect, dirtyRect);