RenderTheme::volumeSliderOffsetFromMuteButton should take const& RenderBox.
[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     DEPRECATED_DEFINE_STATIC_LOCAL(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     ControlPart part = box.style().appearance();
279     IntRect integralSnappedRect = snappedIntRect(rect);
280     float deviceScaleFactor = box.document().deviceScaleFactor();
281     FloatRect devicePixelSnappedRect = snapRectToDevicePixels(rect, deviceScaleFactor);
282
283 #if USE(NEW_THEME)
284     float pageScaleFactor = box.document().page() ? box.document().page()->pageScaleFactor() : 1.0f;
285     
286     switch (part) {
287     case CheckboxPart:
288     case RadioPart:
289     case PushButtonPart:
290     case SquareButtonPart:
291     case DefaultButtonPart:
292     case ButtonPart:
293     case InnerSpinButtonPart:
294         updateControlStatesForRenderer(box, controlStates);
295         m_theme->paint(part, controlStates, const_cast<GraphicsContext*>(paintInfo.context), devicePixelSnappedRect, box.style().effectiveZoom(), &box.view().frameView(), deviceScaleFactor, pageScaleFactor);
296         return false;
297     default:
298         break;
299     }
300 #else
301     UNUSED_PARAM(controlStates);
302 #endif
303
304     // Call the appropriate paint method based off the appearance value.
305     switch (part) {
306 #if !USE(NEW_THEME)
307     case CheckboxPart:
308         return paintCheckbox(box, paintInfo, integralSnappedRect);
309     case RadioPart:
310         return paintRadio(box, paintInfo, integralSnappedRect);
311     case PushButtonPart:
312     case SquareButtonPart:
313     case DefaultButtonPart:
314     case ButtonPart:
315         return paintButton(box, paintInfo, integralSnappedRect);
316     case InnerSpinButtonPart:
317         return paintInnerSpinButton(box, paintInfo, integralSnappedRect);
318 #endif
319     case MenulistPart:
320         return paintMenuList(box, paintInfo, devicePixelSnappedRect);
321 #if ENABLE(METER_ELEMENT)
322     case MeterPart:
323     case RelevancyLevelIndicatorPart:
324     case ContinuousCapacityLevelIndicatorPart:
325     case DiscreteCapacityLevelIndicatorPart:
326     case RatingLevelIndicatorPart:
327         return paintMeter(box, paintInfo, integralSnappedRect);
328 #endif
329     case ProgressBarPart:
330         return paintProgressBar(box, paintInfo, integralSnappedRect);
331     case SliderHorizontalPart:
332     case SliderVerticalPart:
333         return paintSliderTrack(box, paintInfo, integralSnappedRect);
334     case SliderThumbHorizontalPart:
335     case SliderThumbVerticalPart:
336         return paintSliderThumb(box, paintInfo, integralSnappedRect);
337     case MediaEnterFullscreenButtonPart:
338     case MediaExitFullscreenButtonPart:
339         return paintMediaFullscreenButton(box, paintInfo, integralSnappedRect);
340     case MediaPlayButtonPart:
341         return paintMediaPlayButton(box, paintInfo, integralSnappedRect);
342     case MediaOverlayPlayButtonPart:
343         return paintMediaOverlayPlayButton(box, paintInfo, integralSnappedRect);
344     case MediaMuteButtonPart:
345         return paintMediaMuteButton(box, paintInfo, integralSnappedRect);
346     case MediaSeekBackButtonPart:
347         return paintMediaSeekBackButton(box, paintInfo, integralSnappedRect);
348     case MediaSeekForwardButtonPart:
349         return paintMediaSeekForwardButton(box, paintInfo, integralSnappedRect);
350     case MediaRewindButtonPart:
351         return paintMediaRewindButton(box, paintInfo, integralSnappedRect);
352     case MediaReturnToRealtimeButtonPart:
353         return paintMediaReturnToRealtimeButton(box, paintInfo, integralSnappedRect);
354     case MediaToggleClosedCaptionsButtonPart:
355         return paintMediaToggleClosedCaptionsButton(box, paintInfo, integralSnappedRect);
356     case MediaSliderPart:
357         return paintMediaSliderTrack(box, paintInfo, integralSnappedRect);
358     case MediaSliderThumbPart:
359         return paintMediaSliderThumb(box, paintInfo, integralSnappedRect);
360     case MediaVolumeSliderMuteButtonPart:
361         return paintMediaMuteButton(box, paintInfo, integralSnappedRect);
362     case MediaVolumeSliderContainerPart:
363         return paintMediaVolumeSliderContainer(box, paintInfo, integralSnappedRect);
364     case MediaVolumeSliderPart:
365         return paintMediaVolumeSliderTrack(box, paintInfo, integralSnappedRect);
366     case MediaVolumeSliderThumbPart:
367         return paintMediaVolumeSliderThumb(box, paintInfo, integralSnappedRect);
368     case MediaFullScreenVolumeSliderPart:
369         return paintMediaFullScreenVolumeSliderTrack(box, paintInfo, integralSnappedRect);
370     case MediaFullScreenVolumeSliderThumbPart:
371         return paintMediaFullScreenVolumeSliderThumb(box, paintInfo, integralSnappedRect);
372     case MediaTimeRemainingPart:
373         return paintMediaTimeRemaining(box, paintInfo, integralSnappedRect);
374     case MediaCurrentTimePart:
375         return paintMediaCurrentTime(box, paintInfo, integralSnappedRect);
376     case MediaControlsBackgroundPart:
377         return paintMediaControlsBackground(box, paintInfo, integralSnappedRect);
378     case MenulistButtonPart:
379     case TextFieldPart:
380     case TextAreaPart:
381     case ListboxPart:
382         return true;
383     case SearchFieldPart:
384         return paintSearchField(box, paintInfo, integralSnappedRect);
385     case SearchFieldCancelButtonPart:
386         return paintSearchFieldCancelButton(box, paintInfo, integralSnappedRect);
387     case SearchFieldDecorationPart:
388         return paintSearchFieldDecorationPart(box, paintInfo, integralSnappedRect);
389     case SearchFieldResultsDecorationPart:
390         return paintSearchFieldResultsDecorationPart(box, paintInfo, integralSnappedRect);
391     case SearchFieldResultsButtonPart:
392         return paintSearchFieldResultsButton(box, paintInfo, integralSnappedRect);
393     case SnapshottedPluginOverlayPart:
394         return paintSnapshottedPluginOverlay(box, paintInfo, integralSnappedRect);
395 #if ENABLE(SERVICE_CONTROLS)
396     case ImageControlsButtonPart:
397         return paintImageControlsButton(box, paintInfo, integralSnappedRect);
398 #endif
399     case CapsLockIndicatorPart:
400         return paintCapsLockIndicator(box, paintInfo, integralSnappedRect);
401 #if ENABLE(ATTACHMENT_ELEMENT)
402     case AttachmentPart:
403         return paintAttachment(box, paintInfo, integralSnappedRect);
404 #endif
405     default:
406         break;
407     }
408
409     return true; // We don't support the appearance, so let the normal background/border paint.
410 }
411
412 bool RenderTheme::paintBorderOnly(const RenderBox& box, const PaintInfo& paintInfo, const LayoutRect& rect)
413 {
414     if (paintInfo.context->paintingDisabled())
415         return false;
416
417 #if PLATFORM(IOS)
418     UNUSED_PARAM(rect);
419     return box.style().appearance() != NoControlPart;
420 #else
421     FloatRect devicePixelSnappedRect = snapRectToDevicePixels(rect, box.document().deviceScaleFactor());
422     // Call the appropriate paint method based off the appearance value.
423     switch (box.style().appearance()) {
424     case TextFieldPart:
425         return paintTextField(box, paintInfo, devicePixelSnappedRect);
426     case ListboxPart:
427     case TextAreaPart:
428         return paintTextArea(box, paintInfo, devicePixelSnappedRect);
429     case MenulistButtonPart:
430     case SearchFieldPart:
431         return true;
432     case CheckboxPart:
433     case RadioPart:
434     case PushButtonPart:
435     case SquareButtonPart:
436     case DefaultButtonPart:
437     case ButtonPart:
438     case MenulistPart:
439 #if ENABLE(METER_ELEMENT)
440     case MeterPart:
441     case RelevancyLevelIndicatorPart:
442     case ContinuousCapacityLevelIndicatorPart:
443     case DiscreteCapacityLevelIndicatorPart:
444     case RatingLevelIndicatorPart:
445 #endif
446     case ProgressBarPart:
447     case SliderHorizontalPart:
448     case SliderVerticalPart:
449     case SliderThumbHorizontalPart:
450     case SliderThumbVerticalPart:
451     case SearchFieldCancelButtonPart:
452     case SearchFieldDecorationPart:
453     case SearchFieldResultsDecorationPart:
454     case SearchFieldResultsButtonPart:
455 #if ENABLE(SERVICE_CONTROLS)
456     case ImageControlsButtonPart:
457 #endif
458     default:
459         break;
460     }
461
462     return false;
463 #endif
464 }
465
466 bool RenderTheme::paintDecorations(const RenderBox& box, const PaintInfo& paintInfo, const LayoutRect& rect)
467 {
468     if (paintInfo.context->paintingDisabled())
469         return false;
470
471     IntRect integralSnappedRect = snappedIntRect(rect);
472     FloatRect devicePixelSnappedRect = snapRectToDevicePixels(rect, box.document().deviceScaleFactor());
473
474     // Call the appropriate paint method based off the appearance value.
475     switch (box.style().appearance()) {
476     case MenulistButtonPart:
477         return paintMenuListButtonDecorations(box, paintInfo, devicePixelSnappedRect);
478     case TextFieldPart:
479         return paintTextFieldDecorations(box, paintInfo, devicePixelSnappedRect);
480     case TextAreaPart:
481         return paintTextAreaDecorations(box, paintInfo, devicePixelSnappedRect);
482     case CheckboxPart:
483         return paintCheckboxDecorations(box, paintInfo, integralSnappedRect);
484     case RadioPart:
485         return paintRadioDecorations(box, paintInfo, integralSnappedRect);
486     case PushButtonPart:
487         return paintPushButtonDecorations(box, paintInfo, integralSnappedRect);
488     case SquareButtonPart:
489         return paintSquareButtonDecorations(box, paintInfo, integralSnappedRect);
490     case ButtonPart:
491         return paintButtonDecorations(box, paintInfo, integralSnappedRect);
492     case MenulistPart:
493         return paintMenuListDecorations(box, paintInfo, integralSnappedRect);
494     case SliderThumbHorizontalPart:
495     case SliderThumbVerticalPart:
496         return paintSliderThumbDecorations(box, paintInfo, integralSnappedRect);
497     case SearchFieldPart:
498         return paintSearchFieldDecorations(box, paintInfo, integralSnappedRect);
499 #if ENABLE(METER_ELEMENT)
500     case MeterPart:
501     case RelevancyLevelIndicatorPart:
502     case ContinuousCapacityLevelIndicatorPart:
503     case DiscreteCapacityLevelIndicatorPart:
504     case RatingLevelIndicatorPart:
505 #endif
506     case ProgressBarPart:
507     case SliderHorizontalPart:
508     case SliderVerticalPart:
509     case ListboxPart:
510     case DefaultButtonPart:
511     case SearchFieldCancelButtonPart:
512     case SearchFieldDecorationPart:
513     case SearchFieldResultsDecorationPart:
514     case SearchFieldResultsButtonPart:
515 #if ENABLE(SERVICE_CONTROLS)
516     case ImageControlsButtonPart:
517 #endif
518     default:
519         break;
520     }
521
522     return false;
523 }
524
525 #if ENABLE(VIDEO)
526
527 String RenderTheme::formatMediaControlsTime(float time) const
528 {
529     if (!std::isfinite(time))
530         time = 0;
531     int seconds = (int)fabsf(time);
532     int hours = seconds / (60 * 60);
533     int minutes = (seconds / 60) % 60;
534     seconds %= 60;
535     if (hours) {
536         if (hours > 9)
537             return String::format("%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
538
539         return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
540     }
541
542     return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds);
543 }
544
545 String RenderTheme::formatMediaControlsCurrentTime(float currentTime, float /*duration*/) const
546 {
547     return formatMediaControlsTime(currentTime);
548 }
549
550 String RenderTheme::formatMediaControlsRemainingTime(float currentTime, float duration) const
551 {
552     return formatMediaControlsTime(currentTime - duration);
553 }
554
555 IntPoint RenderTheme::volumeSliderOffsetFromMuteButton(const RenderBox& muteButtonBox, const IntSize& size) const
556 {
557     int y = -size.height();
558     FloatPoint absPoint = muteButtonBox.localToAbsolute(FloatPoint(muteButtonBox.pixelSnappedOffsetLeft(), y), IsFixed | UseTransforms);
559     if (absPoint.y() < 0)
560         y = muteButtonBox.height();
561     return IntPoint(0, y);
562 }
563
564 #endif
565
566 Color RenderTheme::activeSelectionBackgroundColor() const
567 {
568     if (!m_activeSelectionBackgroundColor.isValid())
569         m_activeSelectionBackgroundColor = platformActiveSelectionBackgroundColor().blendWithWhite();
570     return m_activeSelectionBackgroundColor;
571 }
572
573 Color RenderTheme::inactiveSelectionBackgroundColor() const
574 {
575     if (!m_inactiveSelectionBackgroundColor.isValid())
576         m_inactiveSelectionBackgroundColor = platformInactiveSelectionBackgroundColor().blendWithWhite();
577     return m_inactiveSelectionBackgroundColor;
578 }
579
580 Color RenderTheme::activeSelectionForegroundColor() const
581 {
582     if (!m_activeSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
583         m_activeSelectionForegroundColor = platformActiveSelectionForegroundColor();
584     return m_activeSelectionForegroundColor;
585 }
586
587 Color RenderTheme::inactiveSelectionForegroundColor() const
588 {
589     if (!m_inactiveSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
590         m_inactiveSelectionForegroundColor = platformInactiveSelectionForegroundColor();
591     return m_inactiveSelectionForegroundColor;
592 }
593
594 Color RenderTheme::activeListBoxSelectionBackgroundColor() const
595 {
596     if (!m_activeListBoxSelectionBackgroundColor.isValid())
597         m_activeListBoxSelectionBackgroundColor = platformActiveListBoxSelectionBackgroundColor();
598     return m_activeListBoxSelectionBackgroundColor;
599 }
600
601 Color RenderTheme::inactiveListBoxSelectionBackgroundColor() const
602 {
603     if (!m_inactiveListBoxSelectionBackgroundColor.isValid())
604         m_inactiveListBoxSelectionBackgroundColor = platformInactiveListBoxSelectionBackgroundColor();
605     return m_inactiveListBoxSelectionBackgroundColor;
606 }
607
608 Color RenderTheme::activeListBoxSelectionForegroundColor() const
609 {
610     if (!m_activeListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
611         m_activeListBoxSelectionForegroundColor = platformActiveListBoxSelectionForegroundColor();
612     return m_activeListBoxSelectionForegroundColor;
613 }
614
615 Color RenderTheme::inactiveListBoxSelectionForegroundColor() const
616 {
617     if (!m_inactiveListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
618         m_inactiveListBoxSelectionForegroundColor = platformInactiveListBoxSelectionForegroundColor();
619     return m_inactiveListBoxSelectionForegroundColor;
620 }
621
622 Color RenderTheme::platformActiveSelectionBackgroundColor() const
623 {
624     // Use a blue color by default if the platform theme doesn't define anything.
625     return Color(0, 0, 255);
626 }
627
628 Color RenderTheme::platformActiveSelectionForegroundColor() const
629 {
630     // Use a white color by default if the platform theme doesn't define anything.
631     return Color::white;
632 }
633
634 Color RenderTheme::platformInactiveSelectionBackgroundColor() const
635 {
636     // Use a grey color by default if the platform theme doesn't define anything.
637     // This color matches Firefox's inactive color.
638     return Color(176, 176, 176);
639 }
640
641 Color RenderTheme::platformInactiveSelectionForegroundColor() const
642 {
643     // Use a black color by default.
644     return Color::black;
645 }
646
647 Color RenderTheme::platformActiveListBoxSelectionBackgroundColor() const
648 {
649     return platformActiveSelectionBackgroundColor();
650 }
651
652 Color RenderTheme::platformActiveListBoxSelectionForegroundColor() const
653 {
654     return platformActiveSelectionForegroundColor();
655 }
656
657 Color RenderTheme::platformInactiveListBoxSelectionBackgroundColor() const
658 {
659     return platformInactiveSelectionBackgroundColor();
660 }
661
662 Color RenderTheme::platformInactiveListBoxSelectionForegroundColor() const
663 {
664     return platformInactiveSelectionForegroundColor();
665 }
666
667 int RenderTheme::baselinePosition(const RenderBox& box) const
668 {
669 #if USE(NEW_THEME)
670     return box.height() + box.marginTop() + m_theme->baselinePositionAdjustment(box.style().appearance()) * box.style().effectiveZoom();
671 #else
672     return box.height() + box.marginTop();
673 #endif
674 }
675
676 bool RenderTheme::isControlContainer(ControlPart appearance) const
677 {
678     // There are more leaves than this, but we'll patch this function as we add support for
679     // more controls.
680     return appearance != CheckboxPart && appearance != RadioPart;
681 }
682
683 bool RenderTheme::isControlStyled(const RenderStyle& style, const BorderData& border, const FillLayer& background, const Color& backgroundColor) const
684 {
685     switch (style.appearance()) {
686     case PushButtonPart:
687     case SquareButtonPart:
688     case DefaultButtonPart:
689     case ButtonPart:
690     case ListboxPart:
691     case MenulistPart:
692     case ProgressBarPart:
693     case MeterPart:
694     case RelevancyLevelIndicatorPart:
695     case ContinuousCapacityLevelIndicatorPart:
696     case DiscreteCapacityLevelIndicatorPart:
697     case RatingLevelIndicatorPart:
698     // FIXME: SearchFieldPart should be included here when making search fields style-able.
699     case TextFieldPart:
700     case TextAreaPart:
701         // Test the style to see if the UA border and background match.
702         return (style.border() != border
703             || *style.backgroundLayers() != background
704             || style.visitedDependentColor(CSSPropertyBackgroundColor) != backgroundColor);
705     default:
706         return false;
707     }
708 }
709
710 void RenderTheme::adjustRepaintRect(const RenderObject& renderer, FloatRect& rect)
711 {
712 #if USE(NEW_THEME)
713     ControlStates states(extractControlStatesForRenderer(renderer));
714     m_theme->inflateControlPaintRect(renderer.style().appearance(), states, rect, renderer.style().effectiveZoom());
715 #else
716     UNUSED_PARAM(renderer);
717     UNUSED_PARAM(rect);
718 #endif
719 }
720
721 bool RenderTheme::supportsFocusRing(const RenderStyle& style) const
722 {
723     return (style.hasAppearance() && style.appearance() != TextFieldPart && style.appearance() != TextAreaPart && style.appearance() != MenulistButtonPart && style.appearance() != ListboxPart);
724 }
725
726 bool RenderTheme::stateChanged(const RenderObject& o, ControlStates::States state) const
727 {
728     // Default implementation assumes the controls don't respond to changes in :hover state
729     if (state == ControlStates::HoverState && !supportsHover(o.style()))
730         return false;
731
732     // Assume pressed state is only responded to if the control is enabled.
733     if (state == ControlStates::PressedState && !isEnabled(o))
734         return false;
735
736     // Repaint the control.
737     o.repaint();
738     return true;
739 }
740
741 void RenderTheme::updateControlStatesForRenderer(const RenderBox& box, ControlStates& controlStates) const
742 {
743     ControlStates newStates = extractControlStatesForRenderer(box);
744     controlStates.setStates(newStates.states());
745     if (isFocused(box))
746         controlStates.setTimeSinceControlWasFocused(box.document().page()->focusController().timeSinceFocusWasSet());
747 }
748
749 ControlStates::States RenderTheme::extractControlStatesForRenderer(const RenderObject& o) const
750 {
751     ControlStates::States states = 0;
752     if (isHovered(o)) {
753         states |= ControlStates::HoverState;
754         if (isSpinUpButtonPartHovered(o))
755             states |= ControlStates::SpinUpState;
756     }
757     if (isPressed(o)) {
758         states |= ControlStates::PressedState;
759         if (isSpinUpButtonPartPressed(o))
760             states |= ControlStates::SpinUpState;
761     }
762     if (isFocused(o) && o.style().outlineStyleIsAuto())
763         states |= ControlStates::FocusState;
764     if (isEnabled(o))
765         states |= ControlStates::EnabledState;
766     if (isChecked(o))
767         states |= ControlStates::CheckedState;
768     if (isDefault(o))
769         states |= ControlStates::DefaultState;
770     if (!isActive(o))
771         states |= ControlStates::WindowInactiveState;
772     if (isIndeterminate(o))
773         states |= ControlStates::IndeterminateState;
774     return states;
775 }
776
777 bool RenderTheme::isActive(const RenderObject& o) const
778 {
779     Page* page = o.document().page();
780     if (!page)
781         return false;
782
783     return page->focusController().isActive();
784 }
785
786 bool RenderTheme::isChecked(const RenderObject& o) const
787 {
788     if (!o.node())
789         return false;
790
791     HTMLInputElement* inputElement = o.node()->toInputElement();
792     if (!inputElement)
793         return false;
794
795     return inputElement->shouldAppearChecked();
796 }
797
798 bool RenderTheme::isIndeterminate(const RenderObject& o) const
799 {
800     if (!o.node())
801         return false;
802
803     HTMLInputElement* inputElement = o.node()->toInputElement();
804     if (!inputElement)
805         return false;
806
807     return inputElement->shouldAppearIndeterminate();
808 }
809
810 bool RenderTheme::isEnabled(const RenderObject& renderer) const
811 {
812     Node* node = renderer.node();
813     if (!is<Element>(node))
814         return true;
815     return !downcast<Element>(*node).isDisabledFormControl();
816 }
817
818 bool RenderTheme::isFocused(const RenderObject& renderer) const
819 {
820     Node* node = renderer.node();
821     if (!is<Element>(node))
822         return false;
823
824     Element* focusDelegate = downcast<Element>(*node).focusDelegate();
825     Document& document = focusDelegate->document();
826     Frame* frame = document.frame();
827     return focusDelegate == document.focusedElement() && frame && frame->selection().isFocusedAndActive();
828 }
829
830 bool RenderTheme::isPressed(const RenderObject& renderer) const
831 {
832     if (!is<Element>(renderer.node()))
833         return false;
834     return downcast<Element>(*renderer.node()).active();
835 }
836
837 bool RenderTheme::isSpinUpButtonPartPressed(const RenderObject& renderer) const
838 {
839     Node* node = renderer.node();
840     if (!is<Element>(node))
841         return false;
842     Element& element = downcast<Element>(*node);
843     if (!element.active() || !is<SpinButtonElement>(element))
844         return false;
845     return downcast<SpinButtonElement>(element).upDownState() == SpinButtonElement::Up;
846 }
847
848 bool RenderTheme::isReadOnlyControl(const RenderObject& renderer) const
849 {
850     Node* node = renderer.node();
851     if (!is<HTMLFormControlElement>(node))
852         return false;
853     return !downcast<Element>(*node).matchesReadWritePseudoClass();
854 }
855
856 bool RenderTheme::isHovered(const RenderObject& renderer) const
857 {
858     Node* node = renderer.node();
859     if (!is<Element>(node))
860         return false;
861     Element& element = downcast<Element>(*node);
862     if (!is<SpinButtonElement>(element))
863         return element.hovered();
864     SpinButtonElement& spinButton = downcast<SpinButtonElement>(element);
865     return spinButton.hovered() && spinButton.upDownState() != SpinButtonElement::Indeterminate;
866 }
867
868 bool RenderTheme::isSpinUpButtonPartHovered(const RenderObject& renderer) const
869 {
870     Node* node = renderer.node();
871     if (!is<SpinButtonElement>(node))
872         return false;
873     return downcast<SpinButtonElement>(*node).upDownState() == SpinButtonElement::Up;
874 }
875
876 bool RenderTheme::isDefault(const RenderObject& o) const
877 {
878     // A button should only have the default appearance if the page is active
879     if (!isActive(o))
880         return false;
881
882     return o.style().appearance() == DefaultButtonPart;
883 }
884
885 #if !USE(NEW_THEME)
886
887 void RenderTheme::adjustCheckboxStyle(StyleResolver&, RenderStyle& style, Element*) const
888 {
889     // A summary of the rules for checkbox designed to match WinIE:
890     // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
891     // font-size - not honored (control has no text), but we use it to decide which control size to use.
892     setCheckboxSize(style);
893
894     // padding - not honored by WinIE, needs to be removed.
895     style.resetPadding();
896
897     // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
898     // for now, we will not honor it.
899     style.resetBorder();
900
901     style.setBoxShadow(nullptr);
902 }
903
904 void RenderTheme::adjustRadioStyle(StyleResolver&, RenderStyle& style, Element*) const
905 {
906     // A summary of the rules for checkbox designed to match WinIE:
907     // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
908     // font-size - not honored (control has no text), but we use it to decide which control size to use.
909     setRadioSize(style);
910
911     // padding - not honored by WinIE, needs to be removed.
912     style.resetPadding();
913
914     // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
915     // for now, we will not honor it.
916     style.resetBorder();
917
918     style.setBoxShadow(nullptr);
919 }
920
921 void RenderTheme::adjustButtonStyle(StyleResolver&, RenderStyle& style, Element*) const
922 {
923     // Most platforms will completely honor all CSS, and so we have no need to
924     // adjust the style at all by default. We will still allow the theme a crack
925     // at setting up a desired vertical size.
926     setButtonSize(style);
927 }
928
929 void RenderTheme::adjustInnerSpinButtonStyle(StyleResolver&, RenderStyle&, Element*) const
930 {
931 }
932 #endif
933
934 void RenderTheme::adjustTextFieldStyle(StyleResolver&, RenderStyle&, Element*) const
935 {
936 }
937
938 void RenderTheme::adjustTextAreaStyle(StyleResolver&, RenderStyle&, Element*) const
939 {
940 }
941
942 void RenderTheme::adjustMenuListStyle(StyleResolver&, RenderStyle&, Element*) const
943 {
944 }
945
946 #if ENABLE(METER_ELEMENT)
947 void RenderTheme::adjustMeterStyle(StyleResolver&, RenderStyle& style, Element*) const
948 {
949     style.setBoxShadow(nullptr);
950 }
951
952 IntSize RenderTheme::meterSizeForBounds(const RenderMeter&, const IntRect& bounds) const
953 {
954     return bounds.size();
955 }
956
957 bool RenderTheme::supportsMeter(ControlPart) const
958 {
959     return false;
960 }
961
962 bool RenderTheme::paintMeter(const RenderObject&, const PaintInfo&, const IntRect&)
963 {
964     return true;
965 }
966 #endif
967
968 void RenderTheme::adjustCapsLockIndicatorStyle(StyleResolver&, RenderStyle&, Element*) const
969 {
970 }
971
972 bool RenderTheme::paintCapsLockIndicator(const RenderObject&, const PaintInfo&, const IntRect&)
973 {
974     return false;
975 }
976
977 #if ENABLE(ATTACHMENT_ELEMENT)
978 void RenderTheme::adjustAttachmentStyle(StyleResolver&, RenderStyle&, Element*) const
979 {
980 }
981
982 bool RenderTheme::paintAttachment(const RenderObject&, const PaintInfo&, const IntRect&)
983 {
984     return false;
985 }
986 #endif
987
988 #if ENABLE(DATALIST_ELEMENT)
989 LayoutUnit RenderTheme::sliderTickSnappingThreshold() const
990 {
991     return 0;
992 }
993
994 void RenderTheme::paintSliderTicks(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& rect)
995 {
996     Node* node = o.node();
997     if (!node)
998         return;
999
1000     HTMLInputElement* input = node->toInputElement();
1001     if (!input)
1002         return;
1003
1004     HTMLDataListElement* dataList = downcast<HTMLDataListElement>(input->list());
1005     if (!dataList)
1006         return;
1007
1008     double min = input->minimum();
1009     double max = input->maximum();
1010     ControlPart part = o.style().appearance();
1011     // We don't support ticks on alternate sliders like MediaVolumeSliders.
1012     if (part !=  SliderHorizontalPart && part != SliderVerticalPart)
1013         return;
1014     bool isHorizontal = part ==  SliderHorizontalPart;
1015
1016     IntSize thumbSize;
1017     const RenderObject* thumbRenderer = input->sliderThumbElement()->renderer();
1018     if (thumbRenderer) {
1019         const RenderStyle& thumbStyle = thumbRenderer->style();
1020         int thumbWidth = thumbStyle.width().intValue();
1021         int thumbHeight = thumbStyle.height().intValue();
1022         thumbSize.setWidth(isHorizontal ? thumbWidth : thumbHeight);
1023         thumbSize.setHeight(isHorizontal ? thumbHeight : thumbWidth);
1024     }
1025
1026     IntSize tickSize = sliderTickSize();
1027     float zoomFactor = o.style().effectiveZoom();
1028     FloatRect tickRect;
1029     int tickRegionSideMargin = 0;
1030     int tickRegionWidth = 0;
1031     IntRect trackBounds;
1032     RenderObject* trackRenderer = input->sliderTrackElement()->renderer();
1033     // We can ignoring transforms because transform is handled by the graphics context.
1034     if (trackRenderer)
1035         trackBounds = trackRenderer->absoluteBoundingBoxRectIgnoringTransforms();
1036     IntRect sliderBounds = o.absoluteBoundingBoxRectIgnoringTransforms();
1037
1038     // Make position relative to the transformed ancestor element.
1039     trackBounds.setX(trackBounds.x() - sliderBounds.x() + rect.x());
1040     trackBounds.setY(trackBounds.y() - sliderBounds.y() + rect.y());
1041
1042     if (isHorizontal) {
1043         tickRect.setWidth(floor(tickSize.width() * zoomFactor));
1044         tickRect.setHeight(floor(tickSize.height() * zoomFactor));
1045         tickRect.setY(floor(rect.y() + rect.height() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor));
1046         tickRegionSideMargin = trackBounds.x() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0;
1047         tickRegionWidth = trackBounds.width() - thumbSize.width();
1048     } else {
1049         tickRect.setWidth(floor(tickSize.height() * zoomFactor));
1050         tickRect.setHeight(floor(tickSize.width() * zoomFactor));
1051         tickRect.setX(floor(rect.x() + rect.width() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor));
1052         tickRegionSideMargin = trackBounds.y() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0;
1053         tickRegionWidth = trackBounds.height() - thumbSize.width();
1054     }
1055     Ref<HTMLCollection> options = dataList->options();
1056     GraphicsContextStateSaver stateSaver(*paintInfo.context);
1057     paintInfo.context->setFillColor(o.style().visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB);
1058     for (unsigned i = 0; Node* node = options->item(i); i++) {
1059         ASSERT(is<HTMLOptionElement>(*node));
1060         HTMLOptionElement& optionElement = downcast<HTMLOptionElement>(*node);
1061         String value = optionElement.value();
1062         if (!input->isValidValue(value))
1063             continue;
1064         double parsedValue = parseToDoubleForNumberType(input->sanitizeValue(value));
1065         double tickFraction = (parsedValue - min) / (max - min);
1066         double tickRatio = isHorizontal && o.style().isLeftToRightDirection() ? tickFraction : 1.0 - tickFraction;
1067         double tickPosition = round(tickRegionSideMargin + tickRegionWidth * tickRatio);
1068         if (isHorizontal)
1069             tickRect.setX(tickPosition);
1070         else
1071             tickRect.setY(tickPosition);
1072         paintInfo.context->fillRect(tickRect);
1073     }
1074 }
1075 #endif
1076
1077 double RenderTheme::animationRepeatIntervalForProgressBar(RenderProgress&) const
1078 {
1079     return 0;
1080 }
1081
1082 double RenderTheme::animationDurationForProgressBar(RenderProgress&) const
1083 {
1084     return 0;
1085 }
1086
1087 void RenderTheme::adjustProgressBarStyle(StyleResolver&, RenderStyle&, Element*) const
1088 {
1089 }
1090
1091 IntRect RenderTheme::progressBarRectForBounds(const RenderObject&, const IntRect& bounds) const
1092 {
1093     return bounds;
1094 }
1095
1096 bool RenderTheme::shouldHaveSpinButton(HTMLInputElement& inputElement) const
1097 {
1098     return inputElement.isSteppable() && !inputElement.isRangeControl();
1099 }
1100
1101 bool RenderTheme::shouldHaveCapsLockIndicator(HTMLInputElement&) const
1102 {
1103     return false;
1104 }
1105
1106 void RenderTheme::adjustMenuListButtonStyle(StyleResolver&, RenderStyle&, Element*) const
1107 {
1108 }
1109
1110 void RenderTheme::adjustMediaControlStyle(StyleResolver&, RenderStyle&, Element*) const
1111 {
1112 }
1113
1114 void RenderTheme::adjustSliderTrackStyle(StyleResolver&, RenderStyle&, Element*) const
1115 {
1116 }
1117
1118 void RenderTheme::adjustSliderThumbStyle(StyleResolver&, RenderStyle& style, Element* element) const
1119 {
1120     adjustSliderThumbSize(style, element);
1121 }
1122
1123 void RenderTheme::adjustSliderThumbSize(RenderStyle&, Element*) const
1124 {
1125 }
1126
1127 void RenderTheme::adjustSearchFieldStyle(StyleResolver&, RenderStyle&, Element*) const
1128 {
1129 }
1130
1131 void RenderTheme::adjustSearchFieldCancelButtonStyle(StyleResolver&, RenderStyle&, Element*) const
1132 {
1133 }
1134
1135 void RenderTheme::adjustSearchFieldDecorationPartStyle(StyleResolver&, RenderStyle&, Element*) const
1136 {
1137 }
1138
1139 void RenderTheme::adjustSearchFieldResultsDecorationPartStyle(StyleResolver&, RenderStyle&, Element*) const
1140 {
1141 }
1142
1143 void RenderTheme::adjustSearchFieldResultsButtonStyle(StyleResolver&, RenderStyle&, Element*) const
1144 {
1145 }
1146
1147 void RenderTheme::platformColorsDidChange()
1148 {
1149     m_activeSelectionForegroundColor = Color();
1150     m_inactiveSelectionForegroundColor = Color();
1151     m_activeSelectionBackgroundColor = Color();
1152     m_inactiveSelectionBackgroundColor = Color();
1153
1154     m_activeListBoxSelectionForegroundColor = Color();
1155     m_inactiveListBoxSelectionForegroundColor = Color();
1156     m_activeListBoxSelectionBackgroundColor = Color();
1157     m_inactiveListBoxSelectionForegroundColor = Color();
1158
1159     Page::updateStyleForAllPagesAfterGlobalChangeInEnvironment();
1160 }
1161
1162 FontDescription& RenderTheme::cachedSystemFontDescription(CSSValueID systemFontID) const
1163 {
1164     static NeverDestroyed<FontDescription> caption;
1165     static NeverDestroyed<FontDescription> icon;
1166     static NeverDestroyed<FontDescription> menu;
1167     static NeverDestroyed<FontDescription> messageBox;
1168     static NeverDestroyed<FontDescription> smallCaption;
1169     static NeverDestroyed<FontDescription> statusBar;
1170     static NeverDestroyed<FontDescription> webkitMiniControl;
1171     static NeverDestroyed<FontDescription> webkitSmallControl;
1172     static NeverDestroyed<FontDescription> webkitControl;
1173     static NeverDestroyed<FontDescription> defaultDescription;
1174
1175     switch (systemFontID) {
1176     case CSSValueCaption:
1177         return caption;
1178     case CSSValueIcon:
1179         return icon;
1180     case CSSValueMenu:
1181         return menu;
1182     case CSSValueMessageBox:
1183         return messageBox;
1184     case CSSValueSmallCaption:
1185         return smallCaption;
1186     case CSSValueStatusBar:
1187         return statusBar;
1188     case CSSValueWebkitMiniControl:
1189         return webkitMiniControl;
1190     case CSSValueWebkitSmallControl:
1191         return webkitSmallControl;
1192     case CSSValueWebkitControl:
1193         return webkitControl;
1194     case CSSValueNone:
1195         return defaultDescription;
1196     default:
1197         ASSERT_NOT_REACHED();
1198         return defaultDescription;
1199     }
1200 }
1201
1202 void RenderTheme::systemFont(CSSValueID systemFontID, FontDescription& fontDescription) const
1203 {
1204     fontDescription = cachedSystemFontDescription(systemFontID);
1205     if (fontDescription.isAbsoluteSize())
1206         return;
1207
1208     updateCachedSystemFontDescription(systemFontID, fontDescription);
1209 }
1210
1211 Color RenderTheme::systemColor(CSSValueID cssValueId) const
1212 {
1213     switch (cssValueId) {
1214     case CSSValueActiveborder:
1215         return 0xFFFFFFFF;
1216     case CSSValueActivebuttontext:
1217         return 0xFF000000;
1218     case CSSValueActivecaption:
1219         return 0xFFCCCCCC;
1220     case CSSValueAppworkspace:
1221         return 0xFFFFFFFF;
1222     case CSSValueBackground:
1223         return 0xFF6363CE;
1224     case CSSValueButtonface:
1225         return 0xFFC0C0C0;
1226     case CSSValueButtonhighlight:
1227         return 0xFFDDDDDD;
1228     case CSSValueButtonshadow:
1229         return 0xFF888888;
1230     case CSSValueButtontext:
1231         return 0xFF000000;
1232     case CSSValueCaptiontext:
1233         return 0xFF000000;
1234     case CSSValueGraytext:
1235         return 0xFF808080;
1236     case CSSValueHighlight:
1237         return 0xFFB5D5FF;
1238     case CSSValueHighlighttext:
1239         return 0xFF000000;
1240     case CSSValueInactiveborder:
1241         return 0xFFFFFFFF;
1242     case CSSValueInactivecaption:
1243         return 0xFFFFFFFF;
1244     case CSSValueInactivecaptiontext:
1245         return 0xFF7F7F7F;
1246     case CSSValueInfobackground:
1247         return 0xFFFBFCC5;
1248     case CSSValueInfotext:
1249         return 0xFF000000;
1250     case CSSValueMenu:
1251         return 0xFFC0C0C0;
1252     case CSSValueMenutext:
1253         return 0xFF000000;
1254     case CSSValueScrollbar:
1255         return 0xFFFFFFFF;
1256     case CSSValueText:
1257         return 0xFF000000;
1258     case CSSValueThreeddarkshadow:
1259         return 0xFF666666;
1260     case CSSValueThreedface:
1261         return 0xFFC0C0C0;
1262     case CSSValueThreedhighlight:
1263         return 0xFFDDDDDD;
1264     case CSSValueThreedlightshadow:
1265         return 0xFFC0C0C0;
1266     case CSSValueThreedshadow:
1267         return 0xFF888888;
1268     case CSSValueWindow:
1269         return 0xFFFFFFFF;
1270     case CSSValueWindowframe:
1271         return 0xFFCCCCCC;
1272     case CSSValueWindowtext:
1273         return 0xFF000000;
1274     default:
1275         break;
1276     }
1277     return Color();
1278 }
1279
1280 Color RenderTheme::platformActiveTextSearchHighlightColor() const
1281 {
1282     return Color(255, 150, 50); // Orange.
1283 }
1284
1285 Color RenderTheme::platformInactiveTextSearchHighlightColor() const
1286 {
1287     return Color(255, 255, 0); // Yellow.
1288 }
1289
1290 #if ENABLE(TOUCH_EVENTS)
1291 Color RenderTheme::tapHighlightColor()
1292 {
1293     return defaultTheme()->platformTapHighlightColor();
1294 }
1295 #endif
1296
1297 // Value chosen by observation. This can be tweaked.
1298 static const int minColorContrastValue = 1300;
1299 // For transparent or translucent background color, use lightening.
1300 static const int minDisabledColorAlphaValue = 128;
1301
1302 Color RenderTheme::disabledTextColor(const Color& textColor, const Color& backgroundColor) const
1303 {
1304     // The explicit check for black is an optimization for the 99% case (black on white).
1305     // This also means that black on black will turn into grey on black when disabled.
1306     Color disabledColor;
1307     if (textColor.rgb() == Color::black || backgroundColor.alpha() < minDisabledColorAlphaValue || differenceSquared(textColor, Color::white) > differenceSquared(backgroundColor, Color::white))
1308         disabledColor = textColor.light();
1309     else
1310         disabledColor = textColor.dark();
1311     
1312     // If there's not very much contrast between the disabled color and the background color,
1313     // just leave the text color alone. We don't want to change a good contrast color scheme so that it has really bad contrast.
1314     // If the the contrast was already poor, then it doesn't do any good to change it to a different poor contrast color scheme.
1315     if (differenceSquared(disabledColor, backgroundColor) < minColorContrastValue)
1316         return textColor;
1317     
1318     return disabledColor;
1319 }
1320
1321 void RenderTheme::setCustomFocusRingColor(const Color& c)
1322 {
1323     customFocusRingColor() = c;
1324 }
1325
1326 Color RenderTheme::focusRingColor()
1327 {
1328     return customFocusRingColor().isValid() ? customFocusRingColor() : defaultTheme()->platformFocusRingColor();
1329 }
1330
1331 String RenderTheme::fileListDefaultLabel(bool multipleFilesAllowed) const
1332 {
1333     if (multipleFilesAllowed)
1334         return fileButtonNoFilesSelectedLabel();
1335     return fileButtonNoFileSelectedLabel();
1336 }
1337
1338 String RenderTheme::fileListNameForWidth(const FileList* fileList, const FontCascade& font, int width, bool multipleFilesAllowed) const
1339 {
1340     if (width <= 0)
1341         return String();
1342
1343     String string;
1344     if (fileList->isEmpty())
1345         string = fileListDefaultLabel(multipleFilesAllowed);
1346     else if (fileList->length() == 1)
1347         string = fileList->item(0)->name();
1348     else
1349         return StringTruncator::rightTruncate(multipleFileUploadText(fileList->length()), width, font, StringTruncator::EnableRoundingHacks);
1350
1351     return StringTruncator::centerTruncate(string, width, font, StringTruncator::EnableRoundingHacks);
1352 }
1353
1354 } // namespace WebCore