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