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