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