3a52b2b1d2b2e5c95cb3622a8ffbed2950ea6888
[WebKit-https.git] / Source / WebCore / rendering / RenderScrollbarPart.cpp
1 /*
2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "RenderScrollbarPart.h"
28
29 #include "PaintInfo.h"
30 #include "RenderScrollbar.h"
31 #include "RenderScrollbarTheme.h"
32 #include "RenderView.h"
33 #include <wtf/IsoMallocInlines.h>
34 #include <wtf/StackStats.h>
35
36 namespace WebCore {
37
38 WTF_MAKE_ISO_ALLOCATED_IMPL(RenderScrollbarPart);
39
40 RenderScrollbarPart::RenderScrollbarPart(Document& document, RenderStyle&& style, RenderScrollbar* scrollbar, ScrollbarPart part)
41     : RenderBlock(document, WTFMove(style), 0)
42     , m_scrollbar(scrollbar)
43     , m_part(part)
44 {
45 }
46
47 RenderScrollbarPart::~RenderScrollbarPart() = default;
48
49 void RenderScrollbarPart::layout()
50 {
51     StackStats::LayoutCheckPoint layoutCheckPoint;
52     setLocation(LayoutPoint()); // We don't worry about positioning ourselves. We're just determining our minimum width/height.
53     if (m_scrollbar->orientation() == HorizontalScrollbar)
54         layoutHorizontalPart();
55     else
56         layoutVerticalPart();
57
58     clearNeedsLayout();
59 }
60
61 void RenderScrollbarPart::layoutHorizontalPart()
62 {
63     if (m_part == ScrollbarBGPart) {
64         setWidth(m_scrollbar->width());
65         computeScrollbarHeight();
66     } else {
67         computeScrollbarWidth();
68         setHeight(m_scrollbar->height());
69     }
70 }
71
72 void RenderScrollbarPart::layoutVerticalPart()
73 {
74     if (m_part == ScrollbarBGPart) {
75         computeScrollbarWidth();
76         setHeight(m_scrollbar->height());
77     } else {
78         setWidth(m_scrollbar->width());
79         computeScrollbarHeight();
80     } 
81 }
82
83 static int calcScrollbarThicknessUsing(SizeType sizeType, const Length& length, int containingLength)
84 {
85     if (!length.isIntrinsicOrAuto() || (sizeType == MinSize && length.isAuto()))
86         return minimumValueForLength(length, containingLength);
87     return ScrollbarTheme::theme().scrollbarThickness();
88 }
89
90 void RenderScrollbarPart::computeScrollbarWidth()
91 {
92     if (!m_scrollbar->owningRenderer())
93         return;
94     // FIXME: We are querying layout information but nothing guarantees that it's up-to-date, especially since we are called at style change.
95     // FIXME: Querying the style's border information doesn't work on table cells with collapsing borders.
96     int visibleSize = m_scrollbar->owningRenderer()->width() - m_scrollbar->owningRenderer()->style().borderLeftWidth() - m_scrollbar->owningRenderer()->style().borderRightWidth();
97     int w = calcScrollbarThicknessUsing(MainOrPreferredSize, style().width(), visibleSize);
98     int minWidth = calcScrollbarThicknessUsing(MinSize, style().minWidth(), visibleSize);
99     int maxWidth = style().maxWidth().isUndefined() ? w : calcScrollbarThicknessUsing(MaxSize, style().maxWidth(), visibleSize);
100     setWidth(std::max(minWidth, std::min(maxWidth, w)));
101     
102     // Buttons and track pieces can all have margins along the axis of the scrollbar. 
103     m_marginBox.setLeft(minimumValueForLength(style().marginLeft(), visibleSize));
104     m_marginBox.setRight(minimumValueForLength(style().marginRight(), visibleSize));
105 }
106
107 void RenderScrollbarPart::computeScrollbarHeight()
108 {
109     if (!m_scrollbar->owningRenderer())
110         return;
111     // FIXME: We are querying layout information but nothing guarantees that it's up-to-date, especially since we are called at style change.
112     // FIXME: Querying the style's border information doesn't work on table cells with collapsing borders.
113     int visibleSize = m_scrollbar->owningRenderer()->height() -  m_scrollbar->owningRenderer()->style().borderTopWidth() - m_scrollbar->owningRenderer()->style().borderBottomWidth();
114     int h = calcScrollbarThicknessUsing(MainOrPreferredSize, style().height(), visibleSize);
115     int minHeight = calcScrollbarThicknessUsing(MinSize, style().minHeight(), visibleSize);
116     int maxHeight = style().maxHeight().isUndefined() ? h : calcScrollbarThicknessUsing(MaxSize, style().maxHeight(), visibleSize);
117     setHeight(std::max(minHeight, std::min(maxHeight, h)));
118
119     // Buttons and track pieces can all have margins along the axis of the scrollbar. 
120     m_marginBox.setTop(minimumValueForLength(style().marginTop(), visibleSize));
121     m_marginBox.setBottom(minimumValueForLength(style().marginBottom(), visibleSize));
122 }
123
124 void RenderScrollbarPart::computePreferredLogicalWidths()
125 {
126     if (!preferredLogicalWidthsDirty())
127         return;
128     
129     m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0;
130
131     setPreferredLogicalWidthsDirty(false);
132 }
133
134 void RenderScrollbarPart::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
135 {
136     RenderBlock::styleDidChange(diff, oldStyle);
137     setInline(false);
138     clearPositionedState();
139     setFloating(false);
140     setHasOverflowClip(false);
141     if (oldStyle && m_scrollbar && m_part != NoPart && diff >= StyleDifference::Repaint)
142         m_scrollbar->theme().invalidatePart(*m_scrollbar, m_part);
143 }
144
145 void RenderScrollbarPart::imageChanged(WrappedImagePtr image, const IntRect* rect)
146 {
147     if (m_scrollbar && m_part != NoPart)
148         m_scrollbar->theme().invalidatePart(*m_scrollbar, m_part);
149     else {
150         if (view().frameView().isFrameViewScrollCorner(*this)) {
151             view().frameView().invalidateScrollCorner(view().frameView().scrollCornerRect());
152             return;
153         }
154         
155         RenderBlock::imageChanged(image, rect);
156     }
157 }
158
159 void RenderScrollbarPart::paintIntoRect(GraphicsContext& graphicsContext, const LayoutPoint& paintOffset, const LayoutRect& rect)
160 {
161     // Make sure our dimensions match the rect.
162     setLocation(rect.location() - toLayoutSize(paintOffset));
163     setWidth(rect.width());
164     setHeight(rect.height());
165
166     if (graphicsContext.paintingDisabled() || !style().opacity())
167         return;
168
169     // We don't use RenderLayers for scrollbar parts, so we need to handle opacity here.
170     // Opacity for ScrollbarBGPart is handled by RenderScrollbarTheme::willPaintScrollbar().
171     bool needsTransparencyLayer = m_part != ScrollbarBGPart && style().opacity() < 1;
172     if (needsTransparencyLayer) {
173         graphicsContext.save();
174         graphicsContext.clip(rect);
175         graphicsContext.beginTransparencyLayer(style().opacity());
176     }
177     
178     // Now do the paint.
179     PaintInfo paintInfo(graphicsContext, snappedIntRect(rect), PaintPhaseBlockBackground, PaintBehaviorNormal);
180     paint(paintInfo, paintOffset);
181     paintInfo.phase = PaintPhaseChildBlockBackgrounds;
182     paint(paintInfo, paintOffset);
183     paintInfo.phase = PaintPhaseFloat;
184     paint(paintInfo, paintOffset);
185     paintInfo.phase = PaintPhaseForeground;
186     paint(paintInfo, paintOffset);
187     paintInfo.phase = PaintPhaseOutline;
188     paint(paintInfo, paintOffset);
189
190     if (needsTransparencyLayer) {
191         graphicsContext.endTransparencyLayer();
192         graphicsContext.restore();
193     }
194 }
195
196 RenderBox* RenderScrollbarPart::rendererOwningScrollbar() const
197 {
198     if (!m_scrollbar)
199         return nullptr;
200     return m_scrollbar->owningRenderer();
201 }
202
203 }