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