| Index: Source/core/paint/FramePainter.cpp
|
| diff --git a/Source/core/paint/FramePainter.cpp b/Source/core/paint/FramePainter.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a2e721af44a8e90dfba9d3c280d12f801eb3f317
|
| --- /dev/null
|
| +++ b/Source/core/paint/FramePainter.cpp
|
| @@ -0,0 +1,225 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "config.h"
|
| +#include "core/paint/FramePainter.h"
|
| +
|
| +#include "core/dom/DocumentMarkerController.h"
|
| +#include "core/frame/FrameView.h"
|
| +#include "core/inspector/InspectorInstrumentation.h"
|
| +#include "core/inspector/InspectorTraceEvents.h"
|
| +#include "core/page/Chrome.h"
|
| +#include "core/page/ChromeClient.h"
|
| +#include "core/page/Page.h"
|
| +#include "core/paint/LayerPainter.h"
|
| +#include "core/paint/ScrollbarPainter.h"
|
| +#include "core/rendering/RenderLayer.h"
|
| +#include "core/rendering/RenderView.h"
|
| +#include "platform/fonts/FontCache.h"
|
| +#include "platform/graphics/GraphicsContext.h"
|
| +#include "platform/graphics/GraphicsContextStateSaver.h"
|
| +#include "platform/scroll/ScrollbarTheme.h"
|
| +
|
| +namespace blink {
|
| +
|
| +bool FramePainter::s_inPaintContents = false;
|
| +
|
| +void FramePainter::paint(GraphicsContext* context, const IntRect& rect)
|
| +{
|
| + m_frameView.notifyPageThatContentAreaWillPaint();
|
| +
|
| + IntRect documentDirtyRect = rect;
|
| + IntRect visibleAreaWithoutScrollbars(m_frameView.location(), m_frameView.visibleContentRect().size());
|
| + documentDirtyRect.intersect(visibleAreaWithoutScrollbars);
|
| +
|
| + if (!documentDirtyRect.isEmpty()) {
|
| + GraphicsContextStateSaver stateSaver(*context);
|
| +
|
| + context->translate(m_frameView.x() - m_frameView.scrollX(), m_frameView.y() - m_frameView.scrollY());
|
| + context->clip(m_frameView.visibleContentRect());
|
| +
|
| + documentDirtyRect.moveBy(-m_frameView.location() + m_frameView.scrollPosition());
|
| + paintContents(context, documentDirtyRect);
|
| + }
|
| +
|
| + calculateAndPaintOverhangAreas(context, rect);
|
| +
|
| + // Now paint the scrollbars.
|
| + if (!m_frameView.scrollbarsSuppressed() && (m_frameView.horizontalScrollbar() || m_frameView.verticalScrollbar())) {
|
| + GraphicsContextStateSaver stateSaver(*context);
|
| + IntRect scrollViewDirtyRect = rect;
|
| + IntRect visibleAreaWithScrollbars(m_frameView.location(), m_frameView.visibleContentRect(IncludeScrollbars).size());
|
| + scrollViewDirtyRect.intersect(visibleAreaWithScrollbars);
|
| + context->translate(m_frameView.x(), m_frameView.y());
|
| + scrollViewDirtyRect.moveBy(-m_frameView.location());
|
| + context->clip(IntRect(IntPoint(), visibleAreaWithScrollbars.size()));
|
| +
|
| + paintScrollbars(context, scrollViewDirtyRect);
|
| + }
|
| +
|
| + // Paint the panScroll Icon
|
| + if (m_frameView.drawPanScrollIcon())
|
| + m_frameView.paintPanScrollIcon(context);
|
| +}
|
| +
|
| +void FramePainter::paintContents(GraphicsContext* p, const IntRect& rect)
|
| +{
|
| + Document* document = m_frameView.frame().document();
|
| +
|
| +#ifndef NDEBUG
|
| + bool fillWithRed;
|
| + if (document->printing())
|
| + fillWithRed = false; // Printing, don't fill with red (can't remember why).
|
| + else if (m_frameView.frame().owner())
|
| + fillWithRed = false; // Subframe, don't fill with red.
|
| + else if (m_frameView.isTransparent())
|
| + fillWithRed = false; // Transparent, don't fill with red.
|
| + else if (m_frameView.paintBehavior() & PaintBehaviorSelectionOnly)
|
| + fillWithRed = false; // Selections are transparent, don't fill with red.
|
| + else if (m_frameView.nodeToDraw())
|
| + fillWithRed = false; // Element images are transparent, don't fill with red.
|
| + else
|
| + fillWithRed = true;
|
| +
|
| + if (fillWithRed)
|
| + p->fillRect(rect, Color(0xFF, 0, 0));
|
| +#endif
|
| +
|
| + RenderView* renderView = m_frameView.renderView();
|
| + if (!renderView) {
|
| + WTF_LOG_ERROR("called FramePainter::paint with nil renderer");
|
| + return;
|
| + }
|
| +
|
| + RELEASE_ASSERT(!m_frameView.needsLayout());
|
| + ASSERT(document->lifecycle().state() >= DocumentLifecycle::CompositingClean);
|
| +
|
| + TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Paint", "data", InspectorPaintEvent::data(renderView, rect, 0));
|
| + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack());
|
| + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
|
| + InspectorInstrumentation::willPaint(renderView, 0);
|
| +
|
| + bool isTopLevelPainter = !s_inPaintContents;
|
| + s_inPaintContents = true;
|
| +
|
| + FontCachePurgePreventer fontCachePurgePreventer;
|
| +
|
| + PaintBehavior oldPaintBehavior = m_frameView.paintBehavior();
|
| +
|
| + if (FrameView* parentView = m_frameView.parentFrameView()) {
|
| + if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
|
| + m_frameView.setPaintBehavior(m_frameView.paintBehavior() | PaintBehaviorFlattenCompositingLayers);
|
| + }
|
| +
|
| + if (m_frameView.paintBehavior() == PaintBehaviorNormal)
|
| + document->markers().invalidateRenderedRectsForMarkersInRect(rect);
|
| +
|
| + if (document->printing())
|
| + m_frameView.setPaintBehavior(m_frameView.paintBehavior() | PaintBehaviorFlattenCompositingLayers);
|
| +
|
| + ASSERT(!m_frameView.isPainting());
|
| + m_frameView.setIsPainting(true);
|
| +
|
| + // m_frameView.nodeToDraw() is used to draw only one element (and its descendants)
|
| + RenderObject* renderer = m_frameView.nodeToDraw() ? m_frameView.nodeToDraw()->renderer() : 0;
|
| + RenderLayer* rootLayer = renderView->layer();
|
| +
|
| +#if ENABLE(ASSERT)
|
| + renderView->assertSubtreeIsLaidOut();
|
| + RenderObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(*rootLayer->renderer());
|
| +#endif
|
| +
|
| + LayerPainter layerPainter(*rootLayer);
|
| +
|
| + layerPainter.paint(p, rect, m_frameView.paintBehavior(), renderer);
|
| +
|
| + if (rootLayer->containsDirtyOverlayScrollbars())
|
| + layerPainter.paintOverlayScrollbars(p, rect, m_frameView.paintBehavior(), renderer);
|
| +
|
| + m_frameView.setIsPainting(false);
|
| +
|
| + m_frameView.setPaintBehavior(oldPaintBehavior);
|
| + m_frameView.setLastPaintTime(currentTime());
|
| +
|
| + // Regions may have changed as a result of the visibility/z-index of element changing.
|
| + if (document->annotatedRegionsDirty())
|
| + m_frameView.updateAnnotatedRegions();
|
| +
|
| + if (isTopLevelPainter) {
|
| + // Everything that happens after paintContents completions is considered
|
| + // to be part of the next frame.
|
| + m_frameView.setCurrentFrameTimeStamp(currentTime());
|
| + s_inPaintContents = false;
|
| + }
|
| +
|
| + InspectorInstrumentation::didPaint(renderView, 0, p, rect);
|
| +}
|
| +
|
| +void FramePainter::paintScrollbars(GraphicsContext* context, const IntRect& rect)
|
| +{
|
| + if (m_frameView.horizontalScrollbar() && !m_frameView.layerForHorizontalScrollbar())
|
| + paintScrollbar(context, m_frameView.horizontalScrollbar(), rect);
|
| + if (m_frameView.verticalScrollbar() && !m_frameView.layerForVerticalScrollbar())
|
| + paintScrollbar(context, m_frameView.verticalScrollbar(), rect);
|
| +
|
| + if (m_frameView.layerForScrollCorner())
|
| + return;
|
| + paintScrollCorner(context, m_frameView.scrollCornerRect());
|
| +}
|
| +
|
| +void FramePainter::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
|
| +{
|
| + if (m_frameView.scrollCorner()) {
|
| + bool needsBackground = m_frameView.frame().isMainFrame();
|
| + if (needsBackground)
|
| + context->fillRect(cornerRect, m_frameView.baseBackgroundColor());
|
| + ScrollbarPainter::paintIntoRect(m_frameView.scrollCorner(), context, cornerRect.location(), cornerRect);
|
| + return;
|
| + }
|
| +
|
| + ScrollbarTheme::theme()->paintScrollCorner(context, cornerRect);
|
| +}
|
| +
|
| +void FramePainter::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect)
|
| +{
|
| + bool needsBackground = bar->isCustomScrollbar() && m_frameView.frame().isMainFrame();
|
| + if (needsBackground) {
|
| + IntRect toFill = bar->frameRect();
|
| + toFill.intersect(rect);
|
| + context->fillRect(toFill, m_frameView.baseBackgroundColor());
|
| + }
|
| +
|
| + bar->paint(context, rect);
|
| +}
|
| +
|
| +void FramePainter::paintOverhangAreas(GraphicsContext* context, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect)
|
| +{
|
| + if (m_frameView.frame().document()->printing())
|
| + return;
|
| +
|
| + if (m_frameView.frame().isMainFrame()) {
|
| + if (m_frameView.frame().page()->chrome().client().paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect))
|
| + return;
|
| + }
|
| +
|
| + paintOverhangAreasInternal(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect);
|
| +}
|
| +
|
| +void FramePainter::paintOverhangAreasInternal(GraphicsContext* context, const IntRect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect& dirtyRect)
|
| +{
|
| + ScrollbarTheme::theme()->paintOverhangBackground(context, horizontalOverhangRect, verticalOverhangRect, dirtyRect);
|
| + ScrollbarTheme::theme()->paintOverhangShadows(context, m_frameView.scrollOffset(), horizontalOverhangRect, verticalOverhangRect, dirtyRect);
|
| +}
|
| +
|
| +void FramePainter::calculateAndPaintOverhangAreas(GraphicsContext* context, const IntRect& dirtyRect)
|
| +{
|
| + IntRect horizontalOverhangRect;
|
| + IntRect verticalOverhangRect;
|
| + m_frameView.calculateOverhangAreasForPainting(horizontalOverhangRect, verticalOverhangRect);
|
| +
|
| + if (dirtyRect.intersects(horizontalOverhangRect) || dirtyRect.intersects(verticalOverhangRect))
|
| + paintOverhangAreas(context, horizontalOverhangRect, verticalOverhangRect, dirtyRect);
|
| +}
|
| +
|
| +} // namespace blink
|
|
|