1/*
2 * Copyright (C) 2006, 2007, 2013 Apple Inc.
3 * Copyright (C) 2009 Kenneth Rohde Christiansen
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB.  If not, write to
17 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 *
20 */
21
22#include "config.h"
23#include "RenderThemeWin.h"
24
25#include "CSSValueKeywords.h"
26#include "Element.h"
27#include "FontMetrics.h"
28#include "Frame.h"
29#include "FrameSelection.h"
30#include "GraphicsContext.h"
31#include "HTMLMeterElement.h"
32#include "LocalWindowsContext.h"
33#include "PaintInfo.h"
34#include "RenderMeter.h"
35#include "RenderSlider.h"
36#include "Settings.h"
37#include "SoftLinking.h"
38#include "SystemInfo.h"
39#include "UserAgentStyleSheets.h"
40#include "WebCoreBundleWin.h"
41#include <wtf/win/GDIObject.h>
42
43#if ENABLE(VIDEO)
44#include "RenderMediaControls.h"
45#endif
46
47#include <tchar.h>
48
49/*
50 * The following constants are used to determine how a widget is drawn using
51 * Windows' Theme API. For more information on theme parts and states see
52 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/topics/partsandstates.asp
53 */
54
55// Generic state constants
56#define TS_NORMAL    1
57#define TS_HOVER     2
58#define TS_ACTIVE    3
59#define TS_DISABLED  4
60#define TS_FOCUSED   5
61
62// Button constants
63#define BP_BUTTON    1
64#define BP_RADIO     2
65#define BP_CHECKBOX  3
66
67// Textfield constants
68#define TFP_TEXTFIELD 1
69#define EP_EDITBORDER_NOSCROLL 6
70#define TFS_READONLY  6
71
72// ComboBox constants (from vsstyle.h)
73#define CP_DROPDOWNBUTTON 1
74#define CP_BORDER 4
75#define CP_READONLY 5
76#define CP_DROPDOWNBUTTONRIGHT 6
77
78// TrackBar (slider) parts
79#define TKP_TRACK       1
80#define TKP_TRACKVERT   2
81
82// TrackBar (slider) thumb parts
83#define TKP_THUMBBOTTOM 4
84#define TKP_THUMBTOP    5
85#define TKP_THUMBLEFT   7
86#define TKP_THUMBRIGHT  8
87
88// Trackbar (slider) thumb states
89#define TUS_NORMAL      1
90#define TUS_HOT         2
91#define TUS_PRESSED     3
92#define TUS_FOCUSED     4
93#define TUS_DISABLED    5
94
95// button states
96#define PBS_NORMAL      1
97#define PBS_HOT         2
98#define PBS_PRESSED     3
99#define PBS_DISABLED    4
100#define PBS_DEFAULTED   5
101
102// Spin button parts
103#define SPNP_UP         1
104#define SPNP_DOWN       2
105
106// Spin button states
107#define DNS_NORMAL      1
108#define DNS_HOT         2
109#define DNS_PRESSED     3
110#define DNS_DISABLED    4
111#define UPS_NORMAL      1
112#define UPS_HOT         2
113#define UPS_PRESSED     3
114#define UPS_DISABLED    4
115
116// Progress bar parts
117#define PP_BAR          1
118#define PP_BARVERT      2
119#define PP_CHUNK        3
120#define PP_CHUNKVERT    4
121#define PP_FILL         5
122#define PP_FILLVERT     6
123#define PP_PULSEOVERLAY 7
124#define PP_MOVEOVERLAY  8
125#define PP_PULSEOVERLAYVERT 9
126#define PP_MOVEOVERLAYVERT  10
127#define PP_TRANSPARENTBAR   11
128#define PP_TRANSPARENTBARVERT 12
129
130// Progress bar states
131#define PBBS_NORMAL     1
132#define PBBS_PARTIAL    2
133#define PBBVS_NORMAL    1 // Vertical
134#define PBBVS_PARTIAL   2
135
136// Progress bar fill states
137#define PBFS_NORMAL     1
138#define PBFS_ERROR      2
139#define PBFS_PAUSED     3
140#define PBFS_PARTIAL    4
141#define PBFVS_NORMAL    1 // Vertical
142#define PBFVS_ERROR     2
143#define PBFVS_PAUSED    3
144#define PBFVS_PARTIAL   4
145
146
147SOFT_LINK_LIBRARY(uxtheme)
148SOFT_LINK(uxtheme, OpenThemeData, HANDLE, WINAPI, (HWND hwnd, LPCWSTR pszClassList), (hwnd, pszClassList))
149SOFT_LINK(uxtheme, CloseThemeData, HRESULT, WINAPI, (HANDLE hTheme), (hTheme))
150SOFT_LINK(uxtheme, DrawThemeBackground, HRESULT, WINAPI, (HANDLE hTheme, HDC hdc, int iPartId, int iStateId, const RECT* pRect, const RECT* pClipRect), (hTheme, hdc, iPartId, iStateId, pRect, pClipRect))
151SOFT_LINK(uxtheme, IsThemeActive, BOOL, WINAPI, (), ())
152SOFT_LINK(uxtheme, IsThemeBackgroundPartiallyTransparent, BOOL, WINAPI, (HANDLE hTheme, int iPartId, int iStateId), (hTheme, iPartId, iStateId))
153
154static bool haveTheme;
155
156static const unsigned vistaMenuListButtonOutset = 1;
157
158using namespace std;
159
160namespace WebCore {
161
162// This is the fixed width IE and Firefox use for buttons on dropdown menus
163static const int dropDownButtonWidth = 17;
164
165static const int shell32MagnifierIconIndex = 22;
166
167// Default font size to match Firefox.
168static const float defaultControlFontPixelSize = 13;
169
170static const float defaultCancelButtonSize = 9;
171static const float minCancelButtonSize = 5;
172static const float maxCancelButtonSize = 21;
173static const float defaultSearchFieldResultsDecorationSize = 13;
174static const float minSearchFieldResultsDecorationSize = 9;
175static const float maxSearchFieldResultsDecorationSize = 30;
176static const float defaultSearchFieldResultsButtonWidth = 18;
177
178static bool gWebKitIsBeingUnloaded;
179
180void RenderThemeWin::setWebKitIsBeingUnloaded()
181{
182    gWebKitIsBeingUnloaded = true;
183}
184
185PassRefPtr<RenderTheme> RenderThemeWin::create()
186{
187    return adoptRef(new RenderThemeWin);
188}
189
190#if !USE(SAFARI_THEME)
191PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
192{
193    static RenderTheme* winTheme = RenderThemeWin::create().leakRef();
194    return winTheme;
195}
196#endif
197
198RenderThemeWin::RenderThemeWin()
199    : m_buttonTheme(0)
200    , m_textFieldTheme(0)
201    , m_menuListTheme(0)
202    , m_sliderTheme(0)
203    , m_spinButtonTheme(0)
204    , m_progressBarTheme(0)
205{
206    haveTheme = uxthemeLibrary() && IsThemeActive();
207}
208
209RenderThemeWin::~RenderThemeWin()
210{
211    // If WebKit is being unloaded, then uxtheme.dll is no longer available.
212    if (gWebKitIsBeingUnloaded || !uxthemeLibrary())
213        return;
214    close();
215}
216
217HANDLE RenderThemeWin::buttonTheme() const
218{
219    if (haveTheme && !m_buttonTheme)
220        m_buttonTheme = OpenThemeData(0, L"Button");
221    return m_buttonTheme;
222}
223
224HANDLE RenderThemeWin::textFieldTheme() const
225{
226    if (haveTheme && !m_textFieldTheme)
227        m_textFieldTheme = OpenThemeData(0, L"Edit");
228    return m_textFieldTheme;
229}
230
231HANDLE RenderThemeWin::menuListTheme() const
232{
233    if (haveTheme && !m_menuListTheme)
234        m_menuListTheme = OpenThemeData(0, L"ComboBox");
235    return m_menuListTheme;
236}
237
238HANDLE RenderThemeWin::sliderTheme() const
239{
240    if (haveTheme && !m_sliderTheme)
241        m_sliderTheme = OpenThemeData(0, L"TrackBar");
242    return m_sliderTheme;
243}
244
245HANDLE RenderThemeWin::spinButtonTheme() const
246{
247    if (haveTheme && !m_spinButtonTheme)
248        m_spinButtonTheme = OpenThemeData(0, L"Spin");
249    return m_spinButtonTheme;
250}
251
252HANDLE RenderThemeWin::progressBarTheme() const
253{
254    if (haveTheme && !m_progressBarTheme)
255        m_progressBarTheme = OpenThemeData(0, L"Progress");
256    return m_progressBarTheme;
257}
258
259void RenderThemeWin::close()
260{
261    // This method will need to be called when the OS theme changes to flush our cached themes.
262    if (m_buttonTheme)
263        CloseThemeData(m_buttonTheme);
264    if (m_textFieldTheme)
265        CloseThemeData(m_textFieldTheme);
266    if (m_menuListTheme)
267        CloseThemeData(m_menuListTheme);
268    if (m_sliderTheme)
269        CloseThemeData(m_sliderTheme);
270    if (m_spinButtonTheme)
271        CloseThemeData(m_spinButtonTheme);
272    if (m_progressBarTheme)
273        CloseThemeData(m_progressBarTheme);
274    m_buttonTheme = m_textFieldTheme = m_menuListTheme = m_sliderTheme = m_spinButtonTheme = m_progressBarTheme = 0;
275
276    haveTheme = uxthemeLibrary() && IsThemeActive();
277}
278
279void RenderThemeWin::themeChanged()
280{
281    close();
282}
283
284String RenderThemeWin::extraDefaultStyleSheet()
285{
286    return String(themeWinUserAgentStyleSheet, sizeof(themeWinUserAgentStyleSheet));
287}
288
289String RenderThemeWin::extraQuirksStyleSheet()
290{
291    return String(themeWinQuirksUserAgentStyleSheet, sizeof(themeWinQuirksUserAgentStyleSheet));
292}
293
294bool RenderThemeWin::supportsHover(const RenderStyle&) const
295{
296    // The Classic/2k look has no hover effects.
297    return haveTheme;
298}
299
300Color RenderThemeWin::platformActiveSelectionBackgroundColor() const
301{
302    COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
303    return Color(GetRValue(color), GetGValue(color), GetBValue(color));
304}
305
306Color RenderThemeWin::platformInactiveSelectionBackgroundColor() const
307{
308    // This color matches Firefox.
309    return Color(176, 176, 176);
310}
311
312Color RenderThemeWin::platformActiveSelectionForegroundColor() const
313{
314    COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT);
315    return Color(GetRValue(color), GetGValue(color), GetBValue(color));
316}
317
318Color RenderThemeWin::platformInactiveSelectionForegroundColor() const
319{
320    return platformActiveSelectionForegroundColor();
321}
322
323static void fillFontDescription(FontDescription& fontDescription, LOGFONT& logFont, float fontSize)
324{
325    fontDescription.setIsAbsoluteSize(true);
326    fontDescription.setGenericFamily(FontDescription::NoFamily);
327    fontDescription.setOneFamily(String(logFont.lfFaceName));
328    fontDescription.setSpecifiedSize(fontSize);
329    fontDescription.setWeight(logFont.lfWeight >= 700 ? FontWeightBold : FontWeightNormal); // FIXME: Use real weight.
330    fontDescription.setItalic(logFont.lfItalic);
331}
332
333static void fillFontDescription(FontDescription& fontDescription, LOGFONT& logFont)
334{
335    fillFontDescription(fontDescription, logFont, abs(logFont.lfHeight));
336}
337
338void RenderThemeWin::systemFont(CSSValueID valueID, FontDescription& fontDescription) const
339{
340    static FontDescription captionFont;
341    static FontDescription controlFont;
342    static FontDescription smallCaptionFont;
343    static FontDescription menuFont;
344    static FontDescription iconFont;
345    static FontDescription messageBoxFont;
346    static FontDescription statusBarFont;
347    static FontDescription systemFont;
348
349    static bool initialized;
350    static NONCLIENTMETRICS ncm;
351
352    if (!initialized) {
353        initialized = true;
354        ncm.cbSize = sizeof(NONCLIENTMETRICS);
355        ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);
356    }
357
358    switch (valueID) {
359    case CSSValueIcon: {
360        if (!iconFont.isAbsoluteSize()) {
361            LOGFONT logFont;
362            ::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(logFont), &logFont, 0);
363            fillFontDescription(iconFont, logFont);
364        }
365        fontDescription = iconFont;
366        break;
367    }
368    case CSSValueMenu:
369        if (!menuFont.isAbsoluteSize())
370            fillFontDescription(menuFont, ncm.lfMenuFont);
371        fontDescription = menuFont;
372        break;
373    case CSSValueMessageBox:
374        if (!messageBoxFont.isAbsoluteSize())
375            fillFontDescription(messageBoxFont, ncm.lfMessageFont);
376        fontDescription = messageBoxFont;
377        break;
378    case CSSValueStatusBar:
379        if (!statusBarFont.isAbsoluteSize())
380            fillFontDescription(statusBarFont, ncm.lfStatusFont);
381        fontDescription = statusBarFont;
382        break;
383    case CSSValueCaption:
384        if (!captionFont.isAbsoluteSize())
385            fillFontDescription(captionFont, ncm.lfCaptionFont);
386        fontDescription = captionFont;
387        break;
388    case CSSValueSmallCaption:
389        if (!smallCaptionFont.isAbsoluteSize())
390            fillFontDescription(smallCaptionFont, ncm.lfSmCaptionFont);
391        fontDescription = smallCaptionFont;
392        break;
393    case CSSValueWebkitSmallControl:
394    case CSSValueWebkitMiniControl: // Just map to small.
395    case CSSValueWebkitControl: // Just map to small.
396        if (!controlFont.isAbsoluteSize()) {
397            HGDIOBJ hGDI = ::GetStockObject(DEFAULT_GUI_FONT);
398            if (hGDI) {
399                LOGFONT logFont;
400                if (::GetObject(hGDI, sizeof(logFont), &logFont) > 0)
401                    fillFontDescription(controlFont, logFont, defaultControlFontPixelSize);
402            }
403        }
404        fontDescription = controlFont;
405        break;
406    default: { // Everything else uses the stock GUI font.
407        if (!systemFont.isAbsoluteSize()) {
408            HGDIOBJ hGDI = ::GetStockObject(DEFAULT_GUI_FONT);
409            if (hGDI) {
410                LOGFONT logFont;
411                if (::GetObject(hGDI, sizeof(logFont), &logFont) > 0)
412                    fillFontDescription(systemFont, logFont);
413            }
414        }
415        fontDescription = systemFont;
416    }
417    }
418}
419
420bool RenderThemeWin::supportsFocus(ControlPart appearance) const
421{
422    switch (appearance) {
423        case PushButtonPart:
424        case ButtonPart:
425        case DefaultButtonPart:
426            return true;
427        default:
428            return false;
429    }
430}
431
432bool RenderThemeWin::supportsFocusRing(const RenderStyle& style) const
433{
434    return supportsFocus(style.appearance());
435}
436
437unsigned RenderThemeWin::determineClassicState(const RenderObject& o, ControlSubPart subPart)
438{
439    unsigned state = 0;
440    switch (o.style().appearance()) {
441        case PushButtonPart:
442        case ButtonPart:
443        case DefaultButtonPart:
444            state = DFCS_BUTTONPUSH;
445            if (!isEnabled(o))
446                state |= DFCS_INACTIVE;
447            else if (isPressed(o))
448                state |= DFCS_PUSHED;
449            break;
450        case RadioPart:
451        case CheckboxPart:
452            state = (o.style().appearance() == RadioPart) ? DFCS_BUTTONRADIO : DFCS_BUTTONCHECK;
453            if (isChecked(o))
454                state |= DFCS_CHECKED;
455            if (!isEnabled(o))
456                state |= DFCS_INACTIVE;
457            else if (isPressed(o))
458                state |= DFCS_PUSHED;
459            break;
460        case MenulistPart:
461            state = DFCS_SCROLLCOMBOBOX;
462            if (!isEnabled(o))
463                state |= DFCS_INACTIVE;
464            else if (isPressed(o))
465                state |= DFCS_PUSHED;
466            break;
467        case InnerSpinButtonPart: {
468            bool isUpButton = subPart == SpinButtonUp;
469            state = isUpButton ? DFCS_SCROLLUP : DFCS_SCROLLDOWN;
470            if (!isEnabled(o) || isReadOnlyControl(o))
471                state |= DFCS_INACTIVE;
472            else if (isPressed(o) && isUpButton == isSpinUpButtonPartPressed(o))
473                state |= DFCS_PUSHED;
474            else if (isHovered(o) && isUpButton == isSpinUpButtonPartHovered(o))
475                state |= DFCS_HOT;
476            break;
477        }
478        default:
479            break;
480    }
481    return state;
482}
483
484unsigned RenderThemeWin::determineState(const RenderObject& o)
485{
486    unsigned result = TS_NORMAL;
487    ControlPart appearance = o.style().appearance();
488    if (!isEnabled(o))
489        result = TS_DISABLED;
490    else if (isReadOnlyControl(o) && (TextFieldPart == appearance || TextAreaPart == appearance || SearchFieldPart == appearance))
491        result = TFS_READONLY; // Readonly is supported on textfields.
492    else if (isPressed(o)) // Active overrides hover and focused.
493        result = TS_ACTIVE;
494    else if (supportsFocus(appearance) && isFocused(o))
495        result = TS_FOCUSED;
496    else if (isHovered(o))
497        result = TS_HOVER;
498    if (isChecked(o))
499        result += 4; // 4 unchecked states, 4 checked states.
500    else if (isIndeterminate(o) && appearance == CheckboxPart)
501        result += 8;
502    return result;
503}
504
505unsigned RenderThemeWin::determineSliderThumbState(const RenderObject& o)
506{
507    unsigned result = TUS_NORMAL;
508    if (!isEnabled(o))
509        result = TUS_DISABLED;
510    else if (supportsFocus(o.style().appearance()) && isFocused(o))
511        result = TUS_FOCUSED;
512    else if (isPressed(o))
513        result = TUS_PRESSED;
514    else if (isHovered(o))
515        result = TUS_HOT;
516    return result;
517}
518
519unsigned RenderThemeWin::determineButtonState(const RenderObject& o)
520{
521    unsigned result = PBS_NORMAL;
522    if (!isEnabled(o))
523        result = PBS_DISABLED;
524    else if (isPressed(o))
525        result = PBS_PRESSED;
526    else if (supportsFocus(o.style().appearance()) && isFocused(o))
527        result = PBS_DEFAULTED;
528    else if (isHovered(o))
529        result = PBS_HOT;
530    else if (isDefault(o))
531        result = PBS_DEFAULTED;
532    return result;
533}
534
535unsigned RenderThemeWin::determineSpinButtonState(const RenderObject& o, ControlSubPart subPart)
536{
537    bool isUpButton = subPart == SpinButtonUp;
538    unsigned result = isUpButton ? UPS_NORMAL : DNS_NORMAL;
539    if (!isEnabled(o) || isReadOnlyControl(o))
540        result = isUpButton ? UPS_DISABLED : DNS_DISABLED;
541    else if (isPressed(o) && isUpButton == isSpinUpButtonPartPressed(o))
542        result = isUpButton ? UPS_PRESSED : DNS_PRESSED;
543    else if (isHovered(o) && isUpButton == isSpinUpButtonPartHovered(o))
544        result = isUpButton ? UPS_HOT : DNS_HOT;
545    return result;
546}
547
548ThemeData RenderThemeWin::getClassicThemeData(const RenderObject& o, ControlSubPart subPart)
549{
550    ThemeData result;
551    switch (o.style().appearance()) {
552        case PushButtonPart:
553        case ButtonPart:
554        case DefaultButtonPart:
555        case CheckboxPart:
556        case RadioPart:
557            result.m_part = DFC_BUTTON;
558            result.m_state = determineClassicState(o);
559            break;
560        case MenulistPart:
561            result.m_part = DFC_SCROLL;
562            result.m_state = determineClassicState(o);
563            break;
564        case MeterPart:
565            result.m_part = PP_BAR;
566            result.m_state = determineState(o);
567            break;
568        case SearchFieldPart:
569        case TextFieldPart:
570        case TextAreaPart:
571            result.m_part = TFP_TEXTFIELD;
572            result.m_state = determineState(o);
573            break;
574        case SliderHorizontalPart:
575            result.m_part = TKP_TRACK;
576            result.m_state = TS_NORMAL;
577            break;
578        case SliderVerticalPart:
579            result.m_part = TKP_TRACKVERT;
580            result.m_state = TS_NORMAL;
581            break;
582        case SliderThumbHorizontalPart:
583            result.m_part = TKP_THUMBBOTTOM;
584            result.m_state = determineSliderThumbState(o);
585            break;
586        case SliderThumbVerticalPart:
587            result.m_part = TKP_THUMBRIGHT;
588            result.m_state = determineSliderThumbState(o);
589            break;
590        case InnerSpinButtonPart:
591            result.m_part = DFC_SCROLL;
592            result.m_state = determineClassicState(o, subPart);
593            break;
594        default:
595            break;
596    }
597    return result;
598}
599
600ThemeData RenderThemeWin::getThemeData(const RenderObject& o, ControlSubPart subPart)
601{
602    if (!haveTheme)
603        return getClassicThemeData(o, subPart);
604
605    ThemeData result;
606    switch (o.style().appearance()) {
607        case PushButtonPart:
608        case ButtonPart:
609        case DefaultButtonPart:
610            result.m_part = BP_BUTTON;
611            result.m_state = determineButtonState(o);
612            break;
613        case CheckboxPart:
614            result.m_part = BP_CHECKBOX;
615            result.m_state = determineState(o);
616            break;
617        case MenulistPart:
618        case MenulistButtonPart: {
619            const bool isVistaOrLater = (windowsVersion() >= WindowsVista);
620            result.m_part = isVistaOrLater ? CP_DROPDOWNBUTTONRIGHT : CP_DROPDOWNBUTTON;
621            if (isVistaOrLater && o.frame().settings().applicationChromeMode()) {
622                // The "readonly" look we use in application chrome mode
623                // only uses a "normal" look for the drop down button.
624                result.m_state = TS_NORMAL;
625            } else
626                result.m_state = determineState(o);
627            break;
628        }
629        case MeterPart:
630            result.m_part = PP_BAR;
631            result.m_state = determineState(o);
632            break;
633        case RadioPart:
634            result.m_part = BP_RADIO;
635            result.m_state = determineState(o);
636            break;
637        case SearchFieldPart:
638        case TextFieldPart:
639        case TextAreaPart:
640            result.m_part = (windowsVersion() >= WindowsVista) ? EP_EDITBORDER_NOSCROLL : TFP_TEXTFIELD;
641            result.m_state = determineState(o);
642            break;
643        case SliderHorizontalPart:
644            result.m_part = TKP_TRACK;
645            result.m_state = TS_NORMAL;
646            break;
647        case SliderVerticalPart:
648            result.m_part = TKP_TRACKVERT;
649            result.m_state = TS_NORMAL;
650            break;
651        case SliderThumbHorizontalPart:
652            result.m_part = TKP_THUMBBOTTOM;
653            result.m_state = determineSliderThumbState(o);
654            break;
655        case SliderThumbVerticalPart:
656            result.m_part = TKP_THUMBRIGHT;
657            result.m_state = determineSliderThumbState(o);
658            break;
659        case InnerSpinButtonPart:
660            result.m_part = subPart == SpinButtonUp ? SPNP_UP : SPNP_DOWN;
661            result.m_state = determineSpinButtonState(o, subPart);
662            break;
663    }
664
665    return result;
666}
667
668static void drawControl(GraphicsContext* context, const RenderObject& o, HANDLE theme, const ThemeData& themeData, const IntRect& r)
669{
670    bool alphaBlend = false;
671    if (theme)
672        alphaBlend = IsThemeBackgroundPartiallyTransparent(theme, themeData.m_part, themeData.m_state);
673    LocalWindowsContext windowsContext(context, r, alphaBlend);
674    RECT widgetRect = r;
675    if (theme)
676        DrawThemeBackground(theme, windowsContext.hdc(), themeData.m_part, themeData.m_state, &widgetRect, 0);
677    else {
678        HDC hdc = windowsContext.hdc();
679        if (themeData.m_part == TFP_TEXTFIELD) {
680            ::DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
681            if (themeData.m_state == TS_DISABLED || themeData.m_state ==  TFS_READONLY)
682                ::FillRect(hdc, &widgetRect, (HBRUSH)(COLOR_BTNFACE+1));
683            else
684                ::FillRect(hdc, &widgetRect, (HBRUSH)(COLOR_WINDOW+1));
685        } else if (themeData.m_part == TKP_TRACK || themeData.m_part == TKP_TRACKVERT) {
686            ::DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
687            ::FillRect(hdc, &widgetRect, (HBRUSH)GetStockObject(GRAY_BRUSH));
688        } else if ((o.style().appearance() == SliderThumbHorizontalPart
689        || o.style().appearance() == SliderThumbVerticalPart)
690        && (themeData.m_part == TKP_THUMBBOTTOM || themeData.m_part == TKP_THUMBTOP
691        || themeData.m_part == TKP_THUMBLEFT || themeData.m_part == TKP_THUMBRIGHT)) {
692            ::DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_RECT | BF_SOFT | BF_MIDDLE | BF_ADJUST);
693            if (themeData.m_state == TUS_DISABLED) {
694                static WORD patternBits[8] = {0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55};
695                auto patternBmp = adoptGDIObject(::CreateBitmap(8, 8, 1, 1, patternBits));
696                if (patternBmp) {
697                    auto brush = adoptGDIObject(::CreatePatternBrush(patternBmp.get()));
698                    COLORREF oldForeColor = ::SetTextColor(hdc, ::GetSysColor(COLOR_3DFACE));
699                    COLORREF oldBackColor = ::SetBkColor(hdc, ::GetSysColor(COLOR_3DHILIGHT));
700                    POINT p;
701                    ::GetViewportOrgEx(hdc, &p);
702                    ::SetBrushOrgEx(hdc, p.x + widgetRect.left, p.y + widgetRect.top, NULL);
703                    HGDIOBJ oldBrush = ::SelectObject(hdc, brush.get());
704                    ::FillRect(hdc, &widgetRect, brush.get());
705                    ::SetTextColor(hdc, oldForeColor);
706                    ::SetBkColor(hdc, oldBackColor);
707                    ::SelectObject(hdc, oldBrush);
708                } else
709                    ::FillRect(hdc, &widgetRect, (HBRUSH)COLOR_3DHILIGHT);
710            }
711        } else {
712            // Push buttons, buttons, checkboxes and radios, and the dropdown arrow in menulists.
713            if (o.style().appearance() == DefaultButtonPart) {
714                HBRUSH brush = ::GetSysColorBrush(COLOR_3DDKSHADOW);
715                ::FrameRect(hdc, &widgetRect, brush);
716                ::InflateRect(&widgetRect, -1, -1);
717                ::DrawEdge(hdc, &widgetRect, BDR_RAISEDOUTER, BF_RECT | BF_MIDDLE);
718            }
719            ::DrawFrameControl(hdc, &widgetRect, themeData.m_part, themeData.m_state);
720        }
721    }
722
723    if (!alphaBlend && !context->isInTransparencyLayer())
724        DIBPixelData::setRGBABitmapAlpha(windowsContext.hdc(), r, 255);
725}
726
727bool RenderThemeWin::paintButton(const RenderObject& o, const PaintInfo& i, const IntRect& r)
728{
729    drawControl(i.context,  o, buttonTheme(), getThemeData(o), r);
730    return false;
731}
732
733void RenderThemeWin::adjustInnerSpinButtonStyle(StyleResolver& styleResolver, RenderStyle& style, Element& e) const
734{
735    int width = ::GetSystemMetrics(SM_CXVSCROLL);
736    if (width <= 0)
737        width = 17; // Vista's default.
738    style.setWidth(Length(width, Fixed));
739    style.setMinWidth(Length(width, Fixed));
740}
741
742bool RenderThemeWin::paintInnerSpinButton(const RenderObject& o, const PaintInfo& i, const IntRect& r)
743{
744    // We split the specified rectangle into two vertically. We can't draw a
745    // spin button of which height is less than 2px.
746    if (r.height() < 2)
747        return false;
748    IntRect upRect(r);
749    upRect.setHeight(r.height() / 2);
750    IntRect downRect(r);
751    downRect.setY(upRect.maxY());
752    downRect.setHeight(r.height() - upRect.height());
753    drawControl(i.context, o, spinButtonTheme(), getThemeData(o, SpinButtonUp), upRect);
754    drawControl(i.context, o, spinButtonTheme(), getThemeData(o, SpinButtonDown), downRect);
755    return false;
756}
757
758void RenderThemeWin::setCheckboxSize(RenderStyle& style) const
759{
760    // If the width and height are both specified, then we have nothing to do.
761    if (!style.width().isIntrinsicOrAuto() && !style.height().isAuto())
762        return;
763
764    // FIXME:  A hard-coded size of 13 is used.  This is wrong but necessary for now.  It matches Firefox.
765    // At different DPI settings on Windows, querying the theme gives you a larger size that accounts for
766    // the higher DPI.  Until our entire engine honors a DPI setting other than 96, we can't rely on the theme's
767    // metrics.
768    if (style.width().isIntrinsicOrAuto())
769        style.setWidth(Length(13, Fixed));
770    if (style.height().isAuto())
771        style.setHeight(Length(13, Fixed));
772}
773
774bool RenderThemeWin::paintTextField(const RenderObject& o, const PaintInfo& i, const FloatRect& r)
775{
776    drawControl(i.context,  o, textFieldTheme(), getThemeData(o), IntRect(r));
777    return false;
778}
779
780bool RenderThemeWin::paintMenuList(const RenderObject& renderer, const PaintInfo& paintInfo, const FloatRect& rect)
781{
782    HANDLE theme;
783    int part;
784    if (haveTheme && (windowsVersion() >= WindowsVista)) {
785        theme = menuListTheme();
786        if (renderer.frame().settings().applicationChromeMode())
787            part = CP_READONLY;
788        else
789            part = CP_BORDER;
790    } else {
791        theme = textFieldTheme();
792        part = TFP_TEXTFIELD;
793    }
794
795    drawControl(paintInfo.context, renderer, theme, ThemeData(part, determineState(renderer)), IntRect(rect));
796
797    return paintMenuListButtonDecorations(renderer, paintInfo, FloatRect(rect));
798}
799
800void RenderThemeWin::adjustMenuListStyle(StyleResolver& styleResolver, RenderStyle& style, Element& e) const
801{
802    style.resetBorder();
803    adjustMenuListButtonStyle(styleResolver, style, e);
804}
805
806void RenderThemeWin::adjustMenuListButtonStyle(StyleResolver& styleResolver, RenderStyle& style, Element& e) const
807{
808    // These are the paddings needed to place the text correctly in the <select> box
809    const int dropDownBoxPaddingTop    = 2;
810    const int dropDownBoxPaddingRight  = style.direction() == LTR ? 4 + dropDownButtonWidth : 4;
811    const int dropDownBoxPaddingBottom = 2;
812    const int dropDownBoxPaddingLeft   = style.direction() == LTR ? 4 : 4 + dropDownButtonWidth;
813    // The <select> box must be at least 12px high for the button to render nicely on Windows
814    const int dropDownBoxMinHeight = 12;
815
816    // Position the text correctly within the select box and make the box wide enough to fit the dropdown button
817    style.setPaddingTop(Length(dropDownBoxPaddingTop, Fixed));
818    style.setPaddingRight(Length(dropDownBoxPaddingRight, Fixed));
819    style.setPaddingBottom(Length(dropDownBoxPaddingBottom, Fixed));
820    style.setPaddingLeft(Length(dropDownBoxPaddingLeft, Fixed));
821
822    // Height is locked to auto
823    style.setHeight(Length(Auto));
824
825    // Calculate our min-height
826    int minHeight = style.fontMetrics().height();
827    minHeight = max(minHeight, dropDownBoxMinHeight);
828
829    style.setMinHeight(Length(minHeight, Fixed));
830
831    style.setLineHeight(RenderStyle::initialLineHeight());
832
833    // White-space is locked to pre
834    style.setWhiteSpace(PRE);
835}
836
837bool RenderThemeWin::paintMenuListButtonDecorations(const RenderObject& renderer, const PaintInfo& paintInfo, const FloatRect& rect)
838{
839    // FIXME: Don't make hardcoded assumptions about the thickness of the textfield border.
840    int borderThickness = haveTheme ? 1 : 2;
841
842    // Paint the dropdown button on the inner edge of the text field,
843    // leaving space for the text field's 1px border
844    IntRect buttonRect(rect);
845    buttonRect.inflate(-borderThickness);
846    if (renderer.style().direction() == LTR)
847        buttonRect.setX(buttonRect.maxX() - dropDownButtonWidth);
848    buttonRect.setWidth(dropDownButtonWidth);
849
850    if ((windowsVersion() >= WindowsVista)) {
851        // Outset the top, right, and bottom borders of the button so that they coincide with the <select>'s border.
852        buttonRect.setY(buttonRect.y() - vistaMenuListButtonOutset);
853        buttonRect.setHeight(buttonRect.height() + 2 * vistaMenuListButtonOutset);
854        buttonRect.setWidth(buttonRect.width() + vistaMenuListButtonOutset);
855    }
856
857    drawControl(paintInfo.context, renderer, menuListTheme(), getThemeData(renderer), buttonRect);
858
859    return false;
860}
861
862const int trackWidth = 4;
863
864bool RenderThemeWin::paintSliderTrack(const RenderObject& o, const PaintInfo& i, const IntRect& r)
865{
866    IntRect bounds = r;
867
868    if (o.style().appearance() ==  SliderHorizontalPart) {
869        bounds.setHeight(trackWidth);
870        bounds.setY(r.y() + r.height() / 2 - trackWidth / 2);
871    } else if (o.style().appearance() == SliderVerticalPart) {
872        bounds.setWidth(trackWidth);
873        bounds.setX(r.x() + r.width() / 2 - trackWidth / 2);
874    }
875
876    drawControl(i.context,  o, sliderTheme(), getThemeData(o), bounds);
877    return false;
878}
879
880bool RenderThemeWin::paintSliderThumb(const RenderObject& o, const PaintInfo& i, const IntRect& r)
881{
882    drawControl(i.context,  o, sliderTheme(), getThemeData(o), r);
883    return false;
884}
885
886const int sliderThumbWidth = 7;
887const int sliderThumbHeight = 15;
888
889void RenderThemeWin::adjustSliderThumbSize(RenderStyle& style, Element&) const
890{
891    ControlPart part = style.appearance();
892    if (part == SliderThumbVerticalPart) {
893        style.setWidth(Length(sliderThumbHeight, Fixed));
894        style.setHeight(Length(sliderThumbWidth, Fixed));
895    } else if (part == SliderThumbHorizontalPart) {
896        style.setWidth(Length(sliderThumbWidth, Fixed));
897        style.setHeight(Length(sliderThumbHeight, Fixed));
898    }
899#if ENABLE(VIDEO) && USE(CG)
900    else if (part == MediaSliderThumbPart || part == MediaVolumeSliderThumbPart)
901        RenderMediaControls::adjustMediaSliderThumbSize(style);
902#endif
903}
904
905bool RenderThemeWin::paintSearchField(const RenderObject& o, const PaintInfo& i, const IntRect& r)
906{
907    return paintTextField(o, i, r);
908}
909
910void RenderThemeWin::adjustSearchFieldStyle(StyleResolver& styleResolver, RenderStyle& style, Element& e) const
911{
912    // Override paddingSize to match AppKit text positioning.
913    const int padding = 1;
914    style.setPaddingLeft(Length(padding, Fixed));
915    style.setPaddingRight(Length(padding, Fixed));
916    style.setPaddingTop(Length(padding, Fixed));
917    style.setPaddingBottom(Length(padding, Fixed));
918    if (e.focused() && e.document().frame()->selection().isFocusedAndActive())
919        style.setOutlineOffset(-2);
920}
921
922bool RenderThemeWin::paintSearchFieldCancelButton(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
923{
924    IntRect bounds = r;
925    ASSERT(o.parent());
926    if (!o.parent() || !o.parent()->isBox())
927        return false;
928
929    RenderBox* parentRenderBox = toRenderBox(o.parent());
930
931    IntRect parentBox = parentRenderBox->absoluteContentBox();
932
933    // Make sure the scaled button stays square and will fit in its parent's box
934    bounds.setHeight(min(parentBox.width(), min(parentBox.height(), bounds.height())));
935    bounds.setWidth(bounds.height());
936
937    // Center the button vertically.  Round up though, so if it has to be one pixel off-center, it will
938    // be one pixel closer to the bottom of the field.  This tends to look better with the text.
939    bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
940
941    static Image* cancelImage = Image::loadPlatformResource("searchCancel").leakRef();
942    static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").leakRef();
943    paintInfo.context->drawImage(isPressed(o) ? cancelPressedImage : cancelImage, o.style().colorSpace(), bounds);
944    return false;
945}
946
947void RenderThemeWin::adjustSearchFieldCancelButtonStyle(StyleResolver&, RenderStyle& style, Element&) const
948{
949    // Scale the button size based on the font size
950    float fontScale = style.fontSize() / defaultControlFontPixelSize;
951    int cancelButtonSize = lroundf(min(max(minCancelButtonSize, defaultCancelButtonSize * fontScale), maxCancelButtonSize));
952    style.setWidth(Length(cancelButtonSize, Fixed));
953    style.setHeight(Length(cancelButtonSize, Fixed));
954}
955
956void RenderThemeWin::adjustSearchFieldDecorationPartStyle(StyleResolver&, RenderStyle& style, Element&) const
957{
958    IntSize emptySize(1, 11);
959    style.setWidth(Length(emptySize.width(), Fixed));
960    style.setHeight(Length(emptySize.height(), Fixed));
961}
962
963void RenderThemeWin::adjustSearchFieldResultsDecorationPartStyle(StyleResolver&, RenderStyle& style, Element&) const
964{
965    // Scale the decoration size based on the font size
966    float fontScale = style.fontSize() / defaultControlFontPixelSize;
967    int magnifierSize = lroundf(min(max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
968                                     maxSearchFieldResultsDecorationSize));
969    style.setWidth(Length(magnifierSize, Fixed));
970    style.setHeight(Length(magnifierSize, Fixed));
971}
972
973bool RenderThemeWin::paintSearchFieldResultsDecorationPart(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
974{
975    IntRect bounds = r;
976    ASSERT(o.parent());
977    if (!o.parent() || !o.parent()->isBox())
978        return false;
979
980    RenderBox* parentRenderBox = toRenderBox(o.parent());
981    IntRect parentBox = parentRenderBox->absoluteContentBox();
982
983    // Make sure the scaled decoration stays square and will fit in its parent's box
984    bounds.setHeight(min(parentBox.width(), min(parentBox.height(), bounds.height())));
985    bounds.setWidth(bounds.height());
986
987    // Center the decoration vertically.  Round up though, so if it has to be one pixel off-center, it will
988    // be one pixel closer to the bottom of the field.  This tends to look better with the text.
989    bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
990
991    static Image* magnifierImage = Image::loadPlatformResource("searchMagnifier").leakRef();
992    paintInfo.context->drawImage(magnifierImage, o.style().colorSpace(), bounds);
993    return false;
994}
995
996void RenderThemeWin::adjustSearchFieldResultsButtonStyle(StyleResolver&, RenderStyle& style, Element&) const
997{
998    // Scale the button size based on the font size
999    float fontScale = style.fontSize() / defaultControlFontPixelSize;
1000    int magnifierHeight = lroundf(min(max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
1001                                   maxSearchFieldResultsDecorationSize));
1002    int magnifierWidth = lroundf(magnifierHeight * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize);
1003    style.setWidth(Length(magnifierWidth, Fixed));
1004    style.setHeight(Length(magnifierHeight, Fixed));
1005}
1006
1007bool RenderThemeWin::paintSearchFieldResultsButton(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
1008{
1009    IntRect bounds = r;
1010    ASSERT(o.parent());
1011    if (!o.parent())
1012        return false;
1013    if (!o.parent() || !o.parent()->isBox())
1014        return false;
1015
1016    RenderBox* parentRenderBox = toRenderBox(o.parent());
1017    IntRect parentBox = parentRenderBox->absoluteContentBox();
1018
1019    // Make sure the scaled decoration will fit in its parent's box
1020    bounds.setHeight(min(parentBox.height(), bounds.height()));
1021    bounds.setWidth(min<int>(parentBox.width(), bounds.height() * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize));
1022
1023    // Center the button vertically.  Round up though, so if it has to be one pixel off-center, it will
1024    // be one pixel closer to the bottom of the field.  This tends to look better with the text.
1025    bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
1026
1027    static Image* magnifierImage = Image::loadPlatformResource("searchMagnifierResults").leakRef();
1028    paintInfo.context->drawImage(magnifierImage, o.style().colorSpace(), bounds);
1029    return false;
1030}
1031
1032// Map a CSSValue* system color to an index understood by GetSysColor
1033static int cssValueIdToSysColorIndex(CSSValueID cssValueId)
1034{
1035    switch (cssValueId) {
1036    case CSSValueActiveborder: return COLOR_ACTIVEBORDER;
1037    case CSSValueActivecaption: return COLOR_ACTIVECAPTION;
1038    case CSSValueAppworkspace: return COLOR_APPWORKSPACE;
1039    case CSSValueBackground: return COLOR_BACKGROUND;
1040    case CSSValueButtonface: return COLOR_BTNFACE;
1041    case CSSValueButtonhighlight: return COLOR_BTNHIGHLIGHT;
1042    case CSSValueButtonshadow: return COLOR_BTNSHADOW;
1043    case CSSValueButtontext: return COLOR_BTNTEXT;
1044    case CSSValueCaptiontext: return COLOR_CAPTIONTEXT;
1045    case CSSValueGraytext: return COLOR_GRAYTEXT;
1046    case CSSValueHighlight: return COLOR_HIGHLIGHT;
1047    case CSSValueHighlighttext: return COLOR_HIGHLIGHTTEXT;
1048    case CSSValueInactiveborder: return COLOR_INACTIVEBORDER;
1049    case CSSValueInactivecaption: return COLOR_INACTIVECAPTION;
1050    case CSSValueInactivecaptiontext: return COLOR_INACTIVECAPTIONTEXT;
1051    case CSSValueInfobackground: return COLOR_INFOBK;
1052    case CSSValueInfotext: return COLOR_INFOTEXT;
1053    case CSSValueMenu: return COLOR_MENU;
1054    case CSSValueMenutext: return COLOR_MENUTEXT;
1055    case CSSValueScrollbar: return COLOR_SCROLLBAR;
1056    case CSSValueThreeddarkshadow: return COLOR_3DDKSHADOW;
1057    case CSSValueThreedface: return COLOR_3DFACE;
1058    case CSSValueThreedhighlight: return COLOR_3DHIGHLIGHT;
1059    case CSSValueThreedlightshadow: return COLOR_3DLIGHT;
1060    case CSSValueThreedshadow: return COLOR_3DSHADOW;
1061    case CSSValueWindow: return COLOR_WINDOW;
1062    case CSSValueWindowframe: return COLOR_WINDOWFRAME;
1063    case CSSValueWindowtext: return COLOR_WINDOWTEXT;
1064    default: return -1; // Unsupported CSSValue
1065    }
1066}
1067
1068Color RenderThemeWin::systemColor(CSSValueID cssValueId) const
1069{
1070    int sysColorIndex = cssValueIdToSysColorIndex(cssValueId);
1071    if (sysColorIndex == -1)
1072        return RenderTheme::systemColor(cssValueId);
1073
1074    COLORREF color = GetSysColor(sysColorIndex);
1075    return Color(GetRValue(color), GetGValue(color), GetBValue(color));
1076}
1077
1078#if ENABLE(VIDEO)
1079static const size_t maximumReasonableBufferSize = 32768;
1080
1081static void fillBufferWithContentsOfFile(PlatformFileHandle file, long long filesize, Vector<char>& buffer)
1082{
1083    // Load the file content into buffer
1084    buffer.resize(filesize + 1);
1085
1086    int bufferPosition = 0;
1087    int bufferReadSize = 4096;
1088    int bytesRead = 0;
1089    while (filesize > bufferPosition) {
1090        if (filesize - bufferPosition < bufferReadSize)
1091            bufferReadSize = filesize - bufferPosition;
1092
1093        bytesRead = readFromFile(file, buffer.data() + bufferPosition, bufferReadSize);
1094        if (bytesRead != bufferReadSize) {
1095            buffer.clear();
1096            return;
1097        }
1098
1099        bufferPosition += bufferReadSize;
1100    }
1101
1102    buffer[filesize] = 0;
1103}
1104
1105String RenderThemeWin::stringWithContentsOfFile(CFStringRef name, CFStringRef type)
1106{
1107    RetainPtr<CFURLRef> requestedURLRef = adoptCF(CFBundleCopyResourceURL(webKitBundle(), name, type, 0));
1108    if (!requestedURLRef)
1109        return String();
1110
1111    UInt8 requestedFilePath[MAX_PATH];
1112    if (!CFURLGetFileSystemRepresentation(requestedURLRef.get(), false, requestedFilePath, MAX_PATH))
1113        return String();
1114
1115    PlatformFileHandle requestedFileHandle = openFile(requestedFilePath, OpenForRead);
1116    if (!isHandleValid(requestedFileHandle))
1117        return String();
1118
1119    long long filesize = -1;
1120    if (!getFileSize(requestedFilePath, filesize)) {
1121        closeFile(requestedFileHandle);
1122        return String();
1123    }
1124
1125    Vector<char> fileContents;
1126    fillBufferWithContentsOfFile(requestedFileHandle, filesize, fileContents);
1127    closeFile(requestedFileHandle);
1128
1129    return String(fileContents.data(), static_cast<size_t>(filesize));
1130}
1131
1132String RenderThemeWin::mediaControlsStyleSheet()
1133{
1134#if ENABLE(MEDIA_CONTROLS_SCRIPT)
1135    if (m_mediaControlsStyleSheet.isEmpty())
1136        m_mediaControlsStyleSheet = stringWithContentsOfFile(CFSTR("mediaControlsApple"), CFSTR("css"));
1137    return m_mediaControlsStyleSheet;
1138#else
1139    return emptyString();
1140#endif
1141}
1142
1143String RenderThemeWin::mediaControlsScript()
1144{
1145#if ENABLE(MEDIA_CONTROLS_SCRIPT)
1146    if (m_mediaControlsScript.isEmpty()) {
1147        StringBuilder scriptBuilder;
1148        scriptBuilder.append(stringWithContentsOfFile(CFSTR("mediaControlsLocalizedStrings"), CFSTR("js")));
1149        scriptBuilder.append(stringWithContentsOfFile(CFSTR("mediaControlsApple"), CFSTR("js")));
1150        m_mediaControlsScript = scriptBuilder.toString();
1151    }
1152    return m_mediaControlsScript;
1153#else
1154    return emptyString();
1155#endif
1156}
1157#endif
1158
1159#if ENABLE(METER_ELEMENT)
1160void RenderThemeWin::adjustMeterStyle(StyleResolver&, RenderStyle& style, Element&) const
1161{
1162    style.setBoxShadow(nullptr);
1163}
1164
1165bool RenderThemeWin::supportsMeter(ControlPart part) const
1166{
1167    switch (part) {
1168    case MeterPart:
1169        return true;
1170    default:
1171        return false;
1172    }
1173}
1174
1175IntSize RenderThemeWin::meterSizeForBounds(const RenderMeter&, const IntRect& bounds) const
1176{
1177    return bounds.size();
1178}
1179
1180bool RenderThemeWin::paintMeter(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
1181{
1182    if (!renderObject.isMeter())
1183        return true;
1184
1185    HTMLMeterElement* element = toRenderMeter(renderObject).meterElement();
1186
1187    ThemeData theme = getThemeData(renderObject);
1188
1189    int remaining = static_cast<int>((1.0 - element->valueRatio()) * static_cast<double>(rect.size().width()));
1190
1191    // Draw the background
1192    drawControl(paintInfo.context, renderObject, progressBarTheme(), theme, rect);
1193
1194    // Draw the progress portion
1195    IntRect completedRect(rect);
1196    completedRect.contract(remaining, 0);
1197
1198    theme.m_part = PP_FILL;
1199    drawControl(paintInfo.context, renderObject, progressBarTheme(), theme, completedRect);
1200
1201    return true;
1202}
1203
1204#endif
1205
1206
1207}
1208