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 "ScrollbarThemeMac.h" 28 29#include "ImageBuffer.h" 30#include "LocalCurrentGraphicsContext.h" 31#include "PlatformMouseEvent.h" 32#include "ScrollAnimatorMac.h" 33#include "ScrollView.h" 34#include "WebCoreSystemInterface.h" 35#include <Carbon/Carbon.h> 36#include <wtf/HashMap.h> 37#include <wtf/StdLibExtras.h> 38#include <wtf/UnusedParam.h> 39 40// FIXME: There are repainting problems due to Aqua scroll bar buttons' visual overflow. 41 42using namespace std; 43using namespace WebCore; 44 45namespace WebCore { 46 47#if USE(WK_SCROLLBAR_PAINTER) 48typedef HashMap<Scrollbar*, RetainPtr<WKScrollbarPainterRef> > ScrollbarPainterMap; 49#else 50typedef HashSet<Scrollbar*> ScrollbarPainterMap; 51#endif 52 53static ScrollbarPainterMap* scrollbarMap() 54{ 55 static ScrollbarPainterMap* map = new ScrollbarPainterMap; 56 return map; 57} 58 59} 60 61@interface ScrollbarPrefsObserver : NSObject 62{ 63} 64 65+ (void)registerAsObserver; 66+ (void)appearancePrefsChanged:(NSNotification*)theNotification; 67+ (void)behaviorPrefsChanged:(NSNotification*)theNotification; 68 69@end 70 71@implementation ScrollbarPrefsObserver 72 73+ (void)appearancePrefsChanged:(NSNotification*)unusedNotification 74{ 75 UNUSED_PARAM(unusedNotification); 76 77 static_cast<ScrollbarThemeMac*>(ScrollbarTheme::nativeTheme())->preferencesChanged(); 78 if (scrollbarMap()->isEmpty()) 79 return; 80 ScrollbarPainterMap::iterator end = scrollbarMap()->end(); 81 for (ScrollbarPainterMap::iterator it = scrollbarMap()->begin(); it != end; ++it) { 82#if USE(WK_SCROLLBAR_PAINTER) 83 it->first->styleChanged(); 84 it->first->invalidate(); 85#else 86 (*it)->styleChanged(); 87 (*it)->invalidate(); 88#endif 89 } 90} 91 92+ (void)behaviorPrefsChanged:(NSNotification*)unusedNotification 93{ 94 UNUSED_PARAM(unusedNotification); 95 96 static_cast<ScrollbarThemeMac*>(ScrollbarTheme::nativeTheme())->preferencesChanged(); 97} 98 99+ (void)registerAsObserver 100{ 101 [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(appearancePrefsChanged:) name:@"AppleAquaScrollBarVariantChanged" object:nil suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately]; 102 [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(behaviorPrefsChanged:) name:@"AppleNoRedisplayAppearancePreferenceChanged" object:nil suspensionBehavior:NSNotificationSuspensionBehaviorCoalesce]; 103} 104 105@end 106 107namespace WebCore { 108 109ScrollbarTheme* ScrollbarTheme::nativeTheme() 110{ 111 DEFINE_STATIC_LOCAL(ScrollbarThemeMac, theme, ()); 112 return &theme; 113} 114 115// FIXME: Get these numbers from CoreUI. 116static int cRealButtonLength[] = { 28, 21 }; 117static int cButtonHitInset[] = { 3, 2 }; 118// cRealButtonLength - cButtonInset 119static int cButtonLength[] = { 14, 10 }; 120#if !USE(WK_SCROLLBAR_PAINTER) 121static int cScrollbarThickness[] = { 15, 11 }; 122static int cButtonInset[] = { 14, 11 }; 123static int cThumbMinLength[] = { 26, 20 }; 124#endif 125 126static int cOuterButtonLength[] = { 16, 14 }; // The outer button in a double button pair is a bit bigger. 127static int cOuterButtonOverlap = 2; 128 129static float gInitialButtonDelay = 0.5f; 130static float gAutoscrollButtonDelay = 0.05f; 131static bool gJumpOnTrackClick = false; 132 133#if USE(WK_SCROLLBAR_PAINTER) 134static ScrollbarButtonsPlacement gButtonPlacement = ScrollbarButtonsNone; 135#else 136static ScrollbarButtonsPlacement gButtonPlacement = ScrollbarButtonsDoubleEnd; 137#endif 138 139static void updateArrowPlacement() 140{ 141#if USE(WK_SCROLLBAR_PAINTER) 142 return; 143#endif 144 NSString *buttonPlacement = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleScrollBarVariant"]; 145 if ([buttonPlacement isEqualToString:@"Single"]) 146 gButtonPlacement = ScrollbarButtonsSingle; 147 else if ([buttonPlacement isEqualToString:@"DoubleMin"]) 148 gButtonPlacement = ScrollbarButtonsDoubleStart; 149 else if ([buttonPlacement isEqualToString:@"DoubleBoth"]) 150 gButtonPlacement = ScrollbarButtonsDoubleBoth; 151 else { 152 153 gButtonPlacement = ScrollbarButtonsDoubleEnd; 154 } 155} 156 157void ScrollbarThemeMac::registerScrollbar(Scrollbar* scrollbar) 158{ 159#if USE(WK_SCROLLBAR_PAINTER) 160 bool isHorizontal = scrollbar->orientation() == HorizontalScrollbar; 161 WKScrollbarPainterRef scrollbarPainter = wkMakeScrollbarPainter(scrollbar->controlSize(), isHorizontal); 162 scrollbarMap()->add(scrollbar, scrollbarPainter); 163#else 164 scrollbarMap()->add(scrollbar); 165#endif 166} 167 168void ScrollbarThemeMac::unregisterScrollbar(Scrollbar* scrollbar) 169{ 170 scrollbarMap()->remove(scrollbar); 171} 172 173#if USE(WK_SCROLLBAR_PAINTER) 174void ScrollbarThemeMac::setNewPainterForScrollbar(Scrollbar* scrollbar, WKScrollbarPainterRef newPainter) 175{ 176 scrollbarMap()->set(scrollbar, newPainter); 177} 178 179WKScrollbarPainterRef ScrollbarThemeMac::painterForScrollbar(Scrollbar* scrollbar) 180{ 181 return scrollbarMap()->get(scrollbar).get(); 182} 183#endif 184 185ScrollbarThemeMac::ScrollbarThemeMac() 186{ 187 static bool initialized; 188 if (!initialized) { 189 initialized = true; 190 [ScrollbarPrefsObserver registerAsObserver]; 191 preferencesChanged(); 192 } 193} 194 195ScrollbarThemeMac::~ScrollbarThemeMac() 196{ 197} 198 199void ScrollbarThemeMac::preferencesChanged() 200{ 201 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 202 [defaults synchronize]; 203 updateArrowPlacement(); 204 gInitialButtonDelay = [defaults floatForKey:@"NSScrollerButtonDelay"]; 205 gAutoscrollButtonDelay = [defaults floatForKey:@"NSScrollerButtonPeriod"]; 206 gJumpOnTrackClick = [defaults boolForKey:@"AppleScrollerPagingBehavior"]; 207} 208 209int ScrollbarThemeMac::scrollbarThickness(ScrollbarControlSize controlSize) 210{ 211#if USE(WK_SCROLLBAR_PAINTER) 212 return wkScrollbarThickness(controlSize); 213#else 214 return cScrollbarThickness[controlSize]; 215#endif 216} 217 218bool ScrollbarThemeMac::usesOverlayScrollbars() const 219{ 220#if USE(WK_SCROLLBAR_PAINTER) 221 return wkScrollbarPainterUsesOverlayScrollers(); 222#else 223 return false; 224#endif 225} 226 227double ScrollbarThemeMac::initialAutoscrollTimerDelay() 228{ 229 return gInitialButtonDelay; 230} 231 232double ScrollbarThemeMac::autoscrollTimerDelay() 233{ 234 return gAutoscrollButtonDelay; 235} 236 237ScrollbarButtonsPlacement ScrollbarThemeMac::buttonsPlacement() const 238{ 239 return gButtonPlacement; 240} 241 242bool ScrollbarThemeMac::hasButtons(Scrollbar* scrollbar) 243{ 244 return scrollbar->enabled() && gButtonPlacement != ScrollbarButtonsNone 245 && (scrollbar->orientation() == HorizontalScrollbar 246 ? scrollbar->width() 247 : scrollbar->height()) >= 2 * (cRealButtonLength[scrollbar->controlSize()] - cButtonHitInset[scrollbar->controlSize()]); 248} 249 250bool ScrollbarThemeMac::hasThumb(Scrollbar* scrollbar) 251{ 252 int minLengthForThumb; 253#if USE(WK_SCROLLBAR_PAINTER) 254 minLengthForThumb = wkScrollbarMinimumTotalLengthNeededForThumb(scrollbarMap()->get(scrollbar).get()); 255#else 256 minLengthForThumb = 2 * cButtonInset[scrollbar->controlSize()] + cThumbMinLength[scrollbar->controlSize()] + 1; 257#endif 258 return scrollbar->enabled() && (scrollbar->orientation() == HorizontalScrollbar ? 259 scrollbar->width() : 260 scrollbar->height()) >= minLengthForThumb; 261} 262 263static IntRect buttonRepaintRect(const IntRect& buttonRect, ScrollbarOrientation orientation, ScrollbarControlSize controlSize, bool start) 264{ 265 ASSERT(gButtonPlacement != ScrollbarButtonsNone); 266 267 IntRect paintRect(buttonRect); 268 if (orientation == HorizontalScrollbar) { 269 paintRect.setWidth(cRealButtonLength[controlSize]); 270 if (!start) 271 paintRect.setX(buttonRect.x() - (cRealButtonLength[controlSize] - buttonRect.width())); 272 } else { 273 paintRect.setHeight(cRealButtonLength[controlSize]); 274 if (!start) 275 paintRect.setY(buttonRect.y() - (cRealButtonLength[controlSize] - buttonRect.height())); 276 } 277 278 return paintRect; 279} 280 281IntRect ScrollbarThemeMac::backButtonRect(Scrollbar* scrollbar, ScrollbarPart part, bool painting) 282{ 283 IntRect result; 284 285 if (part == BackButtonStartPart && (buttonsPlacement() == ScrollbarButtonsNone || buttonsPlacement() == ScrollbarButtonsDoubleEnd)) 286 return result; 287 288 if (part == BackButtonEndPart && (buttonsPlacement() == ScrollbarButtonsNone || buttonsPlacement() == ScrollbarButtonsDoubleStart || buttonsPlacement() == ScrollbarButtonsSingle)) 289 return result; 290 291 int thickness = scrollbarThickness(scrollbar->controlSize()); 292 bool outerButton = part == BackButtonStartPart && (buttonsPlacement() == ScrollbarButtonsDoubleStart || buttonsPlacement() == ScrollbarButtonsDoubleBoth); 293 if (outerButton) { 294 if (scrollbar->orientation() == HorizontalScrollbar) 295 result = IntRect(scrollbar->x(), scrollbar->y(), cOuterButtonLength[scrollbar->controlSize()] + painting ? cOuterButtonOverlap : 0, thickness); 296 else 297 result = IntRect(scrollbar->x(), scrollbar->y(), thickness, cOuterButtonLength[scrollbar->controlSize()] + painting ? cOuterButtonOverlap : 0); 298 return result; 299 } 300 301 // Our repaint rect is slightly larger, since we are a button that is adjacent to the track. 302 if (scrollbar->orientation() == HorizontalScrollbar) { 303 int start = part == BackButtonStartPart ? scrollbar->x() : scrollbar->x() + scrollbar->width() - cOuterButtonLength[scrollbar->controlSize()] - cButtonLength[scrollbar->controlSize()]; 304 result = IntRect(start, scrollbar->y(), cButtonLength[scrollbar->controlSize()], thickness); 305 } else { 306 int start = part == BackButtonStartPart ? scrollbar->y() : scrollbar->y() + scrollbar->height() - cOuterButtonLength[scrollbar->controlSize()] - cButtonLength[scrollbar->controlSize()]; 307 result = IntRect(scrollbar->x(), start, thickness, cButtonLength[scrollbar->controlSize()]); 308 } 309 310 if (painting) 311 return buttonRepaintRect(result, scrollbar->orientation(), scrollbar->controlSize(), part == BackButtonStartPart); 312 return result; 313} 314 315IntRect ScrollbarThemeMac::forwardButtonRect(Scrollbar* scrollbar, ScrollbarPart part, bool painting) 316{ 317 IntRect result; 318 319 if (part == ForwardButtonEndPart && (buttonsPlacement() == ScrollbarButtonsNone || buttonsPlacement() == ScrollbarButtonsDoubleStart)) 320 return result; 321 322 if (part == ForwardButtonStartPart && (buttonsPlacement() == ScrollbarButtonsNone || buttonsPlacement() == ScrollbarButtonsDoubleEnd || buttonsPlacement() == ScrollbarButtonsSingle)) 323 return result; 324 325 int thickness = scrollbarThickness(scrollbar->controlSize()); 326 int outerButtonLength = cOuterButtonLength[scrollbar->controlSize()]; 327 int buttonLength = cButtonLength[scrollbar->controlSize()]; 328 329 bool outerButton = part == ForwardButtonEndPart && (buttonsPlacement() == ScrollbarButtonsDoubleEnd || buttonsPlacement() == ScrollbarButtonsDoubleBoth); 330 if (outerButton) { 331 if (scrollbar->orientation() == HorizontalScrollbar) { 332 result = IntRect(scrollbar->x() + scrollbar->width() - outerButtonLength, scrollbar->y(), outerButtonLength, thickness); 333 if (painting) 334 result.inflateX(cOuterButtonOverlap); 335 } else { 336 result = IntRect(scrollbar->x(), scrollbar->y() + scrollbar->height() - outerButtonLength, thickness, outerButtonLength); 337 if (painting) 338 result.inflateY(cOuterButtonOverlap); 339 } 340 return result; 341 } 342 343 if (scrollbar->orientation() == HorizontalScrollbar) { 344 int start = part == ForwardButtonEndPart ? scrollbar->x() + scrollbar->width() - buttonLength : scrollbar->x() + outerButtonLength; 345 result = IntRect(start, scrollbar->y(), buttonLength, thickness); 346 } else { 347 int start = part == ForwardButtonEndPart ? scrollbar->y() + scrollbar->height() - buttonLength : scrollbar->y() + outerButtonLength; 348 result = IntRect(scrollbar->x(), start, thickness, buttonLength); 349 } 350 if (painting) 351 return buttonRepaintRect(result, scrollbar->orientation(), scrollbar->controlSize(), part == ForwardButtonStartPart); 352 return result; 353} 354 355IntRect ScrollbarThemeMac::trackRect(Scrollbar* scrollbar, bool painting) 356{ 357 if (painting || !hasButtons(scrollbar)) 358 return scrollbar->frameRect(); 359 360 IntRect result; 361 int thickness = scrollbarThickness(scrollbar->controlSize()); 362 int startWidth = 0; 363 int endWidth = 0; 364 int outerButtonLength = cOuterButtonLength[scrollbar->controlSize()]; 365 int buttonLength = cButtonLength[scrollbar->controlSize()]; 366 int doubleButtonLength = outerButtonLength + buttonLength; 367 switch (buttonsPlacement()) { 368 case ScrollbarButtonsSingle: 369 startWidth = buttonLength; 370 endWidth = buttonLength; 371 break; 372 case ScrollbarButtonsDoubleStart: 373 startWidth = doubleButtonLength; 374 break; 375 case ScrollbarButtonsDoubleEnd: 376 endWidth = doubleButtonLength; 377 break; 378 case ScrollbarButtonsDoubleBoth: 379 startWidth = doubleButtonLength; 380 endWidth = doubleButtonLength; 381 break; 382 default: 383 break; 384 } 385 386 int totalWidth = startWidth + endWidth; 387 if (scrollbar->orientation() == HorizontalScrollbar) 388 return IntRect(scrollbar->x() + startWidth, scrollbar->y(), scrollbar->width() - totalWidth, thickness); 389 return IntRect(scrollbar->x(), scrollbar->y() + startWidth, thickness, scrollbar->height() - totalWidth); 390} 391 392int ScrollbarThemeMac::minimumThumbLength(Scrollbar* scrollbar) 393{ 394#if USE(WK_SCROLLBAR_PAINTER) 395 return wkScrollbarMinimumThumbLength(scrollbarMap()->get(scrollbar).get()); 396#else 397 return cThumbMinLength[scrollbar->controlSize()]; 398#endif 399} 400 401bool ScrollbarThemeMac::shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent& evt) 402{ 403 if (evt.button() != LeftButton) 404 return false; 405 if (gJumpOnTrackClick) 406 return !evt.altKey(); 407 return evt.altKey(); 408} 409 410bool ScrollbarThemeMac::shouldDragDocumentInsteadOfThumb(Scrollbar*, const PlatformMouseEvent& event) 411{ 412 return event.altKey(); 413} 414 415static int scrollbarPartToHIPressedState(ScrollbarPart part) 416{ 417 switch (part) { 418 case BackButtonStartPart: 419 return kThemeTopOutsideArrowPressed; 420 case BackButtonEndPart: 421 return kThemeTopOutsideArrowPressed; // This does not make much sense. For some reason the outside constant is required. 422 case ForwardButtonStartPart: 423 return kThemeTopInsideArrowPressed; 424 case ForwardButtonEndPart: 425 return kThemeBottomOutsideArrowPressed; 426 case ThumbPart: 427 return kThemeThumbPressed; 428 default: 429 return 0; 430 } 431} 432 433#if USE(WK_SCROLLBAR_PAINTER) 434static inline wkScrollerKnobStyle toScrollbarPainterKnobStyle(ScrollbarOverlayStyle style) 435{ 436 switch (style) { 437 case ScrollbarOverlayStyleDark: 438 return wkScrollerKnobStyleDark; 439 case ScrollbarOverlayStyleLight: 440 return wkScrollerKnobStyleLight; 441 default: 442 return wkScrollerKnobStyleDefault; 443 } 444} 445#endif 446 447bool ScrollbarThemeMac::paint(Scrollbar* scrollbar, GraphicsContext* context, const IntRect& damageRect) 448{ 449#if USE(WK_SCROLLBAR_PAINTER) 450 float value = 0; 451 float overhang = 0; 452 453 if (scrollbar->currentPos() < 0) { 454 // Scrolled past the top. 455 value = 0; 456 overhang = -scrollbar->currentPos(); 457 } else if (scrollbar->visibleSize() + scrollbar->currentPos() > scrollbar->totalSize()) { 458 // Scrolled past the bottom. 459 value = 1; 460 overhang = scrollbar->currentPos() + scrollbar->visibleSize() - scrollbar->totalSize(); 461 } else { 462 // Within the bounds of the scrollable area. 463 int maximum = scrollbar->maximum(); 464 if (maximum > 0) 465 value = scrollbar->currentPos() / maximum; 466 else 467 value = 0; 468 } 469 470 ScrollAnimatorMac* scrollAnimator = static_cast<ScrollAnimatorMac*>(scrollbar->scrollableArea()->scrollAnimator()); 471 scrollAnimator->setIsDrawingIntoLayer(context->isCALayerContext()); 472 473#if USE(WK_SCROLLBAR_PAINTER) 474 wkSetScrollbarPainterKnobStyle(painterForScrollbar(scrollbar), toScrollbarPainterKnobStyle(scrollbar->scrollableArea()->recommendedScrollbarOverlayStyle())); 475#endif 476 477 GraphicsContextStateSaver stateSaver(*context); 478 context->clip(damageRect); 479 context->translate(scrollbar->frameRect().x(), scrollbar->frameRect().y()); 480 LocalCurrentGraphicsContext localContext(context); 481 wkScrollbarPainterPaint(scrollbarMap()->get(scrollbar).get(), 482 scrollbar->enabled(), 483 value, 484 (static_cast<CGFloat>(scrollbar->visibleSize()) - overhang) / scrollbar->totalSize(), 485 scrollbar->frameRect()); 486 487 scrollAnimator->setIsDrawingIntoLayer(false); 488 return true; 489#endif 490 491 HIThemeTrackDrawInfo trackInfo; 492 trackInfo.version = 0; 493 trackInfo.kind = scrollbar->controlSize() == RegularScrollbar ? kThemeMediumScrollBar : kThemeSmallScrollBar; 494 trackInfo.bounds = scrollbar->frameRect(); 495 496 float maximum = 0.0f; 497 float position = 0.0f; 498 if (scrollbar->currentPos() < 0) { 499 // Scrolled past the top. 500 maximum = (scrollbar->totalSize() - scrollbar->currentPos()) - scrollbar->visibleSize(); 501 position = 0; 502 } else if (scrollbar->visibleSize() + scrollbar->currentPos() > scrollbar->totalSize()) { 503 // Scrolled past the bottom. 504 maximum = scrollbar->currentPos(); 505 position = maximum; 506 } else { 507 // Within the bounds of the scrollable area. 508 maximum = scrollbar->maximum(); 509 position = scrollbar->currentPos(); 510 } 511 512 trackInfo.min = 0; 513 trackInfo.max = static_cast<int>(maximum); 514 trackInfo.value = static_cast<int>(position); 515 516 trackInfo.trackInfo.scrollbar.viewsize = scrollbar->visibleSize(); 517 trackInfo.attributes = 0; 518 if (scrollbar->orientation() == HorizontalScrollbar) 519 trackInfo.attributes |= kThemeTrackHorizontal; 520 521 if (!scrollbar->enabled()) 522 trackInfo.enableState = kThemeTrackDisabled; 523 else 524 trackInfo.enableState = scrollbar->scrollableArea()->isActive() ? kThemeTrackActive : kThemeTrackInactive; 525 526 if (hasThumb(scrollbar)) 527 trackInfo.attributes |= kThemeTrackShowThumb; 528 else if (!hasButtons(scrollbar)) 529 trackInfo.enableState = kThemeTrackNothingToScroll; 530 trackInfo.trackInfo.scrollbar.pressState = scrollbarPartToHIPressedState(scrollbar->pressedPart()); 531 532 // The Aqua scrollbar is buggy when rotated and scaled. We will just draw into a bitmap if we detect a scale or rotation. 533 const AffineTransform& currentCTM = context->getCTM(); 534 bool canDrawDirectly = currentCTM.isIdentityOrTranslationOrFlipped(); 535 if (canDrawDirectly) 536 HIThemeDrawTrack(&trackInfo, 0, context->platformContext(), kHIThemeOrientationNormal); 537 else { 538 trackInfo.bounds = IntRect(IntPoint(), scrollbar->frameRect().size()); 539 540 IntRect bufferRect(scrollbar->frameRect()); 541 bufferRect.intersect(damageRect); 542 543 OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(bufferRect.size()); 544 if (!imageBuffer) 545 return true; 546 547 imageBuffer->context()->translate(scrollbar->frameRect().x() - bufferRect.x(), scrollbar->frameRect().y() - bufferRect.y()); 548 HIThemeDrawTrack(&trackInfo, 0, imageBuffer->context()->platformContext(), kHIThemeOrientationNormal); 549 context->drawImageBuffer(imageBuffer.get(), ColorSpaceDeviceRGB, bufferRect.location()); 550 } 551 552 return true; 553} 554 555} 556 557