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