Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
      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 #import "config.h"
     21 #import "RenderThemeMac.h"
     22 
     23 #import "BitmapImage.h"
     24 #import "ColorMac.h"
     25 #import "CSSStyleSelector.h"
     26 #import "CSSValueKeywords.h"
     27 #import "Document.h"
     28 #import "Element.h"
     29 #import "FrameView.h"
     30 #import "GraphicsContext.h"
     31 #import "HTMLInputElement.h"
     32 #import "HTMLMediaElement.h"
     33 #import "HTMLNames.h"
     34 #import "Image.h"
     35 #import "LocalCurrentGraphicsContext.h"
     36 #import "MediaControlElements.h"
     37 #import "RenderMedia.h"
     38 #import "RenderSlider.h"
     39 #import "RenderView.h"
     40 #import "SharedBuffer.h"
     41 #import "TimeRanges.h"
     42 #import "WebCoreSystemInterface.h"
     43 #import "UserAgentStyleSheets.h"
     44 #import <Carbon/Carbon.h>
     45 #import <Cocoa/Cocoa.h>
     46 #import <wtf/RetainPtr.h>
     47 #import <wtf/StdLibExtras.h>
     48 #import <math.h>
     49 
     50 #ifdef BUILDING_ON_TIGER
     51 typedef int NSInteger;
     52 typedef unsigned NSUInteger;
     53 #endif
     54 
     55 using std::min;
     56 
     57 // The methods in this file are specific to the Mac OS X platform.
     58 
     59 // FIXME: The platform-independent code in this class should be factored out and merged with RenderThemeSafari.
     60 
     61 @interface WebCoreRenderThemeNotificationObserver : NSObject
     62 {
     63     WebCore::RenderTheme *_theme;
     64 }
     65 
     66 - (id)initWithTheme:(WebCore::RenderTheme *)theme;
     67 - (void)systemColorsDidChange:(NSNotification *)notification;
     68 
     69 @end
     70 
     71 @implementation WebCoreRenderThemeNotificationObserver
     72 
     73 - (id)initWithTheme:(WebCore::RenderTheme *)theme
     74 {
     75     [super init];
     76     _theme = theme;
     77 
     78     return self;
     79 }
     80 
     81 - (void)systemColorsDidChange:(NSNotification *)unusedNotification
     82 {
     83     ASSERT_UNUSED(unusedNotification, [[unusedNotification name] isEqualToString:NSSystemColorsDidChangeNotification]);
     84     _theme->platformColorsDidChange();
     85 }
     86 
     87 @end
     88 
     89 namespace WebCore {
     90 
     91 using namespace HTMLNames;
     92 
     93 enum {
     94     topMargin,
     95     rightMargin,
     96     bottomMargin,
     97     leftMargin
     98 };
     99 
    100 enum {
    101     topPadding,
    102     rightPadding,
    103     bottomPadding,
    104     leftPadding
    105 };
    106 
    107 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page*)
    108 {
    109     static RenderTheme* rt = RenderThemeMac::create().releaseRef();
    110     return rt;
    111 }
    112 
    113 PassRefPtr<RenderTheme> RenderThemeMac::create()
    114 {
    115     return adoptRef(new RenderThemeMac);
    116 }
    117 
    118 RenderThemeMac::RenderThemeMac()
    119     : m_isSliderThumbHorizontalPressed(false)
    120     , m_isSliderThumbVerticalPressed(false)
    121     , m_notificationObserver(AdoptNS, [[WebCoreRenderThemeNotificationObserver alloc] initWithTheme:this])
    122 {
    123     [[NSNotificationCenter defaultCenter] addObserver:m_notificationObserver.get()
    124                                                         selector:@selector(systemColorsDidChange:)
    125                                                             name:NSSystemColorsDidChangeNotification
    126                                                           object:nil];
    127 }
    128 
    129 RenderThemeMac::~RenderThemeMac()
    130 {
    131     [[NSNotificationCenter defaultCenter] removeObserver:m_notificationObserver.get()];
    132 }
    133 
    134 Color RenderThemeMac::platformActiveSelectionBackgroundColor() const
    135 {
    136     NSColor* color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
    137     return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
    138 }
    139 
    140 Color RenderThemeMac::platformInactiveSelectionBackgroundColor() const
    141 {
    142     NSColor* color = [[NSColor secondarySelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
    143     return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
    144 }
    145 
    146 Color RenderThemeMac::platformActiveListBoxSelectionBackgroundColor() const
    147 {
    148     NSColor* color = [[NSColor alternateSelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
    149     return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
    150 }
    151 
    152 Color RenderThemeMac::platformActiveListBoxSelectionForegroundColor() const
    153 {
    154     return Color::white;
    155 }
    156 
    157 Color RenderThemeMac::platformInactiveListBoxSelectionForegroundColor() const
    158 {
    159     return Color::black;
    160 }
    161 
    162 Color RenderThemeMac::platformFocusRingColor() const
    163 {
    164     if (usesTestModeFocusRingColor())
    165         return oldAquaFocusRingColor();
    166 
    167     return systemColor(CSSValueWebkitFocusRingColor);
    168 }
    169 
    170 Color RenderThemeMac::platformInactiveListBoxSelectionBackgroundColor() const
    171 {
    172     return platformInactiveSelectionBackgroundColor();
    173 }
    174 
    175 static FontWeight toFontWeight(NSInteger appKitFontWeight)
    176 {
    177     ASSERT(appKitFontWeight > 0 && appKitFontWeight < 15);
    178     if (appKitFontWeight > 14)
    179         appKitFontWeight = 14;
    180     else if (appKitFontWeight < 1)
    181         appKitFontWeight = 1;
    182 
    183     static FontWeight fontWeights[] = {
    184         FontWeight100,
    185         FontWeight100,
    186         FontWeight200,
    187         FontWeight300,
    188         FontWeight400,
    189         FontWeight500,
    190         FontWeight600,
    191         FontWeight600,
    192         FontWeight700,
    193         FontWeight800,
    194         FontWeight800,
    195         FontWeight900,
    196         FontWeight900,
    197         FontWeight900
    198     };
    199     return fontWeights[appKitFontWeight - 1];
    200 }
    201 
    202 void RenderThemeMac::systemFont(int cssValueId, FontDescription& fontDescription) const
    203 {
    204     DEFINE_STATIC_LOCAL(FontDescription, systemFont, ());
    205     DEFINE_STATIC_LOCAL(FontDescription, smallSystemFont, ());
    206     DEFINE_STATIC_LOCAL(FontDescription, menuFont, ());
    207     DEFINE_STATIC_LOCAL(FontDescription, labelFont, ());
    208     DEFINE_STATIC_LOCAL(FontDescription, miniControlFont, ());
    209     DEFINE_STATIC_LOCAL(FontDescription, smallControlFont, ());
    210     DEFINE_STATIC_LOCAL(FontDescription, controlFont, ());
    211 
    212     FontDescription* cachedDesc;
    213     NSFont* font = nil;
    214     switch (cssValueId) {
    215         case CSSValueSmallCaption:
    216             cachedDesc = &smallSystemFont;
    217             if (!smallSystemFont.isAbsoluteSize())
    218                 font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
    219             break;
    220         case CSSValueMenu:
    221             cachedDesc = &menuFont;
    222             if (!menuFont.isAbsoluteSize())
    223                 font = [NSFont menuFontOfSize:[NSFont systemFontSize]];
    224             break;
    225         case CSSValueStatusBar:
    226             cachedDesc = &labelFont;
    227             if (!labelFont.isAbsoluteSize())
    228                 font = [NSFont labelFontOfSize:[NSFont labelFontSize]];
    229             break;
    230         case CSSValueWebkitMiniControl:
    231             cachedDesc = &miniControlFont;
    232             if (!miniControlFont.isAbsoluteSize())
    233                 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]];
    234             break;
    235         case CSSValueWebkitSmallControl:
    236             cachedDesc = &smallControlFont;
    237             if (!smallControlFont.isAbsoluteSize())
    238                 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]];
    239             break;
    240         case CSSValueWebkitControl:
    241             cachedDesc = &controlFont;
    242             if (!controlFont.isAbsoluteSize())
    243                 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
    244             break;
    245         default:
    246             cachedDesc = &systemFont;
    247             if (!systemFont.isAbsoluteSize())
    248                 font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
    249     }
    250 
    251     if (font) {
    252         NSFontManager *fontManager = [NSFontManager sharedFontManager];
    253         cachedDesc->setIsAbsoluteSize(true);
    254         cachedDesc->setGenericFamily(FontDescription::NoFamily);
    255         cachedDesc->firstFamily().setFamily([font familyName]);
    256         cachedDesc->setSpecifiedSize([font pointSize]);
    257         cachedDesc->setWeight(toFontWeight([fontManager weightOfFont:font]));
    258         cachedDesc->setItalic([fontManager traitsOfFont:font] & NSItalicFontMask);
    259     }
    260     fontDescription = *cachedDesc;
    261 }
    262 
    263 static RGBA32 convertNSColorToColor(NSColor *color)
    264 {
    265     NSColor *colorInColorSpace = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace];
    266     if (colorInColorSpace) {
    267         static const double scaleFactor = nextafter(256.0, 0.0);
    268         return makeRGB(static_cast<int>(scaleFactor * [colorInColorSpace redComponent]),
    269             static_cast<int>(scaleFactor * [colorInColorSpace greenComponent]),
    270             static_cast<int>(scaleFactor * [colorInColorSpace blueComponent]));
    271     }
    272 
    273     // This conversion above can fail if the NSColor in question is an NSPatternColor
    274     // (as many system colors are). These colors are actually a repeating pattern
    275     // not just a solid color. To work around this we simply draw a 1x1 image of
    276     // the color and use that pixel's color. It might be better to use an average of
    277     // the colors in the pattern instead.
    278     NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
    279                                                                              pixelsWide:1
    280                                                                              pixelsHigh:1
    281                                                                           bitsPerSample:8
    282                                                                         samplesPerPixel:4
    283                                                                                hasAlpha:YES
    284                                                                                isPlanar:NO
    285                                                                          colorSpaceName:NSDeviceRGBColorSpace
    286                                                                             bytesPerRow:4
    287                                                                            bitsPerPixel:32];
    288 
    289     [NSGraphicsContext saveGraphicsState];
    290     [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep]];
    291     NSEraseRect(NSMakeRect(0, 0, 1, 1));
    292     [color drawSwatchInRect:NSMakeRect(0, 0, 1, 1)];
    293     [NSGraphicsContext restoreGraphicsState];
    294 
    295     NSUInteger pixel[4];
    296     [offscreenRep getPixel:pixel atX:0 y:0];
    297 
    298     [offscreenRep release];
    299 
    300     return makeRGB(pixel[0], pixel[1], pixel[2]);
    301 }
    302 
    303 static RGBA32 menuBackgroundColor()
    304 {
    305     NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
    306                                                                              pixelsWide:1
    307                                                                              pixelsHigh:1
    308                                                                           bitsPerSample:8
    309                                                                         samplesPerPixel:4
    310                                                                                hasAlpha:YES
    311                                                                                isPlanar:NO
    312                                                                          colorSpaceName:NSDeviceRGBColorSpace
    313                                                                             bytesPerRow:4
    314                                                                            bitsPerPixel:32];
    315 
    316     CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep] graphicsPort]);
    317     CGRect rect = CGRectMake(0, 0, 1, 1);
    318     HIThemeMenuDrawInfo drawInfo;
    319     drawInfo.version =  0;
    320     drawInfo.menuType = kThemeMenuTypePopUp;
    321     HIThemeDrawMenuBackground(&rect, &drawInfo, context, kHIThemeOrientationInverted);
    322 
    323     NSUInteger pixel[4];
    324     [offscreenRep getPixel:pixel atX:0 y:0];
    325 
    326     [offscreenRep release];
    327 
    328     return makeRGB(pixel[0], pixel[1], pixel[2]);
    329 }
    330 
    331 void RenderThemeMac::platformColorsDidChange()
    332 {
    333     m_systemColorCache.clear();
    334     RenderTheme::platformColorsDidChange();
    335 }
    336 
    337 Color RenderThemeMac::systemColor(int cssValueId) const
    338 {
    339     if (m_systemColorCache.contains(cssValueId))
    340         return m_systemColorCache.get(cssValueId);
    341 
    342     Color color;
    343     switch (cssValueId) {
    344         case CSSValueActiveborder:
    345             color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
    346             break;
    347         case CSSValueActivecaption:
    348             color = convertNSColorToColor([NSColor windowFrameTextColor]);
    349             break;
    350         case CSSValueAppworkspace:
    351             color = convertNSColorToColor([NSColor headerColor]);
    352             break;
    353         case CSSValueBackground:
    354             // Use theme independent default
    355             break;
    356         case CSSValueButtonface:
    357             // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
    358             // We may want to change this to use the NSColor in future.
    359             color = 0xFFC0C0C0;
    360             break;
    361         case CSSValueButtonhighlight:
    362             color = convertNSColorToColor([NSColor controlHighlightColor]);
    363             break;
    364         case CSSValueButtonshadow:
    365             color = convertNSColorToColor([NSColor controlShadowColor]);
    366             break;
    367         case CSSValueButtontext:
    368             color = convertNSColorToColor([NSColor controlTextColor]);
    369             break;
    370         case CSSValueCaptiontext:
    371             color = convertNSColorToColor([NSColor textColor]);
    372             break;
    373         case CSSValueGraytext:
    374             color = convertNSColorToColor([NSColor disabledControlTextColor]);
    375             break;
    376         case CSSValueHighlight:
    377             color = convertNSColorToColor([NSColor selectedTextBackgroundColor]);
    378             break;
    379         case CSSValueHighlighttext:
    380             color = convertNSColorToColor([NSColor selectedTextColor]);
    381             break;
    382         case CSSValueInactiveborder:
    383             color = convertNSColorToColor([NSColor controlBackgroundColor]);
    384             break;
    385         case CSSValueInactivecaption:
    386             color = convertNSColorToColor([NSColor controlBackgroundColor]);
    387             break;
    388         case CSSValueInactivecaptiontext:
    389             color = convertNSColorToColor([NSColor textColor]);
    390             break;
    391         case CSSValueInfobackground:
    392             // There is no corresponding NSColor for this so we use a hard coded value.
    393             color = 0xFFFBFCC5;
    394             break;
    395         case CSSValueInfotext:
    396             color = convertNSColorToColor([NSColor textColor]);
    397             break;
    398         case CSSValueMenu:
    399             color = menuBackgroundColor();
    400             break;
    401         case CSSValueMenutext:
    402             color = convertNSColorToColor([NSColor selectedMenuItemTextColor]);
    403             break;
    404         case CSSValueScrollbar:
    405             color = convertNSColorToColor([NSColor scrollBarColor]);
    406             break;
    407         case CSSValueText:
    408             color = convertNSColorToColor([NSColor textColor]);
    409             break;
    410         case CSSValueThreeddarkshadow:
    411             color = convertNSColorToColor([NSColor controlDarkShadowColor]);
    412             break;
    413         case CSSValueThreedshadow:
    414             color = convertNSColorToColor([NSColor shadowColor]);
    415             break;
    416         case CSSValueThreedface:
    417             // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
    418             // We may want to change this to use the NSColor in future.
    419             color = 0xFFC0C0C0;
    420             break;
    421         case CSSValueThreedhighlight:
    422             color = convertNSColorToColor([NSColor highlightColor]);
    423             break;
    424         case CSSValueThreedlightshadow:
    425             color = convertNSColorToColor([NSColor controlLightHighlightColor]);
    426             break;
    427         case CSSValueWebkitFocusRingColor:
    428             color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
    429             break;
    430         case CSSValueWindow:
    431             color = convertNSColorToColor([NSColor windowBackgroundColor]);
    432             break;
    433         case CSSValueWindowframe:
    434             color = convertNSColorToColor([NSColor windowFrameColor]);
    435             break;
    436         case CSSValueWindowtext:
    437             color = convertNSColorToColor([NSColor windowFrameTextColor]);
    438             break;
    439     }
    440 
    441     if (!color.isValid())
    442         color = RenderTheme::systemColor(cssValueId);
    443 
    444     if (color.isValid())
    445         m_systemColorCache.set(cssValueId, color.rgb());
    446 
    447     return color;
    448 }
    449 
    450 bool RenderThemeMac::isControlStyled(const RenderStyle* style, const BorderData& border,
    451                                      const FillLayer& background, const Color& backgroundColor) const
    452 {
    453     if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart || style->appearance() == ListboxPart)
    454         return style->border() != border;
    455 
    456     // FIXME: This is horrible, but there is not much else that can be done.  Menu lists cannot draw properly when
    457     // scaled.  They can't really draw properly when transformed either.  We can't detect the transform case at style
    458     // adjustment time so that will just have to stay broken.  We can however detect that we're zooming.  If zooming
    459     // is in effect we treat it like the control is styled.
    460     if (style->appearance() == MenulistPart && style->effectiveZoom() != 1.0f)
    461         return true;
    462 
    463     return RenderTheme::isControlStyled(style, border, background, backgroundColor);
    464 }
    465 
    466 void RenderThemeMac::adjustRepaintRect(const RenderObject* o, IntRect& r)
    467 {
    468     ControlPart part = o->style()->appearance();
    469 
    470 #if USE(NEW_THEME)
    471     switch (part) {
    472         case CheckboxPart:
    473         case RadioPart:
    474         case PushButtonPart:
    475         case SquareButtonPart:
    476         case ListButtonPart:
    477         case DefaultButtonPart:
    478         case ButtonPart:
    479             return RenderTheme::adjustRepaintRect(o, r);
    480         default:
    481             break;
    482     }
    483 #endif
    484 
    485     float zoomLevel = o->style()->effectiveZoom();
    486 
    487     if (part == MenulistPart) {
    488         setPopupButtonCellState(o, r);
    489         IntSize size = popupButtonSizes()[[popupButton() controlSize]];
    490         size.setHeight(size.height() * zoomLevel);
    491         size.setWidth(r.width());
    492         r = inflateRect(r, size, popupButtonMargins(), zoomLevel);
    493     }
    494 }
    495 
    496 IntRect RenderThemeMac::inflateRect(const IntRect& r, const IntSize& size, const int* margins, float zoomLevel) const
    497 {
    498     // Only do the inflation if the available width/height are too small.  Otherwise try to
    499     // fit the glow/check space into the available box's width/height.
    500     int widthDelta = r.width() - (size.width() + margins[leftMargin] * zoomLevel + margins[rightMargin] * zoomLevel);
    501     int heightDelta = r.height() - (size.height() + margins[topMargin] * zoomLevel + margins[bottomMargin] * zoomLevel);
    502     IntRect result(r);
    503     if (widthDelta < 0) {
    504         result.setX(result.x() - margins[leftMargin] * zoomLevel);
    505         result.setWidth(result.width() - widthDelta);
    506     }
    507     if (heightDelta < 0) {
    508         result.setY(result.y() - margins[topMargin] * zoomLevel);
    509         result.setHeight(result.height() - heightDelta);
    510     }
    511     return result;
    512 }
    513 
    514 FloatRect RenderThemeMac::convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect& r) const
    515 {
    516     FloatRect partRect(inputRect);
    517 
    518     // Compute an offset between the part renderer and the input renderer
    519     FloatSize offsetFromInputRenderer;
    520     const RenderObject* renderer = partRenderer;
    521     while (renderer && renderer != inputRenderer) {
    522         RenderObject* containingRenderer = renderer->container();
    523         offsetFromInputRenderer -= renderer->offsetFromContainer(containingRenderer);
    524         renderer = containingRenderer;
    525     }
    526     // If the input renderer was not a container, something went wrong
    527     ASSERT(renderer == inputRenderer);
    528     // Move the rect into partRenderer's coords
    529     partRect.move(offsetFromInputRenderer);
    530     // Account for the local drawing offset (tx, ty)
    531     partRect.move(r.x(), r.y());
    532 
    533     return partRect;
    534 }
    535 
    536 void RenderThemeMac::updateCheckedState(NSCell* cell, const RenderObject* o)
    537 {
    538     bool oldIndeterminate = [cell state] == NSMixedState;
    539     bool indeterminate = isIndeterminate(o);
    540     bool checked = isChecked(o);
    541 
    542     if (oldIndeterminate != indeterminate) {
    543         [cell setState:indeterminate ? NSMixedState : (checked ? NSOnState : NSOffState)];
    544         return;
    545     }
    546 
    547     bool oldChecked = [cell state] == NSOnState;
    548     if (checked != oldChecked)
    549         [cell setState:checked ? NSOnState : NSOffState];
    550 }
    551 
    552 void RenderThemeMac::updateEnabledState(NSCell* cell, const RenderObject* o)
    553 {
    554     bool oldEnabled = [cell isEnabled];
    555     bool enabled = isEnabled(o);
    556     if (enabled != oldEnabled)
    557         [cell setEnabled:enabled];
    558 }
    559 
    560 void RenderThemeMac::updateFocusedState(NSCell* cell, const RenderObject* o)
    561 {
    562     bool oldFocused = [cell showsFirstResponder];
    563     bool focused = isFocused(o) && o->style()->outlineStyleIsAuto();
    564     if (focused != oldFocused)
    565         [cell setShowsFirstResponder:focused];
    566 }
    567 
    568 void RenderThemeMac::updatePressedState(NSCell* cell, const RenderObject* o)
    569 {
    570     bool oldPressed = [cell isHighlighted];
    571     bool pressed = (o->node() && o->node()->active());
    572     if (pressed != oldPressed)
    573         [cell setHighlighted:pressed];
    574 }
    575 
    576 bool RenderThemeMac::controlSupportsTints(const RenderObject* o) const
    577 {
    578     // An alternate way to implement this would be to get the appropriate cell object
    579     // and call the private _needRedrawOnWindowChangedKeyState method. An advantage of
    580     // that would be that we would match AppKit behavior more closely, but a disadvantage
    581     // would be that we would rely on an AppKit SPI method.
    582 
    583     if (!isEnabled(o))
    584         return false;
    585 
    586     // Checkboxes only have tint when checked.
    587     if (o->style()->appearance() == CheckboxPart)
    588         return isChecked(o);
    589 
    590     // For now assume other controls have tint if enabled.
    591     return true;
    592 }
    593 
    594 NSControlSize RenderThemeMac::controlSizeForFont(RenderStyle* style) const
    595 {
    596     int fontSize = style->fontSize();
    597     if (fontSize >= 16)
    598         return NSRegularControlSize;
    599     if (fontSize >= 11)
    600         return NSSmallControlSize;
    601     return NSMiniControlSize;
    602 }
    603 
    604 void RenderThemeMac::setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minSize, float zoomLevel)
    605 {
    606     NSControlSize size;
    607     if (minSize.width() >= static_cast<int>(sizes[NSRegularControlSize].width() * zoomLevel) &&
    608         minSize.height() >= static_cast<int>(sizes[NSRegularControlSize].height() * zoomLevel))
    609         size = NSRegularControlSize;
    610     else if (minSize.width() >= static_cast<int>(sizes[NSSmallControlSize].width() * zoomLevel) &&
    611              minSize.height() >= static_cast<int>(sizes[NSSmallControlSize].height() * zoomLevel))
    612         size = NSSmallControlSize;
    613     else
    614         size = NSMiniControlSize;
    615     if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same.
    616         [cell setControlSize:size];
    617 }
    618 
    619 IntSize RenderThemeMac::sizeForFont(RenderStyle* style, const IntSize* sizes) const
    620 {
    621     if (style->effectiveZoom() != 1.0f) {
    622         IntSize result = sizes[controlSizeForFont(style)];
    623         return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
    624     }
    625     return sizes[controlSizeForFont(style)];
    626 }
    627 
    628 IntSize RenderThemeMac::sizeForSystemFont(RenderStyle* style, const IntSize* sizes) const
    629 {
    630     if (style->effectiveZoom() != 1.0f) {
    631         IntSize result = sizes[controlSizeForSystemFont(style)];
    632         return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
    633     }
    634     return sizes[controlSizeForSystemFont(style)];
    635 }
    636 
    637 void RenderThemeMac::setSizeFromFont(RenderStyle* style, const IntSize* sizes) const
    638 {
    639     // FIXME: Check is flawed, since it doesn't take min-width/max-width into account.
    640     IntSize size = sizeForFont(style, sizes);
    641     if (style->width().isIntrinsicOrAuto() && size.width() > 0)
    642         style->setWidth(Length(size.width(), Fixed));
    643     if (style->height().isAuto() && size.height() > 0)
    644         style->setHeight(Length(size.height(), Fixed));
    645 }
    646 
    647 void RenderThemeMac::setFontFromControlSize(CSSStyleSelector*, RenderStyle* style, NSControlSize controlSize) const
    648 {
    649     FontDescription fontDescription;
    650     fontDescription.setIsAbsoluteSize(true);
    651     fontDescription.setGenericFamily(FontDescription::SerifFamily);
    652 
    653     NSFont* font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:controlSize]];
    654     fontDescription.firstFamily().setFamily([font familyName]);
    655     fontDescription.setComputedSize([font pointSize] * style->effectiveZoom());
    656     fontDescription.setSpecifiedSize([font pointSize] * style->effectiveZoom());
    657 
    658     // Reset line height
    659     style->setLineHeight(RenderStyle::initialLineHeight());
    660 
    661     if (style->setFontDescription(fontDescription))
    662         style->font().update(0);
    663 }
    664 
    665 NSControlSize RenderThemeMac::controlSizeForSystemFont(RenderStyle* style) const
    666 {
    667     int fontSize = style->fontSize();
    668     if (fontSize >= [NSFont systemFontSizeForControlSize:NSRegularControlSize])
    669         return NSRegularControlSize;
    670     if (fontSize >= [NSFont systemFontSizeForControlSize:NSSmallControlSize])
    671         return NSSmallControlSize;
    672     return NSMiniControlSize;
    673 }
    674 
    675 bool RenderThemeMac::paintTextField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
    676 {
    677     LocalCurrentGraphicsContext localContext(paintInfo.context);
    678     wkDrawBezeledTextFieldCell(r, isEnabled(o) && !isReadOnlyControl(o));
    679     return false;
    680 }
    681 
    682 void RenderThemeMac::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
    683 {
    684 }
    685 
    686 bool RenderThemeMac::paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
    687 {
    688     if (paintInfo.context->paintingDisabled())
    689         return true;
    690 
    691     LocalCurrentGraphicsContext localContext(paintInfo.context);
    692     wkDrawCapsLockIndicator(paintInfo.context->platformContext(), r);
    693 
    694     return false;
    695 }
    696 
    697 bool RenderThemeMac::paintTextArea(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
    698 {
    699     LocalCurrentGraphicsContext localContext(paintInfo.context);
    700     wkDrawBezeledTextArea(r, isEnabled(o) && !isReadOnlyControl(o));
    701     return false;
    702 }
    703 
    704 void RenderThemeMac::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const
    705 {
    706 }
    707 
    708 const int* RenderThemeMac::popupButtonMargins() const
    709 {
    710     static const int margins[3][4] =
    711     {
    712         { 0, 3, 1, 3 },
    713         { 0, 3, 2, 3 },
    714         { 0, 1, 0, 1 }
    715     };
    716     return margins[[popupButton() controlSize]];
    717 }
    718 
    719 const IntSize* RenderThemeMac::popupButtonSizes() const
    720 {
    721     static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
    722     return sizes;
    723 }
    724 
    725 const int* RenderThemeMac::popupButtonPadding(NSControlSize size) const
    726 {
    727     static const int padding[3][4] =
    728     {
    729         { 2, 26, 3, 8 },
    730         { 2, 23, 3, 8 },
    731         { 2, 22, 3, 10 }
    732     };
    733     return padding[size];
    734 }
    735 
    736 bool RenderThemeMac::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
    737 {
    738     setPopupButtonCellState(o, r);
    739 
    740     NSPopUpButtonCell* popupButton = this->popupButton();
    741 
    742     float zoomLevel = o->style()->effectiveZoom();
    743     IntSize size = popupButtonSizes()[[popupButton controlSize]];
    744     size.setHeight(size.height() * zoomLevel);
    745     size.setWidth(r.width());
    746 
    747     // Now inflate it to account for the shadow.
    748     IntRect inflatedRect = r;
    749     if (r.width() >= minimumMenuListSize(o->style()))
    750         inflatedRect = inflateRect(inflatedRect, size, popupButtonMargins(), zoomLevel);
    751 
    752     paintInfo.context->save();
    753 
    754 #ifndef BUILDING_ON_TIGER
    755     // On Leopard, the cell will draw outside of the given rect, so we have to clip to the rect
    756     paintInfo.context->clip(inflatedRect);
    757 #endif
    758 
    759     if (zoomLevel != 1.0f) {
    760         inflatedRect.setWidth(inflatedRect.width() / zoomLevel);
    761         inflatedRect.setHeight(inflatedRect.height() / zoomLevel);
    762         paintInfo.context->translate(inflatedRect.x(), inflatedRect.y());
    763         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
    764         paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y());
    765     }
    766 
    767     [popupButton drawWithFrame:inflatedRect inView:o->view()->frameView()->documentView()];
    768     [popupButton setControlView:nil];
    769 
    770     paintInfo.context->restore();
    771 
    772     return false;
    773 }
    774 
    775 const float baseFontSize = 11.0f;
    776 const float baseArrowHeight = 4.0f;
    777 const float baseArrowWidth = 5.0f;
    778 const float baseSpaceBetweenArrows = 2.0f;
    779 const int arrowPaddingLeft = 6;
    780 const int arrowPaddingRight = 6;
    781 const int paddingBeforeSeparator = 4;
    782 const int baseBorderRadius = 5;
    783 const int styledPopupPaddingLeft = 8;
    784 const int styledPopupPaddingTop = 1;
    785 const int styledPopupPaddingBottom = 2;
    786 
    787 static void TopGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
    788 {
    789     static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.4f };
    790     static float light[4] = { 1.0f, 1.0f, 1.0f, 0.15f };
    791     float a = inData[0];
    792     int i = 0;
    793     for (i = 0; i < 4; i++)
    794         outData[i] = (1.0f - a) * dark[i] + a * light[i];
    795 }
    796 
    797 static void BottomGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
    798 {
    799     static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.0f };
    800     static float light[4] = { 1.0f, 1.0f, 1.0f, 0.3f };
    801     float a = inData[0];
    802     int i = 0;
    803     for (i = 0; i < 4; i++)
    804         outData[i] = (1.0f - a) * dark[i] + a * light[i];
    805 }
    806 
    807 static void MainGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
    808 {
    809     static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.15f };
    810     static float light[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
    811     float a = inData[0];
    812     int i = 0;
    813     for (i = 0; i < 4; i++)
    814         outData[i] = (1.0f - a) * dark[i] + a * light[i];
    815 }
    816 
    817 static void TrackGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData)
    818 {
    819     static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.678f };
    820     static float light[4] = { 0.0f, 0.0f, 0.0f, 0.13f };
    821     float a = inData[0];
    822     int i = 0;
    823     for (i = 0; i < 4; i++)
    824         outData[i] = (1.0f - a) * dark[i] + a * light[i];
    825 }
    826 
    827 void RenderThemeMac::paintMenuListButtonGradients(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
    828 {
    829     if (r.isEmpty())
    830         return;
    831 
    832     CGContextRef context = paintInfo.context->platformContext();
    833 
    834     paintInfo.context->save();
    835 
    836     IntSize topLeftRadius;
    837     IntSize topRightRadius;
    838     IntSize bottomLeftRadius;
    839     IntSize bottomRightRadius;
    840 
    841     o->style()->getBorderRadiiForRect(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
    842 
    843     int radius = topLeftRadius.width();
    844 
    845     RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB());
    846 
    847     FloatRect topGradient(r.x(), r.y(), r.width(), r.height() / 2.0f);
    848     struct CGFunctionCallbacks topCallbacks = { 0, TopGradientInterpolate, NULL };
    849     RetainPtr<CGFunctionRef> topFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &topCallbacks));
    850     RetainPtr<CGShadingRef> topShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(topGradient.x(), topGradient.y()), CGPointMake(topGradient.x(), topGradient.bottom()), topFunction.get(), false, false));
    851 
    852     FloatRect bottomGradient(r.x() + radius, r.y() + r.height() / 2.0f, r.width() - 2.0f * radius, r.height() / 2.0f);
    853     struct CGFunctionCallbacks bottomCallbacks = { 0, BottomGradientInterpolate, NULL };
    854     RetainPtr<CGFunctionRef> bottomFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &bottomCallbacks));
    855     RetainPtr<CGShadingRef> bottomShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(bottomGradient.x(),  bottomGradient.y()), CGPointMake(bottomGradient.x(), bottomGradient.bottom()), bottomFunction.get(), false, false));
    856 
    857     struct CGFunctionCallbacks mainCallbacks = { 0, MainGradientInterpolate, NULL };
    858     RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
    859     RetainPtr<CGShadingRef> mainShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(),  r.y()), CGPointMake(r.x(), r.bottom()), mainFunction.get(), false, false));
    860 
    861     RetainPtr<CGShadingRef> leftShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(),  r.y()), CGPointMake(r.x() + radius, r.y()), mainFunction.get(), false, false));
    862 
    863     RetainPtr<CGShadingRef> rightShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.right(),  r.y()), CGPointMake(r.right() - radius, r.y()), mainFunction.get(), false, false));
    864     paintInfo.context->save();
    865     CGContextClipToRect(context, r);
    866     paintInfo.context->addRoundedRectClip(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
    867     CGContextDrawShading(context, mainShading.get());
    868     paintInfo.context->restore();
    869 
    870     paintInfo.context->save();
    871     CGContextClipToRect(context, topGradient);
    872     paintInfo.context->addRoundedRectClip(enclosingIntRect(topGradient), topLeftRadius, topRightRadius, IntSize(), IntSize());
    873     CGContextDrawShading(context, topShading.get());
    874     paintInfo.context->restore();
    875 
    876     if (!bottomGradient.isEmpty()) {
    877         paintInfo.context->save();
    878         CGContextClipToRect(context, bottomGradient);
    879         paintInfo.context->addRoundedRectClip(enclosingIntRect(bottomGradient), IntSize(), IntSize(), bottomLeftRadius, bottomRightRadius);
    880         CGContextDrawShading(context, bottomShading.get());
    881         paintInfo.context->restore();
    882     }
    883 
    884     paintInfo.context->save();
    885     CGContextClipToRect(context, r);
    886     paintInfo.context->addRoundedRectClip(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
    887     CGContextDrawShading(context, leftShading.get());
    888     CGContextDrawShading(context, rightShading.get());
    889     paintInfo.context->restore();
    890 
    891     paintInfo.context->restore();
    892 }
    893 
    894 bool RenderThemeMac::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
    895 {
    896     IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(),
    897                              r.y() + o->style()->borderTopWidth(),
    898                              r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(),
    899                              r.height() - o->style()->borderTopWidth() - o->style()->borderBottomWidth());
    900     // Draw the gradients to give the styled popup menu a button appearance
    901     paintMenuListButtonGradients(o, paintInfo, bounds);
    902 
    903     // Since we actually know the size of the control here, we restrict the font scale to make sure the arrows will fit vertically in the bounds
    904     float fontScale = min(o->style()->fontSize() / baseFontSize, bounds.height() / (baseArrowHeight * 2 + baseSpaceBetweenArrows));
    905     float centerY = bounds.y() + bounds.height() / 2.0f;
    906     float arrowHeight = baseArrowHeight * fontScale;
    907     float arrowWidth = baseArrowWidth * fontScale;
    908     float leftEdge = bounds.right() - arrowPaddingRight * o->style()->effectiveZoom() - arrowWidth;
    909     float spaceBetweenArrows = baseSpaceBetweenArrows * fontScale;
    910 
    911     if (bounds.width() < arrowWidth + arrowPaddingLeft * o->style()->effectiveZoom())
    912         return false;
    913 
    914     paintInfo.context->save();
    915 
    916     paintInfo.context->setFillColor(o->style()->color(), o->style()->colorSpace());
    917     paintInfo.context->setStrokeStyle(NoStroke);
    918 
    919     FloatPoint arrow1[3];
    920     arrow1[0] = FloatPoint(leftEdge, centerY - spaceBetweenArrows / 2.0f);
    921     arrow1[1] = FloatPoint(leftEdge + arrowWidth, centerY - spaceBetweenArrows / 2.0f);
    922     arrow1[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY - spaceBetweenArrows / 2.0f - arrowHeight);
    923 
    924     // Draw the top arrow
    925     paintInfo.context->drawConvexPolygon(3, arrow1, true);
    926 
    927     FloatPoint arrow2[3];
    928     arrow2[0] = FloatPoint(leftEdge, centerY + spaceBetweenArrows / 2.0f);
    929     arrow2[1] = FloatPoint(leftEdge + arrowWidth, centerY + spaceBetweenArrows / 2.0f);
    930     arrow2[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY + spaceBetweenArrows / 2.0f + arrowHeight);
    931 
    932     // Draw the bottom arrow
    933     paintInfo.context->drawConvexPolygon(3, arrow2, true);
    934 
    935     Color leftSeparatorColor(0, 0, 0, 40);
    936     Color rightSeparatorColor(255, 255, 255, 40);
    937 
    938     // FIXME: Should the separator thickness and space be scaled up by fontScale?
    939     int separatorSpace = 2; // Deliberately ignores zoom since it looks nicer if it stays thin.
    940     int leftEdgeOfSeparator = static_cast<int>(leftEdge - arrowPaddingLeft * o->style()->effectiveZoom()); // FIXME: Round?
    941 
    942     // Draw the separator to the left of the arrows
    943     paintInfo.context->setStrokeThickness(1.0f); // Deliberately ignores zoom since it looks nicer if it stays thin.
    944     paintInfo.context->setStrokeStyle(SolidStroke);
    945     paintInfo.context->setStrokeColor(leftSeparatorColor, DeviceColorSpace);
    946     paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()),
    947                                 IntPoint(leftEdgeOfSeparator, bounds.bottom()));
    948 
    949     paintInfo.context->setStrokeColor(rightSeparatorColor, DeviceColorSpace);
    950     paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()),
    951                                 IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.bottom()));
    952 
    953     paintInfo.context->restore();
    954     return false;
    955 }
    956 
    957 static const IntSize* menuListButtonSizes()
    958 {
    959     static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
    960     return sizes;
    961 }
    962 
    963 void RenderThemeMac::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
    964 {
    965     NSControlSize controlSize = controlSizeForFont(style);
    966 
    967     style->resetBorder();
    968     style->resetPadding();
    969 
    970     // Height is locked to auto.
    971     style->setHeight(Length(Auto));
    972 
    973     // White-space is locked to pre
    974     style->setWhiteSpace(PRE);
    975 
    976     // Set the foreground color to black or gray when we have the aqua look.
    977     // Cast to RGB32 is to work around a compiler bug.
    978     style->setColor(e && e->isEnabledFormControl() ? static_cast<RGBA32>(Color::black) : Color::darkGray);
    979 
    980     // Set the button's vertical size.
    981     setSizeFromFont(style, menuListButtonSizes());
    982 
    983     // 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
    984     // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
    985     // system font for the control size instead.
    986     setFontFromControlSize(selector, style, controlSize);
    987 
    988     style->setBoxShadow(0);
    989 }
    990 
    991 int RenderThemeMac::popupInternalPaddingLeft(RenderStyle* style) const
    992 {
    993     if (style->appearance() == MenulistPart)
    994         return popupButtonPadding(controlSizeForFont(style))[leftPadding] * style->effectiveZoom();
    995     if (style->appearance() == MenulistButtonPart)
    996         return styledPopupPaddingLeft * style->effectiveZoom();
    997     return 0;
    998 }
    999 
   1000 int RenderThemeMac::popupInternalPaddingRight(RenderStyle* style) const
   1001 {
   1002     if (style->appearance() == MenulistPart)
   1003         return popupButtonPadding(controlSizeForFont(style))[rightPadding] * style->effectiveZoom();
   1004     if (style->appearance() == MenulistButtonPart) {
   1005         float fontScale = style->fontSize() / baseFontSize;
   1006         float arrowWidth = baseArrowWidth * fontScale;
   1007         return static_cast<int>(ceilf(arrowWidth + (arrowPaddingLeft + arrowPaddingRight + paddingBeforeSeparator) * style->effectiveZoom()));
   1008     }
   1009     return 0;
   1010 }
   1011 
   1012 int RenderThemeMac::popupInternalPaddingTop(RenderStyle* style) const
   1013 {
   1014     if (style->appearance() == MenulistPart)
   1015         return popupButtonPadding(controlSizeForFont(style))[topPadding] * style->effectiveZoom();
   1016     if (style->appearance() == MenulistButtonPart)
   1017         return styledPopupPaddingTop * style->effectiveZoom();
   1018     return 0;
   1019 }
   1020 
   1021 int RenderThemeMac::popupInternalPaddingBottom(RenderStyle* style) const
   1022 {
   1023     if (style->appearance() == MenulistPart)
   1024         return popupButtonPadding(controlSizeForFont(style))[bottomPadding] * style->effectiveZoom();
   1025     if (style->appearance() == MenulistButtonPart)
   1026         return styledPopupPaddingBottom * style->effectiveZoom();
   1027     return 0;
   1028 }
   1029 
   1030 void RenderThemeMac::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
   1031 {
   1032     float fontScale = style->fontSize() / baseFontSize;
   1033 
   1034     style->resetPadding();
   1035     style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up?
   1036 
   1037     const int minHeight = 15;
   1038     style->setMinHeight(Length(minHeight, Fixed));
   1039 
   1040     style->setLineHeight(RenderStyle::initialLineHeight());
   1041 }
   1042 
   1043 void RenderThemeMac::setPopupButtonCellState(const RenderObject* o, const IntRect& r)
   1044 {
   1045     NSPopUpButtonCell* popupButton = this->popupButton();
   1046 
   1047     // Set the control size based off the rectangle we're painting into.
   1048     setControlSize(popupButton, popupButtonSizes(), r.size(), o->style()->effectiveZoom());
   1049 
   1050     // Update the various states we respond to.
   1051     updateCheckedState(popupButton, o);
   1052     updateEnabledState(popupButton, o);
   1053     updatePressedState(popupButton, o);
   1054     updateFocusedState(popupButton, o);
   1055 }
   1056 
   1057 const IntSize* RenderThemeMac::menuListSizes() const
   1058 {
   1059     static const IntSize sizes[3] = { IntSize(9, 0), IntSize(5, 0), IntSize(0, 0) };
   1060     return sizes;
   1061 }
   1062 
   1063 int RenderThemeMac::minimumMenuListSize(RenderStyle* style) const
   1064 {
   1065     return sizeForSystemFont(style, menuListSizes()).width();
   1066 }
   1067 
   1068 const int trackWidth = 5;
   1069 const int trackRadius = 2;
   1070 
   1071 void RenderThemeMac::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
   1072 {
   1073     style->setBoxShadow(0);
   1074 }
   1075 
   1076 bool RenderThemeMac::paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1077 {
   1078     IntRect bounds = r;
   1079     float zoomLevel = o->style()->effectiveZoom();
   1080     float zoomedTrackWidth = trackWidth * zoomLevel;
   1081 
   1082     if (o->style()->appearance() ==  SliderHorizontalPart || o->style()->appearance() ==  MediaSliderPart) {
   1083         bounds.setHeight(zoomedTrackWidth);
   1084         bounds.setY(r.y() + r.height() / 2 - zoomedTrackWidth / 2);
   1085     } else if (o->style()->appearance() == SliderVerticalPart) {
   1086         bounds.setWidth(zoomedTrackWidth);
   1087         bounds.setX(r.x() + r.width() / 2 - zoomedTrackWidth / 2);
   1088     }
   1089 
   1090     LocalCurrentGraphicsContext localContext(paintInfo.context);
   1091     CGContextRef context = paintInfo.context->platformContext();
   1092     RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB());
   1093 
   1094     paintInfo.context->save();
   1095     CGContextClipToRect(context, bounds);
   1096 
   1097     struct CGFunctionCallbacks mainCallbacks = { 0, TrackGradientInterpolate, NULL };
   1098     RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
   1099     RetainPtr<CGShadingRef> mainShading;
   1100     if (o->style()->appearance() == SliderVerticalPart)
   1101         mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(),  bounds.bottom()), CGPointMake(bounds.right(), bounds.bottom()), mainFunction.get(), false, false));
   1102     else
   1103         mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(),  bounds.y()), CGPointMake(bounds.x(), bounds.bottom()), mainFunction.get(), false, false));
   1104 
   1105     IntSize radius(trackRadius, trackRadius);
   1106     paintInfo.context->addRoundedRectClip(bounds,
   1107         radius, radius,
   1108         radius, radius);
   1109     CGContextDrawShading(context, mainShading.get());
   1110     paintInfo.context->restore();
   1111 
   1112     return false;
   1113 }
   1114 
   1115 void RenderThemeMac::adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
   1116 {
   1117     style->setBoxShadow(0);
   1118 }
   1119 
   1120 const float verticalSliderHeightPadding = 0.1f;
   1121 
   1122 bool RenderThemeMac::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1123 {
   1124     ASSERT(o->parent()->isSlider());
   1125 
   1126     NSSliderCell* sliderThumbCell = o->style()->appearance() == SliderThumbVerticalPart
   1127         ? sliderThumbVertical()
   1128         : sliderThumbHorizontal();
   1129 
   1130     LocalCurrentGraphicsContext localContext(paintInfo.context);
   1131 
   1132     // Update the various states we respond to.
   1133     updateEnabledState(sliderThumbCell, o->parent());
   1134     updateFocusedState(sliderThumbCell, o->parent());
   1135 
   1136     // Update the pressed state using the NSCell tracking methods, since that's how NSSliderCell keeps track of it.
   1137     bool oldPressed;
   1138     if (o->style()->appearance() == SliderThumbVerticalPart)
   1139         oldPressed = m_isSliderThumbVerticalPressed;
   1140     else
   1141         oldPressed = m_isSliderThumbHorizontalPressed;
   1142 
   1143     bool pressed = toRenderSlider(o->parent())->inDragMode();
   1144 
   1145     if (o->style()->appearance() == SliderThumbVerticalPart)
   1146         m_isSliderThumbVerticalPressed = pressed;
   1147     else
   1148         m_isSliderThumbHorizontalPressed = pressed;
   1149 
   1150     if (pressed != oldPressed) {
   1151         if (pressed)
   1152             [sliderThumbCell startTrackingAt:NSPoint() inView:nil];
   1153         else
   1154             [sliderThumbCell stopTracking:NSPoint() at:NSPoint() inView:nil mouseIsUp:YES];
   1155     }
   1156 
   1157     FloatRect bounds = r;
   1158     // Make the height of the vertical slider slightly larger so NSSliderCell will draw a vertical slider.
   1159     if (o->style()->appearance() == SliderThumbVerticalPart)
   1160         bounds.setHeight(bounds.height() + verticalSliderHeightPadding * o->style()->effectiveZoom());
   1161 
   1162     paintInfo.context->save();
   1163     float zoomLevel = o->style()->effectiveZoom();
   1164 
   1165     FloatRect unzoomedRect = bounds;
   1166     if (zoomLevel != 1.0f) {
   1167         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
   1168         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
   1169         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
   1170         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
   1171         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
   1172     }
   1173 
   1174     [sliderThumbCell drawWithFrame:unzoomedRect inView:o->view()->frameView()->documentView()];
   1175     [sliderThumbCell setControlView:nil];
   1176 
   1177     paintInfo.context->restore();
   1178 
   1179     return false;
   1180 }
   1181 
   1182 bool RenderThemeMac::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1183 {
   1184     NSSearchFieldCell* search = this->search();
   1185     LocalCurrentGraphicsContext localContext(paintInfo.context);
   1186 
   1187     setSearchCellState(o, r);
   1188 
   1189     paintInfo.context->save();
   1190 
   1191     float zoomLevel = o->style()->effectiveZoom();
   1192 
   1193     IntRect unzoomedRect = r;
   1194 
   1195     if (zoomLevel != 1.0f) {
   1196         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
   1197         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
   1198         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
   1199         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
   1200         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
   1201     }
   1202 
   1203     // Set the search button to nil before drawing.  Then reset it so we can draw it later.
   1204     [search setSearchButtonCell:nil];
   1205 
   1206     [search drawWithFrame:NSRect(unzoomedRect) inView:o->view()->frameView()->documentView()];
   1207 #ifdef BUILDING_ON_TIGER
   1208     if ([search showsFirstResponder])
   1209         wkDrawTextFieldCellFocusRing(search, NSRect(unzoomedRect));
   1210 #endif
   1211 
   1212     [search setControlView:nil];
   1213     [search resetSearchButtonCell];
   1214 
   1215     paintInfo.context->restore();
   1216 
   1217     return false;
   1218 }
   1219 
   1220 void RenderThemeMac::setSearchCellState(RenderObject* o, const IntRect&)
   1221 {
   1222     NSSearchFieldCell* search = this->search();
   1223 
   1224     [search setControlSize:controlSizeForFont(o->style())];
   1225 
   1226     // Update the various states we respond to.
   1227     updateEnabledState(search, o);
   1228     updateFocusedState(search, o);
   1229 }
   1230 
   1231 const IntSize* RenderThemeMac::searchFieldSizes() const
   1232 {
   1233     static const IntSize sizes[3] = { IntSize(0, 22), IntSize(0, 19), IntSize(0, 17) };
   1234     return sizes;
   1235 }
   1236 
   1237 void RenderThemeMac::setSearchFieldSize(RenderStyle* style) const
   1238 {
   1239     // If the width and height are both specified, then we have nothing to do.
   1240     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
   1241         return;
   1242 
   1243     // Use the font size to determine the intrinsic width of the control.
   1244     setSizeFromFont(style, searchFieldSizes());
   1245 }
   1246 
   1247 void RenderThemeMac::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element*) const
   1248 {
   1249     // Override border.
   1250     style->resetBorder();
   1251     const short borderWidth = 2 * style->effectiveZoom();
   1252     style->setBorderLeftWidth(borderWidth);
   1253     style->setBorderLeftStyle(INSET);
   1254     style->setBorderRightWidth(borderWidth);
   1255     style->setBorderRightStyle(INSET);
   1256     style->setBorderBottomWidth(borderWidth);
   1257     style->setBorderBottomStyle(INSET);
   1258     style->setBorderTopWidth(borderWidth);
   1259     style->setBorderTopStyle(INSET);
   1260 
   1261     // Override height.
   1262     style->setHeight(Length(Auto));
   1263     setSearchFieldSize(style);
   1264 
   1265     // Override padding size to match AppKit text positioning.
   1266     const int padding = 1 * style->effectiveZoom();
   1267     style->setPaddingLeft(Length(padding, Fixed));
   1268     style->setPaddingRight(Length(padding, Fixed));
   1269     style->setPaddingTop(Length(padding, Fixed));
   1270     style->setPaddingBottom(Length(padding, Fixed));
   1271 
   1272     NSControlSize controlSize = controlSizeForFont(style);
   1273     setFontFromControlSize(selector, style, controlSize);
   1274 
   1275     style->setBoxShadow(0);
   1276 }
   1277 
   1278 bool RenderThemeMac::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1279 {
   1280     Node* input = o->node()->shadowAncestorNode();
   1281     if (!input->renderer()->isBox())
   1282         return false;
   1283 
   1284     setSearchCellState(input->renderer(), r);
   1285 
   1286     NSSearchFieldCell* search = this->search();
   1287 
   1288     updatePressedState([search cancelButtonCell], o);
   1289 
   1290     paintInfo.context->save();
   1291 
   1292     float zoomLevel = o->style()->effectiveZoom();
   1293 
   1294     FloatRect localBounds = [search cancelButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())];
   1295     localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
   1296 
   1297     FloatRect unzoomedRect(localBounds);
   1298     if (zoomLevel != 1.0f) {
   1299         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
   1300         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
   1301         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
   1302         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
   1303         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
   1304     }
   1305 
   1306     [[search cancelButtonCell] drawWithFrame:unzoomedRect inView:o->view()->frameView()->documentView()];
   1307     [[search cancelButtonCell] setControlView:nil];
   1308 
   1309     paintInfo.context->restore();
   1310     return false;
   1311 }
   1312 
   1313 const IntSize* RenderThemeMac::cancelButtonSizes() const
   1314 {
   1315     static const IntSize sizes[3] = { IntSize(16, 13), IntSize(13, 11), IntSize(13, 9) };
   1316     return sizes;
   1317 }
   1318 
   1319 void RenderThemeMac::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
   1320 {
   1321     IntSize size = sizeForSystemFont(style, cancelButtonSizes());
   1322     style->setWidth(Length(size.width(), Fixed));
   1323     style->setHeight(Length(size.height(), Fixed));
   1324     style->setBoxShadow(0);
   1325 }
   1326 
   1327 const IntSize* RenderThemeMac::resultsButtonSizes() const
   1328 {
   1329     static const IntSize sizes[3] = { IntSize(19, 13), IntSize(17, 11), IntSize(17, 9) };
   1330     return sizes;
   1331 }
   1332 
   1333 const int emptyResultsOffset = 9;
   1334 void RenderThemeMac::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
   1335 {
   1336     IntSize size = sizeForSystemFont(style, resultsButtonSizes());
   1337     style->setWidth(Length(size.width() - emptyResultsOffset, Fixed));
   1338     style->setHeight(Length(size.height(), Fixed));
   1339     style->setBoxShadow(0);
   1340 }
   1341 
   1342 bool RenderThemeMac::paintSearchFieldDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&)
   1343 {
   1344     return false;
   1345 }
   1346 
   1347 void RenderThemeMac::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
   1348 {
   1349     IntSize size = sizeForSystemFont(style, resultsButtonSizes());
   1350     style->setWidth(Length(size.width(), Fixed));
   1351     style->setHeight(Length(size.height(), Fixed));
   1352     style->setBoxShadow(0);
   1353 }
   1354 
   1355 bool RenderThemeMac::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo&, const IntRect& r)
   1356 {
   1357     Node* input = o->node()->shadowAncestorNode();
   1358     if (!input->renderer()->isBox())
   1359         return false;
   1360 
   1361     setSearchCellState(input->renderer(), r);
   1362 
   1363     NSSearchFieldCell* search = this->search();
   1364 
   1365     if ([search searchMenuTemplate] != nil)
   1366         [search setSearchMenuTemplate:nil];
   1367 
   1368     FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())];
   1369     localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
   1370 
   1371     [[search searchButtonCell] drawWithFrame:localBounds inView:o->view()->frameView()->documentView()];
   1372     [[search searchButtonCell] setControlView:nil];
   1373     return false;
   1374 }
   1375 
   1376 const int resultsArrowWidth = 5;
   1377 void RenderThemeMac::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
   1378 {
   1379     IntSize size = sizeForSystemFont(style, resultsButtonSizes());
   1380     style->setWidth(Length(size.width() + resultsArrowWidth, Fixed));
   1381     style->setHeight(Length(size.height(), Fixed));
   1382     style->setBoxShadow(0);
   1383 }
   1384 
   1385 bool RenderThemeMac::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1386 {
   1387     Node* input = o->node()->shadowAncestorNode();
   1388     if (!input->renderer()->isBox())
   1389         return false;
   1390 
   1391     setSearchCellState(input->renderer(), r);
   1392 
   1393     NSSearchFieldCell* search = this->search();
   1394 
   1395     if (![search searchMenuTemplate])
   1396         [search setSearchMenuTemplate:searchMenuTemplate()];
   1397 
   1398     paintInfo.context->save();
   1399 
   1400     float zoomLevel = o->style()->effectiveZoom();
   1401 
   1402     FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())];
   1403     localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
   1404 
   1405     IntRect unzoomedRect(localBounds);
   1406     if (zoomLevel != 1.0f) {
   1407         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
   1408         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
   1409         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
   1410         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
   1411         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
   1412     }
   1413 
   1414     [[search searchButtonCell] drawWithFrame:unzoomedRect inView:o->view()->frameView()->documentView()];
   1415     [[search searchButtonCell] setControlView:nil];
   1416 
   1417     paintInfo.context->restore();
   1418 
   1419     return false;
   1420 }
   1421 
   1422 #if ENABLE(VIDEO)
   1423 typedef enum {
   1424     MediaControllerThemeClassic   = 1,
   1425     MediaControllerThemeQuickTime = 2
   1426 } MediaControllerThemeStyle;
   1427 
   1428 static int mediaControllerTheme()
   1429 {
   1430     static int controllerTheme = -1;
   1431 
   1432     if (controllerTheme != -1)
   1433         return controllerTheme;
   1434 
   1435     controllerTheme = MediaControllerThemeClassic;
   1436 
   1437     Boolean validKey;
   1438     Boolean useQTMediaUIPref = CFPreferencesGetAppBooleanValue(CFSTR("UseQuickTimeMediaUI"), CFSTR("com.apple.WebCore"), &validKey);
   1439 
   1440 #if !defined(BUILDING_ON_TIGER)
   1441     if (validKey && !useQTMediaUIPref)
   1442         return controllerTheme;
   1443 #else
   1444     if (!validKey || !useQTMediaUIPref)
   1445         return controllerTheme;
   1446 #endif
   1447 
   1448     controllerTheme = MediaControllerThemeQuickTime;
   1449     return controllerTheme;
   1450 }
   1451 #endif
   1452 
   1453 const int sliderThumbWidth = 15;
   1454 const int sliderThumbHeight = 15;
   1455 const int mediaSliderThumbWidth = 13;
   1456 const int mediaSliderThumbHeight = 14;
   1457 
   1458 void RenderThemeMac::adjustSliderThumbSize(RenderObject* o) const
   1459 {
   1460     float zoomLevel = o->style()->effectiveZoom();
   1461     if (o->style()->appearance() == SliderThumbHorizontalPart || o->style()->appearance() == SliderThumbVerticalPart) {
   1462         o->style()->setWidth(Length(static_cast<int>(sliderThumbWidth * zoomLevel), Fixed));
   1463         o->style()->setHeight(Length(static_cast<int>(sliderThumbHeight * zoomLevel), Fixed));
   1464     }
   1465 
   1466 #if ENABLE(VIDEO)
   1467     else if (o->style()->appearance() == MediaSliderThumbPart) {
   1468         int width = mediaSliderThumbWidth;
   1469         int height = mediaSliderThumbHeight;
   1470 
   1471         if (mediaControllerTheme() == MediaControllerThemeQuickTime) {
   1472             CGSize  size;
   1473 
   1474             wkMeasureMediaUIPart(MediaSliderThumb, MediaControllerThemeQuickTime, NULL, &size);
   1475             width = size.width;
   1476             height = size.height;
   1477         }
   1478 
   1479         o->style()->setWidth(Length(static_cast<int>(width * zoomLevel), Fixed));
   1480         o->style()->setHeight(Length(static_cast<int>(height * zoomLevel), Fixed));
   1481     }
   1482 #endif
   1483 }
   1484 
   1485 
   1486 #if ENABLE(VIDEO)
   1487 
   1488 enum WKMediaControllerThemeState {
   1489     MediaUIPartDisabledFlag = 1 << 0,
   1490     MediaUIPartPressedFlag = 1 << 1,
   1491     MediaUIPartDrawEndCapsFlag = 1 << 3,
   1492 };
   1493 
   1494 static unsigned getMediaUIPartStateFlags(Node* node)
   1495 {
   1496     unsigned flags = 0;
   1497 
   1498     if (node->disabled())
   1499         flags |= MediaUIPartDisabledFlag;
   1500     else if (node->active())
   1501         flags |= MediaUIPartPressedFlag;
   1502     return flags;
   1503 }
   1504 
   1505 // Utility to scale when the UI part are not scaled by wkDrawMediaUIPart
   1506 static FloatRect getUnzoomedRectAndAdjustCurrentContext(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect &originalRect)
   1507 {
   1508     float zoomLevel = o->style()->effectiveZoom();
   1509     FloatRect unzoomedRect(originalRect);
   1510     if (zoomLevel != 1.0f && mediaControllerTheme() == MediaControllerThemeQuickTime) {
   1511         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
   1512         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
   1513         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
   1514         paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
   1515         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
   1516     }
   1517     return unzoomedRect;
   1518 }
   1519 
   1520 
   1521 bool RenderThemeMac::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1522 {
   1523     Node* node = o->node();
   1524     if (!node)
   1525         return false;
   1526 
   1527     LocalCurrentGraphicsContext localContext(paintInfo.context);
   1528     wkDrawMediaUIPart(MediaFullscreenButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
   1529     return false;
   1530 }
   1531 
   1532 bool RenderThemeMac::paintMediaMuteButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1533 {
   1534     Node* node = o->node();
   1535     Node* mediaNode = node ? node->shadowAncestorNode() : 0;
   1536     if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
   1537         return false;
   1538 
   1539     if (MediaControlMuteButtonElement* btn = static_cast<MediaControlMuteButtonElement*>(node)) {
   1540         LocalCurrentGraphicsContext localContext(paintInfo.context);
   1541         wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
   1542 
   1543     }
   1544     return false;
   1545 }
   1546 
   1547 bool RenderThemeMac::paintMediaPlayButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1548 {
   1549     Node* node = o->node();
   1550     Node* mediaNode = node ? node->shadowAncestorNode() : 0;
   1551     if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
   1552         return false;
   1553 
   1554     if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(node)) {
   1555         LocalCurrentGraphicsContext localContext(paintInfo.context);
   1556         wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
   1557     }
   1558     return false;
   1559 }
   1560 
   1561 bool RenderThemeMac::paintMediaSeekBackButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1562 {
   1563     Node* node = o->node();
   1564     if (!node)
   1565         return false;
   1566 
   1567     LocalCurrentGraphicsContext localContext(paintInfo.context);
   1568     wkDrawMediaUIPart(MediaSeekBackButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
   1569     return false;
   1570 }
   1571 
   1572 bool RenderThemeMac::paintMediaSeekForwardButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1573 {
   1574     Node* node = o->node();
   1575     if (!node)
   1576         return false;
   1577 
   1578     LocalCurrentGraphicsContext localContext(paintInfo.context);
   1579     wkDrawMediaUIPart(MediaSeekForwardButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
   1580     return false;
   1581 }
   1582 
   1583 bool RenderThemeMac::paintMediaSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1584 {
   1585     Node* node = o->node();
   1586     Node* mediaNode = node ? node->shadowAncestorNode() : 0;
   1587     if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
   1588         return false;
   1589 
   1590     HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
   1591     if (!mediaElement)
   1592         return false;
   1593 
   1594     RefPtr<TimeRanges> timeRanges = mediaElement->buffered();
   1595     ExceptionCode ignoredException;
   1596     float timeLoaded = timeRanges->length() ? timeRanges->end(0, ignoredException) : 0;
   1597     float currentTime = mediaElement->currentTime();
   1598     float duration = mediaElement->duration();
   1599     if (isnan(duration))
   1600         duration = 0;
   1601 
   1602     paintInfo.context->save();
   1603     FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
   1604     wkDrawMediaSliderTrack(mediaControllerTheme(), paintInfo.context->platformContext(), unzoomedRect,
   1605         timeLoaded, currentTime, duration, getMediaUIPartStateFlags(node));
   1606 
   1607     paintInfo.context->restore();
   1608     return false;
   1609 }
   1610 
   1611 bool RenderThemeMac::paintMediaSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1612 {
   1613     Node* node = o->node();
   1614     if (!node)
   1615         return false;
   1616 
   1617     LocalCurrentGraphicsContext localContext(paintInfo.context);
   1618     wkDrawMediaUIPart(MediaSliderThumb, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
   1619     return false;
   1620 }
   1621 
   1622 bool RenderThemeMac::paintMediaRewindButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1623 {
   1624     Node* node = o->node();
   1625     if (!node)
   1626         return false;
   1627 
   1628     LocalCurrentGraphicsContext localContext(paintInfo.context);
   1629     wkDrawMediaUIPart(MediaRewindButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
   1630     return false;
   1631 }
   1632 
   1633 bool RenderThemeMac::paintMediaReturnToRealtimeButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1634 {
   1635     Node* node = o->node();
   1636     if (!node)
   1637         return false;
   1638 
   1639     LocalCurrentGraphicsContext localContext(paintInfo.context);
   1640     wkDrawMediaUIPart(MediaReturnToRealtimeButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
   1641     return false;
   1642 }
   1643 
   1644 bool RenderThemeMac::paintMediaToggleClosedCaptionsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1645 {
   1646     HTMLInputElement* node = static_cast<HTMLInputElement*>(o->node());
   1647     if (!node)
   1648         return false;
   1649 
   1650     MediaControlToggleClosedCaptionsButtonElement* btn = static_cast<MediaControlToggleClosedCaptionsButtonElement*>(node);
   1651     if (!btn)
   1652         return false;
   1653 
   1654     LocalCurrentGraphicsContext localContext(paintInfo.context);
   1655     wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
   1656 
   1657     return false;
   1658 }
   1659 
   1660 bool RenderThemeMac::paintMediaControlsBackground(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1661 {
   1662     Node* node = o->node();
   1663     if (!node)
   1664         return false;
   1665 
   1666     LocalCurrentGraphicsContext localContext(paintInfo.context);
   1667     wkDrawMediaUIPart(MediaTimelineContainer, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
   1668     return false;
   1669 }
   1670 
   1671 bool RenderThemeMac::paintMediaCurrentTime(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1672 {
   1673     Node* node = o->node();
   1674     if (!node)
   1675         return false;
   1676 
   1677     paintInfo.context->save();
   1678     FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
   1679     wkDrawMediaUIPart(MediaCurrentTimeDisplay, mediaControllerTheme(), paintInfo.context->platformContext(), unzoomedRect, getMediaUIPartStateFlags(node));
   1680     paintInfo.context->restore();
   1681     return false;
   1682 }
   1683 
   1684 bool RenderThemeMac::paintMediaTimeRemaining(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1685 {
   1686     Node* node = o->node();
   1687     if (!node)
   1688         return false;
   1689 
   1690     paintInfo.context->save();
   1691     FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
   1692     wkDrawMediaUIPart(MediaTimeRemainingDisplay, mediaControllerTheme(), paintInfo.context->platformContext(), unzoomedRect, getMediaUIPartStateFlags(node));
   1693     paintInfo.context->restore();
   1694     return false;
   1695 }
   1696 
   1697 String RenderThemeMac::extraMediaControlsStyleSheet()
   1698 {
   1699     if (mediaControllerTheme() == MediaControllerThemeQuickTime)
   1700         return String(mediaControlsQuickTimeUserAgentStyleSheet, sizeof(mediaControlsQuickTimeUserAgentStyleSheet));
   1701     else
   1702         return String();
   1703 }
   1704 
   1705 bool RenderThemeMac::shouldRenderMediaControlPart(ControlPart part, Element* element)
   1706 {
   1707     if (part == MediaToggleClosedCaptionsButtonPart) {
   1708 
   1709         // We rely on QTKit to render captions so don't enable the button unless it will be able to do so.
   1710         if (!element->hasTagName(videoTag))
   1711             return false;
   1712     }
   1713 
   1714     return RenderTheme::shouldRenderMediaControlPart(part, element);
   1715 }
   1716 
   1717 #endif // ENABLE(VIDEO)
   1718 
   1719 NSPopUpButtonCell* RenderThemeMac::popupButton() const
   1720 {
   1721     if (!m_popupButton) {
   1722         m_popupButton.adoptNS([[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]);
   1723         [m_popupButton.get() setUsesItemFromMenu:NO];
   1724         [m_popupButton.get() setFocusRingType:NSFocusRingTypeExterior];
   1725     }
   1726 
   1727     return m_popupButton.get();
   1728 }
   1729 
   1730 NSSearchFieldCell* RenderThemeMac::search() const
   1731 {
   1732     if (!m_search) {
   1733         m_search.adoptNS([[NSSearchFieldCell alloc] initTextCell:@""]);
   1734         [m_search.get() setBezelStyle:NSTextFieldRoundedBezel];
   1735         [m_search.get() setBezeled:YES];
   1736         [m_search.get() setEditable:YES];
   1737         [m_search.get() setFocusRingType:NSFocusRingTypeExterior];
   1738     }
   1739 
   1740     return m_search.get();
   1741 }
   1742 
   1743 NSMenu* RenderThemeMac::searchMenuTemplate() const
   1744 {
   1745     if (!m_searchMenuTemplate)
   1746         m_searchMenuTemplate.adoptNS([[NSMenu alloc] initWithTitle:@""]);
   1747 
   1748     return m_searchMenuTemplate.get();
   1749 }
   1750 
   1751 NSSliderCell* RenderThemeMac::sliderThumbHorizontal() const
   1752 {
   1753     if (!m_sliderThumbHorizontal) {
   1754         m_sliderThumbHorizontal.adoptNS([[NSSliderCell alloc] init]);
   1755         [m_sliderThumbHorizontal.get() setTitle:nil];
   1756         [m_sliderThumbHorizontal.get() setSliderType:NSLinearSlider];
   1757         [m_sliderThumbHorizontal.get() setControlSize:NSSmallControlSize];
   1758         [m_sliderThumbHorizontal.get() setFocusRingType:NSFocusRingTypeExterior];
   1759     }
   1760 
   1761     return m_sliderThumbHorizontal.get();
   1762 }
   1763 
   1764 NSSliderCell* RenderThemeMac::sliderThumbVertical() const
   1765 {
   1766     if (!m_sliderThumbVertical) {
   1767         m_sliderThumbVertical.adoptNS([[NSSliderCell alloc] init]);
   1768         [m_sliderThumbVertical.get() setTitle:nil];
   1769         [m_sliderThumbVertical.get() setSliderType:NSLinearSlider];
   1770         [m_sliderThumbVertical.get() setControlSize:NSSmallControlSize];
   1771         [m_sliderThumbVertical.get() setFocusRingType:NSFocusRingTypeExterior];
   1772     }
   1773 
   1774     return m_sliderThumbVertical.get();
   1775 }
   1776 
   1777 } // namespace WebCore
   1778