| Index: Source/core/paint/ScrollableAreaPainter.cpp
|
| diff --git a/Source/core/paint/ScrollableAreaPainter.cpp b/Source/core/paint/ScrollableAreaPainter.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..525a5215155b1d60086069f9062a5eb58a62c7ca
|
| --- /dev/null
|
| +++ b/Source/core/paint/ScrollableAreaPainter.cpp
|
| @@ -0,0 +1,181 @@
|
| +// 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/ScrollableAreaPainter.h"
|
| +
|
| +#include "core/page/Page.h"
|
| +#include "core/paint/ScrollbarPainter.h"
|
| +#include "core/rendering/PaintInfo.h"
|
| +#include "core/rendering/RenderLayer.h"
|
| +#include "core/rendering/RenderLayerScrollableArea.h"
|
| +#include "core/rendering/RenderView.h"
|
| +#include "platform/graphics/GraphicsContext.h"
|
| +#include "platform/graphics/GraphicsContextStateSaver.h"
|
| +
|
| +namespace blink {
|
| +
|
| +void ScrollableAreaPainter::paintResizer(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect)
|
| +{
|
| + if (m_renderLayerScrollableArea.box().style()->resize() == RESIZE_NONE)
|
| + return;
|
| +
|
| + IntRect absRect = m_renderLayerScrollableArea.resizerCornerRect(m_renderLayerScrollableArea.box().pixelSnappedBorderBoxRect(), ResizerForPointer);
|
| + absRect.moveBy(paintOffset);
|
| + if (!absRect.intersects(damageRect))
|
| + return;
|
| +
|
| + if (m_renderLayerScrollableArea.resizer()) {
|
| + ScrollbarPainter::paintIntoRect(m_renderLayerScrollableArea.resizer(), context, paintOffset, absRect);
|
| + return;
|
| + }
|
| +
|
| + drawPlatformResizerImage(context, absRect);
|
| +
|
| + // Draw a frame around the resizer (1px grey line) if there are any scrollbars present.
|
| + // Clipping will exclude the right and bottom edges of this frame.
|
| + if (!m_renderLayerScrollableArea.hasOverlayScrollbars() && m_renderLayerScrollableArea.hasScrollbar()) {
|
| + GraphicsContextStateSaver stateSaver(*context);
|
| + context->clip(absRect);
|
| + IntRect largerCorner = absRect;
|
| + largerCorner.setSize(IntSize(largerCorner.width() + 1, largerCorner.height() + 1));
|
| + context->setStrokeColor(Color(217, 217, 217));
|
| + context->setStrokeThickness(1.0f);
|
| + context->setFillColor(Color::transparent);
|
| + context->drawRect(largerCorner);
|
| + }
|
| +}
|
| +
|
| +void ScrollableAreaPainter::drawPlatformResizerImage(GraphicsContext* context, IntRect resizerCornerRect)
|
| +{
|
| + float deviceScaleFactor = blink::deviceScaleFactor(m_renderLayerScrollableArea.box().frame());
|
| +
|
| + RefPtr<Image> resizeCornerImage;
|
| + IntSize cornerResizerSize;
|
| + if (deviceScaleFactor >= 2) {
|
| + DEFINE_STATIC_REF(Image, resizeCornerImageHiRes, (Image::loadPlatformResource("textAreaResizeCorner@2x")));
|
| + resizeCornerImage = resizeCornerImageHiRes;
|
| + cornerResizerSize = resizeCornerImage->size();
|
| + cornerResizerSize.scale(0.5f);
|
| + } else {
|
| + DEFINE_STATIC_REF(Image, resizeCornerImageLoRes, (Image::loadPlatformResource("textAreaResizeCorner")));
|
| + resizeCornerImage = resizeCornerImageLoRes;
|
| + cornerResizerSize = resizeCornerImage->size();
|
| + }
|
| +
|
| + if (m_renderLayerScrollableArea.box().style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) {
|
| + context->save();
|
| + context->translate(resizerCornerRect.x() + cornerResizerSize.width(), resizerCornerRect.y() + resizerCornerRect.height() - cornerResizerSize.height());
|
| + context->scale(-1.0, 1.0);
|
| + context->drawImage(resizeCornerImage.get(), IntRect(IntPoint(), cornerResizerSize));
|
| + context->restore();
|
| + return;
|
| + }
|
| + IntRect imageRect(resizerCornerRect.maxXMaxYCorner() - cornerResizerSize, cornerResizerSize);
|
| + context->drawImage(resizeCornerImage.get(), imageRect);
|
| +}
|
| +
|
| +void ScrollableAreaPainter::paintOverflowControls(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect, bool paintingOverlayControls)
|
| +{
|
| + // Don't do anything if we have no overflow.
|
| + if (!m_renderLayerScrollableArea.box().hasOverflowClip())
|
| + return;
|
| +
|
| + IntPoint adjustedPaintOffset = paintOffset;
|
| + if (paintingOverlayControls)
|
| + adjustedPaintOffset = m_renderLayerScrollableArea.cachedOverlayScrollbarOffset();
|
| +
|
| + // Move the scrollbar widgets if necessary. We normally move and resize widgets during layout,
|
| + // but sometimes widgets can move without layout occurring (most notably when you scroll a
|
| + // document that contains fixed positioned elements).
|
| +
|
| + // FIXME: this code should not be necessary.
|
| + m_renderLayerScrollableArea.positionOverflowControls(toIntSize(adjustedPaintOffset));
|
| +
|
| + // Overlay scrollbars paint in a second pass through the layer tree so that they will paint
|
| + // on top of everything else. If this is the normal painting pass, paintingOverlayControls
|
| + // will be false, and we should just tell the root layer that there are overlay scrollbars
|
| + // that need to be painted. That will cause the second pass through the layer tree to run,
|
| + // and we'll paint the scrollbars then. In the meantime, cache tx and ty so that the
|
| + // second pass doesn't need to re-enter the RenderTree to get it right.
|
| + if (m_renderLayerScrollableArea.hasOverlayScrollbars() && !paintingOverlayControls) {
|
| + m_renderLayerScrollableArea.setCachedOverlayScrollbarOffset(paintOffset);
|
| + // It's not necessary to do the second pass if the scrollbars paint into layers.
|
| + if ((m_renderLayerScrollableArea.horizontalScrollbar() && m_renderLayerScrollableArea.layerForHorizontalScrollbar()) || (m_renderLayerScrollableArea.verticalScrollbar() && m_renderLayerScrollableArea.layerForVerticalScrollbar()))
|
| + return;
|
| + IntRect localDamgeRect = damageRect;
|
| + localDamgeRect.moveBy(-paintOffset);
|
| + if (!overflowControlsIntersectRect(localDamgeRect))
|
| + return;
|
| +
|
| + RenderView* renderView = m_renderLayerScrollableArea.box().view();
|
| +
|
| + RenderLayer* paintingRoot = m_renderLayerScrollableArea.layer()->enclosingLayerWithCompositedLayerMapping(IncludeSelf);
|
| + if (!paintingRoot)
|
| + paintingRoot = renderView->layer();
|
| +
|
| + paintingRoot->setContainsDirtyOverlayScrollbars(true);
|
| + return;
|
| + }
|
| +
|
| + // This check is required to avoid painting custom CSS scrollbars twice.
|
| + if (paintingOverlayControls && !m_renderLayerScrollableArea.hasOverlayScrollbars())
|
| + return;
|
| +
|
| + // Now that we're sure the scrollbars are in the right place, paint them.
|
| + if (m_renderLayerScrollableArea.horizontalScrollbar() && !m_renderLayerScrollableArea.layerForHorizontalScrollbar())
|
| + m_renderLayerScrollableArea.horizontalScrollbar()->paint(context, damageRect);
|
| + if (m_renderLayerScrollableArea.verticalScrollbar() && !m_renderLayerScrollableArea.layerForVerticalScrollbar())
|
| + m_renderLayerScrollableArea.verticalScrollbar()->paint(context, damageRect);
|
| +
|
| + if (m_renderLayerScrollableArea.layerForScrollCorner())
|
| + return;
|
| +
|
| + // We fill our scroll corner with white if we have a scrollbar that doesn't run all the way up to the
|
| + // edge of the box.
|
| + paintScrollCorner(context, adjustedPaintOffset, damageRect);
|
| +
|
| + // Paint our resizer last, since it sits on top of the scroll corner.
|
| + paintResizer(context, adjustedPaintOffset, damageRect);
|
| +}
|
| +
|
| +bool ScrollableAreaPainter::overflowControlsIntersectRect(const IntRect& localRect) const
|
| +{
|
| + const IntRect borderBox = m_renderLayerScrollableArea.box().pixelSnappedBorderBoxRect();
|
| +
|
| + if (m_renderLayerScrollableArea.rectForHorizontalScrollbar(borderBox).intersects(localRect))
|
| + return true;
|
| +
|
| + if (m_renderLayerScrollableArea.rectForVerticalScrollbar(borderBox).intersects(localRect))
|
| + return true;
|
| +
|
| + if (m_renderLayerScrollableArea.scrollCornerRect().intersects(localRect))
|
| + return true;
|
| +
|
| + if (m_renderLayerScrollableArea.resizerCornerRect(borderBox, ResizerForPointer).intersects(localRect))
|
| + return true;
|
| +
|
| + return false;
|
| +}
|
| +
|
| +
|
| +void ScrollableAreaPainter::paintScrollCorner(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect)
|
| +{
|
| + IntRect absRect = m_renderLayerScrollableArea.scrollCornerRect();
|
| + absRect.moveBy(paintOffset);
|
| + if (!absRect.intersects(damageRect))
|
| + return;
|
| +
|
| + if (m_renderLayerScrollableArea.scrollCorner()) {
|
| + ScrollbarPainter::paintIntoRect(m_renderLayerScrollableArea.scrollCorner(), context, paintOffset, absRect);
|
| + return;
|
| + }
|
| +
|
| + // We don't want to paint white if we have overlay scrollbars, since we need
|
| + // to see what is behind it.
|
| + if (!m_renderLayerScrollableArea.hasOverlayScrollbars())
|
| + context->fillRect(absRect, Color::white);
|
| +}
|
| +
|
| +} // namespace blink
|
|
|