OLD | NEW |
(Empty) | |
| 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/ScrollableAreaPainter.h" |
| 7 |
| 8 #include "core/page/Page.h" |
| 9 #include "core/paint/ScrollbarPainter.h" |
| 10 #include "core/rendering/PaintInfo.h" |
| 11 #include "core/rendering/RenderLayer.h" |
| 12 #include "core/rendering/RenderLayerScrollableArea.h" |
| 13 #include "core/rendering/RenderView.h" |
| 14 #include "platform/graphics/GraphicsContext.h" |
| 15 #include "platform/graphics/GraphicsContextStateSaver.h" |
| 16 |
| 17 namespace blink { |
| 18 |
| 19 void ScrollableAreaPainter::paintResizer(GraphicsContext* context, const IntPoin
t& paintOffset, const IntRect& damageRect) |
| 20 { |
| 21 if (m_renderLayerScrollableArea.box().style()->resize() == RESIZE_NONE) |
| 22 return; |
| 23 |
| 24 IntRect absRect = m_renderLayerScrollableArea.resizerCornerRect(m_renderLaye
rScrollableArea.box().pixelSnappedBorderBoxRect(), ResizerForPointer); |
| 25 absRect.moveBy(paintOffset); |
| 26 if (!absRect.intersects(damageRect)) |
| 27 return; |
| 28 |
| 29 if (m_renderLayerScrollableArea.resizer()) { |
| 30 ScrollbarPainter::paintIntoRect(m_renderLayerScrollableArea.resizer(), c
ontext, paintOffset, absRect); |
| 31 return; |
| 32 } |
| 33 |
| 34 drawPlatformResizerImage(context, absRect); |
| 35 |
| 36 // Draw a frame around the resizer (1px grey line) if there are any scrollba
rs present. |
| 37 // Clipping will exclude the right and bottom edges of this frame. |
| 38 if (!m_renderLayerScrollableArea.hasOverlayScrollbars() && m_renderLayerScro
llableArea.hasScrollbar()) { |
| 39 GraphicsContextStateSaver stateSaver(*context); |
| 40 context->clip(absRect); |
| 41 IntRect largerCorner = absRect; |
| 42 largerCorner.setSize(IntSize(largerCorner.width() + 1, largerCorner.heig
ht() + 1)); |
| 43 context->setStrokeColor(Color(217, 217, 217)); |
| 44 context->setStrokeThickness(1.0f); |
| 45 context->setFillColor(Color::transparent); |
| 46 context->drawRect(largerCorner); |
| 47 } |
| 48 } |
| 49 |
| 50 void ScrollableAreaPainter::drawPlatformResizerImage(GraphicsContext* context, I
ntRect resizerCornerRect) |
| 51 { |
| 52 float deviceScaleFactor = blink::deviceScaleFactor(m_renderLayerScrollableAr
ea.box().frame()); |
| 53 |
| 54 RefPtr<Image> resizeCornerImage; |
| 55 IntSize cornerResizerSize; |
| 56 if (deviceScaleFactor >= 2) { |
| 57 DEFINE_STATIC_REF(Image, resizeCornerImageHiRes, (Image::loadPlatformRes
ource("textAreaResizeCorner@2x"))); |
| 58 resizeCornerImage = resizeCornerImageHiRes; |
| 59 cornerResizerSize = resizeCornerImage->size(); |
| 60 cornerResizerSize.scale(0.5f); |
| 61 } else { |
| 62 DEFINE_STATIC_REF(Image, resizeCornerImageLoRes, (Image::loadPlatformRes
ource("textAreaResizeCorner"))); |
| 63 resizeCornerImage = resizeCornerImageLoRes; |
| 64 cornerResizerSize = resizeCornerImage->size(); |
| 65 } |
| 66 |
| 67 if (m_renderLayerScrollableArea.box().style()->shouldPlaceBlockDirectionScro
llbarOnLogicalLeft()) { |
| 68 context->save(); |
| 69 context->translate(resizerCornerRect.x() + cornerResizerSize.width(), re
sizerCornerRect.y() + resizerCornerRect.height() - cornerResizerSize.height()); |
| 70 context->scale(-1.0, 1.0); |
| 71 context->drawImage(resizeCornerImage.get(), IntRect(IntPoint(), cornerRe
sizerSize)); |
| 72 context->restore(); |
| 73 return; |
| 74 } |
| 75 IntRect imageRect(resizerCornerRect.maxXMaxYCorner() - cornerResizerSize, co
rnerResizerSize); |
| 76 context->drawImage(resizeCornerImage.get(), imageRect); |
| 77 } |
| 78 |
| 79 void ScrollableAreaPainter::paintOverflowControls(GraphicsContext* context, cons
t IntPoint& paintOffset, const IntRect& damageRect, bool paintingOverlayControls
) |
| 80 { |
| 81 // Don't do anything if we have no overflow. |
| 82 if (!m_renderLayerScrollableArea.box().hasOverflowClip()) |
| 83 return; |
| 84 |
| 85 IntPoint adjustedPaintOffset = paintOffset; |
| 86 if (paintingOverlayControls) |
| 87 adjustedPaintOffset = m_renderLayerScrollableArea.cachedOverlayScrollbar
Offset(); |
| 88 |
| 89 // Move the scrollbar widgets if necessary. We normally move and resize widg
ets during layout, |
| 90 // but sometimes widgets can move without layout occurring (most notably whe
n you scroll a |
| 91 // document that contains fixed positioned elements). |
| 92 |
| 93 // FIXME: this code should not be necessary. |
| 94 m_renderLayerScrollableArea.positionOverflowControls(toIntSize(adjustedPaint
Offset)); |
| 95 |
| 96 // Overlay scrollbars paint in a second pass through the layer tree so that
they will paint |
| 97 // on top of everything else. If this is the normal painting pass, paintingO
verlayControls |
| 98 // will be false, and we should just tell the root layer that there are over
lay scrollbars |
| 99 // that need to be painted. That will cause the second pass through the laye
r tree to run, |
| 100 // and we'll paint the scrollbars then. In the meantime, cache tx and ty so
that the |
| 101 // second pass doesn't need to re-enter the RenderTree to get it right. |
| 102 if (m_renderLayerScrollableArea.hasOverlayScrollbars() && !paintingOverlayCo
ntrols) { |
| 103 m_renderLayerScrollableArea.setCachedOverlayScrollbarOffset(paintOffset)
; |
| 104 // It's not necessary to do the second pass if the scrollbars paint into
layers. |
| 105 if ((m_renderLayerScrollableArea.horizontalScrollbar() && m_renderLayerS
crollableArea.layerForHorizontalScrollbar()) || (m_renderLayerScrollableArea.ver
ticalScrollbar() && m_renderLayerScrollableArea.layerForVerticalScrollbar())) |
| 106 return; |
| 107 IntRect localDamgeRect = damageRect; |
| 108 localDamgeRect.moveBy(-paintOffset); |
| 109 if (!overflowControlsIntersectRect(localDamgeRect)) |
| 110 return; |
| 111 |
| 112 RenderView* renderView = m_renderLayerScrollableArea.box().view(); |
| 113 |
| 114 RenderLayer* paintingRoot = m_renderLayerScrollableArea.layer()->enclosi
ngLayerWithCompositedLayerMapping(IncludeSelf); |
| 115 if (!paintingRoot) |
| 116 paintingRoot = renderView->layer(); |
| 117 |
| 118 paintingRoot->setContainsDirtyOverlayScrollbars(true); |
| 119 return; |
| 120 } |
| 121 |
| 122 // This check is required to avoid painting custom CSS scrollbars twice. |
| 123 if (paintingOverlayControls && !m_renderLayerScrollableArea.hasOverlayScroll
bars()) |
| 124 return; |
| 125 |
| 126 // Now that we're sure the scrollbars are in the right place, paint them. |
| 127 if (m_renderLayerScrollableArea.horizontalScrollbar() && !m_renderLayerScrol
lableArea.layerForHorizontalScrollbar()) |
| 128 m_renderLayerScrollableArea.horizontalScrollbar()->paint(context, damage
Rect); |
| 129 if (m_renderLayerScrollableArea.verticalScrollbar() && !m_renderLayerScrolla
bleArea.layerForVerticalScrollbar()) |
| 130 m_renderLayerScrollableArea.verticalScrollbar()->paint(context, damageRe
ct); |
| 131 |
| 132 if (m_renderLayerScrollableArea.layerForScrollCorner()) |
| 133 return; |
| 134 |
| 135 // We fill our scroll corner with white if we have a scrollbar that doesn't
run all the way up to the |
| 136 // edge of the box. |
| 137 paintScrollCorner(context, adjustedPaintOffset, damageRect); |
| 138 |
| 139 // Paint our resizer last, since it sits on top of the scroll corner. |
| 140 paintResizer(context, adjustedPaintOffset, damageRect); |
| 141 } |
| 142 |
| 143 bool ScrollableAreaPainter::overflowControlsIntersectRect(const IntRect& localRe
ct) const |
| 144 { |
| 145 const IntRect borderBox = m_renderLayerScrollableArea.box().pixelSnappedBord
erBoxRect(); |
| 146 |
| 147 if (m_renderLayerScrollableArea.rectForHorizontalScrollbar(borderBox).inters
ects(localRect)) |
| 148 return true; |
| 149 |
| 150 if (m_renderLayerScrollableArea.rectForVerticalScrollbar(borderBox).intersec
ts(localRect)) |
| 151 return true; |
| 152 |
| 153 if (m_renderLayerScrollableArea.scrollCornerRect().intersects(localRect)) |
| 154 return true; |
| 155 |
| 156 if (m_renderLayerScrollableArea.resizerCornerRect(borderBox, ResizerForPoint
er).intersects(localRect)) |
| 157 return true; |
| 158 |
| 159 return false; |
| 160 } |
| 161 |
| 162 |
| 163 void ScrollableAreaPainter::paintScrollCorner(GraphicsContext* context, const In
tPoint& paintOffset, const IntRect& damageRect) |
| 164 { |
| 165 IntRect absRect = m_renderLayerScrollableArea.scrollCornerRect(); |
| 166 absRect.moveBy(paintOffset); |
| 167 if (!absRect.intersects(damageRect)) |
| 168 return; |
| 169 |
| 170 if (m_renderLayerScrollableArea.scrollCorner()) { |
| 171 ScrollbarPainter::paintIntoRect(m_renderLayerScrollableArea.scrollCorner
(), context, paintOffset, absRect); |
| 172 return; |
| 173 } |
| 174 |
| 175 // We don't want to paint white if we have overlay scrollbars, since we need |
| 176 // to see what is behind it. |
| 177 if (!m_renderLayerScrollableArea.hasOverlayScrollbars()) |
| 178 context->fillRect(absRect, Color::white); |
| 179 } |
| 180 |
| 181 } // namespace blink |
OLD | NEW |