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