Purge PassRefPtr in WebCore/rendering
[WebKit-https.git] / Source / WebCore / rendering / RenderThemeSafari.cpp
1 /*
2  * Copyright (C) 2007, 2008, 2009, 2013 Apple Inc.
3  * Copyright (C) 2009 Kenneth Rohde Christiansen
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  */
21
22 #include "config.h"
23 #include "RenderThemeSafari.h"
24 #include "RenderThemeWin.h"
25 #include "Settings.h"
26
27 #if USE(SAFARI_THEME)
28
29 #include "CSSFontSelector.h"
30 #include "CSSValueKeywords.h"
31 #include "Document.h"
32 #include "Element.h"
33 #include "FloatRoundedRect.h"
34 #include "Frame.h"
35 #include "FrameView.h"
36 #include "GraphicsContextCG.h"
37 #include "HTMLInputElement.h"
38 #include "HTMLMediaElement.h"
39 #include "HTMLMeterElement.h"
40 #include "HTMLNames.h"
41 #include "PaintInfo.h"
42 #include "RenderMediaControls.h"
43 #include "RenderMeter.h"
44 #include "RenderSlider.h"
45 #include "RenderView.h"
46 #include "SoftLinking.h"
47 #include "StyleResolver.h"
48 #include "UserAgentStyleSheets.h"
49 #include "WebCoreBundleWin.h"
50 #include <CoreGraphics/CoreGraphics.h>
51 #include <wtf/RetainPtr.h>
52
53 using std::min;
54
55 // FIXME: The platform-independent code in this class should be factored out and merged with RenderThemeMac. 
56  
57 namespace WebCore {
58
59 using namespace HTMLNames;
60 using namespace SafariTheme;
61
62 enum {
63     topMargin,
64     rightMargin,
65     bottomMargin,
66     leftMargin
67 };
68
69 enum {
70     topPadding,
71     rightPadding,
72     bottomPadding,
73     leftPadding
74 };
75
76 Ref<RenderTheme> RenderThemeSafari::create()
77 {
78     return adoptRef(*new RenderThemeSafari);
79 }
80
81 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
82 {
83     static RenderTheme& safariTheme = RenderThemeSafari::create().leakRef();
84     static RenderTheme& windowsTheme = RenderThemeWin::create().leakRef();
85
86     // FIXME: This is called before Settings has been initialized by WebKit, so will return a
87     // potentially wrong answer the very first time it's called (see
88     // <https://bugs.webkit.org/show_bug.cgi?id=26493>).
89     if (Settings::shouldPaintNativeControls()) {
90         RenderTheme::setCustomFocusRingColor(safariTheme->platformFocusRingColor());
91         return &windowsTheme;
92     }
93     return &safariTheme;
94 }
95
96 #ifdef DEBUG_ALL
97 SOFT_LINK_DEBUG_LIBRARY(SafariTheme)
98 #else
99 SOFT_LINK_LIBRARY(SafariTheme)
100 #endif
101
102 SOFT_LINK(SafariTheme, paintThemePart, void, __stdcall, (ThemePart part, CGContextRef context, const CGRect& rect, NSControlSize size, ThemeControlState state), (part, context, rect, size, state))
103 #if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2
104 SOFT_LINK(SafariTheme, STPaintProgressIndicator, void, APIENTRY, (ProgressIndicatorType type, CGContextRef context, const CGRect& rect, NSControlSize size, ThemeControlState state, float value), (type, context, rect, size, state, value))
105 #endif
106 SOFT_LINK_OPTIONAL(SafariTheme, STCopyThemeColor, CGColorRef, APIENTRY, (unsigned color, SafariTheme::ThemeControlState));
107
108 static const unsigned stFocusRingColorID = 4;
109
110 static const unsigned aquaFocusRingColor = 0xFF7DADD9;
111
112 static RGBA32 makeRGBAFromCGColor(CGColorRef color)
113 {
114     const CGFloat* components = CGColorGetComponents(color);
115     return makeRGBA(255 * components[0], 255 * components[1], 255 * components[2], 255 * components[3]);
116 }
117
118 ThemeControlState RenderThemeSafari::determineState(const RenderObject& o) const
119 {
120     ThemeControlState result = 0;
121     if (isActive(o))
122         result |= SafariTheme::ActiveState;
123     if (isEnabled(o) && !isReadOnlyControl(o))
124         result |= SafariTheme::EnabledState;
125     if (isPressed(o))
126         result |= SafariTheme::PressedState;
127     if (isChecked(o))
128         result |= SafariTheme::CheckedState;
129     if (isIndeterminate(o))
130         result |= SafariTheme::IndeterminateCheckedState;
131     if (isFocused(o))
132         result |= SafariTheme::FocusedState;
133     if (isDefault(o))
134         result |= SafariTheme::DefaultState;
135     return result;
136 }
137
138 static NSControlSize controlSizeFromRect(const IntRect& rect, const IntSize sizes[])
139 {
140     if (sizes[NSRegularControlSize].height() == rect.height())
141         return NSRegularControlSize;
142     else if (sizes[NSMiniControlSize].height() == rect.height())
143         return NSMiniControlSize;
144     
145     return NSSmallControlSize;
146 }
147
148 RenderThemeSafari::RenderThemeSafari()
149 {
150 }
151
152 RenderThemeSafari::~RenderThemeSafari()
153 {
154 }
155
156 Color RenderThemeSafari::platformActiveSelectionBackgroundColor() const
157 {
158     return Color(181, 213, 255);
159 }
160
161 Color RenderThemeSafari::platformInactiveSelectionBackgroundColor() const
162 {
163     return Color(212, 212, 212);
164 }
165
166 Color RenderThemeSafari::activeListBoxSelectionBackgroundColor() const
167 {
168     // FIXME: This should probably just be a darker version of the platformActiveSelectionBackgroundColor
169     return Color(56, 117, 215);
170 }
171
172 Color RenderThemeSafari::platformFocusRingColor() const
173 {
174     static Color focusRingColor;
175
176     if (!focusRingColor.isValid()) {
177         if (STCopyThemeColorPtr()) {
178             RetainPtr<CGColorRef> color = adoptCF(STCopyThemeColorPtr()(stFocusRingColorID, SafariTheme::ActiveState));
179             focusRingColor = makeRGBAFromCGColor(color.get());
180         }
181         if (!focusRingColor.isValid())
182             focusRingColor = aquaFocusRingColor;
183     }
184
185     return focusRingColor;
186 }
187
188 static float systemFontSizeForControlSize(NSControlSize controlSize)
189 {
190     static float sizes[] = { 13.0f, 11.0f, 9.0f };
191     
192     return sizes[controlSize];
193 }
194
195 void RenderThemeSafari::updateCachedSystemFontDescription(CSSValueID valueID, FontDescription& fontDescription) const
196 {
197     float fontSize;
198     switch (valueID) {
199     case CSSValueSmallCaption:
200         fontSize = systemFontSizeForControlSize(NSSmallControlSize);
201         break;
202     case CSSValueMenu:
203         fontSize = systemFontSizeForControlSize(NSRegularControlSize);
204         break;
205     case CSSValueStatusBar:
206         fontSize = 10.0f;
207         break;
208     case CSSValueWebkitMiniControl:
209         fontSize = systemFontSizeForControlSize(NSMiniControlSize);
210         break;
211     case CSSValueWebkitSmallControl:
212         fontSize = systemFontSizeForControlSize(NSSmallControlSize);
213         break;
214     case CSSValueWebkitControl:
215         fontSize = systemFontSizeForControlSize(NSRegularControlSize);
216         break;
217     default:
218         fontSize = 13.0f;
219     }
220
221     if (!fontSize)
222         return;
223
224     fontDescription.setIsAbsoluteSize(true);
225     fontDescription.setOneFamily("Lucida Grande");
226     fontDescription.setSpecifiedSize(fontSize);
227     fontDescription.setWeight(FontWeightNormal);
228     fontDescription.setItalic(FontItalicOff);
229 }
230
231 bool RenderThemeSafari::isControlStyled(const RenderStyle& style, const BorderData& border,
232                                      const FillLayer& background, const Color& backgroundColor) const
233 {
234     // If we didn't find SafariTheme.dll we won't be able to paint any themed controls.
235     if (!SafariThemeLibrary())
236         return true;
237
238     if (style.appearance() == TextFieldPart || style.appearance() == TextAreaPart || style.appearance() == ListboxPart)
239         return style.border() != border;
240     return RenderTheme::isControlStyled(style, border, background, backgroundColor);
241 }
242
243 void RenderThemeSafari::adjustRepaintRect(const RenderObject& o, IntRect& r)
244 {
245     NSControlSize controlSize = controlSizeForFont(o.style());
246
247     switch (o.style().appearance()) {
248         case CheckboxPart: {
249             // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
250             // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
251             r = inflateRect(r, checkboxSizes()[controlSize], checkboxMargins(controlSize));
252             break;
253         }
254         case RadioPart: {
255             // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
256             // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
257             r = inflateRect(r, radioSizes()[controlSize], radioMargins(controlSize));
258             break;
259         }
260         case PushButtonPart:
261         case DefaultButtonPart:
262         case ButtonPart: {
263             // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
264             // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
265             if (r.height() <= buttonSizes()[NSRegularControlSize].height())
266                 r = inflateRect(r, buttonSizes()[controlSize], buttonMargins(controlSize));
267             break;
268         }
269         case MenulistPart: {
270             r = inflateRect(r, popupButtonSizes()[controlSize], popupButtonMargins(controlSize));
271             break;
272         }
273         default:
274             break;
275     }
276 }
277
278 IntRect RenderThemeSafari::inflateRect(const IntRect& r, const IntSize& size, const int* margins) const
279 {
280     // Only do the inflation if the available width/height are too small.  Otherwise try to
281     // fit the glow/check space into the available box's width/height.
282     int widthDelta = r.width() - (size.width() + margins[leftMargin] + margins[rightMargin]);
283     int heightDelta = r.height() - (size.height() + margins[topMargin] + margins[bottomMargin]);
284     IntRect result(r);
285     if (widthDelta < 0) {
286         result.setX(result.x() - margins[leftMargin]);
287         result.setWidth(result.width() - widthDelta);
288     }
289     if (heightDelta < 0) {
290         result.setY(result.y() - margins[topMargin]);
291         result.setHeight(result.height() - heightDelta);
292     }
293     return result;
294 }
295
296 int RenderThemeSafari::baselinePosition(const RenderObject& renderer) const
297 {
298     if (!is<RenderBox>(renderer))
299         return 0;
300
301     if (renderer.style().appearance() == CheckboxPart || renderer.style().appearance() == RadioPart) {
302         const auto& box = downcast<RenderBox>(renderer);
303         return box.marginTop() + box.height() - 2; // The baseline is 2px up from the bottom of the checkbox/radio in AppKit.
304     }
305
306     return RenderTheme::baselinePosition(renderer);
307 }
308
309 bool RenderThemeSafari::controlSupportsTints(const RenderObject& o) const
310 {
311     if (!isEnabled(o))
312         return false;
313
314     // Checkboxes only have tint when checked.
315     if (o.style().appearance() == CheckboxPart)
316         return isChecked(o);
317
318     // For now assume other controls have tint if enabled.
319     return true;
320 }
321
322 NSControlSize RenderThemeSafari::controlSizeForFont(RenderStyle& style) const
323 {
324     int fontSize = style.fontSize();
325     if (fontSize >= 16)
326         return NSRegularControlSize;
327     if (fontSize >= 11)
328         return NSSmallControlSize;
329     return NSMiniControlSize;
330 }
331 /*
332 void RenderThemeSafari::setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minSize)
333 {
334     NSControlSize size;
335     if (minSize.width() >= sizes[NSRegularControlSize].width() &&
336         minSize.height() >= sizes[NSRegularControlSize].height())
337         size = NSRegularControlSize;
338     else if (minSize.width() >= sizes[NSSmallControlSize].width() &&
339              minSize.height() >= sizes[NSSmallControlSize].height())
340         size = NSSmallControlSize;
341     else
342         size = NSMiniControlSize;
343     if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same.
344         [cell setControlSize:size];
345 }
346 */
347 IntSize RenderThemeSafari::sizeForFont(RenderStyle& style, const IntSize* sizes) const
348 {
349     return sizes[controlSizeForFont(style)];
350 }
351
352 IntSize RenderThemeSafari::sizeForSystemFont(RenderStyle& style, const IntSize* sizes) const
353 {
354     return sizes[controlSizeForSystemFont(style)];
355 }
356
357 void RenderThemeSafari::setSizeFromFont(RenderStyle& style, const IntSize* sizes) const
358 {
359     // FIXME: Check is flawed, since it doesn't take min-width/max-width into account.
360     IntSize size = sizeForFont(style, sizes);
361     if (style.width().isIntrinsicOrAuto() && size.width() > 0)
362         style.setWidth(Length(size.width(), Fixed));
363     if (style.height().isAuto() && size.height() > 0)
364         style.setHeight(Length(size.height(), Fixed));
365 }
366
367 void RenderThemeSafari::setFontFromControlSize(StyleResolver& styleResolver, RenderStyle& style, NSControlSize controlSize) const
368 {
369     FontDescription fontDescription;
370     fontDescription.setIsAbsoluteSize(true);
371
372     float fontSize = systemFontSizeForControlSize(controlSize);
373     fontDescription.setOneFamily("Lucida Grande");
374     fontDescription.setComputedSize(fontSize);
375     fontDescription.setSpecifiedSize(fontSize);
376
377     // Reset line height
378     style.setLineHeight(RenderStyle::initialLineHeight());
379
380     if (style.setFontDescription(fontDescription))
381         style.fontCascade().update(&styleResolver.document().fontSelector());
382 }
383
384 NSControlSize RenderThemeSafari::controlSizeForSystemFont(RenderStyle& style) const
385 {
386     int fontSize = style.fontSize();
387     if (fontSize >= 13)
388         return NSRegularControlSize;
389     if (fontSize >= 11)
390         return NSSmallControlSize;
391     return NSMiniControlSize;
392 }
393
394 bool RenderThemeSafari::paintCheckbox(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
395 {
396     ASSERT(SafariThemeLibrary());
397
398     NSControlSize controlSize = controlSizeForFont(o.style());
399
400     IntRect inflatedRect = inflateRect(r, checkboxSizes()[controlSize], checkboxMargins(controlSize));  
401     paintThemePart(SafariTheme::CheckboxPart, paintInfo.context->platformContext(), inflatedRect, controlSize, determineState(o));
402
403     return false;
404 }
405
406 const IntSize* RenderThemeSafari::checkboxSizes() const
407 {
408     static const IntSize sizes[3] = { IntSize(14, 14), IntSize(12, 12), IntSize(10, 10) };
409     return sizes;
410 }
411
412 const int* RenderThemeSafari::checkboxMargins(NSControlSize controlSize) const
413 {
414     static const int margins[3][4] =
415     {
416         { 2, 2, 2, 2 },
417         { 2, 2, 2, 1 },
418         { 1, 0, 0, 0 },
419     };
420     return margins[controlSize];
421 }
422
423 void RenderThemeSafari::setCheckboxSize(RenderStyle& style) const
424 {
425     // If the width and height are both specified, then we have nothing to do.
426     if (!style.width().isIntrinsicOrAuto() && !style.height().isAuto())
427         return;
428
429     // Use the font size to determine the intrinsic width of the control.
430     setSizeFromFont(style, checkboxSizes());
431 }
432
433 bool RenderThemeSafari::paintRadio(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
434 {
435     ASSERT(SafariThemeLibrary());
436
437     NSControlSize controlSize = controlSizeForFont(o.style());
438  
439     IntRect inflatedRect = inflateRect(r, radioSizes()[controlSize], radioMargins(controlSize));    
440     paintThemePart(RadioButtonPart, paintInfo.context->platformContext(), inflatedRect, controlSize, determineState(o));
441
442     return false;
443 }
444
445 const IntSize* RenderThemeSafari::radioSizes() const
446 {
447     static const IntSize sizes[3] = { IntSize(14, 15), IntSize(12, 13), IntSize(10, 10) };
448     return sizes;
449 }
450
451 const int* RenderThemeSafari::radioMargins(NSControlSize controlSize) const
452 {
453     static const int margins[3][4] =
454     {
455         { 1, 2, 2, 2 },
456         { 0, 1, 2, 1 },
457         { 0, 0, 1, 0 },
458      };
459     return margins[controlSize];
460 }
461
462 void RenderThemeSafari::setRadioSize(RenderStyle& style) const
463 {
464     // If the width and height are both specified, then we have nothing to do.
465     if (!style.width().isIntrinsicOrAuto() && !style.height().isAuto())
466         return;
467
468     // Use the font size to determine the intrinsic width of the control.
469     setSizeFromFont(style, radioSizes());
470 }
471
472 void RenderThemeSafari::setButtonPaddingFromControlSize(RenderStyle& style, NSControlSize size) const
473 {
474     // Just use 8px.  AppKit wants to use 11px for mini buttons, but that padding is just too large
475     // for real-world Web sites (creating a huge necessary minimum width for buttons whose space is
476     // by definition constrained, since we select mini only for small cramped environments.
477     // This also guarantees the HTML4 <button> will match our rendering by default, since we're using a consistent
478     // padding.
479     const int padding = 8;
480     style.setPaddingLeft(Length(padding, Fixed));
481     style.setPaddingRight(Length(padding, Fixed));
482     style.setPaddingTop(Length(0, Fixed));
483     style.setPaddingBottom(Length(0, Fixed));
484 }
485
486 void RenderThemeSafari::adjustButtonStyle(StyleResolver& styleResolver, RenderStyle& style, Element*) const
487 {
488     // There are three appearance constants for buttons.
489     // (1) Push-button is the constant for the default Aqua system button.  Push buttons will not scale vertically and will not allow
490     // custom fonts or colors.  <input>s use this constant.  This button will allow custom colors and font weights/variants but won't
491     // scale vertically.
492     // (2) square-button is the constant for the square button.  This button will allow custom fonts and colors and will scale vertically.
493     // (3) Button is the constant that means "pick the best button as appropriate."  <button>s use this constant.  This button will
494     // also scale vertically and allow custom fonts and colors.  It will attempt to use Aqua if possible and will make this determination
495     // solely on the rectangle of the control.
496
497     // Determine our control size based off our font.
498     NSControlSize controlSize = controlSizeForFont(style);
499
500     if (style.appearance() == PushButtonPart) {
501         // Ditch the border.
502         style.resetBorder();
503
504         // Height is locked to auto.
505         style.setHeight(Length(Auto));
506
507         // White-space is locked to pre
508         style.setWhiteSpace(PRE);
509
510         // Set the button's vertical size.
511         setButtonSize(style);
512
513         // Add in the padding that we'd like to use.
514         setButtonPaddingFromControlSize(style, controlSize);
515
516         // Our font is locked to the appropriate system font size for the control.  To clarify, we first use the CSS-specified font to figure out
517         // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
518         // system font for the control size instead.
519         setFontFromControlSize(styleResolver, style, controlSize);
520     } else {
521         // Set a min-height so that we can't get smaller than the mini button.
522         style.setMinHeight(Length(15, Fixed));
523
524         // Reset the top and bottom borders.
525         style.resetBorderTop();
526         style.resetBorderBottom();
527     }
528 }
529
530 const IntSize* RenderThemeSafari::buttonSizes() const
531 {
532     static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
533     return sizes;
534 }
535
536 const int* RenderThemeSafari::buttonMargins(NSControlSize controlSize) const
537 {
538     static const int margins[3][4] =
539     {
540         { 4, 6, 7, 6 },
541         { 4, 5, 6, 5 },
542         { 0, 1, 1, 1 },
543     };
544     return margins[controlSize];
545 }
546
547 void RenderThemeSafari::setButtonSize(RenderStyle& style) const
548 {
549     // If the width and height are both specified, then we have nothing to do.
550     if (!style.width().isIntrinsicOrAuto() && !style.height().isAuto())
551         return;
552
553     // Use the font size to determine the intrinsic width of the control.
554     setSizeFromFont(style, buttonSizes());
555 }
556
557 bool RenderThemeSafari::paintButton(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
558 {
559     ASSERT(SafariThemeLibrary());
560
561     // We inflate the rect as needed to account for padding included in the cell to accommodate the button
562     // shadow.  We don't consider this part of the bounds of the control in WebKit.
563
564     NSControlSize controlSize = controlSizeFromRect(r, buttonSizes());
565     IntRect inflatedRect = r;
566
567     ThemePart part;
568     if (r.height() <= buttonSizes()[NSRegularControlSize].height()) {
569         // Push button
570         part = SafariTheme::PushButtonPart;
571
572         IntSize size = buttonSizes()[controlSize];
573         size.setWidth(r.width());
574
575         // Center the button within the available space.
576         if (inflatedRect.height() > size.height()) {
577             inflatedRect.setY(inflatedRect.y() + (inflatedRect.height() - size.height()) / 2);
578             inflatedRect.setHeight(size.height());
579         }
580
581         // Now inflate it to account for the shadow.
582         inflatedRect = inflateRect(inflatedRect, size, buttonMargins(controlSize));
583     } else
584         part = SafariTheme::SquareButtonPart;
585
586     paintThemePart(part, paintInfo.context->platformContext(), inflatedRect, controlSize, determineState(o));
587     return false;
588 }
589
590 bool RenderThemeSafari::paintTextField(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
591 {
592     ASSERT(SafariThemeLibrary());
593
594     paintThemePart(SafariTheme::TextFieldPart, paintInfo.context->platformContext(), r, (NSControlSize)0, determineState(o) & ~FocusedState);
595     return false;
596 }
597
598 void RenderThemeSafari::adjustTextFieldStyle(StyleResolver&, RenderStyle&, Element*) const
599 {
600 }
601
602 bool RenderThemeSafari::paintCapsLockIndicator(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
603 {    
604 #if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 1
605     ASSERT(SafariThemeLibrary());
606
607     if (paintInfo.context->paintingDisabled())
608         return true;
609
610     paintThemePart(CapsLockPart, paintInfo.context->platformContext(), r, (NSControlSize)0, (ThemeControlState)0);
611
612     return false;
613 #else
614     return true;
615 #endif
616 }
617
618 bool RenderThemeSafari::paintTextArea(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
619 {
620     ASSERT(SafariThemeLibrary());
621
622     paintThemePart(SafariTheme::TextAreaPart, paintInfo.context->platformContext(), r, (NSControlSize)0, determineState(o) & ~FocusedState);
623     return false;
624 }
625
626 void RenderThemeSafari::adjustTextAreaStyle(StyleResolver&, RenderStyle&, Element*) const
627 {
628 }
629
630 const int* RenderThemeSafari::popupButtonMargins(NSControlSize size) const
631 {
632     static const int margins[3][4] =
633     {
634         { 2, 3, 3, 3 },
635         { 1, 3, 3, 3 },
636         { 0, 1, 0, 1 }
637     };
638     return margins[size];
639 }
640
641 const IntSize* RenderThemeSafari::popupButtonSizes() const
642 {
643     static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
644     return sizes;
645 }
646
647 const int* RenderThemeSafari::popupButtonPadding(NSControlSize size) const
648 {
649     static const int padding[3][4] =
650     {
651         { 2, 26, 3, 8 },
652         { 2, 23, 3, 8 },
653         { 2, 22, 3, 10 }
654     };
655     return padding[size];
656 }
657
658 bool RenderThemeSafari::paintMenuList(const RenderObject& o, const PaintInfo& info, const IntRect& r)
659 {
660     ASSERT(SafariThemeLibrary());
661
662     NSControlSize controlSize = controlSizeFromRect(r, popupButtonSizes());
663     IntRect inflatedRect = r;
664     IntSize size = popupButtonSizes()[controlSize];
665     size.setWidth(r.width());
666
667     // Now inflate it to account for the shadow.
668     if (r.width() >= minimumMenuListSize(o.style()))
669         inflatedRect = inflateRect(inflatedRect, size, popupButtonMargins(controlSize));
670
671     paintThemePart(DropDownButtonPart, info.context->platformContext(), inflatedRect, controlSize, determineState(o));
672
673     return false;
674 }
675
676 const float baseFontSize = 11.0f;
677 const float baseArrowHeight = 5.0f;
678 const float baseArrowWidth = 7.0f;
679 const int arrowPaddingLeft = 5;
680 const int arrowPaddingRight = 5;
681 const int paddingBeforeSeparator = 4;
682 const int baseBorderRadius = 5;
683 const int styledPopupPaddingLeft = 8;
684 const int styledPopupPaddingTop = 1;
685 const int styledPopupPaddingBottom = 2;
686
687 static void TopGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
688 {
689     static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.4f };
690     static float light[4] = { 1.0f, 1.0f, 1.0f, 0.15f };
691     float a = inData[0];
692     int i = 0;
693     for (i = 0; i < 4; i++)
694         outData[i] = (1.0f - a) * dark[i] + a * light[i];
695 }
696
697 static void BottomGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
698 {
699     static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.0f };
700     static float light[4] = { 1.0f, 1.0f, 1.0f, 0.3f };
701     float a = inData[0];
702     int i = 0;
703     for (i = 0; i < 4; i++)
704         outData[i] = (1.0f - a) * dark[i] + a * light[i];
705 }
706
707 static void MainGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
708 {
709     static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.15f };
710     static float light[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
711     float a = inData[0];
712     int i = 0;
713     for (i = 0; i < 4; i++)
714         outData[i] = (1.0f - a) * dark[i] + a * light[i];
715 }
716
717 static void TrackGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
718 {
719     static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.678f };
720     static float light[4] = { 0.0f, 0.0f, 0.0f, 0.13f };
721     float a = inData[0];
722     int i = 0;
723     for (i = 0; i < 4; i++)
724         outData[i] = (1.0f - a) * dark[i] + a * light[i];
725 }
726
727 void RenderThemeSafari::paintMenuListButtonGradients(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
728 {
729     if (r.isEmpty())
730         return;
731
732     CGContextRef context = paintInfo.context->platformContext();
733
734     paintInfo.context->save();
735
736     FloatRoundedRect bound = FloatRoundedRect(o.style().getRoundedBorderFor(r));
737     int radius = bound.radii().topLeft().width();
738
739     CGColorSpaceRef cspace = deviceRGBColorSpaceRef();
740
741     FloatRect topGradient(r.x(), r.y(), r.width(), r.height() / 2.0f);
742     struct CGFunctionCallbacks topCallbacks = { 0, TopGradientInterpolate, NULL };
743     RetainPtr<CGFunctionRef> topFunction = adoptCF(CGFunctionCreate(NULL, 1, NULL, 4, NULL, &topCallbacks));
744     RetainPtr<CGShadingRef> topShading = adoptCF(CGShadingCreateAxial(cspace, CGPointMake(topGradient.x(), topGradient.y()), CGPointMake(topGradient.x(), topGradient.maxY()), topFunction.get(), false, false));
745
746     FloatRect bottomGradient(r.x() + radius, r.y() + r.height() / 2.0f, r.width() - 2.0f * radius, r.height() / 2.0f);
747     struct CGFunctionCallbacks bottomCallbacks = { 0, BottomGradientInterpolate, NULL };
748     RetainPtr<CGFunctionRef> bottomFunction = adoptCF(CGFunctionCreate(NULL, 1, NULL, 4, NULL, &bottomCallbacks));
749     RetainPtr<CGShadingRef> bottomShading = adoptCF(CGShadingCreateAxial(cspace, CGPointMake(bottomGradient.x(),  bottomGradient.y()), CGPointMake(bottomGradient.x(), bottomGradient.maxY()), bottomFunction.get(), false, false));
750
751     struct CGFunctionCallbacks mainCallbacks = { 0, MainGradientInterpolate, NULL };
752     RetainPtr<CGFunctionRef> mainFunction = adoptCF(CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
753     RetainPtr<CGShadingRef> mainShading = adoptCF(CGShadingCreateAxial(cspace, CGPointMake(r.x(),  r.y()), CGPointMake(r.x(), r.maxY()), mainFunction.get(), false, false));
754
755     RetainPtr<CGShadingRef> leftShading = adoptCF(CGShadingCreateAxial(cspace, CGPointMake(r.x(),  r.y()), CGPointMake(r.x() + radius, r.y()), mainFunction.get(), false, false));
756
757     RetainPtr<CGShadingRef> rightShading = adoptCF(CGShadingCreateAxial(cspace, CGPointMake(r.maxX(),  r.y()), CGPointMake(r.maxX() - radius, r.y()), mainFunction.get(), false, false));
758     paintInfo.context->save();
759     CGContextClipToRect(context, r);
760     paintInfo.context->clipRoundedRect(bound);
761     CGContextDrawShading(context, mainShading.get());
762     paintInfo.context->restore();
763
764     paintInfo.context->save();
765     CGContextClipToRect(context, topGradient);
766     paintInfo.context->clipRoundedRect(FloatRoundedRect(enclosingIntRect(topGradient), bound.radii().topLeft(), bound.radii().topRight(), IntSize(), IntSize()));
767     CGContextDrawShading(context, topShading.get());
768     paintInfo.context->restore();
769
770     if (!bottomGradient.isEmpty()) {
771         paintInfo.context->save();
772         CGContextClipToRect(context, bottomGradient);
773         paintInfo.context->clipRoundedRect(FloatRoundedRect(enclosingIntRect(bottomGradient), IntSize(), IntSize(), bound.radii().bottomLeft(), bound.radii().bottomRight()));
774         CGContextDrawShading(context, bottomShading.get());
775         paintInfo.context->restore();
776     }
777
778     paintInfo.context->save();
779     CGContextClipToRect(context, r);
780     paintInfo.context->clipRoundedRect(bound);
781     CGContextDrawShading(context, leftShading.get());
782     CGContextDrawShading(context, rightShading.get());
783     paintInfo.context->restore();
784
785     paintInfo.context->restore();
786 }
787
788 bool RenderThemeSafari::paintMenuListButtonDecorations(const RenderObject& renderer, const PaintInfo& paintInfo, const FloatRect& rect)
789 {
790     IntRect bounds = IntRect(rect.x() + renderer.style().borderLeftWidth(),
791         rect.y() + renderer.style().borderTopWidth(),
792         rect.width() - renderer.style().borderLeftWidth() - renderer.style().borderRightWidth(),
793         rect.height() - renderer.style().borderTopWidth() - renderer.style().borderBottomWidth());
794     // Draw the gradients to give the styled popup menu a button appearance
795     paintMenuListButtonGradients(renderer, paintInfo, bounds);
796
797     // Since we actually know the size of the control here, we restrict the font scale to make sure the arrow will fit vertically in the bounds
798     float fontScale = min(renderer.style().fontSize() / baseFontSize, bounds.height() / baseArrowHeight);
799     float centerY = bounds.y() + bounds.height() / 2.0f;
800     float arrowHeight = baseArrowHeight * fontScale;
801     float arrowWidth = baseArrowWidth * fontScale;
802     float leftEdge = bounds.maxX() - arrowPaddingRight - arrowWidth;
803
804     if (bounds.width() < arrowWidth + arrowPaddingLeft)
805         return false;
806
807     paintInfo.context->save();
808
809     paintInfo.context->setFillColor(renderer.style().visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB);
810     paintInfo.context->setStrokeColor(NoStroke, ColorSpaceDeviceRGB);
811
812     FloatPoint arrow[3];
813     arrow[0] = FloatPoint(leftEdge, centerY - arrowHeight / 2.0f);
814     arrow[1] = FloatPoint(leftEdge + arrowWidth, centerY - arrowHeight / 2.0f);
815     arrow[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY + arrowHeight / 2.0f);
816
817     // Draw the arrow
818     paintInfo.context->drawConvexPolygon(3, arrow, true);
819
820     Color leftSeparatorColor(0, 0, 0, 40);
821     Color rightSeparatorColor(255, 255, 255, 40);
822
823     // FIXME: Should the separator thickness and space be scaled up by fontScale?
824     int separatorSpace = 2;
825     int leftEdgeOfSeparator = static_cast<int>(leftEdge - arrowPaddingLeft); // FIXME: Round?
826
827     // Draw the separator to the left of the arrows
828     paintInfo.context->setStrokeThickness(1);
829     paintInfo.context->setStrokeStyle(SolidStroke);
830     paintInfo.context->setStrokeColor(leftSeparatorColor, ColorSpaceDeviceRGB);
831     paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()),
832                                 IntPoint(leftEdgeOfSeparator, bounds.maxY()));
833
834     paintInfo.context->setStrokeColor(rightSeparatorColor, ColorSpaceDeviceRGB);
835     paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()),
836                                 IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.maxY()));
837
838     paintInfo.context->restore();
839     return false;
840 }
841
842 void RenderThemeSafari::adjustMenuListStyle(StyleResolver& styleResolver, RenderStyle& style, Element* e) const
843 {
844     NSControlSize controlSize = controlSizeForFont(style);
845
846     style.resetBorder();
847     style.resetPadding();
848     
849     // Height is locked to auto.
850     style.setHeight(Length(Auto));
851
852     // White-space is locked to pre
853     style.setWhiteSpace(PRE);
854
855     // Set the foreground color to black or gray when we have the aqua look.
856     // Cast to RGB32 is to work around a compiler bug.
857     style.setColor(e && !e->isDisabledFormControl() ? static_cast<RGBA32>(Color::black) : Color::darkGray);
858
859     // Set the button's vertical size.
860     setButtonSize(style);
861
862     // Our font is locked to the appropriate system font size for the control.  To clarify, we first use the CSS-specified font to figure out
863     // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
864     // system font for the control size instead.
865     setFontFromControlSize(styleResolver, style, controlSize);
866 }
867
868 int RenderThemeSafari::popupInternalPaddingLeft(RenderStyle& style) const
869 {
870     if (style.appearance() == MenulistPart)
871         return popupButtonPadding(controlSizeForFont(style))[leftPadding];
872     if (style.appearance() == MenulistButtonPart)
873         return styledPopupPaddingLeft;
874     return 0;
875 }
876
877 int RenderThemeSafari::popupInternalPaddingRight(RenderStyle& style) const
878 {
879     if (style.appearance() == MenulistPart)
880         return popupButtonPadding(controlSizeForFont(style))[rightPadding];
881     if (style.appearance() == MenulistButtonPart) {
882         float fontScale = style.fontSize() / baseFontSize;
883         float arrowWidth = baseArrowWidth * fontScale;
884         return static_cast<int>(ceilf(arrowWidth + arrowPaddingLeft + arrowPaddingRight + paddingBeforeSeparator));
885     }
886     return 0;
887 }
888
889 int RenderThemeSafari::popupInternalPaddingTop(RenderStyle& style) const
890 {
891     if (style.appearance() == MenulistPart)
892         return popupButtonPadding(controlSizeForFont(style))[topPadding];
893     if (style.appearance() == MenulistButtonPart)
894         return styledPopupPaddingTop;
895     return 0;
896 }
897
898 int RenderThemeSafari::popupInternalPaddingBottom(RenderStyle& style) const
899 {
900     if (style.appearance() == MenulistPart)
901         return popupButtonPadding(controlSizeForFont(style))[bottomPadding];
902     if (style.appearance() == MenulistButtonPart)
903         return styledPopupPaddingBottom;
904     return 0;
905 }
906
907 void RenderThemeSafari::adjustMenuListButtonStyle(StyleResolver&, RenderStyle& style, Element*) const
908 {
909     float fontScale = style.fontSize() / baseFontSize;
910     
911     style.resetPadding();
912     style.setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up?
913
914     const int minHeight = 15;
915     style.setMinHeight(Length(minHeight, Fixed));
916     
917     style.setLineHeight(RenderStyle::initialLineHeight());
918 }
919
920 const IntSize* RenderThemeSafari::menuListSizes() const
921 {
922     static const IntSize sizes[3] = { IntSize(9, 0), IntSize(5, 0), IntSize(0, 0) };
923     return sizes;
924 }
925
926 int RenderThemeSafari::minimumMenuListSize(RenderStyle& style) const
927 {
928     return sizeForSystemFont(style, menuListSizes()).width();
929 }
930
931 const int trackWidth = 5;
932 const int trackRadius = 2;
933
934 bool RenderThemeSafari::paintSliderTrack(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
935 {
936     IntSize radius(trackRadius, trackRadius);
937     FloatRoundedRect bounds(r, radius, radius, radius, radius);
938
939     if (o.style().appearance() ==  SliderHorizontalPart)
940         bounds.setRect(IntRect(r.x(), r.y() + r.height() / 2 - trackWidth / 2, r.width(), trackWidth));
941     else if (o.style().appearance() == SliderVerticalPart)
942         bounds.setRect(IntRect(r.x() + r.width() / 2 - trackWidth / 2, r.y(), trackWidth, r.height()));
943
944     CGContextRef context = paintInfo.context->platformContext();
945     CGColorSpaceRef cspace = deviceRGBColorSpaceRef();
946
947     paintInfo.context->save();
948     CGContextClipToRect(context, bounds.rect());
949
950     struct CGFunctionCallbacks mainCallbacks = { 0, TrackGradientInterpolate, NULL };
951     RetainPtr<CGFunctionRef> mainFunction = adoptCF(CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
952     RetainPtr<CGShadingRef> mainShading;
953     if (o.style().appearance() == SliderVerticalPart)
954         mainShading = adoptCF(CGShadingCreateAxial(cspace, CGPointMake(bounds.rect().x(),  bounds.rect().maxY()), CGPointMake(bounds.rect().maxX(), bounds.rect().maxY()), mainFunction.get(), false, false));
955     else
956         mainShading = adoptCF(CGShadingCreateAxial(cspace, CGPointMake(bounds.rect().x(),  bounds.rect().y()), CGPointMake(bounds.rect().x(), bounds.rect().maxY()), mainFunction.get(), false, false));
957
958     paintInfo.context->clipRoundedRect(bounds);
959     CGContextDrawShading(context, mainShading.get());
960     paintInfo.context->restore();
961     
962     return false;
963 }
964
965 void RenderThemeSafari::adjustSliderThumbStyle(StyleResolver& styleResolver, RenderStyle& style, Element* e) const 
966
967     RenderTheme::adjustSliderThumbStyle(styleResolver, style, e);
968     style.setBoxShadow(nullptr); 
969
970
971 const float verticalSliderHeightPadding = 0.1f;
972
973 bool RenderThemeSafari::paintSliderThumb(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
974 {
975     ASSERT(SafariThemeLibrary());
976     paintThemePart(SliderThumbPart, paintInfo.context->platformContext(), r, NSSmallControlSize, determineState(o));
977     return false;
978 }
979
980 const int sliderThumbWidth = 15;
981 const int sliderThumbHeight = 15;
982
983 void RenderThemeSafari::adjustSliderThumbSize(RenderStyle& style, Element*) const
984 {
985     if (style.appearance() == SliderThumbHorizontalPart || style.appearance() == SliderThumbVerticalPart) {
986         style.setWidth(Length(sliderThumbWidth, Fixed));
987         style.setHeight(Length(sliderThumbHeight, Fixed));
988     } 
989 #if ENABLE(VIDEO)
990     else if (style.appearance() == MediaSliderThumbPart) 
991         RenderMediaControls::adjustMediaSliderThumbSize(style);
992 #endif
993 }
994
995 bool RenderThemeSafari::paintSearchField(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
996 {
997     ASSERT(SafariThemeLibrary());
998
999     paintThemePart(SafariTheme::SearchFieldPart, paintInfo.context->platformContext(), r, controlSizeFromRect(r, searchFieldSizes()), determineState(o));
1000     return false;
1001 }
1002
1003 const IntSize* RenderThemeSafari::searchFieldSizes() const
1004 {
1005     static const IntSize sizes[3] = { IntSize(0, 22), IntSize(0, 19), IntSize(0, 15) };
1006     return sizes;
1007 }
1008
1009 void RenderThemeSafari::setSearchFieldSize(RenderStyle& style) const
1010 {
1011     // If the width and height are both specified, then we have nothing to do.
1012     if (!style.width().isIntrinsicOrAuto() && !style.height().isAuto())
1013         return;
1014     
1015     // Use the font size to determine the intrinsic width of the control.
1016     setSizeFromFont(style, searchFieldSizes());
1017 }
1018
1019 void RenderThemeSafari::adjustSearchFieldStyle(StyleResolver& styleResolver, RenderStyle& style, Element*) const
1020 {
1021     // Override border.
1022     style.resetBorder();
1023     const short borderWidth = 2;
1024     style.setBorderLeftWidth(borderWidth);
1025     style.setBorderLeftStyle(INSET);
1026     style.setBorderRightWidth(borderWidth);
1027     style.setBorderRightStyle(INSET);
1028     style.setBorderBottomWidth(borderWidth);
1029     style.setBorderBottomStyle(INSET);
1030     style.setBorderTopWidth(borderWidth);
1031     style.setBorderTopStyle(INSET);
1032
1033     // Override height.
1034     style.setHeight(Length(Auto));
1035     setSearchFieldSize(style);
1036
1037     // Override padding size to match AppKit text positioning.
1038     const int padding = 1;
1039     style.setPaddingLeft(Length(padding, Fixed));
1040     style.setPaddingRight(Length(padding, Fixed));
1041     style.setPaddingTop(Length(padding, Fixed));
1042     style.setPaddingBottom(Length(padding, Fixed));
1043
1044     NSControlSize controlSize = controlSizeForFont(style);
1045     setFontFromControlSize(styleResolver, style, controlSize);
1046 }
1047
1048 bool RenderThemeSafari::paintSearchFieldCancelButton(const RenderObject& o, const PaintInfo& paintInfo, const IntRect&)
1049 {
1050     ASSERT(SafariThemeLibrary());
1051
1052     Node* input = o.node()->shadowHost();
1053     if (!input)
1054         input = o.node();
1055     RenderObject* renderer = input->renderer();
1056     ASSERT(renderer);
1057
1058     IntRect searchRect = renderer->absoluteBoundingBoxRectIgnoringTransforms();
1059
1060     paintThemePart(SafariTheme::SearchFieldCancelButtonPart, paintInfo.context->platformContext(), searchRect, controlSizeFromRect(searchRect, searchFieldSizes()), determineState(o));
1061     return false;
1062 }
1063
1064 const IntSize* RenderThemeSafari::cancelButtonSizes() const
1065 {
1066     static const IntSize sizes[3] = { IntSize(16, 13), IntSize(13, 11), IntSize(13, 9) };
1067     return sizes;
1068 }
1069
1070 void RenderThemeSafari::adjustSearchFieldCancelButtonStyle(StyleResolver&, RenderStyle& style, Element*) const
1071 {
1072     IntSize size = sizeForSystemFont(style, cancelButtonSizes());
1073     style.setWidth(Length(size.width(), Fixed));
1074     style.setHeight(Length(size.height(), Fixed));
1075 }
1076
1077 const IntSize* RenderThemeSafari::resultsButtonSizes() const
1078 {
1079     static const IntSize sizes[3] = { IntSize(19, 13), IntSize(17, 11), IntSize(17, 9) };
1080     return sizes;
1081 }
1082
1083 const int emptyResultsOffset = 9;
1084 void RenderThemeSafari::adjustSearchFieldDecorationPartStyle(StyleResolver&, RenderStyle& style, Element*) const
1085 {
1086     IntSize size = sizeForSystemFont(style, resultsButtonSizes());
1087     style.setWidth(Length(size.width() - emptyResultsOffset, Fixed));
1088     style.setHeight(Length(size.height(), Fixed));
1089 }
1090
1091 bool RenderThemeSafari::paintSearchFieldDecorationPart(const RenderObject&, const PaintInfo&, const IntRect&)
1092 {
1093     return false;
1094 }
1095
1096 void RenderThemeSafari::adjustSearchFieldResultsDecorationPartStyle(StyleResolver&, RenderStyle& style, Element*) const
1097 {
1098     IntSize size = sizeForSystemFont(style, resultsButtonSizes());
1099     style.setWidth(Length(size.width(), Fixed));
1100     style.setHeight(Length(size.height(), Fixed));
1101 }
1102
1103 bool RenderThemeSafari::paintSearchFieldResultsDecorationPart(const RenderObject& o, const PaintInfo& paintInfo, const IntRect&)
1104 {
1105     ASSERT(SafariThemeLibrary());
1106
1107     Node* input = o.node()->shadowHost();
1108     if (!input)
1109         input = o.node();
1110     RenderObject* renderer = input->renderer();
1111     ASSERT(renderer);
1112
1113     IntRect searchRect = renderer->absoluteBoundingBoxRectIgnoringTransforms();
1114
1115     paintThemePart(SafariTheme::SearchFieldResultsDecorationPart, paintInfo.context->platformContext(), searchRect, controlSizeFromRect(searchRect, searchFieldSizes()), determineState(o));
1116     return false;
1117 }
1118
1119 const int resultsArrowWidth = 5;
1120 void RenderThemeSafari::adjustSearchFieldResultsButtonStyle(StyleResolver&, RenderStyle& style, Element*) const
1121 {
1122     IntSize size = sizeForSystemFont(style, resultsButtonSizes());
1123     style.setWidth(Length(size.width() + resultsArrowWidth, Fixed));
1124     style.setHeight(Length(size.height(), Fixed));
1125 }
1126
1127 bool RenderThemeSafari::paintSearchFieldResultsButton(const RenderObject& o, const PaintInfo& paintInfo, const IntRect&)
1128 {
1129     ASSERT(SafariThemeLibrary());
1130
1131     Node* input = o.node()->shadowHost();
1132     if (!input)
1133         input = o.node();
1134     RenderObject* renderer = input->renderer();
1135     ASSERT(renderer);
1136
1137     IntRect searchRect = renderer->absoluteBoundingBoxRectIgnoringTransforms();
1138
1139     paintThemePart(SafariTheme::SearchFieldResultsButtonPart, paintInfo.context->platformContext(), searchRect, controlSizeFromRect(searchRect, searchFieldSizes()), determineState(o));
1140     return false;
1141 }
1142
1143 #if ENABLE(VIDEO)
1144 String RenderThemeSafari::mediaControlsStyleSheet()
1145 {
1146 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
1147     if (m_mediaControlsStyleSheet.isEmpty())
1148         m_mediaControlsStyleSheet = RenderThemeWin::stringWithContentsOfFile(CFSTR("mediaControlsApple"), CFSTR("css"));
1149     return m_mediaControlsStyleSheet;
1150 #else
1151     return emptyString();
1152 #endif
1153 }
1154
1155 String RenderThemeSafari::mediaControlsScript()
1156 {
1157 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
1158     StringBuilder scriptBuilder;
1159     scriptBuilder.append(RenderThemeWin::stringWithContentsOfFile(CFSTR("mediaControlsLocalizedStrings"), CFSTR("js")));
1160     scriptBuilder.append(RenderThemeWin::stringWithContentsOfFile(CFSTR("mediaControlsApple"), CFSTR("js")));
1161     m_mediaControlsScript = scriptBuilder.toString();
1162     return m_mediaControlsScript;
1163 #else
1164     return emptyString();
1165 #endif
1166 }
1167 #endif
1168
1169 #if ENABLE(METER_ELEMENT)
1170 void RenderThemeSafari::adjustMeterStyle(StyleResolver&, RenderStyle& style, Element*) const
1171 {
1172     style.setBoxShadow(nullptr);
1173 }
1174
1175 bool RenderThemeSafari::supportsMeter(ControlPart part) const
1176 {
1177     switch (part) {
1178     case MeterPart:
1179         return true;
1180     default:
1181         return false;
1182     }
1183 }
1184
1185 IntSize RenderThemeSafari::meterSizeForBounds(const RenderMeter&, const IntRect& bounds) const
1186 {
1187     return bounds.size();
1188 }
1189
1190 bool RenderThemeSafari::paintMeter(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
1191 {
1192     // NOTE: This routine is for testing only. It should be fleshed out with a real CG-based implementation.
1193     // Right now it uses a slider, with the thumb positioned at the meter point.
1194     if (!is<RenderMeter>(renderObject))
1195         return true;
1196
1197     HTMLMeterElement* element = downcast<RenderMeter>(renderObject).meterElement();
1198
1199     int remaining = static_cast<int>((1.0 - element->valueRatio()) * static_cast<double>(rect.size().width()));
1200
1201     // Draw the background
1202     paintSliderTrack(renderObject, paintInfo, rect);
1203
1204     // Draw the progress portion
1205     IntRect completedRect(rect);
1206     completedRect.contract(remaining, 0);
1207
1208     paintSliderThumb(renderObject, paintInfo, completedRect);
1209
1210     return true;
1211 }
1212
1213 #endif
1214
1215 } // namespace WebCore
1216
1217 #endif // #if USE(SAFARI_THEME)