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/BlockFlowPainter.h"
8 #include "core/layout/FloatingObjects.h"
9 #include "core/layout/LayoutBlockFlow.h"
10 #include "core/paint/ClipScope.h"
11 #include "core/paint/DeprecatedPaintLayer.h"
12 #include "core/paint/LayoutObjectDrawingRecorder.h"
13 #include "core/paint/PaintInfo.h"
17 void BlockFlowPainter::paintFloats(const PaintInfo
& paintInfo
, const LayoutPoint
& paintOffset
, bool preservePhase
)
19 if (!m_layoutBlockFlow
.floatingObjects())
22 const FloatingObjectSet
& floatingObjectSet
= m_layoutBlockFlow
.floatingObjects()->set();
23 FloatingObjectSetIterator end
= floatingObjectSet
.end();
24 for (FloatingObjectSetIterator it
= floatingObjectSet
.begin(); it
!= end
; ++it
) {
25 const FloatingObject
& floatingObject
= *it
->get();
26 if (floatingObject
.isDirectlyContained() && !floatingObject
.layoutObject()->hasSelfPaintingLayer()) {
27 PaintInfo
currentPaintInfo(paintInfo
);
28 currentPaintInfo
.phase
= preservePhase
? paintInfo
.phase
: PaintPhaseBlockBackground
;
29 // FIXME: LayoutPoint version of xPositionForFloatIncludingMargin would make this much cleaner.
30 LayoutPoint childPoint
= m_layoutBlockFlow
.flipFloatForWritingModeForChild(
31 floatingObject
, LayoutPoint(paintOffset
.x()
32 + m_layoutBlockFlow
.xPositionForFloatIncludingMargin(floatingObject
) - floatingObject
.layoutObject()->location().x(), paintOffset
.y()
33 + m_layoutBlockFlow
.yPositionForFloatIncludingMargin(floatingObject
) - floatingObject
.layoutObject()->location().y()));
34 floatingObject
.layoutObject()->paint(currentPaintInfo
, childPoint
);
36 currentPaintInfo
.phase
= PaintPhaseChildBlockBackgrounds
;
37 floatingObject
.layoutObject()->paint(currentPaintInfo
, childPoint
);
38 currentPaintInfo
.phase
= PaintPhaseFloat
;
39 floatingObject
.layoutObject()->paint(currentPaintInfo
, childPoint
);
40 currentPaintInfo
.phase
= PaintPhaseForeground
;
41 floatingObject
.layoutObject()->paint(currentPaintInfo
, childPoint
);
42 currentPaintInfo
.phase
= PaintPhaseOutline
;
43 floatingObject
.layoutObject()->paint(currentPaintInfo
, childPoint
);
49 void BlockFlowPainter::paintSelection(const PaintInfo
& paintInfo
, const LayoutPoint
& paintOffset
)
51 ASSERT(paintInfo
.phase
== PaintPhaseForeground
);
52 if (!m_layoutBlockFlow
.shouldPaintSelectionGaps())
55 LayoutUnit lastTop
= 0;
56 LayoutUnit lastLeft
= m_layoutBlockFlow
.logicalLeftSelectionOffset(&m_layoutBlockFlow
, lastTop
);
57 LayoutUnit lastRight
= m_layoutBlockFlow
.logicalRightSelectionOffset(&m_layoutBlockFlow
, lastTop
);
59 LayoutRect bounds
= m_layoutBlockFlow
.visualOverflowRect();
60 bounds
.moveBy(paintOffset
);
62 // Only create a DrawingRecorder and ClipScope if skipRecording is false. This logic is needed
63 // because selectionGaps(...) needs to be called even when we do not record.
64 bool skipRecording
= LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintInfo
.context
, m_layoutBlockFlow
, DisplayItem::SelectionGap
, paintOffset
);
65 Optional
<LayoutObjectDrawingRecorder
> drawingRecorder
;
66 Optional
<ClipScope
> clipScope
;
68 drawingRecorder
.emplace(*paintInfo
.context
, m_layoutBlockFlow
, DisplayItem::SelectionGap
, FloatRect(bounds
), paintOffset
);
69 clipScope
.emplace(paintInfo
.context
);
72 LayoutRect gapRectsBounds
= m_layoutBlockFlow
.selectionGaps(&m_layoutBlockFlow
, paintOffset
, LayoutSize(), lastTop
, lastLeft
, lastRight
,
73 skipRecording
? nullptr : &paintInfo
,
74 skipRecording
? nullptr : &(*clipScope
));
75 // TODO(wkorman): Rework below to process paint invalidation rects during layout rather than paint.
76 if (!gapRectsBounds
.isEmpty()) {
77 DeprecatedPaintLayer
* layer
= m_layoutBlockFlow
.enclosingLayer();
78 gapRectsBounds
.moveBy(-paintOffset
);
79 if (!m_layoutBlockFlow
.hasLayer()) {
80 LayoutRect
localBounds(gapRectsBounds
);
81 m_layoutBlockFlow
.flipForWritingMode(localBounds
);
82 gapRectsBounds
= LayoutRect(m_layoutBlockFlow
.localToContainerQuad(FloatRect(localBounds
), layer
->layoutObject()).enclosingBoundingBox());
83 if (layer
->layoutObject()->hasOverflowClip())
84 gapRectsBounds
.move(layer
->layoutBox()->scrolledContentOffset());
86 layer
->addBlockSelectionGapsBounds(gapRectsBounds
);