Fix the issue that Web Audio test case fails on PR3.
[framework/web/webkit-efl.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 "StringTruncator.h"
45 #include "TextControlInnerElements.h"
46
47 #if ENABLE(METER_ELEMENT)
48 #include "HTMLMeterElement.h"
49 #include "RenderMeter.h"
50 #endif
51
52 #if ENABLE(INPUT_SPEECH)
53 #include "RenderInputSpeech.h"
54 #endif
55
56 #if ENABLE(DATALIST_ELEMENT)
57 #include "ElementShadow.h"
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,
84                               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() == RUN_IN || 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         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 adjustSearchFieldDecorationStyle(styleResolver, style, e);
236         case SearchFieldResultsDecorationPart:
237             return adjustSearchFieldResultsDecorationStyle(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 paintSearchFieldDecoration(o, paintInfo, r);
379         case SearchFieldResultsDecorationPart:
380             return paintSearchFieldResultsDecoration(o, paintInfo, r);
381         case SearchFieldResultsButtonPart:
382             return paintSearchFieldResultsButton(o, paintInfo, r);
383 #if ENABLE(INPUT_SPEECH)
384         case InputSpeechButtonPart:
385             return paintInputFieldSpeechButton(o, paintInfo, r);
386 #endif
387         default:
388             break;
389     }
390
391     return true; // We don't support the appearance, so let the normal background/border paint.
392 }
393
394 bool RenderTheme::paintBorderOnly(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
395 {
396     if (paintInfo.context->paintingDisabled())
397         return false;
398
399     // Call the appropriate paint method based off the appearance value.
400     switch (o->style()->appearance()) {
401         case TextFieldPart:
402             return paintTextField(o, paintInfo, r);
403         case ListboxPart:
404         case TextAreaPart:
405             return paintTextArea(o, paintInfo, r);
406         case MenulistButtonPart:
407         case SearchFieldPart:
408             return true;
409         case CheckboxPart:
410         case RadioPart:
411         case PushButtonPart:
412         case SquareButtonPart:
413         case DefaultButtonPart:
414         case ButtonPart:
415         case MenulistPart:
416 #if ENABLE(METER_ELEMENT)
417         case MeterPart:
418         case RelevancyLevelIndicatorPart:
419         case ContinuousCapacityLevelIndicatorPart:
420         case DiscreteCapacityLevelIndicatorPart:
421         case RatingLevelIndicatorPart:
422 #endif
423 #if ENABLE(PROGRESS_ELEMENT)
424         case ProgressBarPart:
425 #endif
426         case SliderHorizontalPart:
427         case SliderVerticalPart:
428         case SliderThumbHorizontalPart:
429         case SliderThumbVerticalPart:
430         case SearchFieldCancelButtonPart:
431         case SearchFieldDecorationPart:
432         case SearchFieldResultsDecorationPart:
433         case SearchFieldResultsButtonPart:
434 #if ENABLE(INPUT_SPEECH)
435         case InputSpeechButtonPart:
436 #endif
437         default:
438             break;
439     }
440
441     return false;
442 }
443
444 bool RenderTheme::paintDecorations(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
445 {
446     if (paintInfo.context->paintingDisabled())
447         return false;
448
449     // Call the appropriate paint method based off the appearance value.
450     switch (o->style()->appearance()) {
451         case MenulistButtonPart:
452             return paintMenuListButton(o, paintInfo, r);
453         case TextFieldPart:
454         case TextAreaPart:
455         case ListboxPart:
456         case CheckboxPart:
457         case RadioPart:
458         case PushButtonPart:
459         case SquareButtonPart:
460         case DefaultButtonPart:
461         case ButtonPart:
462         case MenulistPart:
463 #if ENABLE(METER_ELEMENT)
464         case MeterPart:
465         case RelevancyLevelIndicatorPart:
466         case ContinuousCapacityLevelIndicatorPart:
467         case DiscreteCapacityLevelIndicatorPart:
468         case RatingLevelIndicatorPart:
469 #endif
470 #if ENABLE(PROGRESS_ELEMENT)
471         case ProgressBarPart:
472 #endif
473         case SliderHorizontalPart:
474         case SliderVerticalPart:
475         case SliderThumbHorizontalPart:
476         case SliderThumbVerticalPart:
477         case SearchFieldPart:
478         case SearchFieldCancelButtonPart:
479         case SearchFieldDecorationPart:
480         case SearchFieldResultsDecorationPart:
481         case SearchFieldResultsButtonPart:
482 #if ENABLE(INPUT_SPEECH)
483         case InputSpeechButtonPart:
484 #endif
485         default:
486             break;
487     }
488
489     return false;
490 }
491
492 #if ENABLE(VIDEO)
493
494 String RenderTheme::formatMediaControlsTime(float time) const
495 {
496     if (!isfinite(time))
497         time = 0;
498     int seconds = (int)fabsf(time);
499     int hours = seconds / (60 * 60);
500     int minutes = (seconds / 60) % 60;
501     seconds %= 60;
502     if (hours) {
503         if (hours > 9)
504             return String::format("%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
505
506         return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
507     }
508
509     return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds);
510 }
511
512 String RenderTheme::formatMediaControlsCurrentTime(float currentTime, float /*duration*/) const
513 {
514     return formatMediaControlsTime(currentTime);
515 }
516
517 String RenderTheme::formatMediaControlsRemainingTime(float currentTime, float duration) const
518 {
519     return formatMediaControlsTime(currentTime - duration);
520 }
521
522 IntPoint RenderTheme::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const IntSize& size) const
523 {
524     int y = -size.height();
525     FloatPoint absPoint = muteButtonBox->localToAbsolute(FloatPoint(muteButtonBox->pixelSnappedOffsetLeft(), y), true, true);
526     if (absPoint.y() < 0)
527         y = muteButtonBox->height();
528     return IntPoint(0, y);
529 }
530
531 #endif
532
533 Color RenderTheme::activeSelectionBackgroundColor() const
534 {
535     if (!m_activeSelectionBackgroundColor.isValid())
536         m_activeSelectionBackgroundColor = platformActiveSelectionBackgroundColor().blendWithWhite();
537     return m_activeSelectionBackgroundColor;
538 }
539
540 Color RenderTheme::inactiveSelectionBackgroundColor() const
541 {
542     if (!m_inactiveSelectionBackgroundColor.isValid())
543         m_inactiveSelectionBackgroundColor = platformInactiveSelectionBackgroundColor().blendWithWhite();
544     return m_inactiveSelectionBackgroundColor;
545 }
546
547 Color RenderTheme::activeSelectionForegroundColor() const
548 {
549     if (!m_activeSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
550         m_activeSelectionForegroundColor = platformActiveSelectionForegroundColor();
551     return m_activeSelectionForegroundColor;
552 }
553
554 Color RenderTheme::inactiveSelectionForegroundColor() const
555 {
556     if (!m_inactiveSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
557         m_inactiveSelectionForegroundColor = platformInactiveSelectionForegroundColor();
558     return m_inactiveSelectionForegroundColor;
559 }
560
561 Color RenderTheme::activeListBoxSelectionBackgroundColor() const
562 {
563     if (!m_activeListBoxSelectionBackgroundColor.isValid())
564         m_activeListBoxSelectionBackgroundColor = platformActiveListBoxSelectionBackgroundColor();
565     return m_activeListBoxSelectionBackgroundColor;
566 }
567
568 Color RenderTheme::inactiveListBoxSelectionBackgroundColor() const
569 {
570     if (!m_inactiveListBoxSelectionBackgroundColor.isValid())
571         m_inactiveListBoxSelectionBackgroundColor = platformInactiveListBoxSelectionBackgroundColor();
572     return m_inactiveListBoxSelectionBackgroundColor;
573 }
574
575 Color RenderTheme::activeListBoxSelectionForegroundColor() const
576 {
577     if (!m_activeListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
578         m_activeListBoxSelectionForegroundColor = platformActiveListBoxSelectionForegroundColor();
579     return m_activeListBoxSelectionForegroundColor;
580 }
581
582 Color RenderTheme::inactiveListBoxSelectionForegroundColor() const
583 {
584     if (!m_inactiveListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
585         m_inactiveListBoxSelectionForegroundColor = platformInactiveListBoxSelectionForegroundColor();
586     return m_inactiveListBoxSelectionForegroundColor;
587 }
588
589 Color RenderTheme::platformActiveSelectionBackgroundColor() const
590 {
591     // Use a blue color by default if the platform theme doesn't define anything.
592     return Color(0, 0, 255);
593 }
594
595 Color RenderTheme::platformActiveSelectionForegroundColor() const
596 {
597     // Use a white color by default if the platform theme doesn't define anything.
598     return Color::white;
599 }
600
601 Color RenderTheme::platformInactiveSelectionBackgroundColor() const
602 {
603     // Use a grey color by default if the platform theme doesn't define anything.
604     // This color matches Firefox's inactive color.
605     return Color(176, 176, 176);
606 }
607
608 Color RenderTheme::platformInactiveSelectionForegroundColor() const
609 {
610     // Use a black color by default.
611     return Color::black;
612 }
613
614 Color RenderTheme::platformActiveListBoxSelectionBackgroundColor() const
615 {
616     return platformActiveSelectionBackgroundColor();
617 }
618
619 Color RenderTheme::platformActiveListBoxSelectionForegroundColor() const
620 {
621     return platformActiveSelectionForegroundColor();
622 }
623
624 Color RenderTheme::platformInactiveListBoxSelectionBackgroundColor() const
625 {
626     return platformInactiveSelectionBackgroundColor();
627 }
628
629 Color RenderTheme::platformInactiveListBoxSelectionForegroundColor() const
630 {
631     return platformInactiveSelectionForegroundColor();
632 }
633
634 #if ENABLE(CALENDAR_PICKER)
635 CString RenderTheme::extraCalendarPickerStyleSheet()
636 {
637     return CString();
638 }
639 #endif
640
641 LayoutUnit RenderTheme::baselinePosition(const RenderObject* o) const
642 {
643     if (!o->isBox())
644         return 0;
645
646     const RenderBox* box = toRenderBox(o);
647
648 #if USE(NEW_THEME)
649     return box->height() + box->marginTop() + m_theme->baselinePositionAdjustment(o->style()->appearance()) * o->style()->effectiveZoom();
650 #else
651     return box->height() + box->marginTop();
652 #endif
653 }
654
655 bool RenderTheme::isControlContainer(ControlPart appearance) const
656 {
657     // There are more leaves than this, but we'll patch this function as we add support for
658     // more controls.
659     return appearance != CheckboxPart && appearance != RadioPart;
660 }
661
662 bool RenderTheme::isControlStyled(const RenderStyle* style, const BorderData& border, const FillLayer& background,
663                                   const Color& backgroundColor) const
664 {
665     switch (style->appearance()) {
666         case PushButtonPart:
667         case SquareButtonPart:
668         case DefaultButtonPart:
669         case ButtonPart:
670         case ListboxPart:
671         case MenulistPart:
672         case ProgressBarPart:
673         case MeterPart:
674         case RelevancyLevelIndicatorPart:
675         case ContinuousCapacityLevelIndicatorPart:
676         case DiscreteCapacityLevelIndicatorPart:
677         case RatingLevelIndicatorPart:
678 #if ENABLE(TIZEN_SEARCH_FIELD_STYLE)
679         case SearchFieldPart:
680 #else
681         // FIXME: Uncomment this when making search fields style-able.
682         // case SearchFieldPart:
683 #endif
684         case TextFieldPart:
685         case TextAreaPart:
686             // Test the style to see if the UA border and background match.
687             return (style->border() != border ||
688                     *style->backgroundLayers() != background ||
689                     style->visitedDependentColor(CSSPropertyBackgroundColor) != backgroundColor);
690         default:
691             return false;
692     }
693 }
694
695 void RenderTheme::adjustRepaintRect(const RenderObject* o, IntRect& r)
696 {
697 #if USE(NEW_THEME)
698     m_theme->inflateControlPaintRect(o->style()->appearance(), controlStatesForRenderer(o), r, o->style()->effectiveZoom());
699 #endif
700 }
701
702 bool RenderTheme::supportsFocusRing(const RenderStyle* style) const
703 {
704     return (style->hasAppearance() && style->appearance() != TextFieldPart && style->appearance() != TextAreaPart && style->appearance() != MenulistButtonPart && style->appearance() != ListboxPart);
705 }
706
707 bool RenderTheme::stateChanged(RenderObject* o, ControlState state) const
708 {
709     // Default implementation assumes the controls don't respond to changes in :hover state
710     if (state == HoverState && !supportsHover(o->style()))
711         return false;
712
713     // Assume pressed state is only responded to if the control is enabled.
714     if (state == PressedState && !isEnabled(o))
715         return false;
716
717     // Repaint the control.
718     o->repaint();
719     return true;
720 }
721
722 ControlStates RenderTheme::controlStatesForRenderer(const RenderObject* o) const
723 {
724     ControlStates result = 0;
725     if (isHovered(o)) {
726         result |= HoverState;
727         if (isSpinUpButtonPartHovered(o))
728             result |= SpinUpState;
729     }
730     if (isPressed(o)) {
731         result |= PressedState;
732         if (isSpinUpButtonPartPressed(o))
733             result |= SpinUpState;
734     }
735     if (isFocused(o) && o->style()->outlineStyleIsAuto())
736         result |= FocusState;
737     if (isEnabled(o))
738         result |= EnabledState;
739     if (isChecked(o))
740         result |= CheckedState;
741     if (isReadOnlyControl(o))
742         result |= ReadOnlyState;
743     if (isDefault(o))
744         result |= DefaultState;
745     if (!isActive(o))
746         result |= WindowInactiveState;
747     if (isIndeterminate(o))
748         result |= IndeterminateState;
749     return result;
750 }
751
752 bool RenderTheme::isActive(const RenderObject* o) const
753 {
754     Node* node = o->node();
755     if (!node)
756         return false;
757
758     Frame* frame = node->document()->frame();
759     if (!frame)
760         return false;
761
762     Page* page = frame->page();
763     if (!page)
764         return false;
765
766     return page->focusController()->isActive();
767 }
768
769 bool RenderTheme::isChecked(const RenderObject* o) const
770 {
771     if (!o->node())
772         return false;
773
774     HTMLInputElement* inputElement = o->node()->toInputElement();
775     if (!inputElement)
776         return false;
777
778     return inputElement->shouldAppearChecked();
779 }
780
781 bool RenderTheme::isIndeterminate(const RenderObject* o) const
782 {
783     if (!o->node())
784         return false;
785
786     HTMLInputElement* inputElement = o->node()->toInputElement();
787     if (!inputElement)
788         return false;
789
790     return inputElement->isIndeterminate();
791 }
792
793 bool RenderTheme::isEnabled(const RenderObject* o) const
794 {
795     Node* node = o->node();
796     if (!node || !node->isElementNode())
797         return true;
798     return static_cast<Element*>(node)->isEnabledFormControl();
799 }
800
801 bool RenderTheme::isFocused(const RenderObject* o) const
802 {
803     Node* node = o->node();
804     if (!node)
805         return false;
806
807     node = node->focusDelegate();
808     Document* document = node->document();
809     Frame* frame = document->frame();
810     return node == document->focusedNode() && frame && frame->selection()->isFocusedAndActive();
811 }
812
813 bool RenderTheme::isPressed(const RenderObject* o) const
814 {
815     if (!o->node())
816         return false;
817     return o->node()->active();
818 }
819
820 bool RenderTheme::isSpinUpButtonPartPressed(const RenderObject* o) const
821 {
822     Node* node = o->node();
823     if (!node || !node->active() || !node->isElementNode()
824         || !static_cast<Element*>(node)->isSpinButtonElement())
825         return false;
826     SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
827     return element->upDownState() == SpinButtonElement::Up;
828 }
829
830 bool RenderTheme::isReadOnlyControl(const RenderObject* o) const
831 {
832     Node* node = o->node();
833     if (!node || !node->isElementNode())
834         return false;
835     return static_cast<Element*>(node)->isReadOnlyFormControl();
836 }
837
838 bool RenderTheme::isHovered(const RenderObject* o) const
839 {
840     Node* node = o->node();
841     if (!node)
842         return false;
843     if (!node->isElementNode() || !static_cast<Element*>(node)->isSpinButtonElement())
844         return node->hovered();
845     SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
846     return element->hovered() && element->upDownState() != SpinButtonElement::Indeterminate;
847 }
848
849 bool RenderTheme::isSpinUpButtonPartHovered(const RenderObject* o) const
850 {
851     Node* node = o->node();
852     if (!node || !node->isElementNode() || !static_cast<Element*>(node)->isSpinButtonElement())
853         return false;
854     SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
855     return element->upDownState() == SpinButtonElement::Up;
856 }
857
858 bool RenderTheme::isDefault(const RenderObject* o) const
859 {
860     // A button should only have the default appearance if the page is active
861     if (!isActive(o))
862         return false;
863
864     if (!o->document())
865         return false;
866
867     Settings* settings = o->document()->settings();
868     if (!settings || !settings->inApplicationChromeMode())
869         return false;
870     
871     return o->style()->appearance() == DefaultButtonPart;
872 }
873
874 #if !USE(NEW_THEME)
875
876 void RenderTheme::adjustCheckboxStyle(StyleResolver*, RenderStyle* style, Element*) const
877 {
878     // A summary of the rules for checkbox designed to match WinIE:
879     // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
880     // font-size - not honored (control has no text), but we use it to decide which control size to use.
881     setCheckboxSize(style);
882
883     // padding - not honored by WinIE, needs to be removed.
884     style->resetPadding();
885
886     // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
887     // for now, we will not honor it.
888     style->resetBorder();
889
890     style->setBoxShadow(nullptr);
891 }
892
893 void RenderTheme::adjustRadioStyle(StyleResolver*, RenderStyle* style, Element*) const
894 {
895     // A summary of the rules for checkbox designed to match WinIE:
896     // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
897     // font-size - not honored (control has no text), but we use it to decide which control size to use.
898     setRadioSize(style);
899
900     // padding - not honored by WinIE, needs to be removed.
901     style->resetPadding();
902
903     // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
904     // for now, we will not honor it.
905     style->resetBorder();
906
907     style->setBoxShadow(nullptr);
908 }
909
910 void RenderTheme::adjustButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
911 {
912     // Most platforms will completely honor all CSS, and so we have no need to adjust the style
913     // at all by default.  We will still allow the theme a crack at setting up a desired vertical size.
914     setButtonSize(style);
915 }
916
917 void RenderTheme::adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle*, Element*) const
918 {
919 }
920 #endif
921
922 void RenderTheme::adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const
923 {
924 }
925
926 void RenderTheme::adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const
927 {
928 }
929
930 void RenderTheme::adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const
931 {
932 }
933
934 #if ENABLE(INPUT_SPEECH)
935 void RenderTheme::adjustInputFieldSpeechButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
936 {
937     RenderInputSpeech::adjustInputFieldSpeechButtonStyle(styleResolver, style, element);
938 }
939
940 bool RenderTheme::paintInputFieldSpeechButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
941 {
942     return RenderInputSpeech::paintInputFieldSpeechButton(object, paintInfo, rect);
943 }
944 #endif
945
946 #if ENABLE(METER_ELEMENT)
947 void RenderTheme::adjustMeterStyle(StyleResolver*, RenderStyle* style, Element*) const
948 {
949     style->setBoxShadow(nullptr);
950 }
951
952 IntSize RenderTheme::meterSizeForBounds(const RenderMeter*, const IntRect& bounds) const
953 {
954     return bounds.size();
955 }
956
957 bool RenderTheme::supportsMeter(ControlPart) const
958 {
959     return false;
960 }
961
962 bool RenderTheme::paintMeter(RenderObject*, const PaintInfo&, const IntRect&)
963 {
964     return true;
965 }
966
967 #endif
968
969 #if ENABLE(DATALIST_ELEMENT)
970 void RenderTheme::paintSliderTicks(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect)
971 {
972     Node* node = o->node();
973     if (!node)
974         return;
975
976     HTMLInputElement* input = node->toInputElement();
977     if (!input)
978         return;
979
980     HTMLDataListElement* dataList = static_cast<HTMLDataListElement*>(input->list());
981     if (!dataList)
982         return;
983
984     double min = input->minimum();
985     double max = input->maximum();
986     ControlPart part = o->style()->appearance();
987     // We don't support ticks on alternate sliders like MediaVolumeSliders.
988     if (part !=  SliderHorizontalPart && part != SliderVerticalPart)
989         return;
990     bool isHorizontal = part ==  SliderHorizontalPart;
991
992     IntSize thumbSize;
993     RenderObject* thumbRenderer = input->sliderThumbElement()->renderer();
994     if (thumbRenderer) {
995         RenderStyle* thumbStyle = thumbRenderer->style();
996         int thumbWidth = thumbStyle->width().intValue();
997         int thumbHeight = thumbStyle->height().intValue();
998         thumbSize.setWidth(isHorizontal ? thumbWidth : thumbHeight);
999         thumbSize.setHeight(isHorizontal ? thumbHeight : thumbWidth);
1000     }
1001
1002     IntSize tickSize = sliderTickSize();
1003     float zoomFactor = o->style()->effectiveZoom();
1004     FloatRect tickRect;
1005     int tickRegionMargin = (thumbSize.width() - tickSize.width()) / 2.0;
1006     int tickRegionSideMargin = 0;
1007     int tickRegionWidth = 0;
1008     if (isHorizontal) {
1009         tickRect.setWidth(floor(tickSize.width() * zoomFactor));
1010         tickRect.setHeight(floor(tickSize.height() * zoomFactor));
1011         tickRect.setY(floor(rect.y() + rect.height() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor));
1012         tickRegionSideMargin = rect.x() + tickRegionMargin;
1013         tickRegionWidth = rect.width() - tickRegionMargin * 2 - tickSize.width() * zoomFactor;
1014     } else {
1015         tickRect.setWidth(floor(tickSize.height() * zoomFactor));
1016         tickRect.setHeight(floor(tickSize.width() * zoomFactor));
1017         tickRect.setX(floor(rect.x() + rect.width() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor));
1018         tickRegionSideMargin = rect.y() + tickRegionMargin;
1019         tickRegionWidth = rect.height() - tickRegionMargin * 2 - tickSize.width() * zoomFactor;
1020     }
1021     RefPtr<HTMLCollection> options = dataList->options();
1022     GraphicsContextStateSaver stateSaver(*paintInfo.context);
1023     paintInfo.context->setFillColor(o->style()->visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB);
1024     for (unsigned i = 0; Node* node = options->item(i); i++) {
1025         ASSERT(node->hasTagName(optionTag));
1026         HTMLOptionElement* optionElement = static_cast<HTMLOptionElement*>(node);
1027         String value = optionElement->value();
1028         if (!input->isValidValue(value))
1029             continue;
1030         double parsedValue = parseToDoubleForNumberType(input->sanitizeValue(value));
1031         double tickPosition = (parsedValue - min) / (max - min);
1032         if (!o->style()->isLeftToRightDirection())
1033             tickPosition = 1.0 - tickPosition;
1034         if (isHorizontal)
1035             tickRect.setX(floor(tickRegionSideMargin + tickRegionWidth * tickPosition));
1036         else
1037             tickRect.setY(floor(tickRegionSideMargin + tickRegionWidth * tickPosition));
1038         paintInfo.context->fillRect(tickRect);
1039     }
1040 }
1041 #endif
1042
1043 #if ENABLE(PROGRESS_ELEMENT)
1044 double RenderTheme::animationRepeatIntervalForProgressBar(RenderProgress*) const
1045 {
1046     return 0;
1047 }
1048
1049 double RenderTheme::animationDurationForProgressBar(RenderProgress*) const
1050 {
1051     return 0;
1052 }
1053
1054 void RenderTheme::adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const
1055 {
1056 }
1057 #endif
1058
1059 bool RenderTheme::shouldHaveSpinButton(HTMLInputElement* inputElement) const
1060 {
1061     return inputElement->isSteppable() && !inputElement->isRangeControl();
1062 }
1063
1064 void RenderTheme::adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const
1065 {
1066 }
1067
1068 void RenderTheme::adjustMediaControlStyle(StyleResolver*, RenderStyle*, Element*) const
1069 {
1070 }
1071
1072 void RenderTheme::adjustSliderTrackStyle(StyleResolver*, RenderStyle*, Element*) const
1073 {
1074 }
1075
1076 void RenderTheme::adjustSliderThumbStyle(StyleResolver*, RenderStyle* style, Element* element) const
1077 {
1078     adjustSliderThumbSize(style, element);
1079 }
1080
1081 void RenderTheme::adjustSliderThumbSize(RenderStyle*, Element*) const
1082 {
1083 }
1084
1085 void RenderTheme::adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const
1086 {
1087 }
1088
1089 void RenderTheme::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const
1090 {
1091 }
1092
1093 void RenderTheme::adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle*, Element*) const
1094 {
1095 }
1096
1097 void RenderTheme::adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const
1098 {
1099 }
1100
1101 void RenderTheme::adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const
1102 {
1103 }
1104
1105 void RenderTheme::platformColorsDidChange()
1106 {
1107     m_activeSelectionForegroundColor = Color();
1108     m_inactiveSelectionForegroundColor = Color();
1109     m_activeSelectionBackgroundColor = Color();
1110     m_inactiveSelectionBackgroundColor = Color();
1111
1112     m_activeListBoxSelectionForegroundColor = Color();
1113     m_inactiveListBoxSelectionForegroundColor = Color();
1114     m_activeListBoxSelectionBackgroundColor = Color();
1115     m_inactiveListBoxSelectionForegroundColor = Color();
1116
1117     Page::scheduleForcedStyleRecalcForAllPages();
1118 }
1119
1120 Color RenderTheme::systemColor(int cssValueId) const
1121 {
1122     switch (cssValueId) {
1123         case CSSValueActiveborder:
1124             return 0xFFFFFFFF;
1125         case CSSValueActivecaption:
1126             return 0xFFCCCCCC;
1127         case CSSValueAppworkspace:
1128             return 0xFFFFFFFF;
1129         case CSSValueBackground:
1130             return 0xFF6363CE;
1131         case CSSValueButtonface:
1132             return 0xFFC0C0C0;
1133         case CSSValueButtonhighlight:
1134             return 0xFFDDDDDD;
1135         case CSSValueButtonshadow:
1136             return 0xFF888888;
1137         case CSSValueButtontext:
1138             return 0xFF000000;
1139         case CSSValueCaptiontext:
1140             return 0xFF000000;
1141         case CSSValueGraytext:
1142             return 0xFF808080;
1143         case CSSValueHighlight:
1144             return 0xFFB5D5FF;
1145         case CSSValueHighlighttext:
1146             return 0xFF000000;
1147         case CSSValueInactiveborder:
1148             return 0xFFFFFFFF;
1149         case CSSValueInactivecaption:
1150             return 0xFFFFFFFF;
1151         case CSSValueInactivecaptiontext:
1152             return 0xFF7F7F7F;
1153         case CSSValueInfobackground:
1154             return 0xFFFBFCC5;
1155         case CSSValueInfotext:
1156             return 0xFF000000;
1157         case CSSValueMenu:
1158             return 0xFFC0C0C0;
1159         case CSSValueMenutext:
1160             return 0xFF000000;
1161         case CSSValueScrollbar:
1162             return 0xFFFFFFFF;
1163         case CSSValueText:
1164             return 0xFF000000;
1165         case CSSValueThreeddarkshadow:
1166             return 0xFF666666;
1167         case CSSValueThreedface:
1168             return 0xFFC0C0C0;
1169         case CSSValueThreedhighlight:
1170             return 0xFFDDDDDD;
1171         case CSSValueThreedlightshadow:
1172             return 0xFFC0C0C0;
1173         case CSSValueThreedshadow:
1174             return 0xFF888888;
1175         case CSSValueWindow:
1176             return 0xFFFFFFFF;
1177         case CSSValueWindowframe:
1178             return 0xFFCCCCCC;
1179         case CSSValueWindowtext:
1180             return 0xFF000000;
1181     }
1182     return Color();
1183 }
1184
1185 Color RenderTheme::platformActiveTextSearchHighlightColor() const
1186 {
1187     return Color(255, 150, 50); // Orange.
1188 }
1189
1190 Color RenderTheme::platformInactiveTextSearchHighlightColor() const
1191 {
1192     return Color(255, 255, 0); // Yellow.
1193 }
1194
1195 #if ENABLE(TOUCH_EVENTS)
1196 Color RenderTheme::tapHighlightColor()
1197 {
1198     return defaultTheme()->platformTapHighlightColor();
1199 }
1200 #endif
1201
1202 // Value chosen by observation. This can be tweaked.
1203 static const int minColorContrastValue = 1300;
1204 // For transparent or translucent background color, use lightening.
1205 static const int minDisabledColorAlphaValue = 128;
1206
1207 Color RenderTheme::disabledTextColor(const Color& textColor, const Color& backgroundColor) const
1208 {
1209     // The explicit check for black is an optimization for the 99% case (black on white).
1210     // This also means that black on black will turn into grey on black when disabled.
1211     Color disabledColor;
1212     if (textColor.rgb() == Color::black || backgroundColor.alpha() < minDisabledColorAlphaValue || differenceSquared(textColor, Color::white) > differenceSquared(backgroundColor, Color::white))
1213         disabledColor = textColor.light();
1214     else
1215         disabledColor = textColor.dark();
1216     
1217     // If there's not very much contrast between the disabled color and the background color,
1218     // just leave the text color alone. We don't want to change a good contrast color scheme so that it has really bad contrast.
1219     // If the the contrast was already poor, then it doesn't do any good to change it to a different poor contrast color scheme.
1220     if (differenceSquared(disabledColor, backgroundColor) < minColorContrastValue)
1221         return textColor;
1222     
1223     return disabledColor;
1224 }
1225
1226 void RenderTheme::setCustomFocusRingColor(const Color& c)
1227 {
1228     customFocusRingColor() = c;
1229 }
1230
1231 Color RenderTheme::focusRingColor()
1232 {
1233     return customFocusRingColor().isValid() ? customFocusRingColor() : defaultTheme()->platformFocusRingColor();
1234 }
1235
1236 String RenderTheme::fileListDefaultLabel(bool multipleFilesAllowed) const
1237 {
1238     if (multipleFilesAllowed)
1239         return fileButtonNoFilesSelectedLabel();
1240     return fileButtonNoFileSelectedLabel();
1241 }
1242
1243 String RenderTheme::fileListNameForWidth(const FileList* fileList, const Font& font, int width, bool multipleFilesAllowed) const
1244 {
1245     if (width <= 0)
1246         return String();
1247
1248     String string;
1249     if (fileList->isEmpty())
1250         string = fileListDefaultLabel(multipleFilesAllowed);
1251     else if (fileList->length() == 1)
1252         string = fileList->item(0)->name();
1253     else
1254         return StringTruncator::rightTruncate(multipleFileUploadText(fileList->length()), width, font, StringTruncator::EnableRoundingHacks);
1255
1256     return StringTruncator::centerTruncate(string, width, font, StringTruncator::EnableRoundingHacks);
1257 }
1258
1259 } // namespace WebCore