1f04100fb4ac875020c0e6927175cbba33adb188
[WebKit-https.git] / Source / WebCore / rendering / RenderTheme.cpp
1 /**
2  * This file is part of the theme implementation for form controls in WebCore.
3  *
4  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 #include "config.h"
23 #include "RenderTheme.h"
24
25 #include "CSSValueKeywords.h"
26 #include "ControlStates.h"
27 #include "Document.h"
28 #include "FileList.h"
29 #include "FileSystem.h"
30 #include "FloatConversion.h"
31 #include "FocusController.h"
32 #include "FontSelector.h"
33 #include "Frame.h"
34 #include "FrameSelection.h"
35 #include "GraphicsContext.h"
36 #include "HTMLInputElement.h"
37 #include "HTMLNames.h"
38 #include "LocalizedStrings.h"
39 #include "MediaControlElements.h"
40 #include "Page.h"
41 #include "PaintInfo.h"
42 #include "RenderStyle.h"
43 #include "RenderView.h"
44 #include "Settings.h"
45 #include "SpinButtonElement.h"
46 #include "StringTruncator.h"
47 #include "TextControlInnerElements.h"
48
49 #if ENABLE(METER_ELEMENT)
50 #include "HTMLMeterElement.h"
51 #include "RenderMeter.h"
52 #endif
53
54 #if ENABLE(INPUT_SPEECH)
55 #include "RenderInputSpeech.h"
56 #endif
57
58 #if ENABLE(DATALIST_ELEMENT)
59 #include "HTMLCollection.h"
60 #include "HTMLDataListElement.h"
61 #include "HTMLOptionElement.h"
62 #include "HTMLParserIdioms.h"
63 #endif
64
65 // The methods in this file are shared by all themes on every platform.
66
67 namespace WebCore {
68
69 using namespace HTMLNames;
70
71 static Color& customFocusRingColor()
72 {
73     DEPRECATED_DEFINE_STATIC_LOCAL(Color, color, ());
74     return color;
75 }
76
77 RenderTheme::RenderTheme()
78 #if USE(NEW_THEME)
79     : m_theme(platformTheme())
80 #endif
81 {
82 }
83
84 void RenderTheme::adjustStyle(StyleResolver& styleResolver, RenderStyle& style, Element* e, bool UAHasAppearance, const BorderData& border, const FillLayer& background, const Color& backgroundColor)
85 {
86     // Force inline and table display styles to be inline-block (except for table- which is block)
87     ControlPart part = style.appearance();
88     if (style.display() == INLINE || style.display() == INLINE_TABLE || style.display() == TABLE_ROW_GROUP
89         || style.display() == TABLE_HEADER_GROUP || style.display() == TABLE_FOOTER_GROUP
90         || style.display() == TABLE_ROW || style.display() == TABLE_COLUMN_GROUP || style.display() == TABLE_COLUMN
91         || style.display() == TABLE_CELL || style.display() == TABLE_CAPTION)
92         style.setDisplay(INLINE_BLOCK);
93     else if (style.display() == COMPACT || style.display() == LIST_ITEM || style.display() == TABLE)
94         style.setDisplay(BLOCK);
95
96     if (UAHasAppearance && isControlStyled(&style, border, background, backgroundColor)) {
97         if (part == MenulistPart) {
98             style.setAppearance(MenulistButtonPart);
99             part = MenulistButtonPart;
100         } else
101             style.setAppearance(NoControlPart);
102     }
103
104     if (!style.hasAppearance())
105         return;
106
107     // Never support box-shadow on native controls.
108     style.setBoxShadow(nullptr);
109     
110 #if USE(NEW_THEME)
111     switch (part) {
112     case CheckboxPart:
113     case InnerSpinButtonPart:
114     case RadioPart:
115     case PushButtonPart:
116     case SquareButtonPart:
117     case DefaultButtonPart:
118     case ButtonPart: {
119         // Border
120         LengthBox borderBox(style.borderTopWidth(), style.borderRightWidth(), style.borderBottomWidth(), style.borderLeftWidth());
121         borderBox = m_theme->controlBorder(part, style.font(), borderBox, style.effectiveZoom());
122         if (borderBox.top().value() != static_cast<int>(style.borderTopWidth())) {
123             if (borderBox.top().value())
124                 style.setBorderTopWidth(borderBox.top().value());
125             else
126                 style.resetBorderTop();
127         }
128         if (borderBox.right().value() != static_cast<int>(style.borderRightWidth())) {
129             if (borderBox.right().value())
130                 style.setBorderRightWidth(borderBox.right().value());
131             else
132                 style.resetBorderRight();
133         }
134         if (borderBox.bottom().value() != static_cast<int>(style.borderBottomWidth())) {
135             style.setBorderBottomWidth(borderBox.bottom().value());
136             if (borderBox.bottom().value())
137                 style.setBorderBottomWidth(borderBox.bottom().value());
138             else
139                 style.resetBorderBottom();
140         }
141         if (borderBox.left().value() != static_cast<int>(style.borderLeftWidth())) {
142             style.setBorderLeftWidth(borderBox.left().value());
143             if (borderBox.left().value())
144                 style.setBorderLeftWidth(borderBox.left().value());
145             else
146                 style.resetBorderLeft();
147         }
148
149         // Padding
150         LengthBox paddingBox = m_theme->controlPadding(part, style.font(), style.paddingBox(), style.effectiveZoom());
151         if (paddingBox != style.paddingBox())
152             style.setPaddingBox(paddingBox);
153
154         // Whitespace
155         if (m_theme->controlRequiresPreWhiteSpace(part))
156             style.setWhiteSpace(PRE);
157             
158         // Width / Height
159         // The width and height here are affected by the zoom.
160         // FIXME: Check is flawed, since it doesn't take min-width/max-width into account.
161         LengthSize controlSize = m_theme->controlSize(part, style.font(), LengthSize(style.width(), style.height()), style.effectiveZoom());
162         if (controlSize.width() != style.width())
163             style.setWidth(controlSize.width());
164         if (controlSize.height() != style.height())
165             style.setHeight(controlSize.height());
166                 
167         // Min-Width / Min-Height
168         LengthSize minControlSize = m_theme->minimumControlSize(part, style.font(), style.effectiveZoom());
169         if (minControlSize.width() != style.minWidth())
170             style.setMinWidth(minControlSize.width());
171         if (minControlSize.height() != style.minHeight())
172             style.setMinHeight(minControlSize.height());
173                 
174         // Font
175         FontDescription controlFont = m_theme->controlFont(part, style.font(), style.effectiveZoom());
176         if (controlFont != style.font().fontDescription()) {
177             // Reset our line-height
178             style.setLineHeight(RenderStyle::initialLineHeight());
179
180             // Now update our font.
181             if (style.setFontDescription(controlFont))
182                 style.font().update(0);
183         }
184     }
185     break;
186     default:
187         break;
188     }
189 #endif
190
191     // Call the appropriate style adjustment method based off the appearance value.
192     switch (style.appearance()) {
193 #if !USE(NEW_THEME)
194     case CheckboxPart:
195         return adjustCheckboxStyle(&styleResolver, &style, e);
196     case RadioPart:
197         return adjustRadioStyle(&styleResolver, &style, e);
198     case PushButtonPart:
199     case SquareButtonPart:
200     case DefaultButtonPart:
201     case ButtonPart:
202         return adjustButtonStyle(&styleResolver, &style, e);
203     case InnerSpinButtonPart:
204         return adjustInnerSpinButtonStyle(&styleResolver, &style, e);
205 #endif
206     case TextFieldPart:
207         return adjustTextFieldStyle(&styleResolver, &style, e);
208     case TextAreaPart:
209         return adjustTextAreaStyle(&styleResolver, &style, e);
210     case MenulistPart:
211         return adjustMenuListStyle(&styleResolver, &style, e);
212     case MenulistButtonPart:
213         return adjustMenuListButtonStyle(&styleResolver, &style, e);
214     case MediaPlayButtonPart:
215     case MediaCurrentTimePart:
216     case MediaTimeRemainingPart:
217     case MediaEnterFullscreenButtonPart:
218     case MediaExitFullscreenButtonPart:
219     case MediaMuteButtonPart:
220     case MediaVolumeSliderContainerPart:
221         return adjustMediaControlStyle(&styleResolver, &style, e);
222     case MediaSliderPart:
223     case MediaVolumeSliderPart:
224     case MediaFullScreenVolumeSliderPart:
225     case SliderHorizontalPart:
226     case SliderVerticalPart:
227         return adjustSliderTrackStyle(&styleResolver, &style, e);
228     case SliderThumbHorizontalPart:
229     case SliderThumbVerticalPart:
230         return adjustSliderThumbStyle(&styleResolver, &style, e);
231     case SearchFieldPart:
232         return adjustSearchFieldStyle(&styleResolver, &style, e);
233     case SearchFieldCancelButtonPart:
234         return adjustSearchFieldCancelButtonStyle(&styleResolver, &style, e);
235     case SearchFieldDecorationPart:
236         return adjustSearchFieldDecorationPartStyle(&styleResolver, &style, e);
237     case SearchFieldResultsDecorationPart:
238         return adjustSearchFieldResultsDecorationPartStyle(&styleResolver, &style, e);
239     case SearchFieldResultsButtonPart:
240         return adjustSearchFieldResultsButtonStyle(&styleResolver, &style, e);
241 #if ENABLE(PROGRESS_ELEMENT)
242     case ProgressBarPart:
243         return adjustProgressBarStyle(&styleResolver, &style, e);
244 #endif
245 #if ENABLE(METER_ELEMENT)
246     case MeterPart:
247     case RelevancyLevelIndicatorPart:
248     case ContinuousCapacityLevelIndicatorPart:
249     case DiscreteCapacityLevelIndicatorPart:
250     case RatingLevelIndicatorPart:
251         return adjustMeterStyle(&styleResolver, &style, e);
252 #endif
253 #if ENABLE(INPUT_SPEECH)
254     case InputSpeechButtonPart:
255         return adjustInputFieldSpeechButtonStyle(&styleResolver, &style, e);
256 #endif
257 #if ENABLE(SERVICE_CONTROLS)
258     case ImageControlsButtonPart:
259         break;
260 #endif
261     default:
262         break;
263     }
264 }
265
266 bool RenderTheme::paint(const RenderObject& o, ControlStates* controlStates, const PaintInfo& paintInfo, const LayoutRect& r)
267 {
268     // If painting is disabled, but we aren't updating control tints, then just bail.
269     // If we are updating control tints, just schedule a repaint if the theme supports tinting
270     // for that control.
271     if (paintInfo.context->updatingControlTints()) {
272         if (controlSupportsTints(o))
273             o.repaint();
274         return false;
275     }
276     if (paintInfo.context->paintingDisabled())
277         return false;
278
279     ControlPart part = o.style().appearance();
280     IntRect integralSnappedRect = pixelSnappedIntRect(r);
281
282 #if USE(NEW_THEME)
283     switch (part) {
284     case CheckboxPart:
285     case RadioPart:
286     case PushButtonPart:
287     case SquareButtonPart:
288     case DefaultButtonPart:
289     case ButtonPart:
290     case InnerSpinButtonPart:
291         updateControlStatesForRenderer(o, controlStates);
292         m_theme->paint(part, controlStates, const_cast<GraphicsContext*>(paintInfo.context), integralSnappedRect, o.style().effectiveZoom(), &o.view().frameView());
293         return false;
294     default:
295         break;
296     }
297 #else
298     UNUSED_PARAM(controlStates);
299 #endif
300
301     // Call the appropriate paint method based off the appearance value.
302     switch (part) {
303 #if !USE(NEW_THEME)
304     case CheckboxPart:
305         return paintCheckbox(o, paintInfo, integralSnappedRect);
306     case RadioPart:
307         return paintRadio(o, paintInfo, integralSnappedRect);
308     case PushButtonPart:
309     case SquareButtonPart:
310     case DefaultButtonPart:
311     case ButtonPart:
312         return paintButton(o, paintInfo, integralSnappedRect);
313     case InnerSpinButtonPart:
314         return paintInnerSpinButton(o, paintInfo, integralSnappedRect);
315 #endif
316     case MenulistPart:
317         return paintMenuList(o, paintInfo, integralSnappedRect);
318 #if ENABLE(METER_ELEMENT)
319     case MeterPart:
320     case RelevancyLevelIndicatorPart:
321     case ContinuousCapacityLevelIndicatorPart:
322     case DiscreteCapacityLevelIndicatorPart:
323     case RatingLevelIndicatorPart:
324         return paintMeter(o, paintInfo, integralSnappedRect);
325 #endif
326 #if ENABLE(PROGRESS_ELEMENT)
327     case ProgressBarPart:
328         return paintProgressBar(o, paintInfo, integralSnappedRect);
329 #endif
330     case SliderHorizontalPart:
331     case SliderVerticalPart:
332         return paintSliderTrack(o, paintInfo, integralSnappedRect);
333     case SliderThumbHorizontalPart:
334     case SliderThumbVerticalPart:
335         return paintSliderThumb(o, paintInfo, integralSnappedRect);
336     case MediaEnterFullscreenButtonPart:
337     case MediaExitFullscreenButtonPart:
338         return paintMediaFullscreenButton(o, paintInfo, integralSnappedRect);
339     case MediaPlayButtonPart:
340         return paintMediaPlayButton(o, paintInfo, integralSnappedRect);
341     case MediaOverlayPlayButtonPart:
342         return paintMediaOverlayPlayButton(o, paintInfo, integralSnappedRect);
343     case MediaMuteButtonPart:
344         return paintMediaMuteButton(o, paintInfo, integralSnappedRect);
345     case MediaSeekBackButtonPart:
346         return paintMediaSeekBackButton(o, paintInfo, integralSnappedRect);
347     case MediaSeekForwardButtonPart:
348         return paintMediaSeekForwardButton(o, paintInfo, integralSnappedRect);
349     case MediaRewindButtonPart:
350         return paintMediaRewindButton(o, paintInfo, integralSnappedRect);
351     case MediaReturnToRealtimeButtonPart:
352         return paintMediaReturnToRealtimeButton(o, paintInfo, integralSnappedRect);
353     case MediaToggleClosedCaptionsButtonPart:
354         return paintMediaToggleClosedCaptionsButton(o, paintInfo, integralSnappedRect);
355     case MediaSliderPart:
356         return paintMediaSliderTrack(o, paintInfo, integralSnappedRect);
357     case MediaSliderThumbPart:
358         return paintMediaSliderThumb(o, paintInfo, integralSnappedRect);
359     case MediaVolumeSliderMuteButtonPart:
360         return paintMediaMuteButton(o, paintInfo, integralSnappedRect);
361     case MediaVolumeSliderContainerPart:
362         return paintMediaVolumeSliderContainer(o, paintInfo, integralSnappedRect);
363     case MediaVolumeSliderPart:
364         return paintMediaVolumeSliderTrack(o, paintInfo, integralSnappedRect);
365     case MediaVolumeSliderThumbPart:
366         return paintMediaVolumeSliderThumb(o, paintInfo, integralSnappedRect);
367     case MediaFullScreenVolumeSliderPart:
368         return paintMediaFullScreenVolumeSliderTrack(o, paintInfo, integralSnappedRect);
369     case MediaFullScreenVolumeSliderThumbPart:
370         return paintMediaFullScreenVolumeSliderThumb(o, paintInfo, integralSnappedRect);
371     case MediaTimeRemainingPart:
372         return paintMediaTimeRemaining(o, paintInfo, integralSnappedRect);
373     case MediaCurrentTimePart:
374         return paintMediaCurrentTime(o, paintInfo, integralSnappedRect);
375     case MediaControlsBackgroundPart:
376         return paintMediaControlsBackground(o, paintInfo, integralSnappedRect);
377     case MenulistButtonPart:
378     case TextFieldPart:
379     case TextAreaPart:
380     case ListboxPart:
381         return true;
382     case SearchFieldPart:
383         return paintSearchField(o, paintInfo, integralSnappedRect);
384     case SearchFieldCancelButtonPart:
385         return paintSearchFieldCancelButton(o, paintInfo, integralSnappedRect);
386     case SearchFieldDecorationPart:
387         return paintSearchFieldDecorationPart(o, paintInfo, integralSnappedRect);
388     case SearchFieldResultsDecorationPart:
389         return paintSearchFieldResultsDecorationPart(o, paintInfo, integralSnappedRect);
390     case SearchFieldResultsButtonPart:
391         return paintSearchFieldResultsButton(o, paintInfo, integralSnappedRect);
392     case SnapshottedPluginOverlayPart:
393         return paintSnapshottedPluginOverlay(o, paintInfo, integralSnappedRect);
394 #if ENABLE(INPUT_SPEECH)
395     case InputSpeechButtonPart:
396         return paintInputFieldSpeechButton(o, paintInfo, integralSnappedRect);
397 #endif
398 #if ENABLE(SERVICE_CONTROLS)
399     case ImageControlsButtonPart:
400         return paintImageControlsButton(o, paintInfo, integralSnappedRect);
401 #endif
402     default:
403         break;
404     }
405
406     return true; // We don't support the appearance, so let the normal background/border paint.
407 }
408
409 bool RenderTheme::paintBorderOnly(const RenderObject& o, const PaintInfo& paintInfo, const LayoutRect& r)
410 {
411     if (paintInfo.context->paintingDisabled())
412         return false;
413
414 #if PLATFORM(IOS)
415     UNUSED_PARAM(r);
416     return o.style().appearance() != NoControlPart;
417 #else
418     FloatRect devicePixelSnappedRect = pixelSnappedForPainting(r, o.document().deviceScaleFactor());
419     // Call the appropriate paint method based off the appearance value.
420     switch (o.style().appearance()) {
421     case TextFieldPart:
422         return paintTextField(o, paintInfo, devicePixelSnappedRect);
423     case ListboxPart:
424     case TextAreaPart:
425         return paintTextArea(o, paintInfo, devicePixelSnappedRect);
426     case MenulistButtonPart:
427     case SearchFieldPart:
428         return true;
429     case CheckboxPart:
430     case RadioPart:
431     case PushButtonPart:
432     case SquareButtonPart:
433     case DefaultButtonPart:
434     case ButtonPart:
435     case MenulistPart:
436 #if ENABLE(METER_ELEMENT)
437     case MeterPart:
438     case RelevancyLevelIndicatorPart:
439     case ContinuousCapacityLevelIndicatorPart:
440     case DiscreteCapacityLevelIndicatorPart:
441     case RatingLevelIndicatorPart:
442 #endif
443 #if ENABLE(PROGRESS_ELEMENT)
444     case ProgressBarPart:
445 #endif
446     case SliderHorizontalPart:
447     case SliderVerticalPart:
448     case SliderThumbHorizontalPart:
449     case SliderThumbVerticalPart:
450     case SearchFieldCancelButtonPart:
451     case SearchFieldDecorationPart:
452     case SearchFieldResultsDecorationPart:
453     case SearchFieldResultsButtonPart:
454 #if ENABLE(INPUT_SPEECH)
455     case InputSpeechButtonPart:
456 #endif
457 #if ENABLE(SERVICE_CONTROLS)
458     case ImageControlsButtonPart:
459 #endif
460     default:
461         break;
462     }
463
464     return false;
465 #endif
466 }
467
468 bool RenderTheme::paintDecorations(const RenderObject& renderer, const PaintInfo& paintInfo, const LayoutRect& rect)
469 {
470     if (paintInfo.context->paintingDisabled())
471         return false;
472
473     IntRect integralSnappedRect = pixelSnappedIntRect(rect);
474     FloatRect devicePixelSnappedRect = pixelSnappedForPainting(rect, renderer.document().deviceScaleFactor());
475
476     // Call the appropriate paint method based off the appearance value.
477     switch (renderer.style().appearance()) {
478     case MenulistButtonPart:
479         return paintMenuListButtonDecorations(renderer, paintInfo, integralSnappedRect);
480     case TextFieldPart:
481         return paintTextFieldDecorations(renderer, paintInfo, devicePixelSnappedRect);
482     case TextAreaPart:
483         return paintTextAreaDecorations(renderer, paintInfo, devicePixelSnappedRect);
484     case CheckboxPart:
485         return paintCheckboxDecorations(renderer, paintInfo, integralSnappedRect);
486     case RadioPart:
487         return paintRadioDecorations(renderer, paintInfo, integralSnappedRect);
488     case PushButtonPart:
489         return paintPushButtonDecorations(renderer, paintInfo, integralSnappedRect);
490     case SquareButtonPart:
491         return paintSquareButtonDecorations(renderer, paintInfo, integralSnappedRect);
492     case ButtonPart:
493         return paintButtonDecorations(renderer, paintInfo, integralSnappedRect);
494     case MenulistPart:
495         return paintMenuListDecorations(renderer, paintInfo, integralSnappedRect);
496     case SliderThumbHorizontalPart:
497     case SliderThumbVerticalPart:
498         return paintSliderThumbDecorations(renderer, paintInfo, integralSnappedRect);
499     case SearchFieldPart:
500         return paintSearchFieldDecorations(renderer, paintInfo, integralSnappedRect);
501 #if ENABLE(METER_ELEMENT)
502     case MeterPart:
503     case RelevancyLevelIndicatorPart:
504     case ContinuousCapacityLevelIndicatorPart:
505     case DiscreteCapacityLevelIndicatorPart:
506     case RatingLevelIndicatorPart:
507 #endif
508 #if ENABLE(PROGRESS_ELEMENT)
509     case ProgressBarPart:
510 #endif
511     case SliderHorizontalPart:
512     case SliderVerticalPart:
513     case ListboxPart:
514     case DefaultButtonPart:
515     case SearchFieldCancelButtonPart:
516     case SearchFieldDecorationPart:
517     case SearchFieldResultsDecorationPart:
518     case SearchFieldResultsButtonPart:
519 #if ENABLE(INPUT_SPEECH)
520     case InputSpeechButtonPart:
521 #endif
522 #if ENABLE(SERVICE_CONTROLS)
523     case ImageControlsButtonPart:
524 #endif
525     default:
526         break;
527     }
528
529     return false;
530 }
531
532 #if ENABLE(VIDEO)
533
534 String RenderTheme::formatMediaControlsTime(float time) const
535 {
536     if (!std::isfinite(time))
537         time = 0;
538     int seconds = (int)fabsf(time);
539     int hours = seconds / (60 * 60);
540     int minutes = (seconds / 60) % 60;
541     seconds %= 60;
542     if (hours) {
543         if (hours > 9)
544             return String::format("%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
545
546         return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
547     }
548
549     return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds);
550 }
551
552 String RenderTheme::formatMediaControlsCurrentTime(float currentTime, float /*duration*/) const
553 {
554     return formatMediaControlsTime(currentTime);
555 }
556
557 String RenderTheme::formatMediaControlsRemainingTime(float currentTime, float duration) const
558 {
559     return formatMediaControlsTime(currentTime - duration);
560 }
561
562 IntPoint RenderTheme::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const IntSize& size) const
563 {
564     int y = -size.height();
565     FloatPoint absPoint = muteButtonBox->localToAbsolute(FloatPoint(muteButtonBox->pixelSnappedOffsetLeft(), y), IsFixed | UseTransforms);
566     if (absPoint.y() < 0)
567         y = muteButtonBox->height();
568     return IntPoint(0, y);
569 }
570
571 #endif
572
573 Color RenderTheme::activeSelectionBackgroundColor() const
574 {
575     if (!m_activeSelectionBackgroundColor.isValid())
576         m_activeSelectionBackgroundColor = platformActiveSelectionBackgroundColor().blendWithWhite();
577     return m_activeSelectionBackgroundColor;
578 }
579
580 Color RenderTheme::inactiveSelectionBackgroundColor() const
581 {
582     if (!m_inactiveSelectionBackgroundColor.isValid())
583         m_inactiveSelectionBackgroundColor = platformInactiveSelectionBackgroundColor().blendWithWhite();
584     return m_inactiveSelectionBackgroundColor;
585 }
586
587 Color RenderTheme::activeSelectionForegroundColor() const
588 {
589     if (!m_activeSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
590         m_activeSelectionForegroundColor = platformActiveSelectionForegroundColor();
591     return m_activeSelectionForegroundColor;
592 }
593
594 Color RenderTheme::inactiveSelectionForegroundColor() const
595 {
596     if (!m_inactiveSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
597         m_inactiveSelectionForegroundColor = platformInactiveSelectionForegroundColor();
598     return m_inactiveSelectionForegroundColor;
599 }
600
601 Color RenderTheme::activeListBoxSelectionBackgroundColor() const
602 {
603     if (!m_activeListBoxSelectionBackgroundColor.isValid())
604         m_activeListBoxSelectionBackgroundColor = platformActiveListBoxSelectionBackgroundColor();
605     return m_activeListBoxSelectionBackgroundColor;
606 }
607
608 Color RenderTheme::inactiveListBoxSelectionBackgroundColor() const
609 {
610     if (!m_inactiveListBoxSelectionBackgroundColor.isValid())
611         m_inactiveListBoxSelectionBackgroundColor = platformInactiveListBoxSelectionBackgroundColor();
612     return m_inactiveListBoxSelectionBackgroundColor;
613 }
614
615 Color RenderTheme::activeListBoxSelectionForegroundColor() const
616 {
617     if (!m_activeListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
618         m_activeListBoxSelectionForegroundColor = platformActiveListBoxSelectionForegroundColor();
619     return m_activeListBoxSelectionForegroundColor;
620 }
621
622 Color RenderTheme::inactiveListBoxSelectionForegroundColor() const
623 {
624     if (!m_inactiveListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
625         m_inactiveListBoxSelectionForegroundColor = platformInactiveListBoxSelectionForegroundColor();
626     return m_inactiveListBoxSelectionForegroundColor;
627 }
628
629 Color RenderTheme::platformActiveSelectionBackgroundColor() const
630 {
631     // Use a blue color by default if the platform theme doesn't define anything.
632     return Color(0, 0, 255);
633 }
634
635 Color RenderTheme::platformActiveSelectionForegroundColor() const
636 {
637     // Use a white color by default if the platform theme doesn't define anything.
638     return Color::white;
639 }
640
641 Color RenderTheme::platformInactiveSelectionBackgroundColor() const
642 {
643     // Use a grey color by default if the platform theme doesn't define anything.
644     // This color matches Firefox's inactive color.
645     return Color(176, 176, 176);
646 }
647
648 Color RenderTheme::platformInactiveSelectionForegroundColor() const
649 {
650     // Use a black color by default.
651     return Color::black;
652 }
653
654 Color RenderTheme::platformActiveListBoxSelectionBackgroundColor() const
655 {
656     return platformActiveSelectionBackgroundColor();
657 }
658
659 Color RenderTheme::platformActiveListBoxSelectionForegroundColor() const
660 {
661     return platformActiveSelectionForegroundColor();
662 }
663
664 Color RenderTheme::platformInactiveListBoxSelectionBackgroundColor() const
665 {
666     return platformInactiveSelectionBackgroundColor();
667 }
668
669 Color RenderTheme::platformInactiveListBoxSelectionForegroundColor() const
670 {
671     return platformInactiveSelectionForegroundColor();
672 }
673
674 int RenderTheme::baselinePosition(const RenderObject& o) const
675 {
676     if (!o.isBox())
677         return 0;
678
679     const RenderBox& box = *toRenderBox(&o);
680
681 #if USE(NEW_THEME)
682     return box.height() + box.marginTop() + m_theme->baselinePositionAdjustment(o.style().appearance()) * o.style().effectiveZoom();
683 #else
684     return box.height() + box.marginTop();
685 #endif
686 }
687
688 bool RenderTheme::isControlContainer(ControlPart appearance) const
689 {
690     // There are more leaves than this, but we'll patch this function as we add support for
691     // more controls.
692     return appearance != CheckboxPart && appearance != RadioPart;
693 }
694
695 bool RenderTheme::isControlStyled(const RenderStyle* style, const BorderData& border, const FillLayer& background, const Color& backgroundColor) const
696 {
697     switch (style->appearance()) {
698     case PushButtonPart:
699     case SquareButtonPart:
700     case DefaultButtonPart:
701     case ButtonPart:
702     case ListboxPart:
703     case MenulistPart:
704     case ProgressBarPart:
705     case MeterPart:
706     case RelevancyLevelIndicatorPart:
707     case ContinuousCapacityLevelIndicatorPart:
708     case DiscreteCapacityLevelIndicatorPart:
709     case RatingLevelIndicatorPart:
710     // FIXME: SearchFieldPart should be included here when making search fields style-able.
711     case TextFieldPart:
712     case TextAreaPart:
713         // Test the style to see if the UA border and background match.
714         return (style->border() != border
715             || *style->backgroundLayers() != background
716             || style->visitedDependentColor(CSSPropertyBackgroundColor) != backgroundColor);
717     default:
718         return false;
719     }
720 }
721
722 void RenderTheme::adjustRepaintRect(const RenderObject& o, IntRect& r)
723 {
724 #if USE(NEW_THEME)
725     ControlStates states(extractControlStatesForRenderer(o));
726     m_theme->inflateControlPaintRect(o.style().appearance(), &states, r, o.style().effectiveZoom());
727 #else
728     UNUSED_PARAM(o);
729     UNUSED_PARAM(r);
730 #endif
731 }
732
733 bool RenderTheme::supportsFocusRing(const RenderStyle* style) const
734 {
735     return (style->hasAppearance() && style->appearance() != TextFieldPart && style->appearance() != TextAreaPart && style->appearance() != MenulistButtonPart && style->appearance() != ListboxPart);
736 }
737
738 bool RenderTheme::stateChanged(const RenderObject& o, ControlStates::States state) const
739 {
740     // Default implementation assumes the controls don't respond to changes in :hover state
741     if (state == ControlStates::HoverState && !supportsHover(&o.style()))
742         return false;
743
744     // Assume pressed state is only responded to if the control is enabled.
745     if (state == ControlStates::PressedState && !isEnabled(o))
746         return false;
747
748     // Repaint the control.
749     o.repaint();
750     return true;
751 }
752
753 void RenderTheme::updateControlStatesForRenderer(const RenderObject& o, ControlStates* controlStates) const
754 {
755     ControlStates newStates = extractControlStatesForRenderer(o);
756     controlStates->setStates(newStates.states());
757     if (isFocused(o))
758         controlStates->setTimeSinceControlWasFocused(o.document().page()->focusController().timeSinceFocusWasSet());
759 }
760
761 ControlStates::States RenderTheme::extractControlStatesForRenderer(const RenderObject& o) const
762 {
763     ControlStates::States states = 0;
764     if (isHovered(o)) {
765         states |= ControlStates::HoverState;
766         if (isSpinUpButtonPartHovered(o))
767             states |= ControlStates::SpinUpState;
768     }
769     if (isPressed(o)) {
770         states |= ControlStates::PressedState;
771         if (isSpinUpButtonPartPressed(o))
772             states |= ControlStates::SpinUpState;
773     }
774     if (isFocused(o) && o.style().outlineStyleIsAuto())
775         states |= ControlStates::FocusState;
776     if (isEnabled(o))
777         states |= ControlStates::EnabledState;
778     if (isChecked(o))
779         states |= ControlStates::CheckedState;
780     if (isReadOnlyControl(o))
781         states |= ControlStates::ReadOnlyState;
782     if (isDefault(o))
783         states |= ControlStates::DefaultState;
784     if (!isActive(o))
785         states |= ControlStates::WindowInactiveState;
786     if (isIndeterminate(o))
787         states |= ControlStates::IndeterminateState;
788     return states;
789 }
790
791 bool RenderTheme::isActive(const RenderObject& o) const
792 {
793     Node* node = o.node();
794     if (!node)
795         return false;
796
797     Frame* frame = node->document().frame();
798     if (!frame)
799         return false;
800
801     Page* page = frame->page();
802     if (!page)
803         return false;
804
805     return page->focusController().isActive();
806 }
807
808 bool RenderTheme::isChecked(const RenderObject& o) const
809 {
810     if (!o.node())
811         return false;
812
813     HTMLInputElement* inputElement = o.node()->toInputElement();
814     if (!inputElement)
815         return false;
816
817     return inputElement->shouldAppearChecked();
818 }
819
820 bool RenderTheme::isIndeterminate(const RenderObject& o) const
821 {
822     if (!o.node())
823         return false;
824
825     HTMLInputElement* inputElement = o.node()->toInputElement();
826     if (!inputElement)
827         return false;
828
829     return inputElement->shouldAppearIndeterminate();
830 }
831
832 bool RenderTheme::isEnabled(const RenderObject& o) const
833 {
834     Node* node = o.node();
835     if (!node || !node->isElementNode())
836         return true;
837     return !toElement(node)->isDisabledFormControl();
838 }
839
840 bool RenderTheme::isFocused(const RenderObject& o) const
841 {
842     Node* node = o.node();
843     if (!node || !node->isElementNode())
844         return false;
845
846     Element* focusDelegate = toElement(node)->focusDelegate();
847     Document& document = focusDelegate->document();
848     Frame* frame = document.frame();
849     return focusDelegate == document.focusedElement() && frame && frame->selection().isFocusedAndActive();
850 }
851
852 bool RenderTheme::isPressed(const RenderObject& o) const
853 {
854     if (!o.node() || !o.node()->isElementNode())
855         return false;
856     return toElement(o.node())->active();
857 }
858
859 bool RenderTheme::isSpinUpButtonPartPressed(const RenderObject& o) const
860 {
861     Node* node = o.node();
862     if (!node || !node->isElementNode())
863         return false;
864     Element* element = toElement(node);
865     if (!element->active() || !element->isSpinButtonElement())
866         return false;
867     return static_cast<SpinButtonElement*>(element)->upDownState() == SpinButtonElement::Up;
868 }
869
870 bool RenderTheme::isReadOnlyControl(const RenderObject& o) const
871 {
872     Node* node = o.node();
873     if (!node || !node->isElementNode())
874         return false;
875     return toElement(node)->matchesReadOnlyPseudoClass();
876 }
877
878 bool RenderTheme::isHovered(const RenderObject& o) const
879 {
880     Node* node = o.node();
881     if (!node || !node->isElementNode())
882         return false;
883     if (!toElement(node)->isSpinButtonElement())
884         return toElement(node)->hovered();
885     SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
886     return element->hovered() && element->upDownState() != SpinButtonElement::Indeterminate;
887 }
888
889 bool RenderTheme::isSpinUpButtonPartHovered(const RenderObject& o) const
890 {
891     Node* node = o.node();
892     if (!node || !node->isElementNode() || !toElement(node)->isSpinButtonElement())
893         return false;
894     SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
895     return element->upDownState() == SpinButtonElement::Up;
896 }
897
898 bool RenderTheme::isDefault(const RenderObject& o) const
899 {
900     // A button should only have the default appearance if the page is active
901     if (!isActive(o))
902         return false;
903
904     if (!o.frame().settings().applicationChromeMode())
905         return false;
906     
907     return o.style().appearance() == DefaultButtonPart;
908 }
909
910 #if !USE(NEW_THEME)
911
912 void RenderTheme::adjustCheckboxStyle(StyleResolver*, RenderStyle* style, Element*) const
913 {
914     // A summary of the rules for checkbox designed to match WinIE:
915     // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
916     // font-size - not honored (control has no text), but we use it to decide which control size to use.
917     setCheckboxSize(style);
918
919     // padding - not honored by WinIE, needs to be removed.
920     style->resetPadding();
921
922     // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
923     // for now, we will not honor it.
924     style->resetBorder();
925
926     style->setBoxShadow(nullptr);
927 }
928
929 void RenderTheme::adjustRadioStyle(StyleResolver*, RenderStyle* style, Element*) const
930 {
931     // A summary of the rules for checkbox designed to match WinIE:
932     // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
933     // font-size - not honored (control has no text), but we use it to decide which control size to use.
934     setRadioSize(style);
935
936     // padding - not honored by WinIE, needs to be removed.
937     style->resetPadding();
938
939     // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
940     // for now, we will not honor it.
941     style->resetBorder();
942
943     style->setBoxShadow(nullptr);
944 }
945
946 void RenderTheme::adjustButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
947 {
948     // Most platforms will completely honor all CSS, and so we have no need to
949     // adjust the style at all by default. We will still allow the theme a crack
950     // at setting up a desired vertical size.
951     setButtonSize(style);
952 }
953
954 void RenderTheme::adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle*, Element*) const
955 {
956 }
957 #endif
958
959 void RenderTheme::adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const
960 {
961 }
962
963 void RenderTheme::adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const
964 {
965 }
966
967 void RenderTheme::adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const
968 {
969 }
970
971 #if ENABLE(INPUT_SPEECH)
972 void RenderTheme::adjustInputFieldSpeechButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
973 {
974     RenderInputSpeech::adjustInputFieldSpeechButtonStyle(styleResolver, style, element);
975 }
976
977 bool RenderTheme::paintInputFieldSpeechButton(const RenderObject& object, const PaintInfo& paintInfo, const IntRect& rect)
978 {
979     return RenderInputSpeech::paintInputFieldSpeechButton(object, paintInfo, rect);
980 }
981 #endif
982
983 #if ENABLE(METER_ELEMENT)
984 void RenderTheme::adjustMeterStyle(StyleResolver*, RenderStyle* style, Element*) const
985 {
986     style->setBoxShadow(nullptr);
987 }
988
989 IntSize RenderTheme::meterSizeForBounds(const RenderMeter*, const IntRect& bounds) const
990 {
991     return bounds.size();
992 }
993
994 bool RenderTheme::supportsMeter(ControlPart) const
995 {
996     return false;
997 }
998
999 bool RenderTheme::paintMeter(const RenderObject&, const PaintInfo&, const IntRect&)
1000 {
1001     return true;
1002 }
1003
1004 #endif
1005
1006 #if ENABLE(DATALIST_ELEMENT)
1007 LayoutUnit RenderTheme::sliderTickSnappingThreshold() const
1008 {
1009     return 0;
1010 }
1011
1012 void RenderTheme::paintSliderTicks(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& rect)
1013 {
1014     Node* node = o.node();
1015     if (!node)
1016         return;
1017
1018     HTMLInputElement* input = node->toInputElement();
1019     if (!input)
1020         return;
1021
1022     HTMLDataListElement* dataList = toHTMLDataListElement(input->list());
1023     if (!dataList)
1024         return;
1025
1026     double min = input->minimum();
1027     double max = input->maximum();
1028     ControlPart part = o.style().appearance();
1029     // We don't support ticks on alternate sliders like MediaVolumeSliders.
1030     if (part !=  SliderHorizontalPart && part != SliderVerticalPart)
1031         return;
1032     bool isHorizontal = part ==  SliderHorizontalPart;
1033
1034     IntSize thumbSize;
1035     const RenderObject* thumbRenderer = input->sliderThumbElement()->renderer();
1036     if (thumbRenderer) {
1037         const RenderStyle& thumbStyle = thumbRenderer->style();
1038         int thumbWidth = thumbStyle.width().intValue();
1039         int thumbHeight = thumbStyle.height().intValue();
1040         thumbSize.setWidth(isHorizontal ? thumbWidth : thumbHeight);
1041         thumbSize.setHeight(isHorizontal ? thumbHeight : thumbWidth);
1042     }
1043
1044     IntSize tickSize = sliderTickSize();
1045     float zoomFactor = o.style().effectiveZoom();
1046     FloatRect tickRect;
1047     int tickRegionSideMargin = 0;
1048     int tickRegionWidth = 0;
1049     IntRect trackBounds;
1050     RenderObject* trackRenderer = input->sliderTrackElement()->renderer();
1051     // We can ignoring transforms because transform is handled by the graphics context.
1052     if (trackRenderer)
1053         trackBounds = trackRenderer->absoluteBoundingBoxRectIgnoringTransforms();
1054     IntRect sliderBounds = o.absoluteBoundingBoxRectIgnoringTransforms();
1055
1056     // Make position relative to the transformed ancestor element.
1057     trackBounds.setX(trackBounds.x() - sliderBounds.x() + rect.x());
1058     trackBounds.setY(trackBounds.y() - sliderBounds.y() + rect.y());
1059
1060     if (isHorizontal) {
1061         tickRect.setWidth(floor(tickSize.width() * zoomFactor));
1062         tickRect.setHeight(floor(tickSize.height() * zoomFactor));
1063         tickRect.setY(floor(rect.y() + rect.height() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor));
1064         tickRegionSideMargin = trackBounds.x() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0;
1065         tickRegionWidth = trackBounds.width() - thumbSize.width();
1066     } else {
1067         tickRect.setWidth(floor(tickSize.height() * zoomFactor));
1068         tickRect.setHeight(floor(tickSize.width() * zoomFactor));
1069         tickRect.setX(floor(rect.x() + rect.width() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor));
1070         tickRegionSideMargin = trackBounds.y() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0;
1071         tickRegionWidth = trackBounds.height() - thumbSize.width();
1072     }
1073     RefPtr<HTMLCollection> options = dataList->options();
1074     GraphicsContextStateSaver stateSaver(*paintInfo.context);
1075     paintInfo.context->setFillColor(o.style().visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB);
1076     for (unsigned i = 0; Node* node = options->item(i); i++) {
1077         ASSERT(isHTMLOptionElement(node));
1078         HTMLOptionElement* optionElement = toHTMLOptionElement(node);
1079         String value = optionElement->value();
1080         if (!input->isValidValue(value))
1081             continue;
1082         double parsedValue = parseToDoubleForNumberType(input->sanitizeValue(value));
1083         double tickFraction = (parsedValue - min) / (max - min);
1084         double tickRatio = isHorizontal && o.style().isLeftToRightDirection() ? tickFraction : 1.0 - tickFraction;
1085         double tickPosition = round(tickRegionSideMargin + tickRegionWidth * tickRatio);
1086         if (isHorizontal)
1087             tickRect.setX(tickPosition);
1088         else
1089             tickRect.setY(tickPosition);
1090         paintInfo.context->fillRect(tickRect);
1091     }
1092 }
1093 #endif
1094
1095 #if ENABLE(PROGRESS_ELEMENT)
1096 double RenderTheme::animationRepeatIntervalForProgressBar(RenderProgress*) const
1097 {
1098     return 0;
1099 }
1100
1101 double RenderTheme::animationDurationForProgressBar(RenderProgress*) const
1102 {
1103     return 0;
1104 }
1105
1106 void RenderTheme::adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const
1107 {
1108 }
1109
1110 IntRect RenderTheme::progressBarRectForBounds(const RenderObject&, const IntRect& bounds) const
1111 {
1112     return bounds;
1113 }
1114 #endif
1115
1116 bool RenderTheme::shouldHaveSpinButton(HTMLInputElement* inputElement) const
1117 {
1118     return inputElement->isSteppable() && !inputElement->isRangeControl();
1119 }
1120
1121 void RenderTheme::adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const
1122 {
1123 }
1124
1125 void RenderTheme::adjustMediaControlStyle(StyleResolver*, RenderStyle*, Element*) const
1126 {
1127 }
1128
1129 void RenderTheme::adjustSliderTrackStyle(StyleResolver*, RenderStyle*, Element*) const
1130 {
1131 }
1132
1133 void RenderTheme::adjustSliderThumbStyle(StyleResolver*, RenderStyle* style, Element* element) const
1134 {
1135     adjustSliderThumbSize(style, element);
1136 }
1137
1138 void RenderTheme::adjustSliderThumbSize(RenderStyle*, Element*) const
1139 {
1140 }
1141
1142 void RenderTheme::adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const
1143 {
1144 }
1145
1146 void RenderTheme::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const
1147 {
1148 }
1149
1150 void RenderTheme::adjustSearchFieldDecorationPartStyle(StyleResolver*, RenderStyle*, Element*) const
1151 {
1152 }
1153
1154 void RenderTheme::adjustSearchFieldResultsDecorationPartStyle(StyleResolver*, RenderStyle*, Element*) const
1155 {
1156 }
1157
1158 void RenderTheme::adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const
1159 {
1160 }
1161
1162 void RenderTheme::platformColorsDidChange()
1163 {
1164     m_activeSelectionForegroundColor = Color();
1165     m_inactiveSelectionForegroundColor = Color();
1166     m_activeSelectionBackgroundColor = Color();
1167     m_inactiveSelectionBackgroundColor = Color();
1168
1169     m_activeListBoxSelectionForegroundColor = Color();
1170     m_inactiveListBoxSelectionForegroundColor = Color();
1171     m_activeListBoxSelectionBackgroundColor = Color();
1172     m_inactiveListBoxSelectionForegroundColor = Color();
1173
1174     Page::updateStyleForAllPagesAfterGlobalChangeInEnvironment();
1175 }
1176
1177 Color RenderTheme::systemColor(CSSValueID cssValueId) const
1178 {
1179     switch (cssValueId) {
1180     case CSSValueActiveborder:
1181         return 0xFFFFFFFF;
1182     case CSSValueActivecaption:
1183         return 0xFFCCCCCC;
1184     case CSSValueAppworkspace:
1185         return 0xFFFFFFFF;
1186     case CSSValueBackground:
1187         return 0xFF6363CE;
1188     case CSSValueButtonface:
1189         return 0xFFC0C0C0;
1190     case CSSValueButtonhighlight:
1191         return 0xFFDDDDDD;
1192     case CSSValueButtonshadow:
1193         return 0xFF888888;
1194     case CSSValueButtontext:
1195         return 0xFF000000;
1196     case CSSValueCaptiontext:
1197         return 0xFF000000;
1198     case CSSValueGraytext:
1199         return 0xFF808080;
1200     case CSSValueHighlight:
1201         return 0xFFB5D5FF;
1202     case CSSValueHighlighttext:
1203         return 0xFF000000;
1204     case CSSValueInactiveborder:
1205         return 0xFFFFFFFF;
1206     case CSSValueInactivecaption:
1207         return 0xFFFFFFFF;
1208     case CSSValueInactivecaptiontext:
1209         return 0xFF7F7F7F;
1210     case CSSValueInfobackground:
1211         return 0xFFFBFCC5;
1212     case CSSValueInfotext:
1213         return 0xFF000000;
1214     case CSSValueMenu:
1215         return 0xFFC0C0C0;
1216     case CSSValueMenutext:
1217         return 0xFF000000;
1218     case CSSValueScrollbar:
1219         return 0xFFFFFFFF;
1220     case CSSValueText:
1221         return 0xFF000000;
1222     case CSSValueThreeddarkshadow:
1223         return 0xFF666666;
1224     case CSSValueThreedface:
1225         return 0xFFC0C0C0;
1226     case CSSValueThreedhighlight:
1227         return 0xFFDDDDDD;
1228     case CSSValueThreedlightshadow:
1229         return 0xFFC0C0C0;
1230     case CSSValueThreedshadow:
1231         return 0xFF888888;
1232     case CSSValueWindow:
1233         return 0xFFFFFFFF;
1234     case CSSValueWindowframe:
1235         return 0xFFCCCCCC;
1236     case CSSValueWindowtext:
1237         return 0xFF000000;
1238     default:
1239         break;
1240     }
1241     return Color();
1242 }
1243
1244 Color RenderTheme::platformActiveTextSearchHighlightColor() const
1245 {
1246     return Color(255, 150, 50); // Orange.
1247 }
1248
1249 Color RenderTheme::platformInactiveTextSearchHighlightColor() const
1250 {
1251     return Color(255, 255, 0); // Yellow.
1252 }
1253
1254 #if ENABLE(TOUCH_EVENTS)
1255 Color RenderTheme::tapHighlightColor()
1256 {
1257     return defaultTheme()->platformTapHighlightColor();
1258 }
1259 #endif
1260
1261 // Value chosen by observation. This can be tweaked.
1262 static const int minColorContrastValue = 1300;
1263 // For transparent or translucent background color, use lightening.
1264 static const int minDisabledColorAlphaValue = 128;
1265
1266 Color RenderTheme::disabledTextColor(const Color& textColor, const Color& backgroundColor) const
1267 {
1268     // The explicit check for black is an optimization for the 99% case (black on white).
1269     // This also means that black on black will turn into grey on black when disabled.
1270     Color disabledColor;
1271     if (textColor.rgb() == Color::black || backgroundColor.alpha() < minDisabledColorAlphaValue || differenceSquared(textColor, Color::white) > differenceSquared(backgroundColor, Color::white))
1272         disabledColor = textColor.light();
1273     else
1274         disabledColor = textColor.dark();
1275     
1276     // If there's not very much contrast between the disabled color and the background color,
1277     // just leave the text color alone. We don't want to change a good contrast color scheme so that it has really bad contrast.
1278     // If the the contrast was already poor, then it doesn't do any good to change it to a different poor contrast color scheme.
1279     if (differenceSquared(disabledColor, backgroundColor) < minColorContrastValue)
1280         return textColor;
1281     
1282     return disabledColor;
1283 }
1284
1285 void RenderTheme::setCustomFocusRingColor(const Color& c)
1286 {
1287     customFocusRingColor() = c;
1288 }
1289
1290 Color RenderTheme::focusRingColor()
1291 {
1292     return customFocusRingColor().isValid() ? customFocusRingColor() : defaultTheme()->platformFocusRingColor();
1293 }
1294
1295 String RenderTheme::fileListDefaultLabel(bool multipleFilesAllowed) const
1296 {
1297     if (multipleFilesAllowed)
1298         return fileButtonNoFilesSelectedLabel();
1299     return fileButtonNoFileSelectedLabel();
1300 }
1301
1302 String RenderTheme::fileListNameForWidth(const FileList* fileList, const Font& font, int width, bool multipleFilesAllowed) const
1303 {
1304     if (width <= 0)
1305         return String();
1306
1307     String string;
1308     if (fileList->isEmpty())
1309         string = fileListDefaultLabel(multipleFilesAllowed);
1310     else if (fileList->length() == 1)
1311         string = fileList->item(0)->name();
1312     else
1313         return StringTruncator::rightTruncate(multipleFileUploadText(fileList->length()), width, font, StringTruncator::EnableRoundingHacks);
1314
1315     return StringTruncator::centerTruncate(string, width, font, StringTruncator::EnableRoundingHacks);
1316 }
1317
1318 } // namespace WebCore