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