Rename "IMAGE_CONTROLS" feature to "SERVICE_CONTROLS"
[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 }
758
759 ControlStates::States RenderTheme::extractControlStatesForRenderer(const RenderObject& o) const
760 {
761     ControlStates::States states = 0;
762     if (isHovered(o)) {
763         states |= ControlStates::HoverState;
764         if (isSpinUpButtonPartHovered(o))
765             states |= ControlStates::SpinUpState;
766     }
767     if (isPressed(o)) {
768         states |= ControlStates::PressedState;
769         if (isSpinUpButtonPartPressed(o))
770             states |= ControlStates::SpinUpState;
771     }
772     if (isFocused(o) && o.style().outlineStyleIsAuto())
773         states |= ControlStates::FocusState;
774     if (isEnabled(o))
775         states |= ControlStates::EnabledState;
776     if (isChecked(o))
777         states |= ControlStates::CheckedState;
778     if (isReadOnlyControl(o))
779         states |= ControlStates::ReadOnlyState;
780     if (isDefault(o))
781         states |= ControlStates::DefaultState;
782     if (!isActive(o))
783         states |= ControlStates::WindowInactiveState;
784     if (isIndeterminate(o))
785         states |= ControlStates::IndeterminateState;
786     return states;
787 }
788
789 bool RenderTheme::isActive(const RenderObject& o) const
790 {
791     Node* node = o.node();
792     if (!node)
793         return false;
794
795     Frame* frame = node->document().frame();
796     if (!frame)
797         return false;
798
799     Page* page = frame->page();
800     if (!page)
801         return false;
802
803     return page->focusController().isActive();
804 }
805
806 bool RenderTheme::isChecked(const RenderObject& o) const
807 {
808     if (!o.node())
809         return false;
810
811     HTMLInputElement* inputElement = o.node()->toInputElement();
812     if (!inputElement)
813         return false;
814
815     return inputElement->shouldAppearChecked();
816 }
817
818 bool RenderTheme::isIndeterminate(const RenderObject& o) const
819 {
820     if (!o.node())
821         return false;
822
823     HTMLInputElement* inputElement = o.node()->toInputElement();
824     if (!inputElement)
825         return false;
826
827     return inputElement->shouldAppearIndeterminate();
828 }
829
830 bool RenderTheme::isEnabled(const RenderObject& o) const
831 {
832     Node* node = o.node();
833     if (!node || !node->isElementNode())
834         return true;
835     return !toElement(node)->isDisabledFormControl();
836 }
837
838 bool RenderTheme::isFocused(const RenderObject& o) const
839 {
840     Node* node = o.node();
841     if (!node || !node->isElementNode())
842         return false;
843
844     Element* focusDelegate = toElement(node)->focusDelegate();
845     Document& document = focusDelegate->document();
846     Frame* frame = document.frame();
847     return focusDelegate == document.focusedElement() && frame && frame->selection().isFocusedAndActive();
848 }
849
850 bool RenderTheme::isPressed(const RenderObject& o) const
851 {
852     if (!o.node() || !o.node()->isElementNode())
853         return false;
854     return toElement(o.node())->active();
855 }
856
857 bool RenderTheme::isSpinUpButtonPartPressed(const RenderObject& o) const
858 {
859     Node* node = o.node();
860     if (!node || !node->isElementNode())
861         return false;
862     Element* element = toElement(node);
863     if (!element->active() || !element->isSpinButtonElement())
864         return false;
865     return static_cast<SpinButtonElement*>(element)->upDownState() == SpinButtonElement::Up;
866 }
867
868 bool RenderTheme::isReadOnlyControl(const RenderObject& o) const
869 {
870     Node* node = o.node();
871     if (!node || !node->isElementNode())
872         return false;
873     return toElement(node)->matchesReadOnlyPseudoClass();
874 }
875
876 bool RenderTheme::isHovered(const RenderObject& o) const
877 {
878     Node* node = o.node();
879     if (!node || !node->isElementNode())
880         return false;
881     if (!toElement(node)->isSpinButtonElement())
882         return toElement(node)->hovered();
883     SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
884     return element->hovered() && element->upDownState() != SpinButtonElement::Indeterminate;
885 }
886
887 bool RenderTheme::isSpinUpButtonPartHovered(const RenderObject& o) const
888 {
889     Node* node = o.node();
890     if (!node || !node->isElementNode() || !toElement(node)->isSpinButtonElement())
891         return false;
892     SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
893     return element->upDownState() == SpinButtonElement::Up;
894 }
895
896 bool RenderTheme::isDefault(const RenderObject& o) const
897 {
898     // A button should only have the default appearance if the page is active
899     if (!isActive(o))
900         return false;
901
902     if (!o.frame().settings().applicationChromeMode())
903         return false;
904     
905     return o.style().appearance() == DefaultButtonPart;
906 }
907
908 #if !USE(NEW_THEME)
909
910 void RenderTheme::adjustCheckboxStyle(StyleResolver*, RenderStyle* style, Element*) const
911 {
912     // A summary of the rules for checkbox designed to match WinIE:
913     // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
914     // font-size - not honored (control has no text), but we use it to decide which control size to use.
915     setCheckboxSize(style);
916
917     // padding - not honored by WinIE, needs to be removed.
918     style->resetPadding();
919
920     // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
921     // for now, we will not honor it.
922     style->resetBorder();
923
924     style->setBoxShadow(nullptr);
925 }
926
927 void RenderTheme::adjustRadioStyle(StyleResolver*, RenderStyle* style, Element*) const
928 {
929     // A summary of the rules for checkbox designed to match WinIE:
930     // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
931     // font-size - not honored (control has no text), but we use it to decide which control size to use.
932     setRadioSize(style);
933
934     // padding - not honored by WinIE, needs to be removed.
935     style->resetPadding();
936
937     // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
938     // for now, we will not honor it.
939     style->resetBorder();
940
941     style->setBoxShadow(nullptr);
942 }
943
944 void RenderTheme::adjustButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
945 {
946     // Most platforms will completely honor all CSS, and so we have no need to
947     // adjust the style at all by default. We will still allow the theme a crack
948     // at setting up a desired vertical size.
949     setButtonSize(style);
950 }
951
952 void RenderTheme::adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle*, Element*) const
953 {
954 }
955 #endif
956
957 void RenderTheme::adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const
958 {
959 }
960
961 void RenderTheme::adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const
962 {
963 }
964
965 void RenderTheme::adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const
966 {
967 }
968
969 #if ENABLE(INPUT_SPEECH)
970 void RenderTheme::adjustInputFieldSpeechButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
971 {
972     RenderInputSpeech::adjustInputFieldSpeechButtonStyle(styleResolver, style, element);
973 }
974
975 bool RenderTheme::paintInputFieldSpeechButton(const RenderObject& object, const PaintInfo& paintInfo, const IntRect& rect)
976 {
977     return RenderInputSpeech::paintInputFieldSpeechButton(object, paintInfo, rect);
978 }
979 #endif
980
981 #if ENABLE(METER_ELEMENT)
982 void RenderTheme::adjustMeterStyle(StyleResolver*, RenderStyle* style, Element*) const
983 {
984     style->setBoxShadow(nullptr);
985 }
986
987 IntSize RenderTheme::meterSizeForBounds(const RenderMeter*, const IntRect& bounds) const
988 {
989     return bounds.size();
990 }
991
992 bool RenderTheme::supportsMeter(ControlPart) const
993 {
994     return false;
995 }
996
997 bool RenderTheme::paintMeter(const RenderObject&, const PaintInfo&, const IntRect&)
998 {
999     return true;
1000 }
1001
1002 #endif
1003
1004 #if ENABLE(DATALIST_ELEMENT)
1005 LayoutUnit RenderTheme::sliderTickSnappingThreshold() const
1006 {
1007     return 0;
1008 }
1009
1010 void RenderTheme::paintSliderTicks(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& rect)
1011 {
1012     Node* node = o.node();
1013     if (!node)
1014         return;
1015
1016     HTMLInputElement* input = node->toInputElement();
1017     if (!input)
1018         return;
1019
1020     HTMLDataListElement* dataList = toHTMLDataListElement(input->list());
1021     if (!dataList)
1022         return;
1023
1024     double min = input->minimum();
1025     double max = input->maximum();
1026     ControlPart part = o.style().appearance();
1027     // We don't support ticks on alternate sliders like MediaVolumeSliders.
1028     if (part !=  SliderHorizontalPart && part != SliderVerticalPart)
1029         return;
1030     bool isHorizontal = part ==  SliderHorizontalPart;
1031
1032     IntSize thumbSize;
1033     const RenderObject* thumbRenderer = input->sliderThumbElement()->renderer();
1034     if (thumbRenderer) {
1035         const RenderStyle& thumbStyle = thumbRenderer->style();
1036         int thumbWidth = thumbStyle.width().intValue();
1037         int thumbHeight = thumbStyle.height().intValue();
1038         thumbSize.setWidth(isHorizontal ? thumbWidth : thumbHeight);
1039         thumbSize.setHeight(isHorizontal ? thumbHeight : thumbWidth);
1040     }
1041
1042     IntSize tickSize = sliderTickSize();
1043     float zoomFactor = o.style().effectiveZoom();
1044     FloatRect tickRect;
1045     int tickRegionSideMargin = 0;
1046     int tickRegionWidth = 0;
1047     IntRect trackBounds;
1048     RenderObject* trackRenderer = input->sliderTrackElement()->renderer();
1049     // We can ignoring transforms because transform is handled by the graphics context.
1050     if (trackRenderer)
1051         trackBounds = trackRenderer->absoluteBoundingBoxRectIgnoringTransforms();
1052     IntRect sliderBounds = o.absoluteBoundingBoxRectIgnoringTransforms();
1053
1054     // Make position relative to the transformed ancestor element.
1055     trackBounds.setX(trackBounds.x() - sliderBounds.x() + rect.x());
1056     trackBounds.setY(trackBounds.y() - sliderBounds.y() + rect.y());
1057
1058     if (isHorizontal) {
1059         tickRect.setWidth(floor(tickSize.width() * zoomFactor));
1060         tickRect.setHeight(floor(tickSize.height() * zoomFactor));
1061         tickRect.setY(floor(rect.y() + rect.height() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor));
1062         tickRegionSideMargin = trackBounds.x() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0;
1063         tickRegionWidth = trackBounds.width() - thumbSize.width();
1064     } else {
1065         tickRect.setWidth(floor(tickSize.height() * zoomFactor));
1066         tickRect.setHeight(floor(tickSize.width() * zoomFactor));
1067         tickRect.setX(floor(rect.x() + rect.width() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor));
1068         tickRegionSideMargin = trackBounds.y() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0;
1069         tickRegionWidth = trackBounds.height() - thumbSize.width();
1070     }
1071     RefPtr<HTMLCollection> options = dataList->options();
1072     GraphicsContextStateSaver stateSaver(*paintInfo.context);
1073     paintInfo.context->setFillColor(o.style().visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB);
1074     for (unsigned i = 0; Node* node = options->item(i); i++) {
1075         ASSERT(isHTMLOptionElement(node));
1076         HTMLOptionElement* optionElement = toHTMLOptionElement(node);
1077         String value = optionElement->value();
1078         if (!input->isValidValue(value))
1079             continue;
1080         double parsedValue = parseToDoubleForNumberType(input->sanitizeValue(value));
1081         double tickFraction = (parsedValue - min) / (max - min);
1082         double tickRatio = isHorizontal && o.style().isLeftToRightDirection() ? tickFraction : 1.0 - tickFraction;
1083         double tickPosition = round(tickRegionSideMargin + tickRegionWidth * tickRatio);
1084         if (isHorizontal)
1085             tickRect.setX(tickPosition);
1086         else
1087             tickRect.setY(tickPosition);
1088         paintInfo.context->fillRect(tickRect);
1089     }
1090 }
1091 #endif
1092
1093 #if ENABLE(PROGRESS_ELEMENT)
1094 double RenderTheme::animationRepeatIntervalForProgressBar(RenderProgress*) const
1095 {
1096     return 0;
1097 }
1098
1099 double RenderTheme::animationDurationForProgressBar(RenderProgress*) const
1100 {
1101     return 0;
1102 }
1103
1104 void RenderTheme::adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const
1105 {
1106 }
1107
1108 IntRect RenderTheme::progressBarRectForBounds(const RenderObject&, const IntRect& bounds) const
1109 {
1110     return bounds;
1111 }
1112 #endif
1113
1114 bool RenderTheme::shouldHaveSpinButton(HTMLInputElement* inputElement) const
1115 {
1116     return inputElement->isSteppable() && !inputElement->isRangeControl();
1117 }
1118
1119 void RenderTheme::adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const
1120 {
1121 }
1122
1123 void RenderTheme::adjustMediaControlStyle(StyleResolver*, RenderStyle*, Element*) const
1124 {
1125 }
1126
1127 void RenderTheme::adjustSliderTrackStyle(StyleResolver*, RenderStyle*, Element*) const
1128 {
1129 }
1130
1131 void RenderTheme::adjustSliderThumbStyle(StyleResolver*, RenderStyle* style, Element* element) const
1132 {
1133     adjustSliderThumbSize(style, element);
1134 }
1135
1136 void RenderTheme::adjustSliderThumbSize(RenderStyle*, Element*) const
1137 {
1138 }
1139
1140 void RenderTheme::adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const
1141 {
1142 }
1143
1144 void RenderTheme::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const
1145 {
1146 }
1147
1148 void RenderTheme::adjustSearchFieldDecorationPartStyle(StyleResolver*, RenderStyle*, Element*) const
1149 {
1150 }
1151
1152 void RenderTheme::adjustSearchFieldResultsDecorationPartStyle(StyleResolver*, RenderStyle*, Element*) const
1153 {
1154 }
1155
1156 void RenderTheme::adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const
1157 {
1158 }
1159
1160 void RenderTheme::platformColorsDidChange()
1161 {
1162     m_activeSelectionForegroundColor = Color();
1163     m_inactiveSelectionForegroundColor = Color();
1164     m_activeSelectionBackgroundColor = Color();
1165     m_inactiveSelectionBackgroundColor = Color();
1166
1167     m_activeListBoxSelectionForegroundColor = Color();
1168     m_inactiveListBoxSelectionForegroundColor = Color();
1169     m_activeListBoxSelectionBackgroundColor = Color();
1170     m_inactiveListBoxSelectionForegroundColor = Color();
1171
1172     Page::updateStyleForAllPagesAfterGlobalChangeInEnvironment();
1173 }
1174
1175 Color RenderTheme::systemColor(CSSValueID cssValueId) const
1176 {
1177     switch (cssValueId) {
1178     case CSSValueActiveborder:
1179         return 0xFFFFFFFF;
1180     case CSSValueActivecaption:
1181         return 0xFFCCCCCC;
1182     case CSSValueAppworkspace:
1183         return 0xFFFFFFFF;
1184     case CSSValueBackground:
1185         return 0xFF6363CE;
1186     case CSSValueButtonface:
1187         return 0xFFC0C0C0;
1188     case CSSValueButtonhighlight:
1189         return 0xFFDDDDDD;
1190     case CSSValueButtonshadow:
1191         return 0xFF888888;
1192     case CSSValueButtontext:
1193         return 0xFF000000;
1194     case CSSValueCaptiontext:
1195         return 0xFF000000;
1196     case CSSValueGraytext:
1197         return 0xFF808080;
1198     case CSSValueHighlight:
1199         return 0xFFB5D5FF;
1200     case CSSValueHighlighttext:
1201         return 0xFF000000;
1202     case CSSValueInactiveborder:
1203         return 0xFFFFFFFF;
1204     case CSSValueInactivecaption:
1205         return 0xFFFFFFFF;
1206     case CSSValueInactivecaptiontext:
1207         return 0xFF7F7F7F;
1208     case CSSValueInfobackground:
1209         return 0xFFFBFCC5;
1210     case CSSValueInfotext:
1211         return 0xFF000000;
1212     case CSSValueMenu:
1213         return 0xFFC0C0C0;
1214     case CSSValueMenutext:
1215         return 0xFF000000;
1216     case CSSValueScrollbar:
1217         return 0xFFFFFFFF;
1218     case CSSValueText:
1219         return 0xFF000000;
1220     case CSSValueThreeddarkshadow:
1221         return 0xFF666666;
1222     case CSSValueThreedface:
1223         return 0xFFC0C0C0;
1224     case CSSValueThreedhighlight:
1225         return 0xFFDDDDDD;
1226     case CSSValueThreedlightshadow:
1227         return 0xFFC0C0C0;
1228     case CSSValueThreedshadow:
1229         return 0xFF888888;
1230     case CSSValueWindow:
1231         return 0xFFFFFFFF;
1232     case CSSValueWindowframe:
1233         return 0xFFCCCCCC;
1234     case CSSValueWindowtext:
1235         return 0xFF000000;
1236     default:
1237         break;
1238     }
1239     return Color();
1240 }
1241
1242 Color RenderTheme::platformActiveTextSearchHighlightColor() const
1243 {
1244     return Color(255, 150, 50); // Orange.
1245 }
1246
1247 Color RenderTheme::platformInactiveTextSearchHighlightColor() const
1248 {
1249     return Color(255, 255, 0); // Yellow.
1250 }
1251
1252 #if ENABLE(TOUCH_EVENTS)
1253 Color RenderTheme::tapHighlightColor()
1254 {
1255     return defaultTheme()->platformTapHighlightColor();
1256 }
1257 #endif
1258
1259 // Value chosen by observation. This can be tweaked.
1260 static const int minColorContrastValue = 1300;
1261 // For transparent or translucent background color, use lightening.
1262 static const int minDisabledColorAlphaValue = 128;
1263
1264 Color RenderTheme::disabledTextColor(const Color& textColor, const Color& backgroundColor) const
1265 {
1266     // The explicit check for black is an optimization for the 99% case (black on white).
1267     // This also means that black on black will turn into grey on black when disabled.
1268     Color disabledColor;
1269     if (textColor.rgb() == Color::black || backgroundColor.alpha() < minDisabledColorAlphaValue || differenceSquared(textColor, Color::white) > differenceSquared(backgroundColor, Color::white))
1270         disabledColor = textColor.light();
1271     else
1272         disabledColor = textColor.dark();
1273     
1274     // If there's not very much contrast between the disabled color and the background color,
1275     // just leave the text color alone. We don't want to change a good contrast color scheme so that it has really bad contrast.
1276     // If the the contrast was already poor, then it doesn't do any good to change it to a different poor contrast color scheme.
1277     if (differenceSquared(disabledColor, backgroundColor) < minColorContrastValue)
1278         return textColor;
1279     
1280     return disabledColor;
1281 }
1282
1283 void RenderTheme::setCustomFocusRingColor(const Color& c)
1284 {
1285     customFocusRingColor() = c;
1286 }
1287
1288 Color RenderTheme::focusRingColor()
1289 {
1290     return customFocusRingColor().isValid() ? customFocusRingColor() : defaultTheme()->platformFocusRingColor();
1291 }
1292
1293 String RenderTheme::fileListDefaultLabel(bool multipleFilesAllowed) const
1294 {
1295     if (multipleFilesAllowed)
1296         return fileButtonNoFilesSelectedLabel();
1297     return fileButtonNoFileSelectedLabel();
1298 }
1299
1300 String RenderTheme::fileListNameForWidth(const FileList* fileList, const Font& font, int width, bool multipleFilesAllowed) const
1301 {
1302     if (width <= 0)
1303         return String();
1304
1305     String string;
1306     if (fileList->isEmpty())
1307         string = fileListDefaultLabel(multipleFilesAllowed);
1308     else if (fileList->length() == 1)
1309         string = fileList->item(0)->name();
1310     else
1311         return StringTruncator::rightTruncate(multipleFileUploadText(fileList->length()), width, font, StringTruncator::EnableRoundingHacks);
1312
1313     return StringTruncator::centerTruncate(string, width, font, StringTruncator::EnableRoundingHacks);
1314 }
1315
1316 } // namespace WebCore