OLD | NEW |
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 "core/paint/ScrollableAreaPainter.h" | 5 #include "core/paint/ScrollableAreaPainter.h" |
6 | 6 |
7 #include "core/layout/LayoutView.h" | 7 #include "core/layout/LayoutView.h" |
8 #include "core/page/Page.h" | 8 #include "core/page/Page.h" |
9 #include "core/paint/LayoutObjectDrawingRecorder.h" | 9 #include "core/paint/LayoutObjectDrawingRecorder.h" |
10 #include "core/paint/PaintInfo.h" | 10 #include "core/paint/PaintInfo.h" |
11 #include "core/paint/PaintLayer.h" | 11 #include "core/paint/PaintLayer.h" |
12 #include "core/paint/PaintLayerScrollableArea.h" | 12 #include "core/paint/PaintLayerScrollableArea.h" |
13 #include "core/paint/ScrollbarPainter.h" | 13 #include "core/paint/ScrollbarPainter.h" |
14 #include "core/paint/TransformRecorder.h" | 14 #include "core/paint/TransformRecorder.h" |
15 #include "platform/graphics/GraphicsContext.h" | 15 #include "platform/graphics/GraphicsContext.h" |
16 #include "platform/graphics/GraphicsContextStateSaver.h" | 16 #include "platform/graphics/GraphicsContextStateSaver.h" |
17 | 17 |
18 namespace blink { | 18 namespace blink { |
19 | 19 |
20 void ScrollableAreaPainter::paintResizer(GraphicsContext& context, const IntPoin
t& paintOffset, const CullRect& cullRect) | 20 void ScrollableAreaPainter::paintResizer(GraphicsContext& context, const IntPoin
t& paintOffset, const CullRect& cullRect) |
21 { | 21 { |
22 if (scrollableArea().box().style()->resize() == RESIZE_NONE) | 22 if (getScrollableArea().box().style()->resize() == RESIZE_NONE) |
23 return; | 23 return; |
24 | 24 |
25 IntRect absRect = scrollableArea().resizerCornerRect(scrollableArea().box().
pixelSnappedBorderBoxRect(), ResizerForPointer); | 25 IntRect absRect = getScrollableArea().resizerCornerRect(getScrollableArea().
box().pixelSnappedBorderBoxRect(), ResizerForPointer); |
26 if (absRect.isEmpty()) | 26 if (absRect.isEmpty()) |
27 return; | 27 return; |
28 absRect.moveBy(paintOffset); | 28 absRect.moveBy(paintOffset); |
29 | 29 |
30 if (scrollableArea().resizer()) { | 30 if (getScrollableArea().resizer()) { |
31 if (!cullRect.intersectsCullRect(absRect)) | 31 if (!cullRect.intersectsCullRect(absRect)) |
32 return; | 32 return; |
33 ScrollbarPainter::paintIntoRect(*scrollableArea().resizer(), context, pa
intOffset, LayoutRect(absRect)); | 33 ScrollbarPainter::paintIntoRect(*getScrollableArea().resizer(), context,
paintOffset, LayoutRect(absRect)); |
34 return; | 34 return; |
35 } | 35 } |
36 | 36 |
37 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, scrolla
bleArea().box(), DisplayItem::Resizer)) | 37 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, getScro
llableArea().box(), DisplayItem::Resizer)) |
38 return; | 38 return; |
39 | 39 |
40 LayoutObjectDrawingRecorder recorder(context, scrollableArea().box(), Displa
yItem::Resizer, absRect); | 40 LayoutObjectDrawingRecorder recorder(context, getScrollableArea().box(), Dis
playItem::Resizer, absRect); |
41 | 41 |
42 drawPlatformResizerImage(context, absRect); | 42 drawPlatformResizerImage(context, absRect); |
43 | 43 |
44 // Draw a frame around the resizer (1px grey line) if there are any scrollba
rs present. | 44 // Draw a frame around the resizer (1px grey line) if there are any scrollba
rs present. |
45 // Clipping will exclude the right and bottom edges of this frame. | 45 // Clipping will exclude the right and bottom edges of this frame. |
46 if (!scrollableArea().hasOverlayScrollbars() && scrollableArea().hasScrollba
r()) { | 46 if (!getScrollableArea().hasOverlayScrollbars() && getScrollableArea().hasSc
rollbar()) { |
47 GraphicsContextStateSaver stateSaver(context); | 47 GraphicsContextStateSaver stateSaver(context); |
48 context.clip(absRect); | 48 context.clip(absRect); |
49 IntRect largerCorner = absRect; | 49 IntRect largerCorner = absRect; |
50 largerCorner.setSize(IntSize(largerCorner.width() + 1, largerCorner.heig
ht() + 1)); | 50 largerCorner.setSize(IntSize(largerCorner.width() + 1, largerCorner.heig
ht() + 1)); |
51 context.setStrokeColor(Color(217, 217, 217)); | 51 context.setStrokeColor(Color(217, 217, 217)); |
52 context.setStrokeThickness(1.0f); | 52 context.setStrokeThickness(1.0f); |
53 context.setFillColor(Color::transparent); | 53 context.setFillColor(Color::transparent); |
54 context.drawRect(largerCorner); | 54 context.drawRect(largerCorner); |
55 } | 55 } |
56 } | 56 } |
57 | 57 |
58 void ScrollableAreaPainter::drawPlatformResizerImage(GraphicsContext& context, I
ntRect resizerCornerRect) | 58 void ScrollableAreaPainter::drawPlatformResizerImage(GraphicsContext& context, I
ntRect resizerCornerRect) |
59 { | 59 { |
60 float deviceScaleFactor = blink::deviceScaleFactor(scrollableArea().box().fr
ame()); | 60 float deviceScaleFactor = blink::deviceScaleFactor(getScrollableArea().box()
.frame()); |
61 | 61 |
62 RefPtr<Image> resizeCornerImage; | 62 RefPtr<Image> resizeCornerImage; |
63 IntSize cornerResizerSize; | 63 IntSize cornerResizerSize; |
64 if (deviceScaleFactor >= 2) { | 64 if (deviceScaleFactor >= 2) { |
65 DEFINE_STATIC_REF(Image, resizeCornerImageHiRes, (Image::loadPlatformRes
ource("textAreaResizeCorner@2x"))); | 65 DEFINE_STATIC_REF(Image, resizeCornerImageHiRes, (Image::loadPlatformRes
ource("textAreaResizeCorner@2x"))); |
66 resizeCornerImage = resizeCornerImageHiRes; | 66 resizeCornerImage = resizeCornerImageHiRes; |
67 cornerResizerSize = resizeCornerImage->size(); | 67 cornerResizerSize = resizeCornerImage->size(); |
68 cornerResizerSize.scale(0.5f); | 68 cornerResizerSize.scale(0.5f); |
69 } else { | 69 } else { |
70 DEFINE_STATIC_REF(Image, resizeCornerImageLoRes, (Image::loadPlatformRes
ource("textAreaResizeCorner"))); | 70 DEFINE_STATIC_REF(Image, resizeCornerImageLoRes, (Image::loadPlatformRes
ource("textAreaResizeCorner"))); |
71 resizeCornerImage = resizeCornerImageLoRes; | 71 resizeCornerImage = resizeCornerImageLoRes; |
72 cornerResizerSize = resizeCornerImage->size(); | 72 cornerResizerSize = resizeCornerImage->size(); |
73 } | 73 } |
74 | 74 |
75 if (scrollableArea().box().shouldPlaceBlockDirectionScrollbarOnLogicalLeft()
) { | 75 if (getScrollableArea().box().shouldPlaceBlockDirectionScrollbarOnLogicalLef
t()) { |
76 context.save(); | 76 context.save(); |
77 context.translate(resizerCornerRect.x() + cornerResizerSize.width(), res
izerCornerRect.y() + resizerCornerRect.height() - cornerResizerSize.height()); | 77 context.translate(resizerCornerRect.x() + cornerResizerSize.width(), res
izerCornerRect.y() + resizerCornerRect.height() - cornerResizerSize.height()); |
78 context.scale(-1.0, 1.0); | 78 context.scale(-1.0, 1.0); |
79 context.drawImage(resizeCornerImage.get(), IntRect(IntPoint(), cornerRes
izerSize)); | 79 context.drawImage(resizeCornerImage.get(), IntRect(IntPoint(), cornerRes
izerSize)); |
80 context.restore(); | 80 context.restore(); |
81 return; | 81 return; |
82 } | 82 } |
83 IntRect imageRect(resizerCornerRect.maxXMaxYCorner() - cornerResizerSize, co
rnerResizerSize); | 83 IntRect imageRect(resizerCornerRect.maxXMaxYCorner() - cornerResizerSize, co
rnerResizerSize); |
84 context.drawImage(resizeCornerImage.get(), imageRect); | 84 context.drawImage(resizeCornerImage.get(), imageRect); |
85 } | 85 } |
86 | 86 |
87 void ScrollableAreaPainter::paintOverflowControls(GraphicsContext& context, cons
t IntPoint& paintOffset, const CullRect& cullRect, bool paintingOverlayControls) | 87 void ScrollableAreaPainter::paintOverflowControls(GraphicsContext& context, cons
t IntPoint& paintOffset, const CullRect& cullRect, bool paintingOverlayControls) |
88 { | 88 { |
89 // Don't do anything if we have no overflow. | 89 // Don't do anything if we have no overflow. |
90 if (!scrollableArea().box().hasOverflowClip()) | 90 if (!getScrollableArea().box().hasOverflowClip()) |
91 return; | 91 return; |
92 | 92 |
93 IntPoint adjustedPaintOffset = paintOffset; | 93 IntPoint adjustedPaintOffset = paintOffset; |
94 if (paintingOverlayControls) | 94 if (paintingOverlayControls) |
95 adjustedPaintOffset = scrollableArea().cachedOverlayScrollbarOffset(); | 95 adjustedPaintOffset = getScrollableArea().cachedOverlayScrollbarOffset()
; |
96 | 96 |
97 CullRect adjustedCullRect(cullRect, -adjustedPaintOffset); | 97 CullRect adjustedCullRect(cullRect, -adjustedPaintOffset); |
98 | 98 |
99 // Overlay scrollbars paint in a second pass through the layer tree so that
they will paint | 99 // Overlay scrollbars paint in a second pass through the layer tree so that
they will paint |
100 // on top of everything else. If this is the normal painting pass, paintingO
verlayControls | 100 // on top of everything else. If this is the normal painting pass, paintingO
verlayControls |
101 // will be false, and we should just tell the root layer that there are over
lay scrollbars | 101 // will be false, and we should just tell the root layer that there are over
lay scrollbars |
102 // that need to be painted. That will cause the second pass through the laye
r tree to run, | 102 // that need to be painted. That will cause the second pass through the laye
r tree to run, |
103 // and we'll paint the scrollbars then. In the meantime, cache tx and ty so
that the | 103 // and we'll paint the scrollbars then. In the meantime, cache tx and ty so
that the |
104 // second pass doesn't need to re-enter the LayoutTree to get it right. | 104 // second pass doesn't need to re-enter the LayoutTree to get it right. |
105 if (scrollableArea().hasOverlayScrollbars() && !paintingOverlayControls) { | 105 if (getScrollableArea().hasOverlayScrollbars() && !paintingOverlayControls)
{ |
106 scrollableArea().setCachedOverlayScrollbarOffset(paintOffset); | 106 getScrollableArea().setCachedOverlayScrollbarOffset(paintOffset); |
107 // It's not necessary to do the second pass if the scrollbars paint into
layers. | 107 // It's not necessary to do the second pass if the scrollbars paint into
layers. |
108 if ((scrollableArea().horizontalScrollbar() && scrollableArea().layerFor
HorizontalScrollbar()) || (scrollableArea().verticalScrollbar() && scrollableAre
a().layerForVerticalScrollbar())) | 108 if ((getScrollableArea().horizontalScrollbar() && getScrollableArea().la
yerForHorizontalScrollbar()) || (getScrollableArea().verticalScrollbar() && getS
crollableArea().layerForVerticalScrollbar())) |
109 return; | 109 return; |
110 if (!overflowControlsIntersectRect(adjustedCullRect)) | 110 if (!overflowControlsIntersectRect(adjustedCullRect)) |
111 return; | 111 return; |
112 | 112 |
113 LayoutView* layoutView = scrollableArea().box().view(); | 113 LayoutView* layoutView = getScrollableArea().box().view(); |
114 | 114 |
115 PaintLayer* paintingRoot = scrollableArea().layer()->enclosingLayerWithC
ompositedLayerMapping(IncludeSelf); | 115 PaintLayer* paintingRoot = getScrollableArea().layer()->enclosingLayerWi
thCompositedLayerMapping(IncludeSelf); |
116 if (!paintingRoot) | 116 if (!paintingRoot) |
117 paintingRoot = layoutView->layer(); | 117 paintingRoot = layoutView->layer(); |
118 | 118 |
119 paintingRoot->setContainsDirtyOverlayScrollbars(true); | 119 paintingRoot->setContainsDirtyOverlayScrollbars(true); |
120 return; | 120 return; |
121 } | 121 } |
122 | 122 |
123 // This check is required to avoid painting custom CSS scrollbars twice. | 123 // This check is required to avoid painting custom CSS scrollbars twice. |
124 if (paintingOverlayControls && !scrollableArea().hasOverlayScrollbars()) | 124 if (paintingOverlayControls && !getScrollableArea().hasOverlayScrollbars()) |
125 return; | 125 return; |
126 | 126 |
127 { | 127 { |
128 if (scrollableArea().horizontalScrollbar() && !scrollableArea().layerFor
HorizontalScrollbar()) { | 128 if (getScrollableArea().horizontalScrollbar() && !getScrollableArea().la
yerForHorizontalScrollbar()) { |
129 TransformRecorder translateRecorder(context, *scrollableArea().horiz
ontalScrollbar(), AffineTransform::translation(adjustedPaintOffset.x(), adjusted
PaintOffset.y())); | 129 TransformRecorder translateRecorder(context, *getScrollableArea().ho
rizontalScrollbar(), AffineTransform::translation(adjustedPaintOffset.x(), adjus
tedPaintOffset.y())); |
130 scrollableArea().horizontalScrollbar()->paint(context, adjustedCullR
ect); | 130 getScrollableArea().horizontalScrollbar()->paint(context, adjustedCu
llRect); |
131 } | 131 } |
132 if (scrollableArea().verticalScrollbar() && !scrollableArea().layerForVe
rticalScrollbar()) { | 132 if (getScrollableArea().verticalScrollbar() && !getScrollableArea().laye
rForVerticalScrollbar()) { |
133 TransformRecorder translateRecorder(context, *scrollableArea().verti
calScrollbar(), AffineTransform::translation(adjustedPaintOffset.x(), adjustedPa
intOffset.y())); | 133 TransformRecorder translateRecorder(context, *getScrollableArea().ve
rticalScrollbar(), AffineTransform::translation(adjustedPaintOffset.x(), adjuste
dPaintOffset.y())); |
134 scrollableArea().verticalScrollbar()->paint(context, adjustedCullRec
t); | 134 getScrollableArea().verticalScrollbar()->paint(context, adjustedCull
Rect); |
135 } | 135 } |
136 } | 136 } |
137 | 137 |
138 if (scrollableArea().layerForScrollCorner()) | 138 if (getScrollableArea().layerForScrollCorner()) |
139 return; | 139 return; |
140 | 140 |
141 // We fill our scroll corner with white if we have a scrollbar that doesn't
run all the way up to the | 141 // We fill our scroll corner with white if we have a scrollbar that doesn't
run all the way up to the |
142 // edge of the box. | 142 // edge of the box. |
143 paintScrollCorner(context, adjustedPaintOffset, cullRect); | 143 paintScrollCorner(context, adjustedPaintOffset, cullRect); |
144 | 144 |
145 // Paint our resizer last, since it sits on top of the scroll corner. | 145 // Paint our resizer last, since it sits on top of the scroll corner. |
146 paintResizer(context, adjustedPaintOffset, cullRect); | 146 paintResizer(context, adjustedPaintOffset, cullRect); |
147 } | 147 } |
148 | 148 |
149 bool ScrollableAreaPainter::overflowControlsIntersectRect(const CullRect& cullRe
ct) const | 149 bool ScrollableAreaPainter::overflowControlsIntersectRect(const CullRect& cullRe
ct) const |
150 { | 150 { |
151 const IntRect borderBox = scrollableArea().box().pixelSnappedBorderBoxRect()
; | 151 const IntRect borderBox = getScrollableArea().box().pixelSnappedBorderBoxRec
t(); |
152 | 152 |
153 if (cullRect.intersectsCullRect(scrollableArea().rectForHorizontalScrollbar(
borderBox))) | 153 if (cullRect.intersectsCullRect(getScrollableArea().rectForHorizontalScrollb
ar(borderBox))) |
154 return true; | 154 return true; |
155 | 155 |
156 if (cullRect.intersectsCullRect(scrollableArea().rectForVerticalScrollbar(bo
rderBox))) | 156 if (cullRect.intersectsCullRect(getScrollableArea().rectForVerticalScrollbar
(borderBox))) |
157 return true; | 157 return true; |
158 | 158 |
159 if (cullRect.intersectsCullRect(scrollableArea().scrollCornerRect())) | 159 if (cullRect.intersectsCullRect(getScrollableArea().scrollCornerRect())) |
160 return true; | 160 return true; |
161 | 161 |
162 if (cullRect.intersectsCullRect(scrollableArea().resizerCornerRect(borderBox
, ResizerForPointer))) | 162 if (cullRect.intersectsCullRect(getScrollableArea().resizerCornerRect(border
Box, ResizerForPointer))) |
163 return true; | 163 return true; |
164 | 164 |
165 return false; | 165 return false; |
166 } | 166 } |
167 | 167 |
168 void ScrollableAreaPainter::paintScrollCorner(GraphicsContext& context, const In
tPoint& paintOffset, const CullRect& adjustedCullRect) | 168 void ScrollableAreaPainter::paintScrollCorner(GraphicsContext& context, const In
tPoint& paintOffset, const CullRect& adjustedCullRect) |
169 { | 169 { |
170 IntRect absRect = scrollableArea().scrollCornerRect(); | 170 IntRect absRect = getScrollableArea().scrollCornerRect(); |
171 if (absRect.isEmpty()) | 171 if (absRect.isEmpty()) |
172 return; | 172 return; |
173 absRect.moveBy(paintOffset); | 173 absRect.moveBy(paintOffset); |
174 | 174 |
175 if (scrollableArea().scrollCorner()) { | 175 if (getScrollableArea().scrollCorner()) { |
176 if (!adjustedCullRect.intersectsCullRect(absRect)) | 176 if (!adjustedCullRect.intersectsCullRect(absRect)) |
177 return; | 177 return; |
178 ScrollbarPainter::paintIntoRect(*scrollableArea().scrollCorner(), contex
t, paintOffset, LayoutRect(absRect)); | 178 ScrollbarPainter::paintIntoRect(*getScrollableArea().scrollCorner(), con
text, paintOffset, LayoutRect(absRect)); |
179 return; | 179 return; |
180 } | 180 } |
181 | 181 |
182 // We don't want to paint white if we have overlay scrollbars, since we need | 182 // We don't want to paint white if we have overlay scrollbars, since we need |
183 // to see what is behind it. | 183 // to see what is behind it. |
184 if (scrollableArea().hasOverlayScrollbars()) | 184 if (getScrollableArea().hasOverlayScrollbars()) |
185 return; | 185 return; |
186 | 186 |
187 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, scrolla
bleArea().box(), DisplayItem::ScrollbarCorner)) | 187 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, getScro
llableArea().box(), DisplayItem::ScrollbarCorner)) |
188 return; | 188 return; |
189 | 189 |
190 LayoutObjectDrawingRecorder recorder(context, scrollableArea().box(), Displa
yItem::ScrollbarCorner, absRect); | 190 LayoutObjectDrawingRecorder recorder(context, getScrollableArea().box(), Dis
playItem::ScrollbarCorner, absRect); |
191 context.fillRect(absRect, Color::white); | 191 context.fillRect(absRect, Color::white); |
192 } | 192 } |
193 | 193 |
194 PaintLayerScrollableArea& ScrollableAreaPainter::scrollableArea() const | 194 PaintLayerScrollableArea& ScrollableAreaPainter::getScrollableArea() const |
195 { | 195 { |
196 return *m_scrollableArea; | 196 return *m_scrollableArea; |
197 } | 197 } |
198 | 198 |
199 } // namespace blink | 199 } // namespace blink |
OLD | NEW |