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