Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / paint / FramePainter.cpp
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.
4
5 #include "config.h"
6 #include "core/paint/FramePainter.h"
7
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"
23
24 namespace blink {
25
26 bool FramePainter::s_inPaintContents = false;
27
28 void FramePainter::paint(GraphicsContext* context, const IntRect& rect)
29 {
30     m_frameView.notifyPageThatContentAreaWillPaint();
31
32     IntRect documentDirtyRect = rect;
33     IntRect visibleAreaWithoutScrollbars(m_frameView.location(), m_frameView.visibleContentRect().size());
34     documentDirtyRect.intersect(visibleAreaWithoutScrollbars);
35
36     if (!documentDirtyRect.isEmpty()) {
37         GraphicsContextStateSaver stateSaver(*context);
38
39         context->translate(m_frameView.x() - m_frameView.scrollX(), m_frameView.y() - m_frameView.scrollY());
40         context->clip(m_frameView.visibleContentRect());
41
42         documentDirtyRect.moveBy(-m_frameView.location() + m_frameView.scrollPosition());
43         paintContents(context, documentDirtyRect);
44     }
45
46     calculateAndPaintOverhangAreas(context, rect);
47
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()));
57
58         paintScrollbars(context, scrollViewDirtyRect);
59     }
60
61     // Paint the panScroll Icon
62     if (m_frameView.drawPanScrollIcon())
63         m_frameView.paintPanScrollIcon(context);
64 }
65
66 void FramePainter::paintContents(GraphicsContext* p, const IntRect& rect)
67 {
68     Document* document = m_frameView.frame().document();
69
70 #ifndef NDEBUG
71     bool fillWithRed;
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.
82     else
83         fillWithRed = true;
84
85     if (fillWithRed)
86         p->fillRect(rect, Color(0xFF, 0, 0));
87 #endif
88
89     RenderView* renderView = m_frameView.renderView();
90     if (!renderView) {
91         WTF_LOG_ERROR("called FramePainter::paint with nil renderer");
92         return;
93     }
94
95     RELEASE_ASSERT(!m_frameView.needsLayout());
96     ASSERT(document->lifecycle().state() >= DocumentLifecycle::CompositingClean);
97
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);
102
103     bool isTopLevelPainter = !s_inPaintContents;
104     s_inPaintContents = true;
105
106     FontCachePurgePreventer fontCachePurgePreventer;
107
108     PaintBehavior oldPaintBehavior = m_frameView.paintBehavior();
109
110     if (FrameView* parentView = m_frameView.parentFrameView()) {
111         if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
112             m_frameView.setPaintBehavior(m_frameView.paintBehavior() | PaintBehaviorFlattenCompositingLayers);
113     }
114
115     if (m_frameView.paintBehavior() == PaintBehaviorNormal)
116         document->markers().invalidateRenderedRectsForMarkersInRect(rect);
117
118     if (document->printing())
119         m_frameView.setPaintBehavior(m_frameView.paintBehavior() | PaintBehaviorFlattenCompositingLayers);
120
121     ASSERT(!m_frameView.isPainting());
122     m_frameView.setIsPainting(true);
123
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();
127
128 #if ENABLE(ASSERT)
129     renderView->assertSubtreeIsLaidOut();
130     RenderObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(*rootLayer->renderer());
131 #endif
132
133     LayerPainter layerPainter(*rootLayer);
134
135     layerPainter.paint(p, rect, m_frameView.paintBehavior(), renderer);
136
137     if (rootLayer->containsDirtyOverlayScrollbars())
138         layerPainter.paintOverlayScrollbars(p, rect, m_frameView.paintBehavior(), renderer);
139
140     m_frameView.setIsPainting(false);
141
142     m_frameView.setPaintBehavior(oldPaintBehavior);
143     m_frameView.setLastPaintTime(currentTime());
144
145     // Regions may have changed as a result of the visibility/z-index of element changing.
146     if (document->annotatedRegionsDirty())
147         m_frameView.updateAnnotatedRegions();
148
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;
154     }
155
156     InspectorInstrumentation::didPaint(renderView, 0, p, rect);
157 }
158
159 void FramePainter::paintScrollbars(GraphicsContext* context, const IntRect& rect)
160 {
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);
165
166     if (m_frameView.layerForScrollCorner())
167         return;
168     paintScrollCorner(context, m_frameView.scrollCornerRect());
169 }
170
171 void FramePainter::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
172 {
173     if (m_frameView.scrollCorner()) {
174         bool needsBackground = m_frameView.frame().isMainFrame();
175         if (needsBackground)
176             context->fillRect(cornerRect, m_frameView.baseBackgroundColor());
177         ScrollbarPainter::paintIntoRect(m_frameView.scrollCorner(), context, cornerRect.location(), cornerRect);
178         return;
179     }
180
181     ScrollbarTheme::theme()->paintScrollCorner(context, cornerRect);
182 }
183
184 void FramePainter::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect)
185 {
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());
191     }
192
193     bar->paint(context, rect);
194 }
195
196 void FramePainter::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect)
197 {
198     if (m_frameView.frame().document()->printing())
199         return;
200
201     if (m_frameView.frame().isMainFrame()) {
202         if (m_frameView.frame().page()->chrome().client().paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect))
203             return;
204     }
205
206     paintOverhangAreasInternal(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect);
207 }
208
209 void FramePainter::paintOverhangAreasInternal(GraphicsContext* context, const IntRect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect& dirtyRect)
210 {
211     ScrollbarTheme::theme()->paintOverhangBackground(context, horizontalOverhangRect, verticalOverhangRect, dirtyRect);
212     ScrollbarTheme::theme()->paintOverhangShadows(context, m_frameView.scrollOffset(), horizontalOverhangRect, verticalOverhangRect, dirtyRect);
213 }
214
215 void FramePainter::calculateAndPaintOverhangAreas(GraphicsContext* context, const IntRect& dirtyRect)
216 {
217     IntRect horizontalOverhangRect;
218     IntRect verticalOverhangRect;
219     m_frameView.calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRect);
220
221     if (dirtyRect.intersects(horizontalOverhangRect) || dirtyRect.intersects(verticalOverhangRect))
222         paintOverhangAreas(context, horizontalOverhangRect, verticalOverhangRect, dirtyRect);
223 }
224
225 } // namespace blink