Home | History | Annotate | Download | only in rendering
      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 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 "RenderTheme.h"
     24 
     25 #include "CSSValueKeywords.h"
     26 #include "Document.h"
     27 #include "FloatConversion.h"
     28 #include "FocusController.h"
     29 #include "FontSelector.h"
     30 #include "Frame.h"
     31 #include "GraphicsContext.h"
     32 #include "HTMLInputElement.h"
     33 #include "HTMLNames.h"
     34 #include "MediaControlElements.h"
     35 #include "Page.h"
     36 #include "PaintInfo.h"
     37 #include "RenderStyle.h"
     38 #include "RenderView.h"
     39 #include "SelectionController.h"
     40 #include "Settings.h"
     41 #include "TextControlInnerElements.h"
     42 
     43 #if ENABLE(METER_TAG)
     44 #include "HTMLMeterElement.h"
     45 #include "RenderMeter.h"
     46 #endif
     47 
     48 #if ENABLE(INPUT_SPEECH)
     49 #include "RenderInputSpeech.h"
     50 #endif
     51 
     52 // The methods in this file are shared by all themes on every platform.
     53 
     54 namespace WebCore {
     55 
     56 using namespace HTMLNames;
     57 
     58 static Color& customFocusRingColor()
     59 {
     60     DEFINE_STATIC_LOCAL(Color, color, ());
     61     return color;
     62 }
     63 
     64 RenderTheme::RenderTheme()
     65 #if USE(NEW_THEME)
     66     : m_theme(platformTheme())
     67 #endif
     68 {
     69 }
     70 
     71 void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e,
     72                               bool UAHasAppearance, const BorderData& border, const FillLayer& background, const Color& backgroundColor)
     73 {
     74     // Force inline and table display styles to be inline-block (except for table- which is block)
     75     ControlPart part = style->appearance();
     76     if (style->display() == INLINE || style->display() == INLINE_TABLE || style->display() == TABLE_ROW_GROUP ||
     77         style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_FOOTER_GROUP ||
     78         style->display() == TABLE_ROW || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_COLUMN ||
     79         style->display() == TABLE_CELL || style->display() == TABLE_CAPTION)
     80         style->setDisplay(INLINE_BLOCK);
     81     else if (style->display() == COMPACT || style->display() == RUN_IN || style->display() == LIST_ITEM || style->display() == TABLE)
     82         style->setDisplay(BLOCK);
     83 
     84     if (UAHasAppearance && isControlStyled(style, border, background, backgroundColor)) {
     85         if (part == MenulistPart) {
     86             style->setAppearance(MenulistButtonPart);
     87             part = MenulistButtonPart;
     88         } else
     89             style->setAppearance(NoControlPart);
     90     }
     91 
     92     if (!style->hasAppearance())
     93         return;
     94 
     95     // Never support box-shadow on native controls.
     96     style->setBoxShadow(0);
     97 
     98 #if USE(NEW_THEME)
     99     switch (part) {
    100         case ListButtonPart:
    101         case CheckboxPart:
    102         case InnerSpinButtonPart:
    103         case OuterSpinButtonPart:
    104         case RadioPart:
    105         case PushButtonPart:
    106         case SquareButtonPart:
    107         case DefaultButtonPart:
    108         case ButtonPart: {
    109             // Border
    110             LengthBox borderBox(style->borderTopWidth(), style->borderRightWidth(), style->borderBottomWidth(), style->borderLeftWidth());
    111             borderBox = m_theme->controlBorder(part, style->font(), borderBox, style->effectiveZoom());
    112             if (borderBox.top().value() != style->borderTopWidth()) {
    113                 if (borderBox.top().value())
    114                     style->setBorderTopWidth(borderBox.top().value());
    115                 else
    116                     style->resetBorderTop();
    117             }
    118             if (borderBox.right().value() != style->borderRightWidth()) {
    119                 if (borderBox.right().value())
    120                     style->setBorderRightWidth(borderBox.right().value());
    121                 else
    122                     style->resetBorderRight();
    123             }
    124             if (borderBox.bottom().value() != style->borderBottomWidth()) {
    125                 style->setBorderBottomWidth(borderBox.bottom().value());
    126                 if (borderBox.bottom().value())
    127                     style->setBorderBottomWidth(borderBox.bottom().value());
    128                 else
    129                     style->resetBorderBottom();
    130             }
    131             if (borderBox.left().value() != style->borderLeftWidth()) {
    132                 style->setBorderLeftWidth(borderBox.left().value());
    133                 if (borderBox.left().value())
    134                     style->setBorderLeftWidth(borderBox.left().value());
    135                 else
    136                     style->resetBorderLeft();
    137             }
    138 
    139             // Padding
    140             LengthBox paddingBox = m_theme->controlPadding(part, style->font(), style->paddingBox(), style->effectiveZoom());
    141             if (paddingBox != style->paddingBox())
    142                 style->setPaddingBox(paddingBox);
    143 
    144             // Whitespace
    145             if (m_theme->controlRequiresPreWhiteSpace(part))
    146                 style->setWhiteSpace(PRE);
    147 
    148             // Width / Height
    149             // The width and height here are affected by the zoom.
    150             // FIXME: Check is flawed, since it doesn't take min-width/max-width into account.
    151             LengthSize controlSize = m_theme->controlSize(part, style->font(), LengthSize(style->width(), style->height()), style->effectiveZoom());
    152             if (controlSize.width() != style->width())
    153                 style->setWidth(controlSize.width());
    154             if (controlSize.height() != style->height())
    155                 style->setHeight(controlSize.height());
    156 
    157             // Min-Width / Min-Height
    158             LengthSize minControlSize = m_theme->minimumControlSize(part, style->font(), style->effectiveZoom());
    159             if (minControlSize.width() != style->minWidth())
    160                 style->setMinWidth(minControlSize.width());
    161             if (minControlSize.height() != style->minHeight())
    162                 style->setMinHeight(minControlSize.height());
    163 
    164             // Font
    165             FontDescription controlFont = m_theme->controlFont(part, style->font(), style->effectiveZoom());
    166             if (controlFont != style->font().fontDescription()) {
    167                 // Reset our line-height
    168                 style->setLineHeight(RenderStyle::initialLineHeight());
    169 
    170                 // Now update our font.
    171                 if (style->setFontDescription(controlFont))
    172                     style->font().update(0);
    173             }
    174         }
    175         default:
    176             break;
    177     }
    178 #endif
    179 
    180     // Call the appropriate style adjustment method based off the appearance value.
    181     switch (style->appearance()) {
    182 #if !USE(NEW_THEME)
    183         case CheckboxPart:
    184             return adjustCheckboxStyle(selector, style, e);
    185         case RadioPart:
    186             return adjustRadioStyle(selector, style, e);
    187         case PushButtonPart:
    188         case SquareButtonPart:
    189         case ListButtonPart:
    190         case DefaultButtonPart:
    191         case ButtonPart:
    192             return adjustButtonStyle(selector, style, e);
    193         case InnerSpinButtonPart:
    194             return adjustInnerSpinButtonStyle(selector, style, e);
    195         case OuterSpinButtonPart:
    196             return adjustOuterSpinButtonStyle(selector, style, e);
    197 #endif
    198         case TextFieldPart:
    199             return adjustTextFieldStyle(selector, style, e);
    200         case TextAreaPart:
    201             return adjustTextAreaStyle(selector, style, e);
    202 #if ENABLE(NO_LISTBOX_RENDERING)
    203         case ListboxPart:
    204             return adjustListboxStyle(selector, style, e);
    205 #endif
    206         case MenulistPart:
    207             return adjustMenuListStyle(selector, style, e);
    208         case MenulistButtonPart:
    209             return adjustMenuListButtonStyle(selector, style, e);
    210         case MediaSliderPart:
    211         case MediaVolumeSliderPart:
    212         case SliderHorizontalPart:
    213         case SliderVerticalPart:
    214             return adjustSliderTrackStyle(selector, style, e);
    215         case SliderThumbHorizontalPart:
    216         case SliderThumbVerticalPart:
    217             return adjustSliderThumbStyle(selector, style, e);
    218         case SearchFieldPart:
    219             return adjustSearchFieldStyle(selector, style, e);
    220         case SearchFieldCancelButtonPart:
    221             return adjustSearchFieldCancelButtonStyle(selector, style, e);
    222         case SearchFieldDecorationPart:
    223             return adjustSearchFieldDecorationStyle(selector, style, e);
    224         case SearchFieldResultsDecorationPart:
    225             return adjustSearchFieldResultsDecorationStyle(selector, style, e);
    226         case SearchFieldResultsButtonPart:
    227             return adjustSearchFieldResultsButtonStyle(selector, style, e);
    228 #if ENABLE(PROGRESS_TAG)
    229         case ProgressBarPart:
    230             return adjustProgressBarStyle(selector, style, e);
    231 #endif
    232 #if ENABLE(METER_TAG)
    233         case MeterPart:
    234         case RelevancyLevelIndicatorPart:
    235         case ContinuousCapacityLevelIndicatorPart:
    236         case DiscreteCapacityLevelIndicatorPart:
    237         case RatingLevelIndicatorPart:
    238             return adjustMeterStyle(selector, style, e);
    239 #endif
    240 #if ENABLE(INPUT_SPEECH)
    241         case InputSpeechButtonPart:
    242             return adjustInputFieldSpeechButtonStyle(selector, style, e);
    243 #endif
    244         default:
    245             break;
    246     }
    247 }
    248 
    249 bool RenderTheme::paint(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
    250 {
    251     // If painting is disabled, but we aren't updating control tints, then just bail.
    252     // If we are updating control tints, just schedule a repaint if the theme supports tinting
    253     // for that control.
    254     if (paintInfo.context->updatingControlTints()) {
    255         if (controlSupportsTints(o))
    256             o->repaint();
    257         return false;
    258     }
    259     if (paintInfo.context->paintingDisabled())
    260         return false;
    261 
    262     ControlPart part = o->style()->appearance();
    263 
    264 #if USE(NEW_THEME)
    265     switch (part) {
    266         case CheckboxPart:
    267         case RadioPart:
    268         case PushButtonPart:
    269         case SquareButtonPart:
    270         case ListButtonPart:
    271         case DefaultButtonPart:
    272         case ButtonPart:
    273         case InnerSpinButtonPart:
    274         case OuterSpinButtonPart:
    275             m_theme->paint(part, controlStatesForRenderer(o), const_cast<GraphicsContext*>(paintInfo.context), r, o->style()->effectiveZoom(), o->view()->frameView());
    276             return false;
    277         default:
    278             break;
    279     }
    280 #endif
    281 
    282     // Call the appropriate paint method based off the appearance value.
    283     switch (part) {
    284 #if !USE(NEW_THEME)
    285         case CheckboxPart:
    286             return paintCheckbox(o, paintInfo, r);
    287         case RadioPart:
    288             return paintRadio(o, paintInfo, r);
    289         case PushButtonPart:
    290         case SquareButtonPart:
    291         case ListButtonPart:
    292         case DefaultButtonPart:
    293         case ButtonPart:
    294             return paintButton(o, paintInfo, r);
    295         case InnerSpinButtonPart:
    296             return paintInnerSpinButton(o, paintInfo, r);
    297         case OuterSpinButtonPart:
    298             return paintOuterSpinButton(o, paintInfo, r);
    299 #endif
    300         case MenulistPart:
    301             return paintMenuList(o, paintInfo, r);
    302 #if ENABLE(METER_TAG)
    303         case MeterPart:
    304         case RelevancyLevelIndicatorPart:
    305         case ContinuousCapacityLevelIndicatorPart:
    306         case DiscreteCapacityLevelIndicatorPart:
    307         case RatingLevelIndicatorPart:
    308             return paintMeter(o, paintInfo, r);
    309 #endif
    310 #if ENABLE(PROGRESS_TAG)
    311         case ProgressBarPart:
    312             return paintProgressBar(o, paintInfo, r);
    313 #endif
    314         case SliderHorizontalPart:
    315         case SliderVerticalPart:
    316             return paintSliderTrack(o, paintInfo, r);
    317         case SliderThumbHorizontalPart:
    318         case SliderThumbVerticalPart:
    319             if (o->parent()->isSlider())
    320                 return paintSliderThumb(o, paintInfo, r);
    321             // We don't support drawing a slider thumb without a parent slider
    322             break;
    323         case MediaFullscreenButtonPart:
    324             return paintMediaFullscreenButton(o, paintInfo, r);
    325         case MediaPlayButtonPart:
    326             return paintMediaPlayButton(o, paintInfo, r);
    327         case MediaMuteButtonPart:
    328             return paintMediaMuteButton(o, paintInfo, r);
    329         case MediaSeekBackButtonPart:
    330             return paintMediaSeekBackButton(o, paintInfo, r);
    331         case MediaSeekForwardButtonPart:
    332             return paintMediaSeekForwardButton(o, paintInfo, r);
    333         case MediaRewindButtonPart:
    334             return paintMediaRewindButton(o, paintInfo, r);
    335         case MediaReturnToRealtimeButtonPart:
    336             return paintMediaReturnToRealtimeButton(o, paintInfo, r);
    337         case MediaToggleClosedCaptionsButtonPart:
    338             return paintMediaToggleClosedCaptionsButton(o, paintInfo, r);
    339         case MediaSliderPart:
    340             return paintMediaSliderTrack(o, paintInfo, r);
    341         case MediaSliderThumbPart:
    342             if (o->parent()->isSlider())
    343                 return paintMediaSliderThumb(o, paintInfo, r);
    344             break;
    345         case MediaVolumeSliderMuteButtonPart:
    346             return paintMediaMuteButton(o, paintInfo, r);
    347         case MediaVolumeSliderContainerPart:
    348             return paintMediaVolumeSliderContainer(o, paintInfo, r);
    349         case MediaVolumeSliderPart:
    350             return paintMediaVolumeSliderTrack(o, paintInfo, r);
    351         case MediaVolumeSliderThumbPart:
    352             if (o->parent()->isSlider())
    353                 return paintMediaVolumeSliderThumb(o, paintInfo, r);
    354             break;
    355         case MediaTimeRemainingPart:
    356             return paintMediaTimeRemaining(o, paintInfo, r);
    357         case MediaCurrentTimePart:
    358             return paintMediaCurrentTime(o, paintInfo, r);
    359         case MediaControlsBackgroundPart:
    360             return paintMediaControlsBackground(o, paintInfo, r);
    361         case MenulistButtonPart:
    362         case TextFieldPart:
    363         case TextAreaPart:
    364         case ListboxPart:
    365             return true;
    366         case SearchFieldPart:
    367             return paintSearchField(o, paintInfo, r);
    368         case SearchFieldCancelButtonPart:
    369             return paintSearchFieldCancelButton(o, paintInfo, r);
    370         case SearchFieldDecorationPart:
    371             return paintSearchFieldDecoration(o, paintInfo, r);
    372         case SearchFieldResultsDecorationPart:
    373             return paintSearchFieldResultsDecoration(o, paintInfo, r);
    374         case SearchFieldResultsButtonPart:
    375             return paintSearchFieldResultsButton(o, paintInfo, r);
    376 #if ENABLE(INPUT_SPEECH)
    377         case InputSpeechButtonPart:
    378             return paintInputFieldSpeechButton(o, paintInfo, r);
    379 #endif
    380         default:
    381             break;
    382     }
    383 
    384     return true; // We don't support the appearance, so let the normal background/border paint.
    385 }
    386 
    387 bool RenderTheme::paintBorderOnly(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
    388 {
    389     if (paintInfo.context->paintingDisabled())
    390         return false;
    391 
    392     // Call the appropriate paint method based off the appearance value.
    393     switch (o->style()->appearance()) {
    394         case TextFieldPart:
    395             return paintTextField(o, paintInfo, r);
    396         case ListboxPart:
    397         case TextAreaPart:
    398             return paintTextArea(o, paintInfo, r);
    399         case MenulistButtonPart:
    400         case SearchFieldPart:
    401             return true;
    402         case CheckboxPart:
    403         case RadioPart:
    404         case PushButtonPart:
    405         case SquareButtonPart:
    406         case ListButtonPart:
    407         case DefaultButtonPart:
    408         case ButtonPart:
    409         case MenulistPart:
    410 #if ENABLE(METER_TAG)
    411         case MeterPart:
    412         case RelevancyLevelIndicatorPart:
    413         case ContinuousCapacityLevelIndicatorPart:
    414         case DiscreteCapacityLevelIndicatorPart:
    415         case RatingLevelIndicatorPart:
    416 #endif
    417 #if ENABLE(PROGRESS_TAG)
    418         case ProgressBarPart:
    419 #endif
    420         case SliderHorizontalPart:
    421         case SliderVerticalPart:
    422         case SliderThumbHorizontalPart:
    423         case SliderThumbVerticalPart:
    424         case SearchFieldCancelButtonPart:
    425         case SearchFieldDecorationPart:
    426         case SearchFieldResultsDecorationPart:
    427         case SearchFieldResultsButtonPart:
    428 #if ENABLE(INPUT_SPEECH)
    429         case InputSpeechButtonPart:
    430 #endif
    431         default:
    432             break;
    433     }
    434 
    435     return false;
    436 }
    437 
    438 bool RenderTheme::paintDecorations(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
    439 {
    440     if (paintInfo.context->paintingDisabled())
    441         return false;
    442 
    443     // Call the appropriate paint method based off the appearance value.
    444     switch (o->style()->appearance()) {
    445         case MenulistButtonPart:
    446             return paintMenuListButton(o, paintInfo, r);
    447         case TextFieldPart:
    448         case TextAreaPart:
    449         case ListboxPart:
    450         case CheckboxPart:
    451         case RadioPart:
    452         case PushButtonPart:
    453         case SquareButtonPart:
    454         case ListButtonPart:
    455         case DefaultButtonPart:
    456         case ButtonPart:
    457         case MenulistPart:
    458 #if ENABLE(METER_TAG)
    459         case MeterPart:
    460         case RelevancyLevelIndicatorPart:
    461         case ContinuousCapacityLevelIndicatorPart:
    462         case DiscreteCapacityLevelIndicatorPart:
    463         case RatingLevelIndicatorPart:
    464 #endif
    465 #if ENABLE(PROGRESS_TAG)
    466         case ProgressBarPart:
    467 #endif
    468         case SliderHorizontalPart:
    469         case SliderVerticalPart:
    470         case SliderThumbHorizontalPart:
    471         case SliderThumbVerticalPart:
    472         case SearchFieldPart:
    473         case SearchFieldCancelButtonPart:
    474         case SearchFieldDecorationPart:
    475         case SearchFieldResultsDecorationPart:
    476         case SearchFieldResultsButtonPart:
    477 #if ENABLE(INPUT_SPEECH)
    478         case InputSpeechButtonPart:
    479 #endif
    480         default:
    481             break;
    482     }
    483 
    484     return false;
    485 }
    486 
    487 #if ENABLE(VIDEO)
    488 
    489 String RenderTheme::formatMediaControlsTime(float time) const
    490 {
    491     if (!isfinite(time))
    492         time = 0;
    493     int seconds = (int)fabsf(time);
    494     int hours = seconds / (60 * 60);
    495     int minutes = (seconds / 60) % 60;
    496     seconds %= 60;
    497     if (hours) {
    498         if (hours > 9)
    499             return String::format("%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
    500 
    501         return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
    502     }
    503 
    504     return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds);
    505 }
    506 
    507 String RenderTheme::formatMediaControlsCurrentTime(float currentTime, float /*duration*/) const
    508 {
    509     return formatMediaControlsTime(currentTime);
    510 }
    511 
    512 String RenderTheme::formatMediaControlsRemainingTime(float currentTime, float duration) const
    513 {
    514     return formatMediaControlsTime(currentTime - duration);
    515 }
    516 
    517 IntPoint RenderTheme::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const IntSize& size) const
    518 {
    519     int y = -size.height();
    520     FloatPoint absPoint = muteButtonBox->localToAbsolute(FloatPoint(muteButtonBox->offsetLeft(), y), true, true);
    521     if (absPoint.y() < 0)
    522         y = muteButtonBox->height();
    523     return IntPoint(0, y);
    524 }
    525 
    526 #endif
    527 
    528 Color RenderTheme::activeSelectionBackgroundColor() const
    529 {
    530     if (!m_activeSelectionBackgroundColor.isValid())
    531         m_activeSelectionBackgroundColor = platformActiveSelectionBackgroundColor().blendWithWhite();
    532     return m_activeSelectionBackgroundColor;
    533 }
    534 
    535 Color RenderTheme::inactiveSelectionBackgroundColor() const
    536 {
    537     if (!m_inactiveSelectionBackgroundColor.isValid())
    538         m_inactiveSelectionBackgroundColor = platformInactiveSelectionBackgroundColor().blendWithWhite();
    539     return m_inactiveSelectionBackgroundColor;
    540 }
    541 
    542 Color RenderTheme::activeSelectionForegroundColor() const
    543 {
    544     if (!m_activeSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
    545         m_activeSelectionForegroundColor = platformActiveSelectionForegroundColor();
    546     return m_activeSelectionForegroundColor;
    547 }
    548 
    549 Color RenderTheme::inactiveSelectionForegroundColor() const
    550 {
    551     if (!m_inactiveSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
    552         m_inactiveSelectionForegroundColor = platformInactiveSelectionForegroundColor();
    553     return m_inactiveSelectionForegroundColor;
    554 }
    555 
    556 Color RenderTheme::activeListBoxSelectionBackgroundColor() const
    557 {
    558     if (!m_activeListBoxSelectionBackgroundColor.isValid())
    559         m_activeListBoxSelectionBackgroundColor = platformActiveListBoxSelectionBackgroundColor();
    560     return m_activeListBoxSelectionBackgroundColor;
    561 }
    562 
    563 Color RenderTheme::inactiveListBoxSelectionBackgroundColor() const
    564 {
    565     if (!m_inactiveListBoxSelectionBackgroundColor.isValid())
    566         m_inactiveListBoxSelectionBackgroundColor = platformInactiveListBoxSelectionBackgroundColor();
    567     return m_inactiveListBoxSelectionBackgroundColor;
    568 }
    569 
    570 Color RenderTheme::activeListBoxSelectionForegroundColor() const
    571 {
    572     if (!m_activeListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
    573         m_activeListBoxSelectionForegroundColor = platformActiveListBoxSelectionForegroundColor();
    574     return m_activeListBoxSelectionForegroundColor;
    575 }
    576 
    577 Color RenderTheme::inactiveListBoxSelectionForegroundColor() const
    578 {
    579     if (!m_inactiveListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
    580         m_inactiveListBoxSelectionForegroundColor = platformInactiveListBoxSelectionForegroundColor();
    581     return m_inactiveListBoxSelectionForegroundColor;
    582 }
    583 
    584 Color RenderTheme::platformActiveSelectionBackgroundColor() const
    585 {
    586     // Use a blue color by default if the platform theme doesn't define anything.
    587     return Color(0, 0, 255);
    588 }
    589 
    590 Color RenderTheme::platformActiveSelectionForegroundColor() const
    591 {
    592     // Use a white color by default if the platform theme doesn't define anything.
    593     return Color::white;
    594 }
    595 
    596 Color RenderTheme::platformInactiveSelectionBackgroundColor() const
    597 {
    598     // Use a grey color by default if the platform theme doesn't define anything.
    599     // This color matches Firefox's inactive color.
    600     return Color(176, 176, 176);
    601 }
    602 
    603 Color RenderTheme::platformInactiveSelectionForegroundColor() const
    604 {
    605     // Use a black color by default.
    606     return Color::black;
    607 }
    608 
    609 Color RenderTheme::platformActiveListBoxSelectionBackgroundColor() const
    610 {
    611     return platformActiveSelectionBackgroundColor();
    612 }
    613 
    614 Color RenderTheme::platformActiveListBoxSelectionForegroundColor() const
    615 {
    616     return platformActiveSelectionForegroundColor();
    617 }
    618 
    619 Color RenderTheme::platformInactiveListBoxSelectionBackgroundColor() const
    620 {
    621     return platformInactiveSelectionBackgroundColor();
    622 }
    623 
    624 Color RenderTheme::platformInactiveListBoxSelectionForegroundColor() const
    625 {
    626     return platformInactiveSelectionForegroundColor();
    627 }
    628 
    629 int RenderTheme::baselinePosition(const RenderObject* o) const
    630 {
    631     if (!o->isBox())
    632         return 0;
    633 
    634     const RenderBox* box = toRenderBox(o);
    635 
    636 #if USE(NEW_THEME)
    637     return box->height() + box->marginTop() + m_theme->baselinePositionAdjustment(o->style()->appearance()) * o->style()->effectiveZoom();
    638 #else
    639     return box->height() + box->marginTop();
    640 #endif
    641 }
    642 
    643 bool RenderTheme::isControlContainer(ControlPart appearance) const
    644 {
    645     // There are more leaves than this, but we'll patch this function as we add support for
    646     // more controls.
    647     return appearance != CheckboxPart && appearance != RadioPart;
    648 }
    649 
    650 bool RenderTheme::isControlStyled(const RenderStyle* style, const BorderData& border, const FillLayer& background,
    651                                   const Color& backgroundColor) const
    652 {
    653     switch (style->appearance()) {
    654         case PushButtonPart:
    655         case SquareButtonPart:
    656         case DefaultButtonPart:
    657         case ButtonPart:
    658         case ListboxPart:
    659         case MenulistPart:
    660         case ProgressBarPart:
    661         case MeterPart:
    662         case RelevancyLevelIndicatorPart:
    663         case ContinuousCapacityLevelIndicatorPart:
    664         case DiscreteCapacityLevelIndicatorPart:
    665         case RatingLevelIndicatorPart:
    666         // FIXME: Uncomment this when making search fields style-able.
    667         // case SearchFieldPart:
    668         case TextFieldPart:
    669         case TextAreaPart:
    670             // Test the style to see if the UA border and background match.
    671             return (style->border() != border ||
    672                     *style->backgroundLayers() != background ||
    673                     style->visitedDependentColor(CSSPropertyBackgroundColor) != backgroundColor);
    674         default:
    675             return false;
    676     }
    677 }
    678 
    679 void RenderTheme::adjustRepaintRect(const RenderObject* o, IntRect& r)
    680 {
    681 #if USE(NEW_THEME)
    682     m_theme->inflateControlPaintRect(o->style()->appearance(), controlStatesForRenderer(o), r, o->style()->effectiveZoom());
    683 #endif
    684 }
    685 
    686 bool RenderTheme::supportsFocusRing(const RenderStyle* style) const
    687 {
    688     return (style->hasAppearance() && style->appearance() != TextFieldPart && style->appearance() != TextAreaPart && style->appearance() != MenulistButtonPart && style->appearance() != ListboxPart);
    689 }
    690 
    691 bool RenderTheme::stateChanged(RenderObject* o, ControlState state) const
    692 {
    693     // Default implementation assumes the controls don't respond to changes in :hover state
    694     if (state == HoverState && !supportsHover(o->style()))
    695         return false;
    696 
    697     // Assume pressed state is only responded to if the control is enabled.
    698     if (state == PressedState && !isEnabled(o))
    699         return false;
    700 
    701     // Repaint the control.
    702     o->repaint();
    703     return true;
    704 }
    705 
    706 ControlStates RenderTheme::controlStatesForRenderer(const RenderObject* o) const
    707 {
    708     ControlStates result = 0;
    709     if (isHovered(o)) {
    710         result |= HoverState;
    711         if (isSpinUpButtonPartHovered(o))
    712             result |= SpinUpState;
    713     }
    714     if (isPressed(o)) {
    715         result |= PressedState;
    716         if (isSpinUpButtonPartPressed(o))
    717             result |= SpinUpState;
    718     }
    719     if (isFocused(o) && o->style()->outlineStyleIsAuto())
    720         result |= FocusState;
    721     if (isEnabled(o))
    722         result |= EnabledState;
    723     if (isChecked(o))
    724         result |= CheckedState;
    725     if (isReadOnlyControl(o))
    726         result |= ReadOnlyState;
    727     if (isDefault(o))
    728         result |= DefaultState;
    729     if (!isActive(o))
    730         result |= WindowInactiveState;
    731     if (isIndeterminate(o))
    732         result |= IndeterminateState;
    733     return result;
    734 }
    735 
    736 bool RenderTheme::isActive(const RenderObject* o) const
    737 {
    738     Node* node = o->node();
    739     if (!node)
    740         return false;
    741 
    742     Frame* frame = node->document()->frame();
    743     if (!frame)
    744         return false;
    745 
    746     Page* page = frame->page();
    747     if (!page)
    748         return false;
    749 
    750     return page->focusController()->isActive();
    751 }
    752 
    753 bool RenderTheme::isChecked(const RenderObject* o) const
    754 {
    755     if (!o->node())
    756         return false;
    757 
    758     InputElement* inputElement = o->node()->toInputElement();
    759     if (!inputElement)
    760         return false;
    761 
    762     return inputElement->isChecked();
    763 }
    764 
    765 bool RenderTheme::isIndeterminate(const RenderObject* o) const
    766 {
    767     if (!o->node())
    768         return false;
    769 
    770     InputElement* inputElement = o->node()->toInputElement();
    771     if (!inputElement)
    772         return false;
    773 
    774     return inputElement->isIndeterminate();
    775 }
    776 
    777 bool RenderTheme::isEnabled(const RenderObject* o) const
    778 {
    779     Node* node = o->node();
    780     if (!node || !node->isElementNode())
    781         return true;
    782     return static_cast<Element*>(node)->isEnabledFormControl();
    783 }
    784 
    785 bool RenderTheme::isFocused(const RenderObject* o) const
    786 {
    787     Node* node = o->node();
    788     if (!node)
    789         return false;
    790     Document* document = node->document();
    791     Frame* frame = document->frame();
    792     return node == document->focusedNode() && frame && frame->selection()->isFocusedAndActive();
    793 }
    794 
    795 bool RenderTheme::isPressed(const RenderObject* o) const
    796 {
    797     if (!o->node())
    798         return false;
    799     return o->node()->active();
    800 }
    801 
    802 bool RenderTheme::isSpinUpButtonPartPressed(const RenderObject* o) const
    803 {
    804     Node* node = o->node();
    805     if (!node || !node->active() || !node->isElementNode()
    806         || !static_cast<Element*>(node)->isSpinButtonElement())
    807         return false;
    808     SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
    809     return element->upDownState() == SpinButtonElement::Up;
    810 }
    811 
    812 bool RenderTheme::isReadOnlyControl(const RenderObject* o) const
    813 {
    814     Node* node = o->node();
    815     if (!node || !node->isElementNode())
    816         return false;
    817     return static_cast<Element*>(node)->isReadOnlyFormControl();
    818 }
    819 
    820 bool RenderTheme::isHovered(const RenderObject* o) const
    821 {
    822     Node* node = o->node();
    823     if (!node)
    824         return false;
    825     if (!node->isElementNode() || !static_cast<Element*>(node)->isSpinButtonElement())
    826         return node->hovered();
    827     SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
    828     return element->hovered() && element->upDownState() != SpinButtonElement::Indeterminate;
    829 }
    830 
    831 bool RenderTheme::isSpinUpButtonPartHovered(const RenderObject* o) const
    832 {
    833     Node* node = o->node();
    834     if (!node || !node->isElementNode() || !static_cast<Element*>(node)->isSpinButtonElement())
    835         return false;
    836     SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
    837     return element->upDownState() == SpinButtonElement::Up;
    838 }
    839 
    840 bool RenderTheme::isDefault(const RenderObject* o) const
    841 {
    842     // A button should only have the default appearance if the page is active
    843     if (!isActive(o))
    844         return false;
    845 
    846     if (!o->document())
    847         return false;
    848 
    849     Settings* settings = o->document()->settings();
    850     if (!settings || !settings->inApplicationChromeMode())
    851         return false;
    852 
    853     return o->style()->appearance() == DefaultButtonPart;
    854 }
    855 
    856 #if !USE(NEW_THEME)
    857 
    858 void RenderTheme::adjustCheckboxStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
    859 {
    860     // A summary of the rules for checkbox designed to match WinIE:
    861     // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
    862     // font-size - not honored (control has no text), but we use it to decide which control size to use.
    863     setCheckboxSize(style);
    864 
    865     // padding - not honored by WinIE, needs to be removed.
    866     style->resetPadding();
    867 
    868     // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
    869     // for now, we will not honor it.
    870     style->resetBorder();
    871 
    872     style->setBoxShadow(0);
    873 }
    874 
    875 void RenderTheme::adjustRadioStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
    876 {
    877     // A summary of the rules for checkbox designed to match WinIE:
    878     // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
    879     // font-size - not honored (control has no text), but we use it to decide which control size to use.
    880     setRadioSize(style);
    881 
    882     // padding - not honored by WinIE, needs to be removed.
    883     style->resetPadding();
    884 
    885     // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
    886     // for now, we will not honor it.
    887     style->resetBorder();
    888 
    889     style->setBoxShadow(0);
    890 }
    891 
    892 void RenderTheme::adjustButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
    893 {
    894     // Most platforms will completely honor all CSS, and so we have no need to adjust the style
    895     // at all by default.  We will still allow the theme a crack at setting up a desired vertical size.
    896     setButtonSize(style);
    897 }
    898 
    899 void RenderTheme::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
    900 {
    901 }
    902 
    903 void RenderTheme::adjustOuterSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
    904 {
    905 }
    906 
    907 #endif
    908 
    909 void RenderTheme::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
    910 {
    911 }
    912 
    913 void RenderTheme::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const
    914 {
    915 }
    916 
    917 void RenderTheme::adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const
    918 {
    919 }
    920 
    921 #if ENABLE(INPUT_SPEECH)
    922 void RenderTheme::adjustInputFieldSpeechButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* element) const
    923 {
    924     RenderInputSpeech::adjustInputFieldSpeechButtonStyle(selector, style, element);
    925 }
    926 
    927 bool RenderTheme::paintInputFieldSpeechButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
    928 {
    929     return RenderInputSpeech::paintInputFieldSpeechButton(object, paintInfo, rect);
    930 }
    931 #endif
    932 
    933 #if ENABLE(METER_TAG)
    934 void RenderTheme::adjustMeterStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
    935 {
    936     style->setBoxShadow(0);
    937 }
    938 
    939 IntSize RenderTheme::meterSizeForBounds(const RenderMeter*, const IntRect& bounds) const
    940 {
    941     return bounds.size();
    942 }
    943 
    944 bool RenderTheme::supportsMeter(ControlPart) const
    945 {
    946     return false;
    947 }
    948 
    949 bool RenderTheme::paintMeter(RenderObject*, const PaintInfo&, const IntRect&)
    950 {
    951     return true;
    952 }
    953 
    954 #endif
    955 
    956 #if ENABLE(PROGRESS_TAG)
    957 double RenderTheme::animationRepeatIntervalForProgressBar(RenderProgress*) const
    958 {
    959     return 0;
    960 }
    961 
    962 double RenderTheme::animationDurationForProgressBar(RenderProgress*) const
    963 {
    964     return 0;
    965 }
    966 
    967 void RenderTheme::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const
    968 {
    969 }
    970 #endif
    971 
    972 void RenderTheme::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
    973 {
    974 }
    975 
    976 void RenderTheme::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const
    977 {
    978 }
    979 
    980 void RenderTheme::adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const
    981 {
    982 }
    983 
    984 void RenderTheme::adjustSliderThumbSize(RenderObject*) const
    985 {
    986 }
    987 
    988 void RenderTheme::adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
    989 {
    990 }
    991 
    992 void RenderTheme::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
    993 {
    994 }
    995 
    996 void RenderTheme::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const
    997 {
    998 }
    999 
   1000 void RenderTheme::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const
   1001 {
   1002 }
   1003 
   1004 void RenderTheme::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
   1005 {
   1006 }
   1007 
   1008 void RenderTheme::platformColorsDidChange()
   1009 {
   1010     m_activeSelectionForegroundColor = Color();
   1011     m_inactiveSelectionForegroundColor = Color();
   1012     m_activeSelectionBackgroundColor = Color();
   1013     m_inactiveSelectionBackgroundColor = Color();
   1014 
   1015     m_activeListBoxSelectionForegroundColor = Color();
   1016     m_inactiveListBoxSelectionForegroundColor = Color();
   1017     m_activeListBoxSelectionBackgroundColor = Color();
   1018     m_inactiveListBoxSelectionForegroundColor = Color();
   1019 
   1020     Page::scheduleForcedStyleRecalcForAllPages();
   1021 }
   1022 
   1023 Color RenderTheme::systemColor(int cssValueId) const
   1024 {
   1025     switch (cssValueId) {
   1026         case CSSValueActiveborder:
   1027             return 0xFFFFFFFF;
   1028         case CSSValueActivecaption:
   1029             return 0xFFCCCCCC;
   1030         case CSSValueAppworkspace:
   1031             return 0xFFFFFFFF;
   1032         case CSSValueBackground:
   1033             return 0xFF6363CE;
   1034         case CSSValueButtonface:
   1035             return 0xFFC0C0C0;
   1036         case CSSValueButtonhighlight:
   1037             return 0xFFDDDDDD;
   1038         case CSSValueButtonshadow:
   1039             return 0xFF888888;
   1040         case CSSValueButtontext:
   1041             return 0xFF000000;
   1042         case CSSValueCaptiontext:
   1043             return 0xFF000000;
   1044         case CSSValueGraytext:
   1045             return 0xFF808080;
   1046         case CSSValueHighlight:
   1047             return 0xFFB5D5FF;
   1048         case CSSValueHighlighttext:
   1049             return 0xFF000000;
   1050         case CSSValueInactiveborder:
   1051             return 0xFFFFFFFF;
   1052         case CSSValueInactivecaption:
   1053             return 0xFFFFFFFF;
   1054         case CSSValueInactivecaptiontext:
   1055             return 0xFF7F7F7F;
   1056         case CSSValueInfobackground:
   1057             return 0xFFFBFCC5;
   1058         case CSSValueInfotext:
   1059             return 0xFF000000;
   1060         case CSSValueMenu:
   1061             return 0xFFC0C0C0;
   1062         case CSSValueMenutext:
   1063             return 0xFF000000;
   1064         case CSSValueScrollbar:
   1065             return 0xFFFFFFFF;
   1066         case CSSValueText:
   1067             return 0xFF000000;
   1068         case CSSValueThreeddarkshadow:
   1069             return 0xFF666666;
   1070         case CSSValueThreedface:
   1071             return 0xFFC0C0C0;
   1072         case CSSValueThreedhighlight:
   1073             return 0xFFDDDDDD;
   1074         case CSSValueThreedlightshadow:
   1075             return 0xFFC0C0C0;
   1076         case CSSValueThreedshadow:
   1077             return 0xFF888888;
   1078         case CSSValueWindow:
   1079             return 0xFFFFFFFF;
   1080         case CSSValueWindowframe:
   1081             return 0xFFCCCCCC;
   1082         case CSSValueWindowtext:
   1083             return 0xFF000000;
   1084     }
   1085     return Color();
   1086 }
   1087 
   1088 Color RenderTheme::platformActiveTextSearchHighlightColor() const
   1089 {
   1090     return Color(255, 150, 50); // Orange.
   1091 }
   1092 
   1093 Color RenderTheme::platformInactiveTextSearchHighlightColor() const
   1094 {
   1095     return Color(255, 255, 0); // Yellow.
   1096 }
   1097 
   1098 void RenderTheme::setCustomFocusRingColor(const Color& c)
   1099 {
   1100     customFocusRingColor() = c;
   1101 }
   1102 
   1103 Color RenderTheme::focusRingColor()
   1104 {
   1105     return customFocusRingColor().isValid() ? customFocusRingColor() : defaultTheme()->platformFocusRingColor();
   1106 }
   1107 
   1108 } // namespace WebCore
   1109