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