| 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 |