1 /* 2 * This file is part of the WebKit project. 3 * 4 * Copyright (C) 2006 Apple Computer, Inc. 5 * Copyright (C) 2008, 2009 Google, Inc. 6 * Copyright (C) 2009 Kenneth Rohde Christiansen 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public License 19 * along with this library; see the file COPYING.LIB. If not, write to 20 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 21 * Boston, MA 02111-1307, USA. 22 * 23 */ 24 25 #include "config.h" 26 #include "core/rendering/RenderThemeChromiumWin.h" 27 28 #include <windows.h> 29 #include <uxtheme.h> 30 #include <vssym32.h> 31 32 #include "CSSValueKeywords.h" 33 #include "HTMLNames.h" 34 #include "core/html/HTMLMediaElement.h" 35 #include "core/html/shadow/MediaControlElements.h" 36 #include "core/platform/LayoutTestSupport.h" 37 #include "core/platform/ScrollbarTheme.h" 38 #include "core/platform/graphics/FontSelector.h" 39 #include "core/platform/graphics/GraphicsContext.h" 40 #include "core/platform/graphics/chromium/FontUtilsChromiumWin.h" 41 #include "core/platform/graphics/chromium/TransparencyWin.h" 42 #include "core/platform/win/SystemInfo.h" 43 #include "core/rendering/PaintInfo.h" 44 #include "core/rendering/RenderBox.h" 45 #include "core/rendering/RenderProgress.h" 46 #include "core/rendering/RenderSlider.h" 47 #include "public/platform/Platform.h" 48 #include "public/platform/WebColor.h" 49 #include "public/platform/WebRect.h" 50 #include "public/platform/win/WebThemeEngine.h" 51 #include "wtf/CurrentTime.h" 52 53 54 // FIXME: This dependency should eventually be removed. 55 #include <skia/ext/skia_utils_win.h> 56 57 namespace WebCore { 58 59 // The standard width for the menu list drop-down button when run under 60 // layout test mode. Use the value that's currently captured in most baselines. 61 static const int kStandardMenuListButtonWidth = 17; 62 63 namespace { 64 // We must not create multiple ThemePainter instances. 65 class ThemePainter { 66 public: 67 ThemePainter(GraphicsContext* context, const IntRect& r) 68 { 69 #ifndef NDEBUG 70 ASSERT(!s_hasInstance); 71 s_hasInstance = true; 72 #endif 73 TransparencyWin::TransformMode transformMode = getTransformMode(context->getCTM()); 74 m_helper.init(context, getLayerMode(context, transformMode), transformMode, r); 75 76 if (!m_helper.context()) { 77 // TransparencyWin doesn't have well-defined copy-ctor nor op=() 78 // so we re-initialize it instead of assigning a fresh istance. 79 // On the reinitialization, we fallback to use NoLayer mode. 80 // Note that the original initialization failure can be caused by 81 // a failure of an internal buffer allocation and NoLayer mode 82 // does not have such buffer allocations. 83 m_helper.~TransparencyWin(); 84 new (&m_helper) TransparencyWin(); 85 m_helper.init(context, TransparencyWin::NoLayer, transformMode, r); 86 } 87 } 88 89 ~ThemePainter() 90 { 91 m_helper.composite(); 92 #ifndef NDEBUG 93 s_hasInstance = false; 94 #endif 95 } 96 97 GraphicsContext* context() { return m_helper.context(); } 98 const IntRect& drawRect() { return m_helper.drawRect(); } 99 100 private: 101 102 static TransparencyWin::LayerMode getLayerMode(GraphicsContext* context, TransparencyWin::TransformMode transformMode) 103 { 104 if (!context->isCertainlyOpaque()) // Might have transparent background. 105 return TransparencyWin::WhiteLayer; 106 if (context->canvas()->isDrawingToLayer()) // Needs antialiasing help. 107 return TransparencyWin::OpaqueCompositeLayer; 108 // Nothing interesting. 109 return transformMode == TransparencyWin::KeepTransform ? TransparencyWin::NoLayer : TransparencyWin::OpaqueCompositeLayer; 110 } 111 112 static TransparencyWin::TransformMode getTransformMode(const AffineTransform& matrix) 113 { 114 if (matrix.b() || matrix.c()) // Skew. 115 return TransparencyWin::Untransform; 116 if (matrix.a() != 1.0 || matrix.d() != 1.0) // Scale. 117 return TransparencyWin::ScaleTransform; 118 // Nothing interesting. 119 return TransparencyWin::KeepTransform; 120 } 121 122 TransparencyWin m_helper; 123 #ifndef NDEBUG 124 static bool s_hasInstance; 125 #endif 126 }; 127 128 #ifndef NDEBUG 129 bool ThemePainter::s_hasInstance = false; 130 #endif 131 132 } // namespace 133 134 // Internal static helper functions. We don't put them in an anonymous 135 // namespace so they have easier access to the WebCore namespace. 136 137 static bool supportsFocus(ControlPart appearance) 138 { 139 switch (appearance) { 140 case SquareButtonPart: 141 case PushButtonPart: 142 case ButtonPart: 143 case SearchFieldPart: 144 case TextFieldPart: 145 case TextAreaPart: 146 return true; 147 } 148 return false; 149 } 150 151 static double querySystemBlinkInterval(double defaultInterval) 152 { 153 UINT blinkTime = GetCaretBlinkTime(); 154 if (!blinkTime) 155 return defaultInterval; 156 if (blinkTime == INFINITE) 157 return 0; 158 return blinkTime / 1000.0; 159 } 160 161 PassRefPtr<RenderTheme> RenderThemeChromiumWin::create() 162 { 163 return adoptRef(new RenderThemeChromiumWin); 164 } 165 166 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page) 167 { 168 static RenderTheme* rt = RenderThemeChromiumWin::create().leakRef(); 169 return rt; 170 } 171 172 bool RenderThemeChromiumWin::supportsFocusRing(const RenderStyle* style) const 173 { 174 // Let webkit draw one of its halo rings around any focused element, 175 // except push buttons. For buttons we use the windows PBS_DEFAULTED 176 // styling to give it a blue border. 177 return style->appearance() == ButtonPart 178 || style->appearance() == PushButtonPart 179 || style->appearance() == SquareButtonPart; 180 } 181 182 Color RenderThemeChromiumWin::platformActiveSelectionBackgroundColor() const 183 { 184 if (isRunningLayoutTest()) 185 return Color(0x00, 0x00, 0xff); // Royal blue. 186 COLORREF color = GetSysColor(COLOR_HIGHLIGHT); 187 return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff); 188 } 189 190 Color RenderThemeChromiumWin::platformInactiveSelectionBackgroundColor() const 191 { 192 if (isRunningLayoutTest()) 193 return Color(0x99, 0x99, 0x99); // Medium gray. 194 COLORREF color = GetSysColor(COLOR_GRAYTEXT); 195 return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff); 196 } 197 198 Color RenderThemeChromiumWin::platformActiveSelectionForegroundColor() const 199 { 200 if (isRunningLayoutTest()) 201 return Color(0xff, 0xff, 0xcc); // Pale yellow. 202 COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT); 203 return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff); 204 } 205 206 Color RenderThemeChromiumWin::platformInactiveSelectionForegroundColor() const 207 { 208 return Color::white; 209 } 210 211 Color RenderThemeChromiumWin::platformActiveTextSearchHighlightColor() const 212 { 213 return Color(0xff, 0x96, 0x32); // Orange. 214 } 215 216 Color RenderThemeChromiumWin::platformInactiveTextSearchHighlightColor() const 217 { 218 return Color(0xff, 0xff, 0x96); // Yellow. 219 } 220 221 // Map a CSSValue* system color to an index understood by GetSysColor(). 222 static int cssValueIdToSysColorIndex(int cssValueId) 223 { 224 switch (cssValueId) { 225 case CSSValueActiveborder: return COLOR_ACTIVEBORDER; 226 case CSSValueActivecaption: return COLOR_ACTIVECAPTION; 227 case CSSValueAppworkspace: return COLOR_APPWORKSPACE; 228 case CSSValueBackground: return COLOR_BACKGROUND; 229 case CSSValueButtonface: return COLOR_BTNFACE; 230 case CSSValueButtonhighlight: return COLOR_BTNHIGHLIGHT; 231 case CSSValueButtonshadow: return COLOR_BTNSHADOW; 232 case CSSValueButtontext: return COLOR_BTNTEXT; 233 case CSSValueCaptiontext: return COLOR_CAPTIONTEXT; 234 case CSSValueGraytext: return COLOR_GRAYTEXT; 235 case CSSValueHighlight: return COLOR_HIGHLIGHT; 236 case CSSValueHighlighttext: return COLOR_HIGHLIGHTTEXT; 237 case CSSValueInactiveborder: return COLOR_INACTIVEBORDER; 238 case CSSValueInactivecaption: return COLOR_INACTIVECAPTION; 239 case CSSValueInactivecaptiontext: return COLOR_INACTIVECAPTIONTEXT; 240 case CSSValueInfobackground: return COLOR_INFOBK; 241 case CSSValueInfotext: return COLOR_INFOTEXT; 242 case CSSValueMenu: return COLOR_MENU; 243 case CSSValueMenutext: return COLOR_MENUTEXT; 244 case CSSValueScrollbar: return COLOR_SCROLLBAR; 245 case CSSValueThreeddarkshadow: return COLOR_3DDKSHADOW; 246 case CSSValueThreedface: return COLOR_3DFACE; 247 case CSSValueThreedhighlight: return COLOR_3DHIGHLIGHT; 248 case CSSValueThreedlightshadow: return COLOR_3DLIGHT; 249 case CSSValueThreedshadow: return COLOR_3DSHADOW; 250 case CSSValueWindow: return COLOR_WINDOW; 251 case CSSValueWindowframe: return COLOR_WINDOWFRAME; 252 case CSSValueWindowtext: return COLOR_WINDOWTEXT; 253 default: return -1; // Unsupported CSSValue 254 } 255 } 256 257 Color RenderThemeChromiumWin::systemColor(CSSValueID cssValueId) const 258 { 259 int sysColorIndex = cssValueIdToSysColorIndex(cssValueId); 260 if (isRunningLayoutTest() || (sysColorIndex == -1)) 261 return RenderTheme::systemColor(cssValueId); 262 263 COLORREF color = GetSysColor(sysColorIndex); 264 return Color(GetRValue(color), GetGValue(color), GetBValue(color)); 265 } 266 267 IntSize RenderThemeChromiumWin::sliderTickSize() const 268 { 269 return IntSize(1, 3); 270 } 271 272 int RenderThemeChromiumWin::sliderTickOffsetFromTrackCenter() const 273 { 274 return 11; 275 } 276 277 void RenderThemeChromiumWin::adjustSliderThumbSize(RenderStyle* style, Element* element) const 278 { 279 // These sizes match what WinXP draws for various menus. 280 const int sliderThumbAlongAxis = 11; 281 const int sliderThumbAcrossAxis = 21; 282 if (style->appearance() == SliderThumbHorizontalPart) { 283 style->setWidth(Length(sliderThumbAlongAxis, Fixed)); 284 style->setHeight(Length(sliderThumbAcrossAxis, Fixed)); 285 } else if (style->appearance() == SliderThumbVerticalPart) { 286 style->setWidth(Length(sliderThumbAcrossAxis, Fixed)); 287 style->setHeight(Length(sliderThumbAlongAxis, Fixed)); 288 } else 289 RenderThemeChromiumSkia::adjustSliderThumbSize(style, element); 290 } 291 292 bool RenderThemeChromiumWin::paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& r) 293 { 294 return paintButton(o, i, r); 295 } 296 bool RenderThemeChromiumWin::paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& r) 297 { 298 return paintButton(o, i, r); 299 } 300 301 bool RenderThemeChromiumWin::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& r) 302 { 303 const ThemeData& themeData = getThemeData(o); 304 305 ThemePainter painter(i.context, r); 306 WebKit::WebCanvas* canvas = painter.context()->canvas(); 307 WebKit::Platform::current()->themeEngine()->paintButton(canvas, themeData.m_part, themeData.m_state, themeData.m_classicState, WebKit::WebRect(painter.drawRect())); 308 return false; 309 } 310 311 bool RenderThemeChromiumWin::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& r) 312 { 313 return paintTextFieldInternal(o, i, r, true); 314 } 315 316 bool RenderThemeChromiumWin::paintSliderTrack(RenderObject* o, const PaintInfo& i, const IntRect& r) 317 { 318 const ThemeData& themeData = getThemeData(o); 319 320 ThemePainter painter(i.context, r); 321 WebKit::WebCanvas* canvas = painter.context()->canvas(); 322 WebKit::Platform::current()->themeEngine()->paintTrackbar(canvas, themeData.m_part, themeData.m_state, themeData.m_classicState, WebKit::WebRect(painter.drawRect())); 323 324 paintSliderTicks(o, i, r); 325 326 return false; 327 } 328 329 bool RenderThemeChromiumWin::paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& r) 330 { 331 const ThemeData& themeData = getThemeData(o); 332 333 ThemePainter painter(i.context, r); 334 WebKit::WebCanvas* canvas = painter.context()->canvas(); 335 WebKit::Platform::current()->themeEngine()->paintTrackbar(canvas, themeData.m_part, themeData.m_state, themeData.m_classicState, WebKit::WebRect(painter.drawRect())); 336 337 return false; 338 } 339 340 static int menuListButtonWidth() 341 { 342 static int width = isRunningLayoutTest() ? kStandardMenuListButtonWidth : 343 IntSize(WebKit::Platform::current()->themeEngine()->getSize(SBP_ARROWBTN)).width(); 344 return width; 345 } 346 347 // Used to paint unstyled menulists (i.e. with the default border) 348 bool RenderThemeChromiumWin::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& r) 349 { 350 if (!o->isBox()) 351 return false; 352 353 const RenderBox* box = toRenderBox(o); 354 int borderRight = box->borderRight(); 355 int borderLeft = box->borderLeft(); 356 int borderTop = box->borderTop(); 357 int borderBottom = box->borderBottom(); 358 359 // If all the borders are 0, then tell skia not to paint the border on the 360 // textfield. FIXME: http://b/1210017 Figure out how to get Windows to not 361 // draw individual borders and then pass that to skia so we can avoid 362 // drawing any borders that are set to 0. For non-zero borders, we draw the 363 // border, but webkit just draws over it. 364 bool drawEdges = !(!borderRight && !borderLeft && !borderTop && !borderBottom); 365 366 paintTextFieldInternal(o, i, r, drawEdges); 367 return paintMenuListButton(o, i, r); 368 } 369 370 bool RenderThemeChromiumWin::paintMenuListButton(RenderObject* o, const PaintInfo& i, const IntRect& r) 371 { 372 if (!o->isBox()) 373 return false; 374 375 const RenderBox* box = toRenderBox(o); 376 // Take padding and border into account. If the MenuList is smaller than 377 // the size of a button, make sure to shrink it appropriately and not put 378 // its x position to the left of the menulist. 379 const int buttonWidth = menuListButtonWidth(); 380 int spacingLeft = box->borderLeft() + box->paddingLeft(); 381 int spacingRight = box->borderRight() + box->paddingRight(); 382 int spacingTop = box->borderTop() + box->paddingTop(); 383 int spacingBottom = box->borderBottom() + box->paddingBottom(); 384 385 int buttonX; 386 if (r.maxX() - r.x() < buttonWidth) 387 buttonX = r.x(); 388 else 389 buttonX = o->style()->direction() == LTR ? r.maxX() - spacingRight - buttonWidth : r.x() + spacingLeft; 390 391 // Compute the rectangle of the button in the destination image. 392 IntRect rect(buttonX, 393 r.y() + spacingTop, 394 std::min(buttonWidth, r.maxX() - r.x()), 395 r.height() - (spacingTop + spacingBottom)); 396 397 // Get the correct theme data for a textfield and paint the menu. 398 ThemePainter painter(i.context, rect); 399 WebKit::WebCanvas* canvas = painter.context()->canvas(); 400 WebKit::Platform::current()->themeEngine()->paintMenuList(canvas, CP_DROPDOWNBUTTON, determineState(o), determineClassicState(o), WebKit::WebRect(painter.drawRect())); 401 return false; 402 } 403 404 double RenderThemeChromiumWin::caretBlinkIntervalInternal() const 405 { 406 // This involves a system call, so we cache the result. 407 static double blinkInterval = querySystemBlinkInterval(RenderTheme::caretBlinkInterval()); 408 return blinkInterval; 409 } 410 411 unsigned RenderThemeChromiumWin::determineState(RenderObject* o, ControlSubPart subPart) 412 { 413 unsigned result = TS_NORMAL; 414 ControlPart appearance = o->style()->appearance(); 415 if (!isEnabled(o)) 416 result = TS_DISABLED; 417 else if (isReadOnlyControl(o)) 418 result = (appearance == TextFieldPart || appearance == TextAreaPart || appearance == SearchFieldPart) ? ETS_READONLY : TS_DISABLED; 419 // Active overrides hover and focused. 420 else if (isPressed(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartPressed(o)) 421 result = TS_PRESSED; 422 else if (supportsFocus(appearance) && isFocused(o)) 423 result = ETS_FOCUSED; 424 else if (isHovered(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartHovered(o)) 425 result = TS_HOT; 426 427 // CBS_UNCHECKED*: 1-4 428 // CBS_CHECKED*: 5-8 429 // CBS_MIXED*: 9-12 430 if (isIndeterminate(o)) 431 result += 8; 432 else if (isChecked(o)) 433 result += 4; 434 return result; 435 } 436 437 unsigned RenderThemeChromiumWin::determineSliderThumbState(RenderObject* o) 438 { 439 unsigned result = TUS_NORMAL; 440 if (!isEnabled(o)) 441 result = TUS_DISABLED; 442 else if (supportsFocus(o->style()->appearance()) && isFocused(o)) 443 result = TUS_FOCUSED; 444 else if (isPressed(o)) 445 result = TUS_PRESSED; 446 else if (isHovered(o)) 447 result = TUS_HOT; 448 return result; 449 } 450 451 unsigned RenderThemeChromiumWin::determineClassicState(RenderObject* o, ControlSubPart subPart) 452 { 453 unsigned result = 0; 454 455 ControlPart part = o->style()->appearance(); 456 457 // Sliders are always in the normal state. 458 if (part == SliderHorizontalPart || part == SliderVerticalPart) 459 return result; 460 461 // So are readonly text fields. 462 if (isReadOnlyControl(o) && (part == TextFieldPart || part == TextAreaPart || part == SearchFieldPart)) 463 return result; 464 465 if (part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart) { 466 if (!isEnabled(o)) 467 result = DFCS_INACTIVE; 468 else if (isPressed(o)) // Active supersedes hover 469 result = DFCS_PUSHED; 470 else if (isHovered(o)) 471 result = DFCS_HOT; 472 } else { 473 if (!isEnabled(o) || isReadOnlyControl(o)) 474 result = DFCS_INACTIVE; 475 // Active supersedes hover 476 else if (isPressed(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartPressed(o)) 477 result = DFCS_PUSHED; 478 else if (supportsFocus(part) && isFocused(o)) // So does focused 479 result = 0; 480 else if (isHovered(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartHovered(o)) 481 result = DFCS_HOT; 482 // Classic theme can't represent indeterminate states. Use unchecked appearance. 483 if (isChecked(o) && !isIndeterminate(o)) 484 result |= DFCS_CHECKED; 485 } 486 return result; 487 } 488 489 ThemeData RenderThemeChromiumWin::getThemeData(RenderObject* o, ControlSubPart subPart) 490 { 491 ThemeData result; 492 switch (o->style()->appearance()) { 493 case CheckboxPart: 494 result.m_part = BP_CHECKBOX; 495 result.m_state = determineState(o); 496 result.m_classicState = DFCS_BUTTONCHECK; 497 break; 498 case RadioPart: 499 result.m_part = BP_RADIOBUTTON; 500 result.m_state = determineState(o); 501 result.m_classicState = DFCS_BUTTONRADIO; 502 break; 503 case SquareButtonPart: 504 case PushButtonPart: 505 case ButtonPart: 506 result.m_part = BP_PUSHBUTTON; 507 result.m_state = determineState(o); 508 result.m_classicState = DFCS_BUTTONPUSH; 509 break; 510 case SliderHorizontalPart: 511 result.m_part = TKP_TRACK; 512 result.m_state = TRS_NORMAL; 513 break; 514 case SliderVerticalPart: 515 result.m_part = TKP_TRACKVERT; 516 result.m_state = TRVS_NORMAL; 517 break; 518 case SliderThumbHorizontalPart: 519 result.m_part = TKP_THUMBBOTTOM; 520 result.m_state = determineSliderThumbState(o); 521 break; 522 case SliderThumbVerticalPart: 523 result.m_part = TKP_THUMBVERT; 524 result.m_state = determineSliderThumbState(o); 525 break; 526 case ListboxPart: 527 case MenulistPart: 528 case MenulistButtonPart: 529 case SearchFieldPart: 530 case TextFieldPart: 531 case TextAreaPart: 532 result.m_part = EP_EDITTEXT; 533 result.m_state = determineState(o); 534 break; 535 case InnerSpinButtonPart: 536 result.m_part = subPart == SpinButtonUp ? SPNP_UP : SPNP_DOWN; 537 result.m_state = determineState(o, subPart); 538 result.m_classicState = subPart == SpinButtonUp ? DFCS_SCROLLUP : DFCS_SCROLLDOWN; 539 break; 540 } 541 542 result.m_classicState |= determineClassicState(o, subPart); 543 544 return result; 545 } 546 547 bool RenderThemeChromiumWin::paintTextFieldInternal(RenderObject* o, 548 const PaintInfo& i, 549 const IntRect& r, 550 bool drawEdges) 551 { 552 // Fallback to white if the specified color object is invalid. 553 Color backgroundColor(Color::white); 554 if (o->style()->visitedDependentColor(CSSPropertyBackgroundColor).isValid()) 555 backgroundColor = o->resolveColor(CSSPropertyBackgroundColor); 556 557 // If we have background-image, don't fill the content area to expose the 558 // parent's background. Also, we shouldn't fill the content area if the 559 // alpha of the color is 0. The API of Windows GDI ignores the alpha. 560 // 561 // Note that we should paint the content area white if we have neither the 562 // background color nor background image explicitly specified to keep the 563 // appearance of select element consistent with other browsers. 564 bool fillContentArea = !o->style()->hasBackgroundImage() && backgroundColor.alpha(); 565 566 if (o->style()->hasBorderRadius()) { 567 // If the style has rounded borders, setup the context to clip the 568 // background (themed or filled) appropriately. 569 // FIXME: make sure we do the right thing if css background-clip is set. 570 i.context->save(); 571 i.context->clipRoundedRect(o->style()->getRoundedBorderFor(r)); 572 } 573 { 574 const ThemeData& themeData = getThemeData(o); 575 ThemePainter painter(i.context, r); 576 WebKit::WebCanvas* canvas = painter.context()->canvas(); 577 WebKit::Platform::current()->themeEngine()->paintTextField(canvas, themeData.m_part, themeData.m_state, themeData.m_classicState, WebKit::WebRect(painter.drawRect()), backgroundColor.rgb(), fillContentArea, drawEdges); 578 // End of block commits the painter before restoring context. 579 } 580 if (o->style()->hasBorderRadius()) 581 i.context->restore(); 582 return false; 583 } 584 585 void RenderThemeChromiumWin::adjustInnerSpinButtonStyle(RenderStyle* style, Element*) const 586 { 587 int width = ScrollbarTheme::theme()->scrollbarThickness(); 588 style->setWidth(Length(width, Fixed)); 589 style->setMinWidth(Length(width, Fixed)); 590 } 591 592 bool RenderThemeChromiumWin::paintInnerSpinButton(RenderObject* object, const PaintInfo& info, const IntRect& rect) 593 { 594 IntRect half = rect; 595 596 // Need explicit blocks to avoid to create multiple ThemePainter instances. 597 { 598 half.setHeight(rect.height() / 2); 599 const ThemeData& upThemeData = getThemeData(object, SpinButtonUp); 600 ThemePainter upPainter(info.context, half); 601 WebKit::WebCanvas* canvas = upPainter.context()->canvas(); 602 WebKit::Platform::current()->themeEngine()->paintSpinButton(canvas, upThemeData.m_part, upThemeData.m_state, upThemeData.m_classicState, WebKit::WebRect(upPainter.drawRect())); 603 } 604 605 { 606 half.setY(rect.y() + rect.height() / 2); 607 const ThemeData& downThemeData = getThemeData(object, SpinButtonDown); 608 ThemePainter downPainter(info.context, half); 609 WebKit::WebCanvas* canvas = downPainter.context()->canvas(); 610 WebKit::Platform::current()->themeEngine()->paintSpinButton(canvas, downThemeData.m_part, downThemeData.m_state, downThemeData.m_classicState, WebKit::WebRect(downPainter.drawRect())); 611 } 612 return false; 613 } 614 615 // MSDN says that update intervals for the bar is 30ms. 616 // http://msdn.microsoft.com/en-us/library/bb760842(v=VS.85).aspx 617 static const double progressAnimationFrameRate = 0.033; 618 619 double RenderThemeChromiumWin::animationRepeatIntervalForProgressBar(RenderProgress*) const 620 { 621 return progressAnimationFrameRate; 622 } 623 624 double RenderThemeChromiumWin::animationDurationForProgressBar(RenderProgress* renderProgress) const 625 { 626 // On Chromium Windows port, animationProgress() and associated values aren't used. 627 // So here we can return arbitrary positive value. 628 return progressAnimationFrameRate; 629 } 630 631 void RenderThemeChromiumWin::adjustProgressBarStyle(RenderStyle*, Element*) const 632 { 633 } 634 635 bool RenderThemeChromiumWin::paintProgressBar(RenderObject* o, const PaintInfo& i, const IntRect& r) 636 { 637 if (!o->isProgress()) 638 return true; 639 640 RenderProgress* renderProgress = toRenderProgress(o); 641 // For indeterminate bar, valueRect is ignored and it is computed by the theme engine 642 // because the animation is a platform detail and WebKit doesn't need to know how. 643 IntRect valueRect = renderProgress->isDeterminate() ? determinateProgressValueRectFor(renderProgress, r) : IntRect(0, 0, 0, 0); 644 double animatedSeconds = renderProgress->animationStartTime() ? WTF::currentTime() - renderProgress->animationStartTime() : 0; 645 ThemePainter painter(i.context, r); 646 DirectionFlippingScope scope(o, i, r); 647 WebKit::WebCanvas* canvas = painter.context()->canvas(); 648 WebKit::Platform::current()->themeEngine()->paintProgressBar(canvas, WebKit::WebRect(r), WebKit::WebRect(valueRect), renderProgress->isDeterminate(), animatedSeconds); 649 return false; 650 } 651 652 bool RenderThemeChromiumWin::shouldOpenPickerWithF4Key() const 653 { 654 return true; 655 } 656 657 bool RenderThemeChromiumWin::shouldUseFallbackTheme(RenderStyle* style) const 658 { 659 ControlPart part = style->appearance(); 660 if (part == CheckboxPart || part == RadioPart) 661 return style->effectiveZoom() != 1; 662 return false; 663 } 664 665 } // namespace WebCore 666