1 /** 2 * This file is part of the theme implementation for form controls in WebCore. 3 * 4 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Computer, Inc. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Library General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Library General Public License for more details. 15 * 16 * You should have received a copy of the GNU Library General Public License 17 * along with this library; see the file COPYING.LIB. If not, write to 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA. 20 */ 21 22 #include "config.h" 23 #include "core/rendering/RenderTheme.h" 24 25 #include "CSSValueKeywords.h" 26 #include "HTMLNames.h" 27 #include "InputTypeNames.h" 28 #include "RuntimeEnabledFeatures.h" 29 #include "core/dom/Document.h" 30 #include "core/dom/shadow/ElementShadow.h" 31 #include "core/editing/FrameSelection.h" 32 #include "core/fileapi/FileList.h" 33 #include "core/html/HTMLCollection.h" 34 #include "core/html/HTMLDataListElement.h" 35 #include "core/html/HTMLInputElement.h" 36 #include "core/html/HTMLMeterElement.h" 37 #include "core/html/HTMLOptionElement.h" 38 #include "core/html/parser/HTMLParserIdioms.h" 39 #include "core/html/shadow/MediaControlElements.h" 40 #include "core/html/shadow/ShadowElementNames.h" 41 #include "core/html/shadow/SpinButtonElement.h" 42 #include "core/html/shadow/TextControlInnerElements.h" 43 #include "core/page/FocusController.h" 44 #include "core/frame/Frame.h" 45 #include "core/page/Page.h" 46 #include "core/frame/Settings.h" 47 #include "core/rendering/PaintInfo.h" 48 #include "core/rendering/RenderMeter.h" 49 #include "core/rendering/RenderView.h" 50 #include "core/rendering/style/RenderStyle.h" 51 #include "platform/FileMetadata.h" 52 #include "platform/FloatConversion.h" 53 #include "platform/fonts/FontSelector.h" 54 #include "platform/graphics/GraphicsContextStateSaver.h" 55 #include "platform/text/PlatformLocale.h" 56 #include "platform/text/StringTruncator.h" 57 #include "public/platform/Platform.h" 58 #include "public/platform/WebFallbackThemeEngine.h" 59 #include "public/platform/WebRect.h" 60 #include "wtf/text/StringBuilder.h" 61 62 #if ENABLE(INPUT_SPEECH) 63 #include "core/rendering/RenderInputSpeech.h" 64 #endif 65 66 // The methods in this file are shared by all themes on every platform. 67 68 namespace WebCore { 69 70 using namespace HTMLNames; 71 72 static Color& customFocusRingColor() 73 { 74 DEFINE_STATIC_LOCAL(Color, color, ()); 75 return color; 76 } 77 78 static blink::WebFallbackThemeEngine::State getWebFallbackThemeState(const RenderTheme* theme, const RenderObject* o) 79 { 80 if (!theme->isEnabled(o)) 81 return blink::WebFallbackThemeEngine::StateDisabled; 82 if (theme->isPressed(o)) 83 return blink::WebFallbackThemeEngine::StatePressed; 84 if (theme->isHovered(o)) 85 return blink::WebFallbackThemeEngine::StateHover; 86 87 return blink::WebFallbackThemeEngine::StateNormal; 88 } 89 90 RenderTheme::RenderTheme() 91 #if USE(NEW_THEME) 92 : m_platformTheme(platformTheme()) 93 #endif 94 { 95 } 96 97 void RenderTheme::adjustStyle(RenderStyle* style, Element* e, const CachedUAStyle& uaStyle) 98 { 99 // Force inline and table display styles to be inline-block (except for table- which is block) 100 ControlPart part = style->appearance(); 101 if (style->display() == INLINE || style->display() == INLINE_TABLE || style->display() == TABLE_ROW_GROUP 102 || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_FOOTER_GROUP 103 || style->display() == TABLE_ROW || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_COLUMN 104 || style->display() == TABLE_CELL || style->display() == TABLE_CAPTION) 105 style->setDisplay(INLINE_BLOCK); 106 else if (style->display() == LIST_ITEM || style->display() == TABLE) 107 style->setDisplay(BLOCK); 108 109 if (uaStyle.hasAppearance && isControlStyled(style, uaStyle)) { 110 if (part == MenulistPart) { 111 style->setAppearance(MenulistButtonPart); 112 part = MenulistButtonPart; 113 } else 114 style->setAppearance(NoControlPart); 115 } 116 117 if (!style->hasAppearance()) 118 return; 119 120 if (shouldUseFallbackTheme(style)) { 121 adjustStyleUsingFallbackTheme(style, e); 122 return; 123 } 124 125 #if USE(NEW_THEME) 126 switch (part) { 127 case CheckboxPart: 128 case InnerSpinButtonPart: 129 case RadioPart: 130 case PushButtonPart: 131 case SquareButtonPart: 132 case ButtonPart: { 133 // Border 134 LengthBox borderBox(style->borderTopWidth(), style->borderRightWidth(), style->borderBottomWidth(), style->borderLeftWidth()); 135 borderBox = m_platformTheme->controlBorder(part, style->font().fontDescription(), borderBox, style->effectiveZoom()); 136 if (borderBox.top().value() != static_cast<int>(style->borderTopWidth())) { 137 if (borderBox.top().value()) 138 style->setBorderTopWidth(borderBox.top().value()); 139 else 140 style->resetBorderTop(); 141 } 142 if (borderBox.right().value() != static_cast<int>(style->borderRightWidth())) { 143 if (borderBox.right().value()) 144 style->setBorderRightWidth(borderBox.right().value()); 145 else 146 style->resetBorderRight(); 147 } 148 if (borderBox.bottom().value() != static_cast<int>(style->borderBottomWidth())) { 149 style->setBorderBottomWidth(borderBox.bottom().value()); 150 if (borderBox.bottom().value()) 151 style->setBorderBottomWidth(borderBox.bottom().value()); 152 else 153 style->resetBorderBottom(); 154 } 155 if (borderBox.left().value() != static_cast<int>(style->borderLeftWidth())) { 156 style->setBorderLeftWidth(borderBox.left().value()); 157 if (borderBox.left().value()) 158 style->setBorderLeftWidth(borderBox.left().value()); 159 else 160 style->resetBorderLeft(); 161 } 162 163 // Padding 164 LengthBox paddingBox = m_platformTheme->controlPadding(part, style->font().fontDescription(), style->paddingBox(), style->effectiveZoom()); 165 if (paddingBox != style->paddingBox()) 166 style->setPaddingBox(paddingBox); 167 168 // Whitespace 169 if (m_platformTheme->controlRequiresPreWhiteSpace(part)) 170 style->setWhiteSpace(PRE); 171 172 // Width / Height 173 // The width and height here are affected by the zoom. 174 // FIXME: Check is flawed, since it doesn't take min-width/max-width into account. 175 LengthSize controlSize = m_platformTheme->controlSize(part, style->font().fontDescription(), LengthSize(style->width(), style->height()), style->effectiveZoom()); 176 if (controlSize.width() != style->width()) 177 style->setWidth(controlSize.width()); 178 if (controlSize.height() != style->height()) 179 style->setHeight(controlSize.height()); 180 181 // Min-Width / Min-Height 182 LengthSize minControlSize = m_platformTheme->minimumControlSize(part, style->font().fontDescription(), style->effectiveZoom()); 183 if (minControlSize.width() != style->minWidth()) 184 style->setMinWidth(minControlSize.width()); 185 if (minControlSize.height() != style->minHeight()) 186 style->setMinHeight(minControlSize.height()); 187 188 // Font 189 FontDescription controlFont = m_platformTheme->controlFont(part, style->font().fontDescription(), style->effectiveZoom()); 190 if (controlFont != style->font().fontDescription()) { 191 // Reset our line-height 192 style->setLineHeight(RenderStyle::initialLineHeight()); 193 194 // Now update our font. 195 if (style->setFontDescription(controlFont)) 196 style->font().update(0); 197 } 198 } 199 default: 200 break; 201 } 202 #endif 203 204 // Call the appropriate style adjustment method based off the appearance value. 205 switch (style->appearance()) { 206 #if !USE(NEW_THEME) 207 case CheckboxPart: 208 return adjustCheckboxStyle(style, e); 209 case RadioPart: 210 return adjustRadioStyle(style, e); 211 case PushButtonPart: 212 case SquareButtonPart: 213 case ButtonPart: 214 return adjustButtonStyle(style, e); 215 case InnerSpinButtonPart: 216 return adjustInnerSpinButtonStyle(style, e); 217 #endif 218 case MenulistPart: 219 return adjustMenuListStyle(style, e); 220 case MenulistButtonPart: 221 return adjustMenuListButtonStyle(style, e); 222 case SliderThumbHorizontalPart: 223 case SliderThumbVerticalPart: 224 return adjustSliderThumbStyle(style, e); 225 case SearchFieldPart: 226 return adjustSearchFieldStyle(style, e); 227 case SearchFieldCancelButtonPart: 228 return adjustSearchFieldCancelButtonStyle(style, e); 229 case SearchFieldDecorationPart: 230 return adjustSearchFieldDecorationStyle(style, e); 231 case SearchFieldResultsDecorationPart: 232 return adjustSearchFieldResultsDecorationStyle(style, e); 233 #if ENABLE(INPUT_SPEECH) 234 case InputSpeechButtonPart: 235 return adjustInputFieldSpeechButtonStyle(style, e); 236 #endif 237 default: 238 break; 239 } 240 } 241 242 bool RenderTheme::paint(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 243 { 244 // If painting is disabled, but we aren't updating control tints, then just bail. 245 // If we are updating control tints, just schedule a repaint if the theme supports tinting 246 // for that control. 247 if (paintInfo.context->updatingControlTints()) { 248 if (controlSupportsTints(o)) 249 o->repaint(); 250 return false; 251 } 252 if (paintInfo.context->paintingDisabled()) 253 return false; 254 255 ControlPart part = o->style()->appearance(); 256 257 if (shouldUseFallbackTheme(o->style())) 258 return paintUsingFallbackTheme(o, paintInfo, r); 259 260 #if USE(NEW_THEME) 261 switch (part) { 262 case CheckboxPart: 263 case RadioPart: 264 case PushButtonPart: 265 case SquareButtonPart: 266 case ButtonPart: 267 case InnerSpinButtonPart: 268 m_platformTheme->paint(part, controlStatesForRenderer(o), const_cast<GraphicsContext*>(paintInfo.context), r, o->style()->effectiveZoom(), o->view()->frameView()); 269 return false; 270 default: 271 break; 272 } 273 #endif 274 275 // Call the appropriate paint method based off the appearance value. 276 switch (part) { 277 #if !USE(NEW_THEME) 278 case CheckboxPart: 279 return paintCheckbox(o, paintInfo, r); 280 case RadioPart: 281 return paintRadio(o, paintInfo, r); 282 case PushButtonPart: 283 case SquareButtonPart: 284 case ButtonPart: 285 return paintButton(o, paintInfo, r); 286 case InnerSpinButtonPart: 287 return paintInnerSpinButton(o, paintInfo, r); 288 #endif 289 case MenulistPart: 290 return paintMenuList(o, paintInfo, r); 291 case MeterPart: 292 case RelevancyLevelIndicatorPart: 293 case ContinuousCapacityLevelIndicatorPart: 294 case DiscreteCapacityLevelIndicatorPart: 295 case RatingLevelIndicatorPart: 296 return paintMeter(o, paintInfo, r); 297 case ProgressBarPart: 298 return paintProgressBar(o, paintInfo, r); 299 case SliderHorizontalPart: 300 case SliderVerticalPart: 301 return paintSliderTrack(o, paintInfo, r); 302 case SliderThumbHorizontalPart: 303 case SliderThumbVerticalPart: 304 return paintSliderThumb(o, paintInfo, r); 305 case MediaEnterFullscreenButtonPart: 306 case MediaExitFullscreenButtonPart: 307 return paintMediaFullscreenButton(o, paintInfo, r); 308 case MediaPlayButtonPart: 309 return paintMediaPlayButton(o, paintInfo, r); 310 case MediaOverlayPlayButtonPart: 311 return paintMediaOverlayPlayButton(o, paintInfo, r); 312 case MediaMuteButtonPart: 313 return paintMediaMuteButton(o, paintInfo, r); 314 case MediaSeekBackButtonPart: 315 return paintMediaSeekBackButton(o, paintInfo, r); 316 case MediaSeekForwardButtonPart: 317 return paintMediaSeekForwardButton(o, paintInfo, r); 318 case MediaRewindButtonPart: 319 return paintMediaRewindButton(o, paintInfo, r); 320 case MediaReturnToRealtimeButtonPart: 321 return paintMediaReturnToRealtimeButton(o, paintInfo, r); 322 case MediaToggleClosedCaptionsButtonPart: 323 return paintMediaToggleClosedCaptionsButton(o, paintInfo, r); 324 case MediaSliderPart: 325 return paintMediaSliderTrack(o, paintInfo, r); 326 case MediaSliderThumbPart: 327 return paintMediaSliderThumb(o, paintInfo, r); 328 case MediaVolumeSliderMuteButtonPart: 329 return paintMediaMuteButton(o, paintInfo, r); 330 case MediaVolumeSliderContainerPart: 331 return paintMediaVolumeSliderContainer(o, paintInfo, r); 332 case MediaVolumeSliderPart: 333 return paintMediaVolumeSliderTrack(o, paintInfo, r); 334 case MediaVolumeSliderThumbPart: 335 return paintMediaVolumeSliderThumb(o, paintInfo, r); 336 case MediaFullScreenVolumeSliderPart: 337 return paintMediaFullScreenVolumeSliderTrack(o, paintInfo, r); 338 case MediaFullScreenVolumeSliderThumbPart: 339 return paintMediaFullScreenVolumeSliderThumb(o, paintInfo, r); 340 case MediaTimeRemainingPart: 341 return paintMediaTimeRemaining(o, paintInfo, r); 342 case MediaCurrentTimePart: 343 return paintMediaCurrentTime(o, paintInfo, r); 344 case MediaControlsBackgroundPart: 345 return paintMediaControlsBackground(o, paintInfo, r); 346 case MenulistButtonPart: 347 case TextFieldPart: 348 case TextAreaPart: 349 case ListboxPart: 350 return true; 351 case SearchFieldPart: 352 return paintSearchField(o, paintInfo, r); 353 case SearchFieldCancelButtonPart: 354 return paintSearchFieldCancelButton(o, paintInfo, r); 355 case SearchFieldDecorationPart: 356 return paintSearchFieldDecoration(o, paintInfo, r); 357 case SearchFieldResultsDecorationPart: 358 return paintSearchFieldResultsDecoration(o, paintInfo, r); 359 #if ENABLE(INPUT_SPEECH) 360 case InputSpeechButtonPart: 361 return paintInputFieldSpeechButton(o, paintInfo, r); 362 #endif 363 default: 364 break; 365 } 366 367 return true; // We don't support the appearance, so let the normal background/border paint. 368 } 369 370 bool RenderTheme::paintBorderOnly(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 371 { 372 if (paintInfo.context->paintingDisabled()) 373 return false; 374 375 // Call the appropriate paint method based off the appearance value. 376 switch (o->style()->appearance()) { 377 case TextFieldPart: 378 return paintTextField(o, paintInfo, r); 379 case ListboxPart: 380 case TextAreaPart: 381 return paintTextArea(o, paintInfo, r); 382 case MenulistButtonPart: 383 case SearchFieldPart: 384 return true; 385 case CheckboxPart: 386 case RadioPart: 387 case PushButtonPart: 388 case SquareButtonPart: 389 case ButtonPart: 390 case MenulistPart: 391 case MeterPart: 392 case RelevancyLevelIndicatorPart: 393 case ContinuousCapacityLevelIndicatorPart: 394 case DiscreteCapacityLevelIndicatorPart: 395 case RatingLevelIndicatorPart: 396 case ProgressBarPart: 397 case SliderHorizontalPart: 398 case SliderVerticalPart: 399 case SliderThumbHorizontalPart: 400 case SliderThumbVerticalPart: 401 case SearchFieldCancelButtonPart: 402 case SearchFieldDecorationPart: 403 case SearchFieldResultsDecorationPart: 404 #if ENABLE(INPUT_SPEECH) 405 case InputSpeechButtonPart: 406 #endif 407 default: 408 break; 409 } 410 411 return false; 412 } 413 414 bool RenderTheme::paintDecorations(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 415 { 416 if (paintInfo.context->paintingDisabled()) 417 return false; 418 419 // Call the appropriate paint method based off the appearance value. 420 switch (o->style()->appearance()) { 421 case MenulistButtonPart: 422 return paintMenuListButton(o, paintInfo, r); 423 case TextFieldPart: 424 case TextAreaPart: 425 case ListboxPart: 426 case CheckboxPart: 427 case RadioPart: 428 case PushButtonPart: 429 case SquareButtonPart: 430 case ButtonPart: 431 case MenulistPart: 432 case MeterPart: 433 case RelevancyLevelIndicatorPart: 434 case ContinuousCapacityLevelIndicatorPart: 435 case DiscreteCapacityLevelIndicatorPart: 436 case RatingLevelIndicatorPart: 437 case ProgressBarPart: 438 case SliderHorizontalPart: 439 case SliderVerticalPart: 440 case SliderThumbHorizontalPart: 441 case SliderThumbVerticalPart: 442 case SearchFieldPart: 443 case SearchFieldCancelButtonPart: 444 case SearchFieldDecorationPart: 445 case SearchFieldResultsDecorationPart: 446 #if ENABLE(INPUT_SPEECH) 447 case InputSpeechButtonPart: 448 #endif 449 default: 450 break; 451 } 452 453 return false; 454 } 455 456 String RenderTheme::extraDefaultStyleSheet() 457 { 458 if (!RuntimeEnabledFeatures::dataListElementEnabled() && !RuntimeEnabledFeatures::dialogElementEnabled()) 459 return String(); 460 StringBuilder runtimeCSS; 461 462 if (RuntimeEnabledFeatures::dataListElementEnabled()) { 463 runtimeCSS.appendLiteral("datalist {display: none ;}"); 464 465 if (RuntimeEnabledFeatures::inputTypeColorEnabled()) { 466 runtimeCSS.appendLiteral("input[type=\"color\"][list] { -webkit-appearance: menulist; width: 88px; height: 23px;}"); 467 runtimeCSS.appendLiteral("input[type=\"color\"][list]::-webkit-color-swatch-wrapper { padding-left: 8px; padding-right: 24px;}"); 468 runtimeCSS.appendLiteral("input[type=\"color\"][list]::-webkit-color-swatch { border-color: #000000;}"); 469 } 470 } 471 if (RuntimeEnabledFeatures::dialogElementEnabled()) { 472 runtimeCSS.appendLiteral("dialog:not([open]) { display: none; }"); 473 runtimeCSS.appendLiteral("dialog { position: absolute; left: 0; right: 0; width: -webkit-fit-content; height: -webkit-fit-content; margin: auto; border: solid; padding: 1em; background: white; color: black;}"); 474 runtimeCSS.appendLiteral("dialog::backdrop { position: fixed; top: 0; right: 0; bottom: 0; left: 0; background: rgba(0,0,0,0.1); }"); 475 } 476 477 return runtimeCSS.toString(); 478 } 479 480 String RenderTheme::formatMediaControlsTime(float time) const 481 { 482 if (!std::isfinite(time)) 483 time = 0; 484 int seconds = (int)fabsf(time); 485 int hours = seconds / (60 * 60); 486 int minutes = (seconds / 60) % 60; 487 seconds %= 60; 488 if (hours) { 489 if (hours > 9) 490 return String::format("%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds); 491 492 return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds); 493 } 494 495 return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds); 496 } 497 498 String RenderTheme::formatMediaControlsCurrentTime(float currentTime, float /*duration*/) const 499 { 500 return formatMediaControlsTime(currentTime); 501 } 502 503 Color RenderTheme::activeSelectionBackgroundColor() const 504 { 505 if (!m_activeSelectionBackgroundColor.isValid()) 506 m_activeSelectionBackgroundColor = platformActiveSelectionBackgroundColor().blendWithWhite(); 507 return m_activeSelectionBackgroundColor; 508 } 509 510 Color RenderTheme::inactiveSelectionBackgroundColor() const 511 { 512 if (!m_inactiveSelectionBackgroundColor.isValid()) 513 m_inactiveSelectionBackgroundColor = platformInactiveSelectionBackgroundColor().blendWithWhite(); 514 return m_inactiveSelectionBackgroundColor; 515 } 516 517 Color RenderTheme::activeSelectionForegroundColor() const 518 { 519 if (!m_activeSelectionForegroundColor.isValid() && supportsSelectionForegroundColors()) 520 m_activeSelectionForegroundColor = platformActiveSelectionForegroundColor(); 521 return m_activeSelectionForegroundColor; 522 } 523 524 Color RenderTheme::inactiveSelectionForegroundColor() const 525 { 526 if (!m_inactiveSelectionForegroundColor.isValid() && supportsSelectionForegroundColors()) 527 m_inactiveSelectionForegroundColor = platformInactiveSelectionForegroundColor(); 528 return m_inactiveSelectionForegroundColor; 529 } 530 531 Color RenderTheme::activeListBoxSelectionBackgroundColor() const 532 { 533 if (!m_activeListBoxSelectionBackgroundColor.isValid()) 534 m_activeListBoxSelectionBackgroundColor = platformActiveListBoxSelectionBackgroundColor(); 535 return m_activeListBoxSelectionBackgroundColor; 536 } 537 538 Color RenderTheme::inactiveListBoxSelectionBackgroundColor() const 539 { 540 if (!m_inactiveListBoxSelectionBackgroundColor.isValid()) 541 m_inactiveListBoxSelectionBackgroundColor = platformInactiveListBoxSelectionBackgroundColor(); 542 return m_inactiveListBoxSelectionBackgroundColor; 543 } 544 545 Color RenderTheme::activeListBoxSelectionForegroundColor() const 546 { 547 if (!m_activeListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors()) 548 m_activeListBoxSelectionForegroundColor = platformActiveListBoxSelectionForegroundColor(); 549 return m_activeListBoxSelectionForegroundColor; 550 } 551 552 Color RenderTheme::inactiveListBoxSelectionForegroundColor() const 553 { 554 if (!m_inactiveListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors()) 555 m_inactiveListBoxSelectionForegroundColor = platformInactiveListBoxSelectionForegroundColor(); 556 return m_inactiveListBoxSelectionForegroundColor; 557 } 558 559 Color RenderTheme::platformActiveSelectionBackgroundColor() const 560 { 561 // Use a blue color by default if the platform theme doesn't define anything. 562 return Color(0, 0, 255); 563 } 564 565 Color RenderTheme::platformActiveSelectionForegroundColor() const 566 { 567 // Use a white color by default if the platform theme doesn't define anything. 568 return Color::white; 569 } 570 571 Color RenderTheme::platformInactiveSelectionBackgroundColor() const 572 { 573 // Use a grey color by default if the platform theme doesn't define anything. 574 // This color matches Firefox's inactive color. 575 return Color(176, 176, 176); 576 } 577 578 Color RenderTheme::platformInactiveSelectionForegroundColor() const 579 { 580 // Use a black color by default. 581 return Color::black; 582 } 583 584 Color RenderTheme::platformActiveListBoxSelectionBackgroundColor() const 585 { 586 return platformActiveSelectionBackgroundColor(); 587 } 588 589 Color RenderTheme::platformActiveListBoxSelectionForegroundColor() const 590 { 591 return platformActiveSelectionForegroundColor(); 592 } 593 594 Color RenderTheme::platformInactiveListBoxSelectionBackgroundColor() const 595 { 596 return platformInactiveSelectionBackgroundColor(); 597 } 598 599 Color RenderTheme::platformInactiveListBoxSelectionForegroundColor() const 600 { 601 return platformInactiveSelectionForegroundColor(); 602 } 603 604 int RenderTheme::baselinePosition(const RenderObject* o) const 605 { 606 if (!o->isBox()) 607 return 0; 608 609 const RenderBox* box = toRenderBox(o); 610 611 #if USE(NEW_THEME) 612 return box->height() + box->marginTop() + m_platformTheme->baselinePositionAdjustment(o->style()->appearance()) * o->style()->effectiveZoom(); 613 #else 614 return box->height() + box->marginTop(); 615 #endif 616 } 617 618 bool RenderTheme::isControlContainer(ControlPart appearance) const 619 { 620 // There are more leaves than this, but we'll patch this function as we add support for 621 // more controls. 622 return appearance != CheckboxPart && appearance != RadioPart; 623 } 624 625 static bool isBackgroundOrBorderStyled(const RenderStyle& style, const CachedUAStyle& uaStyle) 626 { 627 // Code below excludes the background-repeat from comparison by resetting it 628 FillLayer backgroundCopy = uaStyle.backgroundLayers; 629 FillLayer backgroundLayersCopy = *style.backgroundLayers(); 630 backgroundCopy.setRepeatX(NoRepeatFill); 631 backgroundCopy.setRepeatY(NoRepeatFill); 632 backgroundLayersCopy.setRepeatX(NoRepeatFill); 633 backgroundLayersCopy.setRepeatY(NoRepeatFill); 634 // Test the style to see if the UA border and background match. 635 return style.border() != uaStyle.border 636 || backgroundLayersCopy != backgroundCopy 637 || style.visitedDependentColor(CSSPropertyBackgroundColor) != uaStyle.backgroundColor; 638 } 639 640 bool RenderTheme::isControlStyled(const RenderStyle* style, const CachedUAStyle& uaStyle) const 641 { 642 switch (style->appearance()) { 643 case PushButtonPart: 644 case SquareButtonPart: 645 case ButtonPart: 646 case ProgressBarPart: 647 case MeterPart: 648 case RelevancyLevelIndicatorPart: 649 case ContinuousCapacityLevelIndicatorPart: 650 case DiscreteCapacityLevelIndicatorPart: 651 case RatingLevelIndicatorPart: 652 return isBackgroundOrBorderStyled(*style, uaStyle); 653 654 case ListboxPart: 655 case MenulistPart: 656 case SearchFieldPart: 657 case TextAreaPart: 658 case TextFieldPart: 659 return isBackgroundOrBorderStyled(*style, uaStyle) || style->boxShadow(); 660 661 case SliderHorizontalPart: 662 case SliderVerticalPart: 663 return style->boxShadow(); 664 665 default: 666 return false; 667 } 668 } 669 670 void RenderTheme::adjustRepaintRect(const RenderObject* o, IntRect& r) 671 { 672 #if USE(NEW_THEME) 673 m_platformTheme->inflateControlPaintRect(o->style()->appearance(), controlStatesForRenderer(o), r, o->style()->effectiveZoom()); 674 #endif 675 } 676 677 bool RenderTheme::shouldDrawDefaultFocusRing(RenderObject* renderer) const 678 { 679 if (supportsFocusRing(renderer->style())) 680 return false; 681 if (!renderer->style()->hasAppearance()) 682 return true; 683 Node* node = renderer->node(); 684 if (!node) 685 return true; 686 // We can't use RenderTheme::isFocused because outline:auto might be 687 // specified to non-:focus rulesets. 688 if (node->focused() && !node->shouldHaveFocusAppearance()) 689 return false; 690 return true; 691 } 692 693 bool RenderTheme::supportsFocusRing(const RenderStyle* style) const 694 { 695 return (style->hasAppearance() && style->appearance() != TextFieldPart && style->appearance() != TextAreaPart && style->appearance() != MenulistButtonPart && style->appearance() != ListboxPart); 696 } 697 698 bool RenderTheme::stateChanged(RenderObject* o, ControlState state) const 699 { 700 // Default implementation assumes the controls don't respond to changes in :hover state 701 if (state == HoverState && !supportsHover(o->style())) 702 return false; 703 704 // Assume pressed state is only responded to if the control is enabled. 705 if (state == PressedState && !isEnabled(o)) 706 return false; 707 708 // Repaint the control. 709 o->repaint(); 710 return true; 711 } 712 713 ControlStates RenderTheme::controlStatesForRenderer(const RenderObject* o) const 714 { 715 ControlStates result = 0; 716 if (isHovered(o)) { 717 result |= HoverState; 718 if (isSpinUpButtonPartHovered(o)) 719 result |= SpinUpState; 720 } 721 if (isPressed(o)) { 722 result |= PressedState; 723 if (isSpinUpButtonPartPressed(o)) 724 result |= SpinUpState; 725 } 726 if (isFocused(o) && o->style()->outlineStyleIsAuto()) 727 result |= FocusState; 728 if (isEnabled(o)) 729 result |= EnabledState; 730 if (isChecked(o)) 731 result |= CheckedState; 732 if (isReadOnlyControl(o)) 733 result |= ReadOnlyState; 734 if (!isActive(o)) 735 result |= WindowInactiveState; 736 if (isIndeterminate(o)) 737 result |= IndeterminateState; 738 return result; 739 } 740 741 bool RenderTheme::isActive(const RenderObject* o) const 742 { 743 Node* node = o->node(); 744 if (!node) 745 return false; 746 747 Page* page = node->document().page(); 748 if (!page) 749 return false; 750 751 return page->focusController().isActive(); 752 } 753 754 bool RenderTheme::isChecked(const RenderObject* o) const 755 { 756 if (!o->node() || !o->node()->hasTagName(inputTag)) 757 return false; 758 return toHTMLInputElement(o->node())->shouldAppearChecked(); 759 } 760 761 bool RenderTheme::isIndeterminate(const RenderObject* o) const 762 { 763 if (!o->node() || !o->node()->hasTagName(inputTag)) 764 return false; 765 return toHTMLInputElement(o->node())->shouldAppearIndeterminate(); 766 } 767 768 bool RenderTheme::isEnabled(const RenderObject* o) const 769 { 770 Node* node = o->node(); 771 if (!node || !node->isElementNode()) 772 return true; 773 return !toElement(node)->isDisabledFormControl(); 774 } 775 776 bool RenderTheme::isFocused(const RenderObject* o) const 777 { 778 Node* node = o->node(); 779 if (!node) 780 return false; 781 782 node = node->focusDelegate(); 783 Document& document = node->document(); 784 Frame* frame = document.frame(); 785 return node == document.focusedElement() && node->shouldHaveFocusAppearance() && frame && frame->selection().isFocusedAndActive(); 786 } 787 788 bool RenderTheme::isPressed(const RenderObject* o) const 789 { 790 if (!o->node()) 791 return false; 792 return o->node()->active(); 793 } 794 795 bool RenderTheme::isSpinUpButtonPartPressed(const RenderObject* o) const 796 { 797 Node* node = o->node(); 798 if (!node || !node->active() || !node->isElementNode() 799 || !toElement(node)->isSpinButtonElement()) 800 return false; 801 SpinButtonElement* element = toSpinButtonElement(node); 802 return element->upDownState() == SpinButtonElement::Up; 803 } 804 805 bool RenderTheme::isReadOnlyControl(const RenderObject* o) const 806 { 807 Node* node = o->node(); 808 if (!node || !node->isElementNode()) 809 return false; 810 return toElement(node)->matchesReadOnlyPseudoClass(); 811 } 812 813 bool RenderTheme::isHovered(const RenderObject* o) const 814 { 815 Node* node = o->node(); 816 if (!node) 817 return false; 818 if (!node->isElementNode() || !toElement(node)->isSpinButtonElement()) 819 return node->hovered(); 820 SpinButtonElement* element = toSpinButtonElement(node); 821 return element->hovered() && element->upDownState() != SpinButtonElement::Indeterminate; 822 } 823 824 bool RenderTheme::isSpinUpButtonPartHovered(const RenderObject* o) const 825 { 826 Node* node = o->node(); 827 if (!node || !node->isElementNode() || !toElement(node)->isSpinButtonElement()) 828 return false; 829 SpinButtonElement* element = toSpinButtonElement(node); 830 return element->upDownState() == SpinButtonElement::Up; 831 } 832 833 #if !USE(NEW_THEME) 834 835 void RenderTheme::adjustCheckboxStyle(RenderStyle* style, Element*) const 836 { 837 // A summary of the rules for checkbox designed to match WinIE: 838 // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.) 839 // font-size - not honored (control has no text), but we use it to decide which control size to use. 840 setCheckboxSize(style); 841 842 // padding - not honored by WinIE, needs to be removed. 843 style->resetPadding(); 844 845 // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme) 846 // for now, we will not honor it. 847 style->resetBorder(); 848 } 849 850 void RenderTheme::adjustRadioStyle(RenderStyle* style, Element*) const 851 { 852 // A summary of the rules for checkbox designed to match WinIE: 853 // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.) 854 // font-size - not honored (control has no text), but we use it to decide which control size to use. 855 setRadioSize(style); 856 857 // padding - not honored by WinIE, needs to be removed. 858 style->resetPadding(); 859 860 // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme) 861 // for now, we will not honor it. 862 style->resetBorder(); 863 } 864 865 void RenderTheme::adjustButtonStyle(RenderStyle* style, Element*) const 866 { 867 } 868 869 void RenderTheme::adjustInnerSpinButtonStyle(RenderStyle*, Element*) const 870 { 871 } 872 #endif 873 874 void RenderTheme::adjustMenuListStyle(RenderStyle*, Element*) const 875 { 876 } 877 878 #if ENABLE(INPUT_SPEECH) 879 void RenderTheme::adjustInputFieldSpeechButtonStyle(RenderStyle* style, Element* element) const 880 { 881 RenderInputSpeech::adjustInputFieldSpeechButtonStyle(style, element); 882 } 883 884 bool RenderTheme::paintInputFieldSpeechButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect) 885 { 886 return RenderInputSpeech::paintInputFieldSpeechButton(object, paintInfo, rect); 887 } 888 #endif 889 890 IntSize RenderTheme::meterSizeForBounds(const RenderMeter*, const IntRect& bounds) const 891 { 892 return bounds.size(); 893 } 894 895 bool RenderTheme::supportsMeter(ControlPart) const 896 { 897 return false; 898 } 899 900 bool RenderTheme::paintMeter(RenderObject*, const PaintInfo&, const IntRect&) 901 { 902 return true; 903 } 904 905 void RenderTheme::paintSliderTicks(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect) 906 { 907 Node* node = o->node(); 908 if (!node || !node->hasTagName(inputTag)) 909 return; 910 911 HTMLInputElement* input = toHTMLInputElement(node); 912 HTMLDataListElement* dataList = input->dataList(); 913 if (!dataList) 914 return; 915 916 double min = input->minimum(); 917 double max = input->maximum(); 918 ControlPart part = o->style()->appearance(); 919 // We don't support ticks on alternate sliders like MediaVolumeSliders. 920 if (part != SliderHorizontalPart && part != SliderVerticalPart) 921 return; 922 bool isHorizontal = part == SliderHorizontalPart; 923 924 IntSize thumbSize; 925 RenderObject* thumbRenderer = input->userAgentShadowRoot()->getElementById(ShadowElementNames::sliderThumb())->renderer(); 926 if (thumbRenderer) { 927 RenderStyle* thumbStyle = thumbRenderer->style(); 928 int thumbWidth = thumbStyle->width().intValue(); 929 int thumbHeight = thumbStyle->height().intValue(); 930 thumbSize.setWidth(isHorizontal ? thumbWidth : thumbHeight); 931 thumbSize.setHeight(isHorizontal ? thumbHeight : thumbWidth); 932 } 933 934 IntSize tickSize = sliderTickSize(); 935 float zoomFactor = o->style()->effectiveZoom(); 936 FloatRect tickRect; 937 int tickRegionSideMargin = 0; 938 int tickRegionWidth = 0; 939 IntRect trackBounds; 940 RenderObject* trackRenderer = input->userAgentShadowRoot()->getElementById(ShadowElementNames::sliderTrack())->renderer(); 941 // We can ignoring transforms because transform is handled by the graphics context. 942 if (trackRenderer) 943 trackBounds = trackRenderer->absoluteBoundingBoxRectIgnoringTransforms(); 944 IntRect sliderBounds = o->absoluteBoundingBoxRectIgnoringTransforms(); 945 946 // Make position relative to the transformed ancestor element. 947 trackBounds.setX(trackBounds.x() - sliderBounds.x() + rect.x()); 948 trackBounds.setY(trackBounds.y() - sliderBounds.y() + rect.y()); 949 950 if (isHorizontal) { 951 tickRect.setWidth(floor(tickSize.width() * zoomFactor)); 952 tickRect.setHeight(floor(tickSize.height() * zoomFactor)); 953 tickRect.setY(floor(rect.y() + rect.height() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor)); 954 tickRegionSideMargin = trackBounds.x() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0; 955 tickRegionWidth = trackBounds.width() - thumbSize.width(); 956 } else { 957 tickRect.setWidth(floor(tickSize.height() * zoomFactor)); 958 tickRect.setHeight(floor(tickSize.width() * zoomFactor)); 959 tickRect.setX(floor(rect.x() + rect.width() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor)); 960 tickRegionSideMargin = trackBounds.y() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0; 961 tickRegionWidth = trackBounds.height() - thumbSize.width(); 962 } 963 RefPtr<HTMLCollection> options = dataList->options(); 964 GraphicsContextStateSaver stateSaver(*paintInfo.context); 965 paintInfo.context->setFillColor(o->resolveColor(CSSPropertyColor)); 966 for (unsigned i = 0; Node* node = options->item(i); i++) { 967 ASSERT(node->hasTagName(optionTag)); 968 HTMLOptionElement* optionElement = toHTMLOptionElement(node); 969 String value = optionElement->value(); 970 if (!input->isValidValue(value)) 971 continue; 972 double parsedValue = parseToDoubleForNumberType(input->sanitizeValue(value)); 973 double tickFraction = (parsedValue - min) / (max - min); 974 double tickRatio = isHorizontal && o->style()->isLeftToRightDirection() ? tickFraction : 1.0 - tickFraction; 975 double tickPosition = round(tickRegionSideMargin + tickRegionWidth * tickRatio); 976 if (isHorizontal) 977 tickRect.setX(tickPosition); 978 else 979 tickRect.setY(tickPosition); 980 paintInfo.context->fillRect(tickRect); 981 } 982 } 983 984 double RenderTheme::animationRepeatIntervalForProgressBar(RenderProgress*) const 985 { 986 return 0; 987 } 988 989 double RenderTheme::animationDurationForProgressBar(RenderProgress*) const 990 { 991 return 0; 992 } 993 994 bool RenderTheme::shouldHaveSpinButton(HTMLInputElement* inputElement) const 995 { 996 return inputElement->isSteppable() && !inputElement->isRangeControl(); 997 } 998 999 void RenderTheme::adjustMenuListButtonStyle(RenderStyle*, Element*) const 1000 { 1001 } 1002 1003 void RenderTheme::adjustSliderThumbStyle(RenderStyle* style, Element* element) const 1004 { 1005 adjustSliderThumbSize(style, element); 1006 } 1007 1008 void RenderTheme::adjustSliderThumbSize(RenderStyle*, Element*) const 1009 { 1010 } 1011 1012 void RenderTheme::adjustSearchFieldStyle(RenderStyle*, Element*) const 1013 { 1014 } 1015 1016 void RenderTheme::adjustSearchFieldCancelButtonStyle(RenderStyle*, Element*) const 1017 { 1018 } 1019 1020 void RenderTheme::adjustSearchFieldDecorationStyle(RenderStyle*, Element*) const 1021 { 1022 } 1023 1024 void RenderTheme::adjustSearchFieldResultsDecorationStyle(RenderStyle*, Element*) const 1025 { 1026 } 1027 1028 void RenderTheme::platformColorsDidChange() 1029 { 1030 m_activeSelectionForegroundColor = Color(); 1031 m_inactiveSelectionForegroundColor = Color(); 1032 m_activeSelectionBackgroundColor = Color(); 1033 m_inactiveSelectionBackgroundColor = Color(); 1034 1035 m_activeListBoxSelectionForegroundColor = Color(); 1036 m_inactiveListBoxSelectionForegroundColor = Color(); 1037 m_activeListBoxSelectionBackgroundColor = Color(); 1038 m_inactiveListBoxSelectionForegroundColor = Color(); 1039 1040 Page::scheduleForcedStyleRecalcForAllPages(); 1041 } 1042 1043 Color RenderTheme::systemColor(CSSValueID cssValueId) const 1044 { 1045 switch (cssValueId) { 1046 case CSSValueActiveborder: 1047 return 0xFFFFFFFF; 1048 case CSSValueActivecaption: 1049 return 0xFFCCCCCC; 1050 case CSSValueAppworkspace: 1051 return 0xFFFFFFFF; 1052 case CSSValueBackground: 1053 return 0xFF6363CE; 1054 case CSSValueButtonface: 1055 return 0xFFC0C0C0; 1056 case CSSValueButtonhighlight: 1057 return 0xFFDDDDDD; 1058 case CSSValueButtonshadow: 1059 return 0xFF888888; 1060 case CSSValueButtontext: 1061 return 0xFF000000; 1062 case CSSValueCaptiontext: 1063 return 0xFF000000; 1064 case CSSValueGraytext: 1065 return 0xFF808080; 1066 case CSSValueHighlight: 1067 return 0xFFB5D5FF; 1068 case CSSValueHighlighttext: 1069 return 0xFF000000; 1070 case CSSValueInactiveborder: 1071 return 0xFFFFFFFF; 1072 case CSSValueInactivecaption: 1073 return 0xFFFFFFFF; 1074 case CSSValueInactivecaptiontext: 1075 return 0xFF7F7F7F; 1076 case CSSValueInfobackground: 1077 return 0xFFFBFCC5; 1078 case CSSValueInfotext: 1079 return 0xFF000000; 1080 case CSSValueMenu: 1081 return 0xFFC0C0C0; 1082 case CSSValueMenutext: 1083 return 0xFF000000; 1084 case CSSValueScrollbar: 1085 return 0xFFFFFFFF; 1086 case CSSValueText: 1087 return 0xFF000000; 1088 case CSSValueThreeddarkshadow: 1089 return 0xFF666666; 1090 case CSSValueThreedface: 1091 return 0xFFC0C0C0; 1092 case CSSValueThreedhighlight: 1093 return 0xFFDDDDDD; 1094 case CSSValueThreedlightshadow: 1095 return 0xFFC0C0C0; 1096 case CSSValueThreedshadow: 1097 return 0xFF888888; 1098 case CSSValueWindow: 1099 return 0xFFFFFFFF; 1100 case CSSValueWindowframe: 1101 return 0xFFCCCCCC; 1102 case CSSValueWindowtext: 1103 return 0xFF000000; 1104 case CSSValueInternalActiveListBoxSelection: 1105 return activeListBoxSelectionBackgroundColor(); 1106 break; 1107 case CSSValueInternalActiveListBoxSelectionText: 1108 return activeListBoxSelectionForegroundColor(); 1109 break; 1110 case CSSValueInternalInactiveListBoxSelection: 1111 return inactiveListBoxSelectionBackgroundColor(); 1112 break; 1113 case CSSValueInternalInactiveListBoxSelectionText: 1114 return inactiveListBoxSelectionForegroundColor(); 1115 break; 1116 default: 1117 break; 1118 } 1119 return Color(); 1120 } 1121 1122 Color RenderTheme::platformActiveTextSearchHighlightColor() const 1123 { 1124 return Color(255, 150, 50); // Orange. 1125 } 1126 1127 Color RenderTheme::platformInactiveTextSearchHighlightColor() const 1128 { 1129 return Color(255, 255, 0); // Yellow. 1130 } 1131 1132 Color RenderTheme::tapHighlightColor() 1133 { 1134 return theme().platformTapHighlightColor(); 1135 } 1136 1137 void RenderTheme::setCustomFocusRingColor(const Color& c) 1138 { 1139 customFocusRingColor() = c; 1140 } 1141 1142 Color RenderTheme::focusRingColor() 1143 { 1144 return customFocusRingColor().isValid() ? customFocusRingColor() : theme().platformFocusRingColor(); 1145 } 1146 1147 String RenderTheme::fileListNameForWidth(Locale& locale, const FileList* fileList, const Font& font, int width) const 1148 { 1149 if (width <= 0) 1150 return String(); 1151 1152 String string; 1153 if (fileList->isEmpty()) { 1154 string = locale.queryString(blink::WebLocalizedString::FileButtonNoFileSelectedLabel); 1155 } else if (fileList->length() == 1) { 1156 string = fileList->item(0)->name(); 1157 } else { 1158 // FIXME: Localization of fileList->length(). 1159 return StringTruncator::rightTruncate(locale.queryString(blink::WebLocalizedString::MultipleFileUploadText, String::number(fileList->length())), width, font, StringTruncator::EnableRoundingHacks); 1160 } 1161 1162 return StringTruncator::centerTruncate(string, width, font, StringTruncator::EnableRoundingHacks); 1163 } 1164 1165 bool RenderTheme::shouldOpenPickerWithF4Key() const 1166 { 1167 return false; 1168 } 1169 1170 bool RenderTheme::supportsDataListUI(const AtomicString& type) const 1171 { 1172 return type == InputTypeNames::text || type == InputTypeNames::search || type == InputTypeNames::url 1173 || type == InputTypeNames::tel || type == InputTypeNames::email || type == InputTypeNames::number 1174 || type == InputTypeNames::color 1175 || type == InputTypeNames::date 1176 || type == InputTypeNames::datetime 1177 || type == InputTypeNames::datetime_local 1178 || type == InputTypeNames::month 1179 || type == InputTypeNames::week 1180 || type == InputTypeNames::time 1181 || type == InputTypeNames::range; 1182 } 1183 1184 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) 1185 bool RenderTheme::supportsCalendarPicker(const AtomicString& type) const 1186 { 1187 return type == InputTypeNames::date 1188 || type == InputTypeNames::datetime 1189 || type == InputTypeNames::datetime_local 1190 || type == InputTypeNames::month 1191 || type == InputTypeNames::week; 1192 } 1193 #endif 1194 1195 bool RenderTheme::shouldUseFallbackTheme(RenderStyle*) const 1196 { 1197 return false; 1198 } 1199 1200 void RenderTheme::adjustStyleUsingFallbackTheme(RenderStyle* style, Element* e) 1201 { 1202 ControlPart part = style->appearance(); 1203 switch (part) { 1204 case CheckboxPart: 1205 return adjustCheckboxStyleUsingFallbackTheme(style, e); 1206 case RadioPart: 1207 return adjustRadioStyleUsingFallbackTheme(style, e); 1208 default: 1209 break; 1210 } 1211 } 1212 1213 bool RenderTheme::paintUsingFallbackTheme(RenderObject* o, const PaintInfo& i, const IntRect& r) 1214 { 1215 ControlPart part = o->style()->appearance(); 1216 switch (part) { 1217 case CheckboxPart: 1218 return paintCheckboxUsingFallbackTheme(o, i, r); 1219 case RadioPart: 1220 return paintRadioUsingFallbackTheme(o, i, r); 1221 default: 1222 break; 1223 } 1224 return true; 1225 } 1226 1227 // static 1228 void RenderTheme::setSizeIfAuto(RenderStyle* style, const IntSize& size) 1229 { 1230 if (style->width().isIntrinsicOrAuto()) 1231 style->setWidth(Length(size.width(), Fixed)); 1232 if (style->height().isAuto()) 1233 style->setHeight(Length(size.height(), Fixed)); 1234 } 1235 1236 bool RenderTheme::paintCheckboxUsingFallbackTheme(RenderObject* o, const PaintInfo& i, const IntRect& r) 1237 { 1238 blink::WebFallbackThemeEngine::ExtraParams extraParams; 1239 blink::WebCanvas* canvas = i.context->canvas(); 1240 extraParams.button.checked = isChecked(o); 1241 extraParams.button.indeterminate = isIndeterminate(o); 1242 1243 float zoomLevel = o->style()->effectiveZoom(); 1244 GraphicsContextStateSaver stateSaver(*i.context); 1245 IntRect unzoomedRect = r; 1246 if (zoomLevel != 1) { 1247 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); 1248 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); 1249 i.context->translate(unzoomedRect.x(), unzoomedRect.y()); 1250 i.context->scale(FloatSize(zoomLevel, zoomLevel)); 1251 i.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); 1252 } 1253 1254 blink::Platform::current()->fallbackThemeEngine()->paint(canvas, blink::WebFallbackThemeEngine::PartCheckbox, getWebFallbackThemeState(this, o), blink::WebRect(unzoomedRect), &extraParams); 1255 return false; 1256 } 1257 1258 void RenderTheme::adjustCheckboxStyleUsingFallbackTheme(RenderStyle* style, Element*) const 1259 { 1260 // If the width and height are both specified, then we have nothing to do. 1261 if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) 1262 return; 1263 1264 IntSize size = blink::Platform::current()->fallbackThemeEngine()->getSize(blink::WebFallbackThemeEngine::PartCheckbox); 1265 float zoomLevel = style->effectiveZoom(); 1266 size.setWidth(size.width() * zoomLevel); 1267 size.setHeight(size.height() * zoomLevel); 1268 setSizeIfAuto(style, size); 1269 1270 // padding - not honored by WinIE, needs to be removed. 1271 style->resetPadding(); 1272 1273 // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme) 1274 // for now, we will not honor it. 1275 style->resetBorder(); 1276 } 1277 1278 bool RenderTheme::paintRadioUsingFallbackTheme(RenderObject* o, const PaintInfo& i, const IntRect& r) 1279 { 1280 blink::WebFallbackThemeEngine::ExtraParams extraParams; 1281 blink::WebCanvas* canvas = i.context->canvas(); 1282 extraParams.button.checked = isChecked(o); 1283 extraParams.button.indeterminate = isIndeterminate(o); 1284 1285 float zoomLevel = o->style()->effectiveZoom(); 1286 GraphicsContextStateSaver stateSaver(*i.context); 1287 IntRect unzoomedRect = r; 1288 if (zoomLevel != 1) { 1289 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); 1290 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); 1291 i.context->translate(unzoomedRect.x(), unzoomedRect.y()); 1292 i.context->scale(FloatSize(zoomLevel, zoomLevel)); 1293 i.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); 1294 } 1295 1296 blink::Platform::current()->fallbackThemeEngine()->paint(canvas, blink::WebFallbackThemeEngine::PartRadio, getWebFallbackThemeState(this, o), blink::WebRect(unzoomedRect), &extraParams); 1297 return false; 1298 } 1299 1300 void RenderTheme::adjustRadioStyleUsingFallbackTheme(RenderStyle* style, Element*) const 1301 { 1302 // If the width and height are both specified, then we have nothing to do. 1303 if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) 1304 return; 1305 1306 IntSize size = blink::Platform::current()->fallbackThemeEngine()->getSize(blink::WebFallbackThemeEngine::PartRadio); 1307 float zoomLevel = style->effectiveZoom(); 1308 size.setWidth(size.width() * zoomLevel); 1309 size.setHeight(size.height() * zoomLevel); 1310 setSizeIfAuto(style, size); 1311 1312 // padding - not honored by WinIE, needs to be removed. 1313 style->resetPadding(); 1314 1315 // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme) 1316 // for now, we will not honor it. 1317 style->resetBorder(); 1318 } 1319 1320 } // namespace WebCore 1321