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