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