Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(466)

Side by Side Diff: Source/core/platform/ScrollbarThemeMacCommon.mm

Issue 99103006: Moving GraphicsContext and dependencies from core to platform. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Final patch - fixes Android Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2008, 2011 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 "core/platform/ScrollbarThemeMacCommon.h"
28
29 #include <Carbon/Carbon.h>
30 #include "core/platform/ScrollbarThemeMacNonOverlayAPI.h"
31 #include "core/platform/ScrollbarThemeMacOverlayAPI.h"
32 #include "core/platform/graphics/Gradient.h"
33 #include "core/platform/graphics/GraphicsContext.h"
34 #include "core/platform/graphics/GraphicsContextStateSaver.h"
35 #include "core/platform/graphics/GraphicsLayer.h"
36 #include "core/platform/graphics/ImageBuffer.h"
37 #include "core/platform/graphics/mac/ColorMac.h"
38 #include "core/platform/mac/LocalCurrentGraphicsContext.h"
39 #include "core/platform/mac/NSScrollerImpDetails.h"
40 #include "core/platform/mac/ScrollAnimatorMac.h"
41 #include "platform/PlatformMouseEvent.h"
42 #include "platform/scroll/ScrollbarThemeClient.h"
43 #include "public/platform/mac/WebThemeEngine.h"
44 #include "public/platform/Platform.h"
45 #include "public/platform/WebRect.h"
46 #include "skia/ext/skia_utils_mac.h"
47 #include "wtf/HashSet.h"
48 #include "wtf/StdLibExtras.h"
49 #include "wtf/TemporaryChange.h"
50 #include "wtf/UnusedParam.h"
51
52 // FIXME: There are repainting problems due to Aqua scroll bar buttons' visual o verflow.
53
54 using namespace std;
55 using namespace WebCore;
56
57 @interface NSColor (WebNSColorDetails)
58 + (NSImage *)_linenPatternImage;
59 @end
60
61 namespace WebCore {
62
63 typedef HashSet<ScrollbarThemeClient*> ScrollbarSet;
64
65 static ScrollbarSet& scrollbarSet()
66 {
67 DEFINE_STATIC_LOCAL(ScrollbarSet, set, ());
68 return set;
69 }
70
71 }
72
73 namespace WebCore {
74
75 static float gInitialButtonDelay = 0.5f;
76 static float gAutoscrollButtonDelay = 0.05f;
77 static bool gJumpOnTrackClick = false;
78
79 ScrollbarTheme* ScrollbarTheme::nativeTheme()
80 {
81 static ScrollbarThemeMacCommon* theme = NULL;
82 if (theme)
83 return theme;
84 if (isScrollbarOverlayAPIAvailable()) {
85 DEFINE_STATIC_LOCAL(ScrollbarThemeMacOverlayAPI, overlayTheme, ());
86 theme = &overlayTheme;
87 } else {
88 DEFINE_STATIC_LOCAL(ScrollbarThemeMacNonOverlayAPI, nonOverlayTheme, ()) ;
89 theme = &nonOverlayTheme;
90 }
91 return theme;
92 }
93
94 void ScrollbarThemeMacCommon::registerScrollbar(ScrollbarThemeClient* scrollbar)
95 {
96 scrollbarSet().add(scrollbar);
97 }
98
99 void ScrollbarThemeMacCommon::unregisterScrollbar(ScrollbarThemeClient* scrollba r)
100 {
101 scrollbarSet().remove(scrollbar);
102 }
103
104 void ScrollbarThemeMacCommon::paintGivenTickmarks(GraphicsContext* context, Scro llbarThemeClient* scrollbar, const IntRect& rect, const Vector<IntRect>& tickmar ks)
105 {
106 if (scrollbar->orientation() != VerticalScrollbar)
107 return;
108
109 if (rect.height() <= 0 || rect.width() <= 0)
110 return; // nothing to draw on.
111
112 if (!tickmarks.size())
113 return;
114
115 GraphicsContextStateSaver stateSaver(*context);
116 context->setShouldAntialias(false);
117 context->setStrokeColor(Color(0xCC, 0xAA, 0x00, 0xFF));
118 context->setFillColor(Color(0xFF, 0xDD, 0x00, 0xFF));
119
120 for (Vector<IntRect>::const_iterator i = tickmarks.begin(); i != tickmarks.e nd(); ++i) {
121 // Calculate how far down (in %) the tick-mark should appear.
122 const float percent = static_cast<float>(i->y()) / scrollbar->totalSize( );
123 if (percent < 0.0 || percent > 1.0)
124 continue;
125
126 // Calculate how far down (in pixels) the tick-mark should appear.
127 const int yPos = rect.y() + (rect.height() * percent);
128
129 // Paint.
130 FloatRect tickRect(rect.x(), yPos, rect.width(), 2);
131 context->fillRect(tickRect);
132 context->strokeRect(tickRect, 1);
133 }
134 }
135
136 void ScrollbarThemeMacCommon::paintOverhangBackground(GraphicsContext* context, const IntRect& horizontalOverhangRect, const IntRect& verticalOverhangRect, cons t IntRect& dirtyRect)
137 {
138 const bool hasHorizontalOverhang = !horizontalOverhangRect.isEmpty();
139 const bool hasVerticalOverhang = !verticalOverhangRect.isEmpty();
140
141 GraphicsContextStateSaver stateSaver(*context);
142
143 if (!m_overhangPattern) {
144 // Lazily load the linen pattern image used for overhang drawing.
145 RefPtr<Image> patternImage = Image::loadPlatformResource("overhangPatter n");
146 m_overhangPattern = Pattern::create(patternImage, true, true);
147 }
148 context->setFillPattern(m_overhangPattern);
149 if (hasHorizontalOverhang)
150 context->fillRect(intersection(horizontalOverhangRect, dirtyRect));
151 if (hasVerticalOverhang)
152 context->fillRect(intersection(verticalOverhangRect, dirtyRect));
153 }
154
155 void ScrollbarThemeMacCommon::paintOverhangShadows(GraphicsContext* context, con st IntSize& scrollOffset, const IntRect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect& dirtyRect)
156 {
157 // The extent of each shadow in pixels.
158 const int kShadowSize = 4;
159 // Offset of negative one pixel to make the gradient blend with the toolbar' s bottom border.
160 const int kToolbarShadowOffset = -1;
161 const struct {
162 float stop;
163 Color color;
164 } kShadowColors[] = {
165 { 0.000, Color(0, 0, 0, 255) },
166 { 0.125, Color(0, 0, 0, 57) },
167 { 0.375, Color(0, 0, 0, 41) },
168 { 0.625, Color(0, 0, 0, 18) },
169 { 0.875, Color(0, 0, 0, 6) },
170 { 1.000, Color(0, 0, 0, 0) }
171 };
172 const unsigned kNumShadowColors = sizeof(kShadowColors)/sizeof(kShadowColors [0]);
173
174 const bool hasHorizontalOverhang = !horizontalOverhangRect.isEmpty();
175 const bool hasVerticalOverhang = !verticalOverhangRect.isEmpty();
176 // Prefer non-additive shadows, but degrade to additive shadows if there is vertical overhang.
177 const bool useAdditiveShadows = hasVerticalOverhang;
178
179 GraphicsContextStateSaver stateSaver(*context);
180
181 FloatPoint shadowCornerOrigin;
182 FloatPoint shadowCornerOffset;
183
184 // Draw the shadow for the horizontal overhang.
185 if (hasHorizontalOverhang) {
186 int toolbarShadowHeight = kShadowSize;
187 RefPtr<Gradient> gradient;
188 IntRect shadowRect = horizontalOverhangRect;
189 shadowRect.setHeight(kShadowSize);
190 if (scrollOffset.height() < 0) {
191 if (useAdditiveShadows) {
192 toolbarShadowHeight = std::min(horizontalOverhangRect.height(), kShadowSize);
193 } else if (horizontalOverhangRect.height() < 2 * kShadowSize + kTool barShadowOffset) {
194 // Split the overhang area between the web content shadow and to olbar shadow if it's too small.
195 shadowRect.setHeight((horizontalOverhangRect.height() + 1) / 2);
196 toolbarShadowHeight = horizontalOverhangRect.height() - shadowRe ct.height() - kToolbarShadowOffset;
197 }
198 shadowRect.setY(horizontalOverhangRect.maxY() - shadowRect.height()) ;
199 gradient = Gradient::create(FloatPoint(0, shadowRect.maxY()), FloatP oint(0, shadowRect.maxY() - kShadowSize));
200 shadowCornerOrigin.setY(shadowRect.maxY());
201 shadowCornerOffset.setY(-kShadowSize);
202 } else {
203 gradient = Gradient::create(FloatPoint(0, shadowRect.y()), FloatPoin t(0, shadowRect.maxY()));
204 shadowCornerOrigin.setY(shadowRect.y());
205 }
206 if (hasVerticalOverhang) {
207 shadowRect.setWidth(shadowRect.width() - verticalOverhangRect.width( ));
208 if (scrollOffset.width() < 0) {
209 shadowRect.setX(shadowRect.x() + verticalOverhangRect.width());
210 shadowCornerOrigin.setX(shadowRect.x());
211 shadowCornerOffset.setX(-kShadowSize);
212 } else {
213 shadowCornerOrigin.setX(shadowRect.maxX());
214 }
215 }
216 for (unsigned i = 0; i < kNumShadowColors; i++)
217 gradient->addColorStop(kShadowColors[i].stop, kShadowColors[i].color );
218 context->setFillGradient(gradient);
219 context->fillRect(intersection(shadowRect, dirtyRect));
220
221 // Draw a drop-shadow from the toolbar.
222 if (scrollOffset.height() < 0) {
223 shadowRect.setY(kToolbarShadowOffset);
224 shadowRect.setHeight(toolbarShadowHeight);
225 gradient = Gradient::create(FloatPoint(0, shadowRect.y()), FloatPoin t(0, shadowRect.y() + kShadowSize));
226 for (unsigned i = 0; i < kNumShadowColors; i++)
227 gradient->addColorStop(kShadowColors[i].stop, kShadowColors[i].c olor);
228 context->setFillGradient(gradient);
229 context->fillRect(intersection(shadowRect, dirtyRect));
230 }
231 }
232
233 // Draw the shadow for the vertical overhang.
234 if (hasVerticalOverhang) {
235 RefPtr<Gradient> gradient;
236 IntRect shadowRect = verticalOverhangRect;
237 shadowRect.setWidth(kShadowSize);
238 if (scrollOffset.width() < 0) {
239 shadowRect.setX(verticalOverhangRect.maxX() - shadowRect.width());
240 gradient = Gradient::create(FloatPoint(shadowRect.maxX(), 0), FloatP oint(shadowRect.x(), 0));
241 } else {
242 gradient = Gradient::create(FloatPoint(shadowRect.x(), 0), FloatPoin t(shadowRect.maxX(), 0));
243 }
244 for (unsigned i = 0; i < kNumShadowColors; i++)
245 gradient->addColorStop(kShadowColors[i].stop, kShadowColors[i].color );
246 context->setFillGradient(gradient);
247 context->fillRect(intersection(shadowRect, dirtyRect));
248
249 // Draw a drop-shadow from the toolbar.
250 shadowRect = verticalOverhangRect;
251 shadowRect.setY(kToolbarShadowOffset);
252 shadowRect.setHeight(kShadowSize);
253 gradient = Gradient::create(FloatPoint(0, shadowRect.y()), FloatPoint(0, shadowRect.maxY()));
254 for (unsigned i = 0; i < kNumShadowColors; i++)
255 gradient->addColorStop(kShadowColors[i].stop, kShadowColors[i].color );
256 context->setFillGradient(gradient);
257 context->fillRect(intersection(shadowRect, dirtyRect));
258 }
259
260 // If both rectangles present, draw a radial gradient for the corner.
261 if (hasHorizontalOverhang && hasVerticalOverhang) {
262 RefPtr<Gradient> gradient = Gradient::create(shadowCornerOrigin, 0, shad owCornerOrigin, kShadowSize);
263 for (unsigned i = 0; i < kNumShadowColors; i++)
264 gradient->addColorStop(kShadowColors[i].stop, kShadowColors[i].color );
265 context->setFillGradient(gradient);
266 context->fillRect(FloatRect(shadowCornerOrigin.x() + shadowCornerOffset. x(), shadowCornerOrigin.y() + shadowCornerOffset.y(), kShadowSize, kShadowSize)) ;
267 }
268 }
269
270 void ScrollbarThemeMacCommon::paintTickmarks(GraphicsContext* context, Scrollbar ThemeClient* scrollbar, const IntRect& rect)
271 {
272 // Note: This is only used for css-styled scrollbars on mac.
273 if (scrollbar->orientation() != VerticalScrollbar)
274 return;
275
276 if (rect.height() <= 0 || rect.width() <= 0)
277 return;
278
279 Vector<IntRect> tickmarks;
280 scrollbar->getTickmarks(tickmarks);
281 if (!tickmarks.size())
282 return;
283
284 // Inset a bit.
285 IntRect tickmarkTrackRect = rect;
286 tickmarkTrackRect.setX(tickmarkTrackRect.x() + 1);
287 tickmarkTrackRect.setWidth(tickmarkTrackRect.width() - 2);
288 paintGivenTickmarks(context, scrollbar, tickmarkTrackRect, tickmarks);
289 }
290
291 ScrollbarThemeMacCommon::~ScrollbarThemeMacCommon()
292 {
293 }
294
295 void ScrollbarThemeMacCommon::preferencesChanged(float initialButtonDelay, float autoscrollButtonDelay, bool jumpOnTrackClick, bool redraw)
296 {
297 updateButtonPlacement();
298 gInitialButtonDelay = initialButtonDelay;
299 gAutoscrollButtonDelay = autoscrollButtonDelay;
300 gJumpOnTrackClick = jumpOnTrackClick;
301 if (redraw && !scrollbarSet().isEmpty()) {
302 ScrollbarSet::iterator end = scrollbarSet().end();
303 for (ScrollbarSet::iterator it = scrollbarSet().begin(); it != end; ++it ) {
304 (*it)->styleChanged();
305 (*it)->invalidate();
306 }
307 }
308 }
309
310 double ScrollbarThemeMacCommon::initialAutoscrollTimerDelay()
311 {
312 return gInitialButtonDelay;
313 }
314
315 double ScrollbarThemeMacCommon::autoscrollTimerDelay()
316 {
317 return gAutoscrollButtonDelay;
318 }
319
320 bool ScrollbarThemeMacCommon::shouldCenterOnThumb(ScrollbarThemeClient*, const P latformMouseEvent& evt)
321 {
322 if (evt.button() != LeftButton)
323 return false;
324 if (gJumpOnTrackClick)
325 return !evt.altKey();
326 return evt.altKey();
327 }
328
329 bool ScrollbarThemeMacCommon::shouldDragDocumentInsteadOfThumb(ScrollbarThemeCli ent*, const PlatformMouseEvent& event)
330 {
331 return event.altKey();
332 }
333
334 int ScrollbarThemeMacCommon::scrollbarPartToHIPressedState(ScrollbarPart part)
335 {
336 switch (part) {
337 case BackButtonStartPart:
338 return kThemeTopOutsideArrowPressed;
339 case BackButtonEndPart:
340 return kThemeTopOutsideArrowPressed; // This does not make much sens e. For some reason the outside constant is required.
341 case ForwardButtonStartPart:
342 return kThemeTopInsideArrowPressed;
343 case ForwardButtonEndPart:
344 return kThemeBottomOutsideArrowPressed;
345 case ThumbPart:
346 return kThemeThumbPressed;
347 default:
348 return 0;
349 }
350 }
351
352 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/platform/ScrollbarThemeMacCommon.h ('k') | Source/core/platform/ScrollbarThemeMacNonOverlayAPI.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698