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