Fix the issue that Web Audio test case fails on PR3.
[framework/web/webkit-efl.git] / Source / WebCore / rendering / RenderThemeChromiumWin.cpp
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 "RenderThemeChromiumWin.h"
27
28 #include <windows.h>
29 #include <uxtheme.h>
30 #include <vssym32.h>
31
32 #include "CSSValueKeywords.h"
33 #include "FontSelector.h"
34 #include "FontUtilsChromiumWin.h"
35 #include "GraphicsContext.h"
36 #include "HTMLMediaElement.h"
37 #include "HTMLNames.h"
38 #include "HWndDC.h"
39 #include "LayoutTestSupport.h"
40 #include "MediaControlElements.h"
41 #include "PaintInfo.h"
42 #include "PlatformSupport.h"
43 #include "RenderBox.h"
44 #include "RenderProgress.h"
45 #include "RenderSlider.h"
46 #include "ScrollbarTheme.h"
47 #include "SystemInfo.h"
48 #include "TransparencyWin.h"
49 #include <wtf/CurrentTime.h>
50
51
52 // FIXME: This dependency should eventually be removed.
53 #include <skia/ext/skia_utils_win.h>
54
55 #define SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(structName, member) \
56     offsetof(structName, member) + \
57     (sizeof static_cast<structName*>(0)->member)
58 #define NONCLIENTMETRICS_SIZE_PRE_VISTA \
59     SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(NONCLIENTMETRICS, lfMessageFont)
60
61 namespace WebCore {
62
63 // The standard width for the menu list drop-down button when run under
64 // layout test mode. Use the value that's currently captured in most baselines.
65 static const int kStandardMenuListButtonWidth = 17;
66
67 namespace {
68 // We must not create multiple ThemePainter instances.
69 class ThemePainter {
70 public:
71     ThemePainter(GraphicsContext* context, const IntRect& r)
72     {
73 #ifndef NDEBUG
74         ASSERT(!s_hasInstance);
75         s_hasInstance = true;
76 #endif
77         TransparencyWin::TransformMode transformMode = getTransformMode(context->getCTM());
78         m_helper.init(context, getLayerMode(context, transformMode), transformMode, r);
79
80         if (!m_helper.context()) {
81             // TransparencyWin doesn't have well-defined copy-ctor nor op=()
82             // so we re-initialize it instead of assigning a fresh istance.
83             // On the reinitialization, we fallback to use NoLayer mode.
84             // Note that the original initialization failure can be caused by
85             // a failure of an internal buffer allocation and NoLayer mode
86             // does not have such buffer allocations.
87             m_helper.~TransparencyWin();
88             new (&m_helper) TransparencyWin();
89             m_helper.init(context, TransparencyWin::NoLayer, transformMode, r);
90         }
91     }
92
93     ~ThemePainter()
94     {
95         m_helper.composite();
96 #ifndef NDEBUG
97         s_hasInstance = false;
98 #endif
99     }
100
101     GraphicsContext* context() { return m_helper.context(); }
102     const IntRect& drawRect() { return m_helper.drawRect(); }
103
104 private:
105
106     static TransparencyWin::LayerMode getLayerMode(GraphicsContext* context, TransparencyWin::TransformMode transformMode)
107     {
108         if (context->platformContext()->isDrawingToImageBuffer()) // Might have transparent background.
109             return TransparencyWin::WhiteLayer;
110         if (context->platformContext()->canvas()->isDrawingToLayer()) // Needs antialiasing help.
111             return TransparencyWin::OpaqueCompositeLayer;
112         // Nothing interesting.
113         return transformMode == TransparencyWin::KeepTransform ? TransparencyWin::NoLayer : TransparencyWin::OpaqueCompositeLayer;
114     }
115
116     static TransparencyWin::TransformMode getTransformMode(const AffineTransform& matrix)
117     {
118         if (matrix.b() || matrix.c()) // Skew.
119             return TransparencyWin::Untransform;
120         if (matrix.a() != 1.0 || matrix.d() != 1.0) // Scale.
121             return TransparencyWin::ScaleTransform;
122         // Nothing interesting.
123         return TransparencyWin::KeepTransform;
124     }
125
126     TransparencyWin m_helper;
127 #ifndef NDEBUG
128     static bool s_hasInstance;
129 #endif
130 };
131
132 #ifndef NDEBUG
133 bool ThemePainter::s_hasInstance = false;
134 #endif
135
136 } // namespace
137
138 static void getNonClientMetrics(NONCLIENTMETRICS* metrics)
139 {
140     static UINT size = (windowsVersion() >= WindowsVista) ?
141         sizeof(NONCLIENTMETRICS) : NONCLIENTMETRICS_SIZE_PRE_VISTA;
142     metrics->cbSize = size;
143     bool success = !!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, size, metrics, 0);
144     ASSERT(success);
145 }
146
147 static FontDescription smallSystemFont;
148 static FontDescription menuFont;
149 static FontDescription labelFont;
150
151 // Internal static helper functions.  We don't put them in an anonymous
152 // namespace so they have easier access to the WebCore namespace.
153
154 static bool supportsFocus(ControlPart appearance)
155 {
156     switch (appearance) {
157     case SquareButtonPart:
158     case PushButtonPart:
159     case ButtonPart:
160     case DefaultButtonPart:
161     case SearchFieldPart:
162     case TextFieldPart:
163     case TextAreaPart:
164         return true;
165     }
166     return false;
167 }
168
169 // Return the height of system font |font| in pixels.  We use this size by
170 // default for some non-form-control elements.
171 static float systemFontSize(const LOGFONT& font)
172 {
173     float size = -font.lfHeight;
174     if (size < 0) {
175         HFONT hFont = CreateFontIndirect(&font);
176         if (hFont) {
177             HWndDC hdc(0); // What about printing? Is this the right DC?
178             if (hdc) {
179                 HGDIOBJ hObject = SelectObject(hdc, hFont);
180                 TEXTMETRIC tm;
181                 GetTextMetrics(hdc, &tm);
182                 SelectObject(hdc, hObject);
183                 size = tm.tmAscent;
184             }
185             DeleteObject(hFont);
186         }
187     }
188
189     // The "codepage 936" bit here is from Gecko; apparently this helps make
190     // fonts more legible in Simplified Chinese where the default font size is
191     // too small.
192     //
193     // FIXME: http://b/1119883 Since this is only used for "small caption",
194     // "menu", and "status bar" objects, I'm not sure how much this even
195     // matters.  Plus the Gecko patch went in back in 2002, and maybe this
196     // isn't even relevant anymore.  We should investigate whether this should
197     // be removed, or perhaps broadened to be "any CJK locale".
198     //
199     return ((size < 12.0f) && (GetACP() == 936)) ? 12.0f : size;
200 }
201
202 // Converts |points| to pixels.  One point is 1/72 of an inch.
203 static float pointsToPixels(float points)
204 {
205     static float pixelsPerInch = 0.0f;
206     if (!pixelsPerInch) {
207         HWndDC hdc(0); // What about printing? Is this the right DC?
208         if (hdc) // Can this ever actually be NULL?
209             pixelsPerInch = GetDeviceCaps(hdc, LOGPIXELSY);
210         else
211             pixelsPerInch = 96.0f;
212     }
213
214     static const float pointsPerInch = 72.0f;
215     return points / pointsPerInch * pixelsPerInch;
216 }
217
218 static double querySystemBlinkInterval(double defaultInterval)
219 {
220     UINT blinkTime = GetCaretBlinkTime();
221     if (!blinkTime)
222         return defaultInterval;
223     if (blinkTime == INFINITE)
224         return 0;
225     return blinkTime / 1000.0;
226 }
227
228 PassRefPtr<RenderTheme> RenderThemeChromiumWin::create()
229 {
230     return adoptRef(new RenderThemeChromiumWin);
231 }
232
233 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
234 {
235     static RenderTheme* rt = RenderThemeChromiumWin::create().leakRef();
236     return rt;
237 }
238
239 bool RenderThemeChromiumWin::supportsFocusRing(const RenderStyle* style) const
240 {
241     // Let webkit draw one of its halo rings around any focused element,
242     // except push buttons. For buttons we use the windows PBS_DEFAULTED
243     // styling to give it a blue border.
244     return style->appearance() == ButtonPart
245             || style->appearance() == PushButtonPart
246             || style->appearance() == SquareButtonPart;
247 }
248
249 Color RenderThemeChromiumWin::platformActiveSelectionBackgroundColor() const
250 {
251     if (isRunningLayoutTest())
252         return Color(0x00, 0x00, 0xff); // Royal blue.
253     COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
254     return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
255 }
256
257 Color RenderThemeChromiumWin::platformInactiveSelectionBackgroundColor() const
258 {
259     if (isRunningLayoutTest())
260         return Color(0x99, 0x99, 0x99); // Medium gray.
261     COLORREF color = GetSysColor(COLOR_GRAYTEXT);
262     return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
263 }
264
265 Color RenderThemeChromiumWin::platformActiveSelectionForegroundColor() const
266 {
267     if (isRunningLayoutTest())
268         return Color(0xff, 0xff, 0xcc); // Pale yellow.
269     COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT);
270     return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
271 }
272
273 Color RenderThemeChromiumWin::platformInactiveSelectionForegroundColor() const
274 {
275     return Color::white;
276 }
277
278 Color RenderThemeChromiumWin::platformActiveTextSearchHighlightColor() const
279 {
280     return Color(0xff, 0x96, 0x32); // Orange.
281 }
282
283 Color RenderThemeChromiumWin::platformInactiveTextSearchHighlightColor() const
284 {
285     return Color(0xff, 0xff, 0x96); // Yellow.
286 }
287
288 void RenderThemeChromiumWin::systemFont(int propId, FontDescription& fontDescription) const
289 {
290     // This logic owes much to RenderThemeSafari.cpp.
291     FontDescription* cachedDesc = 0;
292     AtomicString faceName;
293     float fontSize = 0;
294     switch (propId) {
295     case CSSValueSmallCaption:
296         cachedDesc = &smallSystemFont;
297         if (!smallSystemFont.isAbsoluteSize()) {
298             NONCLIENTMETRICS metrics;
299             getNonClientMetrics(&metrics);
300             faceName = AtomicString(metrics.lfSmCaptionFont.lfFaceName, wcslen(metrics.lfSmCaptionFont.lfFaceName));
301             fontSize = systemFontSize(metrics.lfSmCaptionFont);
302         }
303         break;
304     case CSSValueMenu:
305         cachedDesc = &menuFont;
306         if (!menuFont.isAbsoluteSize()) {
307             NONCLIENTMETRICS metrics;
308             getNonClientMetrics(&metrics);
309             faceName = AtomicString(metrics.lfMenuFont.lfFaceName, wcslen(metrics.lfMenuFont.lfFaceName));
310             fontSize = systemFontSize(metrics.lfMenuFont);
311         }
312         break;
313     case CSSValueStatusBar:
314         cachedDesc = &labelFont;
315         if (!labelFont.isAbsoluteSize()) {
316             NONCLIENTMETRICS metrics;
317             getNonClientMetrics(&metrics);
318             faceName = metrics.lfStatusFont.lfFaceName;
319             fontSize = systemFontSize(metrics.lfStatusFont);
320         }
321         break;
322     case CSSValueWebkitMiniControl:
323     case CSSValueWebkitSmallControl:
324     case CSSValueWebkitControl:
325         faceName = defaultGUIFont();
326         // Why 2 points smaller?  Because that's what Gecko does.
327         fontSize = defaultFontSize - pointsToPixels(2);
328         break;
329     default:
330         faceName = defaultGUIFont();
331         fontSize = defaultFontSize;
332         break;
333     }
334
335     if (!cachedDesc)
336         cachedDesc = &fontDescription;
337
338     if (fontSize) {
339         cachedDesc->firstFamily().setFamily(faceName);
340         cachedDesc->setIsAbsoluteSize(true);
341         cachedDesc->setGenericFamily(FontDescription::NoFamily);
342         cachedDesc->setSpecifiedSize(fontSize);
343         cachedDesc->setWeight(FontWeightNormal);
344         cachedDesc->setItalic(false);
345     }
346     fontDescription = *cachedDesc;
347 }
348
349 // Map a CSSValue* system color to an index understood by GetSysColor().
350 static int cssValueIdToSysColorIndex(int cssValueId)
351 {
352     switch (cssValueId) {
353     case CSSValueActiveborder: return COLOR_ACTIVEBORDER;
354     case CSSValueActivecaption: return COLOR_ACTIVECAPTION;
355     case CSSValueAppworkspace: return COLOR_APPWORKSPACE;
356     case CSSValueBackground: return COLOR_BACKGROUND;
357     case CSSValueButtonface: return COLOR_BTNFACE;
358     case CSSValueButtonhighlight: return COLOR_BTNHIGHLIGHT;
359     case CSSValueButtonshadow: return COLOR_BTNSHADOW;
360     case CSSValueButtontext: return COLOR_BTNTEXT;
361     case CSSValueCaptiontext: return COLOR_CAPTIONTEXT;
362     case CSSValueGraytext: return COLOR_GRAYTEXT;
363     case CSSValueHighlight: return COLOR_HIGHLIGHT;
364     case CSSValueHighlighttext: return COLOR_HIGHLIGHTTEXT;
365     case CSSValueInactiveborder: return COLOR_INACTIVEBORDER;
366     case CSSValueInactivecaption: return COLOR_INACTIVECAPTION;
367     case CSSValueInactivecaptiontext: return COLOR_INACTIVECAPTIONTEXT;
368     case CSSValueInfobackground: return COLOR_INFOBK;
369     case CSSValueInfotext: return COLOR_INFOTEXT;
370     case CSSValueMenu: return COLOR_MENU;
371     case CSSValueMenutext: return COLOR_MENUTEXT;
372     case CSSValueScrollbar: return COLOR_SCROLLBAR;
373     case CSSValueThreeddarkshadow: return COLOR_3DDKSHADOW;
374     case CSSValueThreedface: return COLOR_3DFACE;
375     case CSSValueThreedhighlight: return COLOR_3DHIGHLIGHT;
376     case CSSValueThreedlightshadow: return COLOR_3DLIGHT;
377     case CSSValueThreedshadow: return COLOR_3DSHADOW;
378     case CSSValueWindow: return COLOR_WINDOW;
379     case CSSValueWindowframe: return COLOR_WINDOWFRAME;
380     case CSSValueWindowtext: return COLOR_WINDOWTEXT;
381     default: return -1; // Unsupported CSSValue
382     }
383 }
384
385 Color RenderThemeChromiumWin::systemColor(int cssValueId) const
386 {
387     int sysColorIndex = cssValueIdToSysColorIndex(cssValueId);
388     if (isRunningLayoutTest() || (sysColorIndex == -1))
389         return RenderTheme::systemColor(cssValueId);
390
391     COLORREF color = GetSysColor(sysColorIndex);
392     return Color(GetRValue(color), GetGValue(color), GetBValue(color));
393 }
394
395 #if ENABLE(DATALIST_ELEMENT)
396 IntSize RenderThemeChromiumWin::sliderTickSize() const
397 {
398     return IntSize(1, 3);
399 }
400
401 int RenderThemeChromiumWin::sliderTickOffsetFromTrackCenter() const
402 {
403     return 11;
404 }
405 #endif
406
407 void RenderThemeChromiumWin::adjustSliderThumbSize(RenderStyle* style, Element* element) const
408 {
409     // These sizes match what WinXP draws for various menus.
410     const int sliderThumbAlongAxis = 11;
411     const int sliderThumbAcrossAxis = 21;
412     if (style->appearance() == SliderThumbHorizontalPart) {
413         style->setWidth(Length(sliderThumbAlongAxis, Fixed));
414         style->setHeight(Length(sliderThumbAcrossAxis, Fixed));
415     } else if (style->appearance() == SliderThumbVerticalPart) {
416         style->setWidth(Length(sliderThumbAcrossAxis, Fixed));
417         style->setHeight(Length(sliderThumbAlongAxis, Fixed));
418     } else
419         RenderThemeChromiumSkia::adjustSliderThumbSize(style, element);
420 }
421
422 bool RenderThemeChromiumWin::paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& r)
423 {
424     return paintButton(o, i, r);
425 }
426 bool RenderThemeChromiumWin::paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& r)
427 {
428     return paintButton(o, i, r);
429 }
430
431 bool RenderThemeChromiumWin::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& r)
432 {
433     const ThemeData& themeData = getThemeData(o);
434
435     ThemePainter painter(i.context, r);
436     PlatformSupport::paintButton(painter.context(),
437                                 themeData.m_part,
438                                 themeData.m_state,
439                                 themeData.m_classicState,
440                                 painter.drawRect());
441     return false;
442 }
443
444 bool RenderThemeChromiumWin::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& r)
445 {
446     return paintTextFieldInternal(o, i, r, true);
447 }
448
449 bool RenderThemeChromiumWin::paintSliderTrack(RenderObject* o, const PaintInfo& i, const IntRect& r)
450 {
451     const ThemeData& themeData = getThemeData(o);
452
453     ThemePainter painter(i.context, r);
454     PlatformSupport::paintTrackbar(painter.context(),
455                                   themeData.m_part,
456                                   themeData.m_state,
457                                   themeData.m_classicState,
458                                   painter.drawRect());
459
460 #if ENABLE(DATALIST_ELEMENT)
461     paintSliderTicks(o, i, r);
462 #endif
463
464     return false;
465 }
466
467 bool RenderThemeChromiumWin::paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& r)
468 {
469     const ThemeData& themeData = getThemeData(o);
470
471     ThemePainter painter(i.context, r);
472     PlatformSupport::paintTrackbar(painter.context(),
473                                    themeData.m_part,
474                                    themeData.m_state,
475                                    themeData.m_classicState,
476                                    painter.drawRect());
477
478     return false;
479 }
480
481 static int menuListButtonWidth()
482 {
483     static int width = isRunningLayoutTest() ? kStandardMenuListButtonWidth : GetSystemMetrics(SM_CXVSCROLL);
484     return width;
485 }
486
487 // Used to paint unstyled menulists (i.e. with the default border)
488 bool RenderThemeChromiumWin::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& r)
489 {
490     if (!o->isBox())
491         return false;
492
493     const RenderBox* box = toRenderBox(o);
494     int borderRight = box->borderRight();
495     int borderLeft = box->borderLeft();
496     int borderTop = box->borderTop();
497     int borderBottom = box->borderBottom();
498
499     // If all the borders are 0, then tell skia not to paint the border on the
500     // textfield.  FIXME: http://b/1210017 Figure out how to get Windows to not
501     // draw individual borders and then pass that to skia so we can avoid
502     // drawing any borders that are set to 0. For non-zero borders, we draw the
503     // border, but webkit just draws over it.
504     bool drawEdges = !(!borderRight && !borderLeft && !borderTop && !borderBottom);
505
506     paintTextFieldInternal(o, i, r, drawEdges);
507
508     // Take padding and border into account.  If the MenuList is smaller than
509     // the size of a button, make sure to shrink it appropriately and not put
510     // its x position to the left of the menulist.
511     const int buttonWidth = menuListButtonWidth();
512     int spacingLeft = borderLeft + box->paddingLeft();
513     int spacingRight = borderRight + box->paddingRight();
514     int spacingTop = borderTop + box->paddingTop();
515     int spacingBottom = borderBottom + box->paddingBottom();
516
517     int buttonX;
518     if (r.maxX() - r.x() < buttonWidth)
519         buttonX = r.x();
520     else
521         buttonX = o->style()->direction() == LTR ? r.maxX() - spacingRight - buttonWidth : r.x() + spacingLeft;
522
523     // Compute the rectangle of the button in the destination image.
524     IntRect rect(buttonX,
525                  r.y() + spacingTop,
526                  std::min(buttonWidth, r.maxX() - r.x()),
527                  r.height() - (spacingTop + spacingBottom));
528
529     // Get the correct theme data for a textfield and paint the menu.
530     ThemePainter painter(i.context, rect);
531     PlatformSupport::paintMenuList(painter.context(),
532                                    CP_DROPDOWNBUTTON,
533                                    determineState(o),
534                                    determineClassicState(o),
535                                    painter.drawRect());
536     return false;
537 }
538
539 // static
540 void RenderThemeChromiumWin::setDefaultFontSize(int fontSize)
541 {
542     RenderThemeChromiumSkia::setDefaultFontSize(fontSize);
543
544     // Reset cached fonts.
545     smallSystemFont = menuFont = labelFont = FontDescription();
546 }
547
548 double RenderThemeChromiumWin::caretBlinkIntervalInternal() const
549 {
550     // This involves a system call, so we cache the result.
551     static double blinkInterval = querySystemBlinkInterval(RenderTheme::caretBlinkInterval());
552     return blinkInterval;
553 }
554
555 unsigned RenderThemeChromiumWin::determineState(RenderObject* o, ControlSubPart subPart)
556 {
557     unsigned result = TS_NORMAL;
558     ControlPart appearance = o->style()->appearance();
559     if (!isEnabled(o))
560         result = TS_DISABLED;
561     else if (isReadOnlyControl(o))
562         result = (appearance == TextFieldPart || appearance == TextAreaPart || appearance == SearchFieldPart) ? ETS_READONLY : TS_DISABLED;
563     // Active overrides hover and focused.
564     else if (isPressed(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartPressed(o))
565         result = TS_PRESSED;
566     else if (supportsFocus(appearance) && isFocused(o))
567         result = ETS_FOCUSED;
568     else if (isHovered(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartHovered(o))
569         result = TS_HOT;
570
571     // CBS_UNCHECKED*: 1-4
572     // CBS_CHECKED*: 5-8
573     // CBS_MIXED*: 9-12
574     if (isIndeterminate(o))
575         result += 8;
576     else if (isChecked(o))
577         result += 4;
578     return result;
579 }
580
581 unsigned RenderThemeChromiumWin::determineSliderThumbState(RenderObject* o)
582 {
583     unsigned result = TUS_NORMAL;
584     if (!isEnabled(o))
585         result = TUS_DISABLED;
586     else if (supportsFocus(o->style()->appearance()) && isFocused(o))
587         result = TUS_FOCUSED;
588     else if (isPressed(o))
589         result = TUS_PRESSED;
590     else if (isHovered(o))
591         result = TUS_HOT;
592     return result;
593 }
594
595 unsigned RenderThemeChromiumWin::determineClassicState(RenderObject* o, ControlSubPart subPart)
596 {
597     unsigned result = 0;
598
599     ControlPart part = o->style()->appearance();
600
601     // Sliders are always in the normal state.
602     if (part == SliderHorizontalPart || part == SliderVerticalPart)
603         return result;
604
605     // So are readonly text fields.
606     if (isReadOnlyControl(o) && (part == TextFieldPart || part == TextAreaPart || part == SearchFieldPart))
607         return result;
608
609     if (part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart) {
610         if (!isEnabled(o))
611             result = DFCS_INACTIVE;
612         else if (isPressed(o)) // Active supersedes hover
613             result = DFCS_PUSHED;
614         else if (isHovered(o))
615             result = DFCS_HOT;
616     } else {
617         if (!isEnabled(o) || isReadOnlyControl(o))
618             result = DFCS_INACTIVE;
619         // Active supersedes hover
620         else if (isPressed(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartPressed(o))
621             result = DFCS_PUSHED;
622         else if (supportsFocus(part) && isFocused(o)) // So does focused
623             result = 0;
624         else if (isHovered(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartHovered(o))
625             result = DFCS_HOT;
626         // Classic theme can't represent indeterminate states. Use unchecked appearance.
627         if (isChecked(o) && !isIndeterminate(o))
628             result |= DFCS_CHECKED;
629     }
630     return result;
631 }
632
633 ThemeData RenderThemeChromiumWin::getThemeData(RenderObject* o, ControlSubPart subPart)
634 {
635     ThemeData result;
636     switch (o->style()->appearance()) {
637     case CheckboxPart:
638         result.m_part = BP_CHECKBOX;
639         result.m_state = determineState(o);
640         result.m_classicState = DFCS_BUTTONCHECK;
641         break;
642     case RadioPart:
643         result.m_part = BP_RADIOBUTTON;
644         result.m_state = determineState(o);
645         result.m_classicState = DFCS_BUTTONRADIO;
646         break;
647     case SquareButtonPart:
648     case PushButtonPart:
649     case ButtonPart:
650         result.m_part = BP_PUSHBUTTON;
651         result.m_state = determineState(o);
652         result.m_classicState = DFCS_BUTTONPUSH;
653         break;
654     case SliderHorizontalPart:
655         result.m_part = TKP_TRACK;
656         result.m_state = TRS_NORMAL;
657         break;
658     case SliderVerticalPart:
659         result.m_part = TKP_TRACKVERT;
660         result.m_state = TRVS_NORMAL;
661         break;
662     case SliderThumbHorizontalPart:
663         result.m_part = TKP_THUMBBOTTOM;
664         result.m_state = determineSliderThumbState(o);
665         break;
666     case SliderThumbVerticalPart:
667         result.m_part = TKP_THUMBVERT;
668         result.m_state = determineSliderThumbState(o);
669         break;
670     case ListboxPart:
671     case MenulistPart:
672     case MenulistButtonPart:
673     case SearchFieldPart:
674     case TextFieldPart:
675     case TextAreaPart:
676         result.m_part = EP_EDITTEXT;
677         result.m_state = determineState(o);
678         break;
679     case InnerSpinButtonPart:
680         result.m_part = subPart == SpinButtonUp ? SPNP_UP : SPNP_DOWN;
681         result.m_state = determineState(o, subPart);
682         result.m_classicState = subPart == SpinButtonUp ? DFCS_SCROLLUP : DFCS_SCROLLDOWN;
683         break;
684     }
685
686     result.m_classicState |= determineClassicState(o, subPart);
687
688     return result;
689 }
690
691 bool RenderThemeChromiumWin::paintTextFieldInternal(RenderObject* o,
692                                                     const PaintInfo& i,
693                                                     const IntRect& r,
694                                                     bool drawEdges)
695 {
696     // Fallback to white if the specified color object is invalid.
697     // (Note PlatformSupport::paintTextField duplicates this check).
698     Color backgroundColor(Color::white);
699     if (o->style()->visitedDependentColor(CSSPropertyBackgroundColor).isValid())
700         backgroundColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor);
701
702     // If we have background-image, don't fill the content area to expose the
703     // parent's background. Also, we shouldn't fill the content area if the
704     // alpha of the color is 0. The API of Windows GDI ignores the alpha.
705     //
706     // Note that we should paint the content area white if we have neither the
707     // background color nor background image explicitly specified to keep the
708     // appearance of select element consistent with other browsers.
709     bool fillContentArea = !o->style()->hasBackgroundImage() && backgroundColor.alpha();
710
711     if (o->style()->hasBorderRadius()) {
712         // If the style has rounded borders, setup the context to clip the
713         // background (themed or filled) appropriately.
714         // FIXME: make sure we do the right thing if css background-clip is set.
715         i.context->save();
716         i.context->addRoundedRectClip(o->style()->getRoundedBorderFor(r));
717     }
718     {
719         const ThemeData& themeData = getThemeData(o);
720         ThemePainter painter(i.context, r);
721         PlatformSupport::paintTextField(painter.context(),
722                                         themeData.m_part,
723                                         themeData.m_state,
724                                         themeData.m_classicState,
725                                         painter.drawRect(),
726                                         backgroundColor,
727                                         fillContentArea,
728                                         drawEdges);
729         // End of block commits the painter before restoring context.
730     }
731     if (o->style()->hasBorderRadius())
732         i.context->restore();
733     return false;
734 }
735
736 void RenderThemeChromiumWin::adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
737 {
738     int width = ScrollbarTheme::theme()->scrollbarThickness();
739     style->setWidth(Length(width, Fixed));
740     style->setMinWidth(Length(width, Fixed));
741 }
742
743 bool RenderThemeChromiumWin::paintInnerSpinButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
744 {
745     IntRect half = rect;
746
747     // Need explicit blocks to avoid to create multiple ThemePainter instances.
748     {
749         half.setHeight(rect.height() / 2);
750         const ThemeData& upThemeData = getThemeData(object, SpinButtonUp);
751         ThemePainter upPainter(info.context, half);
752         PlatformSupport::paintSpinButton(upPainter.context(),
753                                          upThemeData.m_part,
754                                          upThemeData.m_state,
755                                          upThemeData.m_classicState,
756                                          upPainter.drawRect());
757     }
758
759     {
760         half.setY(rect.y() + rect.height() / 2);
761         const ThemeData& downThemeData = getThemeData(object, SpinButtonDown);
762         ThemePainter downPainter(info.context, half);
763         PlatformSupport::paintSpinButton(downPainter.context(),
764                                          downThemeData.m_part,
765                                          downThemeData.m_state,
766                                          downThemeData.m_classicState,
767                                          downPainter.drawRect());
768     }
769     return false;
770 }
771
772 #if ENABLE(PROGRESS_ELEMENT)
773
774 // MSDN says that update intervals for the bar is 30ms.
775 // http://msdn.microsoft.com/en-us/library/bb760842(v=VS.85).aspx
776 static const double progressAnimationFrameRate = 0.033;
777
778 double RenderThemeChromiumWin::animationRepeatIntervalForProgressBar(RenderProgress*) const
779 {
780     return progressAnimationFrameRate;
781 }
782
783 double RenderThemeChromiumWin::animationDurationForProgressBar(RenderProgress* renderProgress) const
784 {
785     // On Chromium Windows port, animationProgress() and associated values aren't used.
786     // So here we can return arbitrary positive value.
787     return progressAnimationFrameRate;
788 }
789
790 void RenderThemeChromiumWin::adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const
791 {
792 }
793
794 bool RenderThemeChromiumWin::paintProgressBar(RenderObject* o, const PaintInfo& i, const IntRect& r)
795 {
796     if (!o->isProgress())
797         return true;
798
799     RenderProgress* renderProgress = toRenderProgress(o);
800     // For indeterminate bar, valueRect is ignored and it is computed by the theme engine
801     // because the animation is a platform detail and WebKit doesn't need to know how.
802     IntRect valueRect = renderProgress->isDeterminate() ? determinateProgressValueRectFor(renderProgress, r) : IntRect(0, 0, 0, 0);
803     double animatedSeconds = renderProgress->animationStartTime() ?  WTF::currentTime() - renderProgress->animationStartTime() : 0;
804     ThemePainter painter(i.context, r);
805     DirectionFlippingScope scope(o, i, r);
806     PlatformSupport::paintProgressBar(painter.context(), r, valueRect, renderProgress->isDeterminate(), animatedSeconds);
807     return false;
808 }
809
810 #endif
811
812 } // namespace WebCore